summaryrefslogtreecommitdiff
path: root/app/models/user.rb
blob: 55ea60f76f7c5b2bdb187efbfc36fcc58d18803a (plain)
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
class User < ActiveRecord::Base

	before_save { self.email = email.downcase }
	before_save { self.user_name = user_name.downcase }

	##
	# 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

	##
	# 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