-
Notifications
You must be signed in to change notification settings - Fork 98
Expand file tree
/
Copy pathhacker.rb
More file actions
135 lines (107 loc) · 4.36 KB
/
hacker.rb
File metadata and controls
135 lines (107 loc) · 4.36 KB
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
#This is the Hacker class. Every user of Hackety Hack gets one!
#most of the stuff in this is based off of then sinatra-authentication plugin.
class Hacker
#our Hacker model is a full-fledged Document
include MongoMapper::Document
#we're storing a unique username
key :username, String, :unique => true
#and a unique email
key :email, String, :unique => true
#a little bit about the Hacker
key :about, String
#we don't store the passwords themselves, we store a 'hash' of them. More about this down in password=
key :hashed_password, String
key :salt, String
#this is a flag to let us know if this Hacker can administrate the site or not.
key :admin, Boolean, :default => false
#the list of hackers this hacker is following
key :following_ids, Array
many :following, :in => :following_ids, :class_name => 'Hacker'
#the list of hackers that are following this hacker
key :followers_ids, Array
many :followers, :in => :followers_ids, :class_name => 'Hacker'
#after we create a hacker, we want to have them follow steve, and vice versa!
after_create :follow_steve
#we don't want to store the password (or the confirmation), so we just make an accessor
attr_accessor :password, :password_confirmation
#okay, this is the method that sets the password
def password=(pass)
@password = pass
#okay, we need to get a 'salt'. You can read about salts here: http://en.wikipedia.org/wiki/Salt_(cryptography)
#basically, we combine the password with the salt, and then encrypt it, and store that in the database.
#The reason that we do this is because we don't want to keep someone's
#password in the database, because you never want to write those down!
#So when we go to look up a password, we can do the same procedure.
#anyway, let's check if we've got a salt yet. If not, make one.
self.salt = random_string(10) if !self.salt
#then, we set the hashed password to the encrypted password + salt.
self.hashed_password = Hacker.encrypt(@password, self.salt)
end
#this method lets will return the user if we've given the right username
#and password for the user. Otherwise, it returns nil.
def self.authenticate(username, pass)
#first we have to dig up the record from the database
current_user = Hacker.first(:username => username)
#and return nil if we didn't find one.
return nil if current_user.nil?
#then, we do the same thing that we did when we stored the hashed password:
#encrypt the password using the salt, and compare it to the one we saved
#if they're the same, we know they entered the right password.
return current_user if Hacker.encrypt(pass, current_user.salt) == current_user.hashed_password
#if that didn't work, well, you're all out of luck!
nil
end
#this is just a nice helper function to see if a hacker is an admin
def admin?
return self.admin == true
end
#a helper function for gravatar urls
def gravatar_url
require 'digest/md5'
"http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(email.downcase)}"
end
#this method makes the hacker follow the followee
def follow! followee
following << followee
save
followee.followers << self
followee.save
end
#this method makes the hacker unfollow the followee
def unfollow! followee
following_ids.delete(followee.id)
save
followee.followers_ids.delete(id)
followee.save
end
#this method returns true if we're following the given Hacker, and
#false otherwise
def following? hacker
following.include? hacker
end
#this method looks up the programs for a given user
def programs
Program.all(:creator_username => username)
end
private
#we're going to use the SHA1 encryption method for now.
def self.encrypt(password, salt)
Digest::SHA1.hexdigest(password + salt)
end
#this is a nifty little method to give us a random string of characters
def random_string(len)
#first, we make a bunch of random characters in an array
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
newpass = ""
#then we grab a random element of that array, and add it onto our newpass
1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
return newpass
end
def follow_steve
return if username == "steve"
steve = Hacker.first(:username => 'steve')
return if steve.nil?
follow! steve
steve.follow! self
end
end