1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
class User < ActiveRecord::Base
has_and_belongs_to_many :tournaments_played, class_name: "Tournament", foreign_key: "tournament_id", join_table: "players_tournaments"
has_and_belongs_to_many :tournaments_hosted, class_name: "Tournament", foreign_key: "tournament_id", join_table: "hosts_tournaments"
before_save { self.email = email.downcase }
before_save { self.user_name = user_name }
##
# Rails looks for the create_remember_token and runs the method
# before anything else.
#
# This method cannot be called by a user since it is denoted
# as private.
before_create :create_remember_token
def in_group?(group)
case group
when :admin
return ((groups & 2) != 0)
when :host
return true #((groups & 1) != 0)
when :player
return true
when :specator
return true
else
return false
end
end
def join_groups(join=[])
# FIXME: race condition
join.each do |group|
case group
when :admin
groups |= 2
when :host
groups |= 1
else
end
end
end
def leave_groups(leave=[])
# FIXME: race condition
leave.each do |group|
case group
when :admin
groups &= ~ 2
when :host
groups &= ~ 1
else
end
end
end
##
# VAILD_EMAIL is the regex used to validate a user given email.
VALID_EMAIL_REG = /\A\S+@\S+\.\S+\z/i
##
# VALID_USER_NAME checks to make sure a user's user_name
# is in the proper format.
VALID_USER_NAME_REG = /\A[a-zA-Z0-9\-]+\z/
##
# The following lines put a user account through a series of
# validations in order to make sure all of their information
# is in the proper format.
#
# validates :symbol_to_be_validated
#
# - presence: determines whether or not a symbol is filled or not
# - length: ensures there is a length limit on the symbol
# - format: checks the format of given information to ensure
# validity
validates(:name, presence: true, length: { maximum: 50 })
validates(:email, presence: true, format: {with:
VALID_EMAIL_REG},
uniqueness: { case_sensitive: false })
validates(:user_name, presence: true, length:{maximum: 50},
format: {with: VALID_USER_NAME_REG },
uniqueness: {case_sensitive: false })
##
# Instead of adding password and password_confirmation
# attributes, requiring the presence of a password,
# requiring that pw and pw_com match, and add an authenticate
# method to compare an encrypted password to the
# password_digest to authenticate users, I can just add
# has_secure_password which does all of this for me.
has_secure_password
validates :password, length: { minimum: 6 }
##
# Create a random remember token for the user. This will be
# changed every time the user creates a new session.
#
# By changing the cookie every new session, any hijacked sessions
# (where the attacker steals a cookie to sign in as a certain
# user) will expire the next time the user signs back in.
#
# The random string is of length 16 composed of A-Z, a-z, 0-9
# This is the browser's cookie value.
def User.new_remember_token
SecureRandom.urlsafe_base64
end
##
# Encrypt the remember token.
# This is the encrypted version of the cookie stored on
# the database.
#
# The reasoning for storing a hashed token is so that even if
# the database is compromised, the attacker won't be able to use
# the remember tokens to sign in.
def User.hash(token)
Digest::SHA1.hexdigest(token.to_s)
end
##
# SHA-1 (Secure Hash Algorithm) is a US engineered hash
# function that produces a 20 byte hash value which typically
# forms a hexadecimal number 40 digits long.
# The reason I am not using the Bcrypt algorithm is because
# SHA-1 is much faster and I will be calling this on
# every page a user accesses.
#
# https://en.wikipedia.org/wiki/SHA-1
# Everything under private is hidden so you cannot call.
private
##
# Create_remember_token in order to ensure a user always has
# a remember token.
def create_remember_token
self.remember_token = User.hash(User.new_remember_token)
end
##
# In order to ensure that someone did not accidentally submit
# two accounts rapidly (which would throw off the validates
# for user_name and email), I added an index to the Users
# email and user_name in the database to ensure uniqueness
# This also gives and index to the user_name and email
# so finding a user SHOULD be easier for the database.
end
|