redsafe 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
@@ -0,0 +1,74 @@
1
+ = RedSafe Gemcutter Setup
2
+
3
+ Gem Cutter set up was more time consuming than I had anticipated. Realized that I needed: task "default" => ["test"] inside the Rakefile to have rake command work for me. Additionally, I needed to use: gem cert before I could upload to Gemcutter.
4
+
5
+ == Notes on the Red Safe Gem Creation
6
+
7
+ * 1) rake
8
+ (Needed to set a default for the task.)
9
+
10
+ Added default task to Rakefile
11
+ task "default" => ["test"]
12
+
13
+ * 2) rake gemspec
14
+ (Worked for me first time.)
15
+
16
+ Generated: redsafe.gemspec
17
+ redsafe.gemspec is valid.
18
+
19
+ * 3) rdoc
20
+ (Created documentation for the redsafe project.)
21
+
22
+ redsafe.rb: mm.m.......c...
23
+ sl_user.rb: c.....cc....
24
+ sl_aah.rb: m.m.....m..
25
+ scarlet_letters.rb: c........
26
+ version.rb: cm
27
+ Generating HTML...
28
+
29
+ Files: 5
30
+ Classes: 6
31
+ Modules: 7
32
+ Methods: 36
33
+ Elapsed: 0.593s
34
+
35
+ * 4) gem build redsafe.gemspec
36
+ (Was able to build after I took author name "Ruby Shot" from an array structure and turned it into a string by removing the brackets, [ ].
37
+
38
+ # gem build redsafe.gemspec
39
+ ERROR: While executing gem ... (Gem::InvalidSpecificationException)
40
+ authors must be Array of Strings
41
+
42
+
43
+ * 5) gem push redsafe.gem
44
+ (As mentioned above, the gem certification was not set. Thus, I couldn't get an upload to Gemcutter.)
45
+
46
+ Your api key has been stored in ~/.gem/credentials
47
+ Pushing gem to Gemcutter...
48
+ ERROR: While executing gem ... (Errno::ENOENT)
49
+ No such file or directory - redsafe.gem
50
+
51
+
52
+ * 6) gem cert --build you@yourmail.com
53
+ (Use this command to create the certification for Gemcutter. I used my email address. I also moved the Public Cert and the Private Key to a safer location.)
54
+
55
+ Public Cert: gem-public_cert.pem
56
+ Private Key: gem-private_key.pem
57
+ Don't forget to move the key file to somewhere private...
58
+
59
+
60
+ * 7)gem push redsafe-0.1.1.gem
61
+ (I was successful when I used the above command. Used the Gemcutter search and verified that redsafe was being hosted on Gemcutter. Didn't test it, but left it in place.)
62
+
63
+ Pushing gem to Gemcutter...
64
+ Successfully registered gem: redsafe (0.1.1)
65
+
66
+ == Copyright
67
+
68
+ Copyright (c) 2010 Ruby Shot. See LICENSE for details.
69
+
70
+
71
+
72
+
73
+
74
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Ruby Shot
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,13 @@
1
+ = RedSafe
2
+
3
+ The Red Safe Project deals with the creation of a gem. The gem's function is to streamline access to various websites through a connection consolidation of procedures.
4
+
5
+ == Notes on the Red Safe Project
6
+ * This Project's focus is learning based.
7
+ * It is designed to function with the appengine jruby.
8
+ * Clone it for your learning needs.
9
+ * git clone git@github.com:rubyshot/redsafe.git
10
+
11
+ == Copyright
12
+
13
+ Copyright (c) 2010 Ruby Shot. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ task "default" => ["test"]
4
+ begin
5
+ require 'jeweler'
6
+ require 'lib/redsafe/version'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "redsafe"
9
+ gem.version = Redsafe::Version::STRING
10
+ gem.description = "Red Safe is a conveyor belt to get your web-based project on a fast roll."
11
+ gem.summary = "This is a gem tool which simplifies signup functionality using various web services for connection credentials."
12
+ gem.homepage = "http://github.com/rubyshot/redsafe"
13
+ gem.author = "Ruby Shot"
14
+ gem.email = "domochoice(at)yahoo:com"
15
+ gem.add_development_dependency "sinatra"
16
+ gem.add_development_dependency "dm-core"
17
+ gem.add_development_dependency "dm-validations"
18
+ gem.add_development_dependency "dm-timestamps"
19
+ gem.add_development_dependency "date"
20
+ gem.add_development_dependency "time"
21
+ end
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
24
+ end
25
+
26
+
27
+
28
+
29
+
30
+
@@ -0,0 +1,90 @@
1
+ if Object.const_defined?("DataMapper")
2
+ #require 'dm-core'
3
+ require 'dm-timestamps'
4
+ require 'dm-validations'
5
+ require 'date'
6
+ require 'time'
7
+
8
+ require Pathname(__FILE__).dirname.expand_path + "sl_user.rb"
9
+ require Pathname(__FILE__).dirname.expand_path + "sl_aah.rb"
10
+
11
+ end
12
+
13
+ class User
14
+ if Object.const_defined?("DataMapper")
15
+ include SlAah
16
+ else
17
+ throw "'dm-core' required for red safe "
18
+ end
19
+
20
+ def initialize(interfacing_class_instance)
21
+ @instance = interfacing_class_instance
22
+ end
23
+
24
+ def id
25
+ @instance.id
26
+ end
27
+
28
+ def self.authenticate(email, pass)
29
+ current_user = get(:email => email)
30
+ return nil if current_user.nil?
31
+ return current_user if User.encrypt(pass, current_user.salt) == current_user.hashed_password
32
+ nil
33
+ end
34
+
35
+ protected
36
+
37
+ def self.encrypt(pass, salt)
38
+ Digest::SHA1.hexdigest(pass+salt)
39
+ end
40
+
41
+ def self.random_string(len)
42
+ #generate a random password consisting of strings and digits
43
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
44
+ newpass = ""
45
+ 1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
46
+ return newpass
47
+ end
48
+
49
+ #Created 3 actions and terminology thereof:
50
+ #1. sist: generates a string
51
+ #2. desist: receives the sist from an authorized server and breaks it apart
52
+ #3. resist: receives the desist string and reviews its integrity
53
+
54
+ def self.sist
55
+ const_set(TIME_FMT, '%Y-%m-%dT%H:%M:%SZ')
56
+ junk = self.random_string(6)
57
+ t = Time.now.getutc
58
+ time_str = t.strftime(TIME_FMT)
59
+ the_sist_str = time_str + junk
60
+ return the_sist_str
61
+ end
62
+
63
+ def self.desist( the_sist_str )
64
+ #"0000-00-00T00:00:00Z"
65
+ const_set(TIME_STR_LEN, 20 )
66
+ const_set(TIME_VALIDATOR,"/\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ/")
67
+ timestamp_str = the_sist_str[0...TIME_STR_LEN]
68
+ raise ArgumentError if timestamp_str.size < TIME_STR_LEN
69
+ raise ArgumentError unless timestamp_str.match(TIME_VALIDATOR)
70
+ timestamp = Time.parse(timestamp_str).to_i
71
+ raise ArgumentError if ts < 0
72
+ return timestamp, the_sist_str[20..-1]
73
+ end
74
+
75
+ def self.resist(the_sist_str)
76
+ const_set(TIME_RANGE, 60*60*5)
77
+ timestamp, junk = self.desist(the_sist_str)
78
+ now = Time.now.to_i
79
+ start = now - TIME_RANGE
80
+ finish = now + TIME_RANGE
81
+ return true if (start <= timestamp and timestamp <= finish)
82
+ return false
83
+ end
84
+
85
+
86
+
87
+ end
88
+
89
+
90
+
@@ -0,0 +1,50 @@
1
+ module SlAah
2
+ def self.included(base)
3
+ base.extend ClassMethods
4
+ base.class_eval { include SlAah::InstanceMethods }
5
+ end
6
+
7
+ module ClassMethods
8
+ def all
9
+ result = SlUser.all
10
+ result.collect {|instance| self.new instance}
11
+ end
12
+
13
+ def get(hash)
14
+ if user = SlUser.first(hash)
15
+ self.new user
16
+ else
17
+ nil
18
+ end
19
+ end
20
+
21
+ def set(attributes)
22
+ user = SlUser.new attributes
23
+ user.save
24
+ user
25
+ end
26
+
27
+ def set!(attributes)
28
+ user = SlUser.new attributes
29
+ user.save!
30
+ user
31
+ end
32
+
33
+ def delete(pk)
34
+ user = User.first(:id => pk)
35
+ user.destroy
36
+ end
37
+ end
38
+
39
+ module InstanceMethods
40
+ def update(attributes)
41
+ @instance.update_attributes attributes
42
+ @instance.save
43
+ end
44
+
45
+ def method_missing(meth, *args, &block)
46
+ #cool I just found out * on an array turns the array into a list of args for a function
47
+ @instance.send(meth, *args, &block)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,119 @@
1
+ class SlUser
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :email, String, :length => (5..40), :unique => true, :format => :email_address
6
+ property :hashed_password, String
7
+ property :salt, String
8
+ property :created_at, DateTime
9
+ property :permission_level, Integer, :default => 1
10
+ property :nickname, String, :length => 255
11
+ property :identifier, String, :length => 255
12
+ property :photo_url, String, :length => 255
13
+
14
+ has n, :oohs
15
+ has n, :direct_messages, :model => "Ooh"
16
+ has n, :relationships
17
+ has n, :followers, :through => :relationships, :model => "SlUser", :child_key => [:SlUser_id]
18
+ has n, :follows, :through => :relationships, :model => "SlUser", :remote_name => :SlUser, :child_key => [:follower_id]
19
+ if Sinatra.const_defined?('FacebookObject')
20
+ property :fb_uid, String
21
+ end
22
+
23
+ attr_accessor :password, :password_confirmation
24
+ #protected equievelant? :protected => true doesn't exist in dm 0.10.0
25
+ #protected :id, :salt
26
+ #doesn't behave correctly, I'm not even sure why I did this.
27
+
28
+ validates_present :password_confirmation, :unless => Proc.new { |t| t.hashed_password }
29
+ validates_present :password, :unless => Proc.new { |t| t.hashed_password }
30
+ validates_is_confirmed :password
31
+
32
+ def password=(pass)
33
+ @password = pass
34
+ self.salt = SlUser.random_string(10) if !self.salt
35
+ self.hashed_password = SlUser.encrypt(@password, self.salt)
36
+ end
37
+
38
+ def admin?
39
+ self.permission_level == -1 || self.id == 1
40
+ end
41
+
42
+ def site_admin?
43
+ self.id == 1
44
+ end
45
+
46
+ def displayed_oohs
47
+ oohs = []
48
+ oohs += self.oohs.all(:recipient_id => nil, :limit => 10, :order => [:created_at.desc]) # don't show direct messsages
49
+ self.follows.each do |follows| oohs += follows.oohs.all(:recipient_id => nil, :limit => 10, :order => [:created_at.desc]) end if @myself == @user
50
+ oohs.sort! { |x,y| y.created_at <=> x.created_at }
51
+ oohs[0..10]
52
+ end
53
+
54
+ protected
55
+
56
+ def method_missing(m, *args)
57
+ return false
58
+ end
59
+ end
60
+ class Relationship
61
+ include DataMapper::Resource
62
+
63
+ property :SlUser_id, Integer, :key => true
64
+ property :follower_id, Integer, :key => true
65
+ belongs_to :SlUser, :child_key => [:SlUser_id]
66
+ belongs_to :follower, :model => "SlUser", :child_key => [:follower_id]
67
+ end
68
+
69
+ class Ooh
70
+ include DataMapper::Resource
71
+
72
+ property :id, Serial
73
+ property :text, String, :length => 140
74
+ property :created_at, DateTime
75
+ belongs_to :recipient, :model => "SlUser", :child_key => [:recipient_id]
76
+ belongs_to :SlUser
77
+
78
+ before :save do
79
+ case
80
+ when starts_with?('dm ')
81
+ process_dm
82
+ when starts_with?('follow ')
83
+ process_follow
84
+ else
85
+ process
86
+ end
87
+ end
88
+
89
+ # general scrubbing of an ooh
90
+ def process
91
+ # process url
92
+ urls = self.text.scan(URL_REGEXP)
93
+ urls.each { |url|
94
+ tiny_url = open("http://tinyurl.com/api-create.php?url=#{url[0]}") {|s| s.read}
95
+ self.text.sub!(url[0], "<a href='#{tiny_url}'>#{tiny_url}</a>")
96
+ }
97
+ # process @
98
+ ats = self.text.scan(AT_REGEXP)
99
+ ats.each { |at| self.text.sub!(at, "<a href='/#{at[2,at.length]}'>#{at}</a>") }
100
+ end
101
+
102
+ # process direct messages
103
+ def process_dm
104
+ self.recipient = SlUser.first(:email => self.text.split[1])
105
+ self.text = self.text.split[2..self.text.split.size].join(' ') # remove the first 2 words
106
+ process
107
+ end
108
+
109
+ # process follow commands
110
+ def process_follow
111
+ Relationship.create(:SlUser => SlUser.first(:email => self.text.split[1]), :follower => self.SlUser)
112
+ throw :halt # don't save
113
+ end
114
+
115
+ def starts_with?(prefix)
116
+ prefix = prefix.to_s
117
+ self.text[0, prefix.length] == prefix
118
+ end
119
+ end
@@ -0,0 +1,9 @@
1
+ class Redsafe
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ PATCH = 5
6
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
+ end
8
+ end
9
+
data/lib/redsafe.rb ADDED
@@ -0,0 +1,268 @@
1
+ require 'sinatra/base'
2
+ require 'pathname'
3
+ require Pathname(__FILE__).dirname.expand_path + "models/scarlet_letters"
4
+
5
+ module Sinatra
6
+ module RedSlash
7
+ def self.registered(app)
8
+ #INVESTIGATE
9
+ #the possibility of sinatra having an array of view_paths to load from
10
+ #PROBLEM
11
+ #sinatra 9.1.1 doesn't have multiple view capability anywhere
12
+ #so to get around I have to do it totally manually by
13
+ #loading the view from this path into a string and rendering it
14
+ set :red_slash_view_path, Pathname(__FILE__).dirname.expand_path + "views/"
15
+
16
+ get '/users' do
17
+ login_required
18
+ redirect "/" unless current_user.admin?
19
+
20
+ @users = User.all
21
+ if @users != []
22
+ haml get_view_as_string("index.haml"), :layout => use_layout?
23
+ else
24
+ redirect '/signup'
25
+ end
26
+ end
27
+
28
+ get '/users/:id' do
29
+ login_required
30
+
31
+ @user = User.get(:id => params[:id])
32
+ haml get_view_as_string("show.haml"), :layout => use_layout?
33
+ end
34
+
35
+ #convenience for ajax but maybe entirely stupid and unnecesary
36
+ get '/logged_in' do
37
+ if session[:user]
38
+ "true"
39
+ else
40
+ "false"
41
+ end
42
+ end
43
+
44
+ get '/login' do
45
+ haml get_view_as_string("login.haml"), :layout => use_layout?
46
+ end
47
+
48
+ post '/login' do
49
+ if user = User.authenticate(params[:email], params[:password])
50
+ session[:user] = user.id
51
+ if session[:return_to]
52
+ redirect_url = session[:return_to]
53
+ session[:return_to] = false
54
+ redirect redirect_url
55
+ else
56
+ redirect '/'
57
+ end
58
+ else
59
+ redirect '/login'
60
+ end
61
+ end
62
+
63
+ get '/logout' do
64
+ session[:user] = nil
65
+ @message = "in case it weren't obvious, you've logged out"
66
+ redirect '/'
67
+ end
68
+
69
+ get '/signup' do
70
+ haml get_view_as_string("signup.haml"), :layout => use_layout?
71
+ end
72
+
73
+ post '/signup' do
74
+ @user = User.set(params[:user])
75
+ if @user
76
+ session[:user] = @user.id
77
+ redirect '/'
78
+ else
79
+ session[:flash] = "failure!"
80
+ redirect '/'
81
+ end
82
+ end
83
+
84
+ get '/users/:id/edit' do
85
+ login_required
86
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
87
+
88
+ @user = User.get(:id => params[:id])
89
+ haml get_view_as_string("edit.haml"), :layout => use_layout?
90
+ end
91
+
92
+ post '/users/:id/edit' do
93
+ login_required
94
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
95
+
96
+ user = User.get(:id => params[:id])
97
+ user_attributes = params[:user]
98
+ if params[:user][:password] == ""
99
+ user_attributes.delete("password")
100
+ user_attributes.delete("password_confirmation")
101
+ end
102
+
103
+ if user.update(user_attributes)
104
+ redirect '/'
105
+ else
106
+ session[:notice] = 'whoops, looks like there were some problems with your updates'
107
+ redirect "/users/#{user.id}/edit"
108
+ end
109
+ end
110
+
111
+ get '/users/:id/delete' do
112
+ login_required
113
+ redirect "/users" unless current_user.admin? || current_user.id.to_s == params[:id]
114
+
115
+ if User.delete(params[:id])
116
+ session[:flash] = "way to go, you deleted a user"
117
+ else
118
+ session[:flash] = "deletion failed, for whatever reason"
119
+ end
120
+ redirect '/'
121
+ end
122
+
123
+
124
+ if Sinatra.const_defined?('FacebookObject')
125
+ get '/connect' do
126
+ if fb[:user]
127
+ if current_user.class != GuestUser
128
+ user = current_user
129
+ else
130
+ user = User.get(:fb_uid => fb[:user])
131
+ end
132
+
133
+ if user
134
+ if !user.fb_uid || user.fb_uid != fb[:user]
135
+ user.update :fb_uid => fb[:user]
136
+ end
137
+ session[:user] = user.id
138
+ else
139
+ user = User.set!(:fb_uid => fb[:user])
140
+ session[:user] = user.id
141
+ end
142
+ end
143
+ redirect '/'
144
+ end
145
+
146
+ get '/receiver' do
147
+ %[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
148
+ <html xmlns="http://www.w3.org/1999/xhtml" >
149
+ <body>
150
+ <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
151
+ </body>
152
+ </html>]
153
+ end
154
+ end
155
+ end
156
+ end
157
+
158
+ module Helpers
159
+ def login_required
160
+ #not as efficient as checking the session. but this inits the fb_user if they are logged in
161
+ if current_user.class != GuestUser
162
+ return true
163
+ else
164
+ session[:return_to] = request.fullpath
165
+ redirect '/login'
166
+ return false
167
+ end
168
+ end
169
+
170
+ def current_user
171
+ if session[:user]
172
+ User.get(:id => session[:user])
173
+ else
174
+ GuestUser.new
175
+ end
176
+ end
177
+
178
+ def logged_in?
179
+ !!session[:user]
180
+ end
181
+
182
+ def use_layout?
183
+ !request.xhr?
184
+ end
185
+
186
+ #BECAUSE sinatra 9.1.1 can't load views from different paths properly
187
+ def get_view_as_string(filename)
188
+ view = options.red_slash_view_path + filename
189
+ data = ""
190
+ f = File.open(view, "r")
191
+ f.each_line do |line|
192
+ data += line
193
+ end
194
+ return data
195
+ end
196
+
197
+ def render_login_logout(html_attributes = {:class => ""})
198
+ css_classes = html_attributes.delete(:class)
199
+ parameters = ''
200
+ html_attributes.each_pair do |attribute, value|
201
+ parameters += "#{attribute}=\"#{value}\" "
202
+ end
203
+
204
+ result = "<div id='sinatra-authentication-login-logout' >"
205
+ if logged_in?
206
+ logout_parameters = html_attributes
207
+ # a tad janky?
208
+ logout_parameters.delete(:rel)
209
+ result += "<a href='/users/#{current_user.id}/edit' class='#{css_classes} sinatra-authentication-edit' #{parameters}>Edit account</a> "
210
+ if Sinatra.const_defined?('FacebookObject')
211
+ if fb[:user]
212
+ result += "<a href='javascript:FB.Connect.logoutAndRedirect(\"/logout\");' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
213
+ else
214
+ result += "<a href='/logout' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
215
+ end
216
+ else
217
+ result += "<a href='/logout' class='#{css_classes} sinatra-authentication-logout' #{logout_parameters}>Logout</a>"
218
+ end
219
+ else
220
+ result += "<a href='/signup' class='#{css_classes} sinatra-authentication-signup' #{parameters}>Signup</a> "
221
+ result += "<a href='/login' class='#{css_classes} sinatra-authentication-login' #{parameters}>Login</a>"
222
+ end
223
+
224
+ result += "</div>"
225
+ end
226
+
227
+ if Sinatra.const_defined?('FacebookObject')
228
+ def render_facebook_connect_link(text = 'Login using facebook', options = {:size => 'small'})
229
+ if options[:size] == 'small'
230
+ size = 'Small'
231
+ elsif options[:size] == 'medium'
232
+ size = 'Medium'
233
+ elsif options[:size] == 'large'
234
+ size = 'Large'
235
+ elsif options[:size] == 'xlarge'
236
+ size = 'BigPun'
237
+ else
238
+ size = 'Small'
239
+ end
240
+
241
+ %[<a href="#" onclick="FB.Connect.requireSession(function(){document.location = '/connect';}); return false;" class="fbconnect_login_button FBConnectButton FBConnectButton_#{size}">
242
+ <span id="RES_ID_fb_login_text" class="FBConnectButton_Text">
243
+ #{text}
244
+ </span>
245
+ </a>]
246
+ end
247
+ end
248
+ end
249
+
250
+ register RedSlash
251
+ end
252
+
253
+ class GuestUser
254
+ def guest?
255
+ true
256
+ end
257
+
258
+ def permission_level
259
+ 0
260
+ end
261
+
262
+ # current_user.admin? returns false. current_user.has_a_baby? returns false.
263
+ # (which is a bit of an assumption I suppose)
264
+ def method_missing(m, *args)
265
+ return false
266
+ end
267
+ end
268
+
@@ -0,0 +1,42 @@
1
+ #redsafe
2
+ %h1
3
+ Edit
4
+ - if @user.id == current_user.id
5
+ account
6
+ - else
7
+ - if @user.email
8
+ = @user.email
9
+ - elsif @user.fb_uid
10
+ <fb:name uid=#{@user.fb_uid} linked='false' />
11
+ - else
12
+ account
13
+ %form{:action => "/users/#{@user.id}/edit", :method => "post"}
14
+ .field
15
+ .label
16
+ %label{:for => "user_email"} Email
17
+ %input{ :id => "user_email", :name => "user[email]", :size => 30, :type => "text", :value => @user.email }
18
+ .field
19
+ .label
20
+ %label{:for => "user_password"} New password
21
+ %input{ :id => "user_password", :name => "user[password]", :size => 30, :type => "password" }
22
+ .field
23
+ .label
24
+ %label{:for => "user_password_confirmation"} Confirm
25
+ %input{ :id => "user_password_confirmation", :name => "user[password_confirmation]", :size => 30, :type => "password" }
26
+ -# don't render permission field if admin and editing yourself so you don't shoot yourself in the foot
27
+ - if current_user.admin? && current_user.id != @user.id
28
+ .field
29
+ .label
30
+ %label{:for => 'permission_level'} Permission level
31
+ %select{ :id => "permission_level", :name => "user[permission_level]" }
32
+ %option{:value => -1, :selected => @user.admin?}
33
+ Admin
34
+ %option{:value => 1, :selected => @user.permission_level == 1}
35
+ Authenticated user
36
+ .buttons
37
+ %input{ :value => "Update", :type => "submit" }
38
+ - if Sinatra.const_defined?('FacebookObject')
39
+ - unless @user.fb_uid
40
+ |
41
+ = render_facebook_connect_link('Link account with Facebook')
42
+
@@ -0,0 +1,30 @@
1
+ #redsafe
2
+ %h1.page_title Users
3
+ %table
4
+ %tr
5
+ %th
6
+ - if current_user.admin?
7
+ %th permission level
8
+ - @users.each do |user|
9
+ %tr
10
+ %td
11
+ - if user.email
12
+ = user.email
13
+ - elsif user.fb_uid
14
+ <fb:name uid=#{user.fb_uid} />
15
+ - else
16
+ "user #{user.id}"
17
+ - if current_user.admin?
18
+ %td= user.permission_level
19
+ %td
20
+ %a{:href => "/users/#{user.id}"} show
21
+ - if current_user.admin?
22
+ %td
23
+ %a{:href => "/users/#{user.id}/edit"} edit
24
+ %td
25
+ -# this doesn't work for tk
26
+ - if !user.site_admin?
27
+ %a{:href => "/users/#{user.id}/delete", :onclick => "return confirm('you sure?')"} delete
28
+ - else
29
+ site admin
30
+
@@ -0,0 +1,21 @@
1
+ #redsafe
2
+ %h1.page_title Login
3
+ %form{:action => "/login", :method => "post"}
4
+ .field
5
+ .label
6
+ %label{:for => "user_email'"} Email
7
+ %input{:id => "user_email", :name => "email", :size => 30, :type => "text"}
8
+ .field
9
+ .label
10
+ %label{:for => "user_password"} Password
11
+ %input{:id => "user_password", :name => "password", :size => 30, :type => "password"}
12
+ .buttons
13
+ %input{:value => "login", :type => "submit"}
14
+ %a{:href => "/signup", :class => 'sinatra_authentication_link'}
15
+ Signup
16
+ - if Sinatra.const_defined?('FacebookObject')
17
+ .third_party_signup
18
+ %h3.section_title One click login:
19
+ .login_link.facebook_login
20
+ = render_facebook_connect_link('Login using facebook', :size => 'large')
21
+
@@ -0,0 +1,10 @@
1
+ #redsafe
2
+ %h1.page_title
3
+ - if @user.email
4
+ = @user.email
5
+ - elsif @user.fb_uid
6
+ <fb:name uid=#{@user.fb_uid} linked='false' />
7
+ - if current_user.admin?
8
+ %h2 permission level
9
+ = @user.permission_level
10
+
@@ -0,0 +1,25 @@
1
+ #redsafe
2
+ %h1.page_title Signup
3
+ %form{:action => "/signup", :method => "post"}
4
+ .field
5
+ .label
6
+ %label{:for => "user_email"} Email
7
+ %input{ :id => "user_email", :name => "user[email]", :size => 30, :type => "text" }
8
+ .field
9
+ .label
10
+ %label{:for => "user_password"} Password
11
+ %input{ :id => "user_password", :name => "user[password]", :size => 30, :type => "password" }
12
+ .field
13
+ .label
14
+ %label{:for => "user_password_confirmation"} Confirm Password
15
+ %input{ :id => "user_password_confirmation", :name => "user[password_confirmation]", :size => 30, :type => "password" }
16
+ .buttons
17
+ %input{ :value => "Create account", :type => "submit" }
18
+ %a{:href => "/login", :class => 'sinatra_authentication_link'}
19
+ Login
20
+ - if Sinatra.const_defined?('FacebookObject')
21
+ .third_party_signup
22
+ %h3.section_title One click signup:
23
+ .login_link.facebook_login
24
+ = render_facebook_connect_link('Signup using facebook', :size => 'large')
25
+
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class RedsafeTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'redsafe'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redsafe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Ruby Shot
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-12 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sinatra
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: dm-core
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: dm-validations
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: dm-timestamps
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: date
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: time
67
+ type: :development
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ description: Red Safe is a conveyor belt to get your web-based project on a fast roll.
76
+ email: domochoice(at)yahoo:com
77
+ executables: []
78
+
79
+ extensions: []
80
+
81
+ extra_rdoc_files:
82
+ - LICENSE
83
+ - README.rdoc
84
+ files:
85
+ - .document
86
+ - .gitignore
87
+ - GemcutterInstructions.rdoc
88
+ - LICENSE
89
+ - README.rdoc
90
+ - Rakefile
91
+ - lib/models/scarlet_letters.rb
92
+ - lib/models/sl_aah.rb
93
+ - lib/models/sl_user.rb
94
+ - lib/redsafe.rb
95
+ - lib/redsafe/version.rb
96
+ - lib/views/edit.haml
97
+ - lib/views/index.haml
98
+ - lib/views/login.haml
99
+ - lib/views/show.haml
100
+ - lib/views/signup.haml
101
+ - test/redsafe_test.rb
102
+ - test/test_helper.rb
103
+ has_rdoc: true
104
+ homepage: http://github.com/rubyshot/redsafe
105
+ licenses: []
106
+
107
+ post_install_message:
108
+ rdoc_options:
109
+ - --charset=UTF-8
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: "0"
117
+ version:
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: "0"
123
+ version:
124
+ requirements: []
125
+
126
+ rubyforge_project:
127
+ rubygems_version: 1.3.5
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: This is a gem tool which simplifies signup functionality using various web services for connection credentials.
131
+ test_files:
132
+ - test/redsafe_test.rb
133
+ - test/test_helper.rb