appoxy_rails 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown ADDED
@@ -0,0 +1 @@
1
+ Nada.
@@ -0,0 +1,106 @@
1
+ module Appoxy
2
+
3
+ module Api
4
+
5
+ # The api controllers that use this should set:
6
+ # protect_from_forgery :only => [] # can add methods to here, eg: :create, :update, :destroy
7
+
8
+ # rescue_from SigError, :with => :send_error
9
+ # rescue_from Api::ApiError, :with => :send_error
10
+ # before_filter :verify_signature(params)
11
+
12
+ # Your Controller must define a secret_key_for_signature method which will return the secret key to use to generate signature.
13
+
14
+ module ApiController
15
+
16
+ def verify_signature
17
+ params2 = nil
18
+ if request.put? || request.post?
19
+ # We'll extract params from body instead here
20
+ # todo: maybe check for json format first in case this is a file or something?
21
+ body = request.body.read
22
+ puts 'body=' + body.inspect
23
+ params2 = ActiveSupport::JSON.decode(body)
24
+ puts 'params2=' + params2.inspect
25
+ params.merge! params2
26
+ end
27
+
28
+ #operation = "#{controller_name}/#{action_name}"
29
+ operation = request.env["PATH_INFO"].gsub(/\/api\//, "")# here we're getting original request url'
30
+ puts "XXX " + operation
31
+
32
+ #getting clean params (without parsed via routes)
33
+ params_for_signature = params2||request.query_parameters
34
+ #removing mandatory params
35
+ params_for_signature = params_for_signature.delete_if {|key, value| ["access_key", "sigv", "sig", "timestamp"].include? key}
36
+
37
+
38
+ #p "params " +operation+Appoxy::Api::Signatures.hash_to_s(params_for_signature)
39
+ access_key = params["access_key"]
40
+ sigv = params["sigv"]
41
+ timestamp = params["timestamp"]
42
+ sig = params["sig"]
43
+
44
+ raise Appoxy::Api::ApiError, "No access_key" if access_key.nil?
45
+ raise Appoxy::Api::ApiError, "No sigv" if sigv.nil?
46
+ raise Appoxy::Api::ApiError, "No timestamp" if timestamp.nil?
47
+ raise Appoxy::Api::ApiError, "No sig" if sig.nil?
48
+ timestamp2 = Appoxy::Api::Signatures.generate_timestamp(Time.now.gmtime)
49
+ raise Appoxy::Api::ApiError, "Request timed out!" unless (Time.parse(timestamp2)-Time.parse(timestamp))<60 # deny all requests older than 60 seconds
50
+ # Get application defined secret_key
51
+ secret_key = secret_key_for_signature(access_key)
52
+ sig2 = Appoxy::Api::Signatures.generate_signature(operation+Appoxy::Api::Signatures.hash_to_s(params_for_signature), timestamp, secret_key)
53
+ #p "signature 1 " + sig2 + " signature 2 " + sig
54
+ raise Appoxy::Api::ApiError, "Invalid signature!" unless sig == sig2
55
+
56
+ puts 'Verified OK'
57
+ true
58
+
59
+ end
60
+
61
+
62
+ def sig_should
63
+ raise "You didn't define a sig_should method in your controller!"
64
+ end
65
+
66
+
67
+ def send_ok(msg={})
68
+ response_as_string = '' # in case we want to add debugging or something
69
+ # respond_to do |format|
70
+ # format.json { render :json=>msg }
71
+ response_as_string = render_to_string :json => msg
72
+ render :json => response_as_string
73
+ # end
74
+ true
75
+ end
76
+
77
+
78
+ def send_error(statuscode_or_error, msg=nil)
79
+ exc = nil
80
+ if statuscode_or_error.is_a? Exception
81
+ exc = statuscode_or_error
82
+ statuscode_or_error = 400
83
+ msg = exc.message
84
+ end
85
+ # deprecate status, should use status_code
86
+ json_msg = {"status_code"=>statuscode_or_error, "msg"=>msg}
87
+ render :json=>json_msg, :status=>statuscode_or_error
88
+ true
89
+ end
90
+
91
+
92
+ end
93
+
94
+
95
+ class ApiError < StandardError
96
+
97
+ def initialize(msg=nil)
98
+ super(msg)
99
+
100
+ end
101
+
102
+ end
103
+
104
+ end
105
+
106
+ end
data/lib/api/client.rb ADDED
@@ -0,0 +1,110 @@
1
+ module Appoxy
2
+ module Api
3
+
4
+ require 'rest_client'
5
+
6
+ # Subclass must define:
7
+ # host: endpoint url for service
8
+ class Client
9
+
10
+ attr_accessor :host, :access_key, :secret_key
11
+
12
+
13
+ def initialize(host, access_key, secret_key, options={})
14
+ @host = host
15
+ @access_key = access_key
16
+ @secret_key = secret_key
17
+ end
18
+
19
+
20
+ def get(method, params={}, options={})
21
+ begin
22
+ # ClientHelper.run_http(host, access_key, secret_key, :get, method, nil, params)
23
+ parse_response RestClient.get(append_params(url(method), add_params(method, params)), headers)
24
+ rescue RestClient::BadRequest => ex
25
+ # puts ex.http_body
26
+ raise "Bad Request: " + ActiveSupport::JSON.decode(ex.http_body)["msg"].to_s
27
+ end
28
+ end
29
+
30
+
31
+ def post(method, params={}, options={})
32
+ begin
33
+ parse_response RestClient.post(url(method), add_params(method, params).to_json, headers)
34
+ #ClientHelper.run_http(host, access_key, secret_key, :post, method, nil, params)
35
+ rescue RestClient::BadRequest => ex
36
+ # puts ex.http_body
37
+ raise "Bad Request: " + ActiveSupport::JSON.decode(ex.http_body)["msg"].to_s
38
+ end
39
+
40
+ end
41
+
42
+
43
+ def put(method, body, options={})
44
+ begin
45
+ parse_response RestClient.put(url(method), add_params(method, body).to_json, headers)
46
+ #ClientHelper.run_http(host, access_key, secret_key, :put, method, body, nil)
47
+ rescue RestClient::BadRequest => ex
48
+ # puts ex.http_body
49
+ raise "Bad Request: " + ActiveSupport::JSON.decode(ex.http_body)["msg"].to_s
50
+ end
51
+ end
52
+
53
+
54
+ def delete(method, params={}, options={})
55
+ begin
56
+ parse_response RestClient.delete(append_params(url(method), add_params(method, params)))
57
+ rescue RestClient::BadRequest => ex
58
+ raise "Bad Request: " + ActiveSupport::JSON.decode(ex.http_body)["msg"].to_s
59
+ end
60
+ end
61
+
62
+
63
+ def url(command_path)
64
+ url = host + command_path
65
+ url
66
+ end
67
+
68
+
69
+ def add_params(command_path, hash)
70
+ ts = Appoxy::Api::Signatures.generate_timestamp(Time.now.gmtime)
71
+ #p "hash_to s" + command_path + Appoxy::Api::Signatures.hash_to_s(hash)
72
+ sig = Appoxy::Api::Signatures.generate_signature(command_path + Appoxy::Api::Signatures.hash_to_s(hash), ts, secret_key)
73
+ extra_params = {'sigv'=>"0.1", 'sig' => sig, 'timestamp' => ts, 'access_key' => access_key}
74
+ hash.merge!(extra_params)
75
+
76
+ end
77
+
78
+
79
+ def append_params(host, params)
80
+ host += "?"
81
+ i = 0
82
+ params.each_pair do |k, v|
83
+ host += "&" if i > 0
84
+ host += k + "=" + CGI.escape(v)
85
+ i+=1
86
+ end
87
+ return host
88
+ end
89
+
90
+
91
+ def headers
92
+ user_agent = "Appoxy API Ruby Client"
93
+ headers = {'User-Agent' => user_agent}
94
+ end
95
+
96
+
97
+ def parse_response(response)
98
+ begin
99
+ return ActiveSupport::JSON.decode(response.to_s)
100
+ rescue => ex
101
+ puts 'response that caused error = ' + response.to_s
102
+ raise ex
103
+ end
104
+ end
105
+
106
+
107
+ end
108
+
109
+ end
110
+ end
@@ -0,0 +1,32 @@
1
+ module Appoxy
2
+ module Api
3
+
4
+ require 'rest_client'
5
+
6
+ module ClientHelper
7
+
8
+
9
+ end
10
+
11
+ class ClientError < StandardError
12
+
13
+ attr_reader :response_hash
14
+
15
+ def initialize(class_name, response_hash)
16
+ puts 'response-hash=' + response_hash.inspect
17
+ super("#{class_name} - #{response_hash["msg"]}")
18
+ @response_hash = response_hash
19
+ end
20
+ end
21
+
22
+ class ServiceError < StandardError
23
+ attr_reader :body
24
+
25
+ def initialize(class_name, body)
26
+ super("#{class_name}")
27
+ @body = body
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ module Appoxy
2
+ module Api
3
+ module Signatures
4
+
5
+
6
+ def self.generate_timestamp(gmtime)
7
+ return gmtime.strftime("%Y-%m-%dT%H:%M:%SZ")
8
+ end
9
+
10
+
11
+ def self.generate_signature(operation, timestamp, secret_key)
12
+ my_sha_hmac = Digest::HMAC.digest(operation + timestamp, secret_key, Digest::SHA1)
13
+ my_b64_hmac_digest = Base64.encode64(my_sha_hmac).strip
14
+ return my_b64_hmac_digest
15
+ end
16
+
17
+
18
+ def self.hash_to_s(hash)
19
+ str = ""
20
+ hash.each_pair {|key, value| str+= "#{key}#{value}" }
21
+ #removing all characters that could differ after parsing with rails
22
+ return str.delete "\"\/:{}[]\' T"
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/appoxy_api.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'active_support/core_ext'
2
+ require 'digest/hmac'
3
+ require 'net/http'
4
+ require 'base64'
5
+
6
+ require File.join(File.dirname(__FILE__), "api", "api_controller")
7
+ require File.join(File.dirname(__FILE__), "api", "client_helper")
8
+ require File.join(File.dirname(__FILE__), "api", "signatures")
9
+ require File.join(File.dirname(__FILE__), "api", "client")
10
+
@@ -0,0 +1,6 @@
1
+ require 'simple_record'
2
+ require File.join(File.dirname(__FILE__), "sessions", "user")
3
+ require File.join(File.dirname(__FILE__), "sessions", "application_controller")
4
+ require File.join(File.dirname(__FILE__), "sessions", "sessions_controller")
5
+ require File.join(File.dirname(__FILE__), "sessions", "users_controller")
6
+ require File.join(File.dirname(__FILE__), "sessions", "shareable")
data/lib/appoxy_ui.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.join(File.dirname(__FILE__), "ui", "application_helper")
2
+
@@ -0,0 +1,82 @@
1
+ module Appoxy
2
+
3
+ module Sessions
4
+ module ApplicationController
5
+
6
+
7
+ def logout_keeping_session!
8
+ @current_user = nil # not logged in, and don't do it for me
9
+ session[:user_id] = nil # keeps the session but kill our variable
10
+ end
11
+
12
+
13
+ def logged_in?
14
+ #puts 'logged_in??'
15
+ #puts 'current_user=' + current_user.inspect
16
+ current_user
17
+ end
18
+
19
+
20
+ def current_user=(new_user)
21
+ session[:user_id] = new_user ? new_user.id : nil
22
+ @current_user = new_user
23
+ end
24
+
25
+
26
+ def current_user
27
+ @current_user ||= (login_from_session)
28
+ @current_user
29
+ end
30
+
31
+
32
+ def login_from_session
33
+ #puts 'Login from session=' + session[:user_id].inspect
34
+ ::User.find_by_id(session[:user_id]) if session[:user_id]
35
+ end
36
+
37
+ #
38
+ # helper_method :logged_in?
39
+ # helper_method :current_user
40
+
41
+
42
+ protected
43
+
44
+ def random_string(length=10)
45
+ chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'
46
+ password = ''
47
+ length.times { password << chars[rand(chars.size)] }
48
+ password
49
+ end
50
+
51
+ def authenticate
52
+ if !logged_in?
53
+ flash[:warning] = "You need to login to access this page."
54
+ session[:return_to] = request.request_uri # return to after logging in
55
+ puts "ac=" + params[:ac].inspect
56
+ if params[:user_id] && params[:ac]
57
+ # todo: should we store ac in cookie? Make it easier to pass around
58
+ cookies[:ac] = params[:ac]
59
+ # then from an invite
60
+ user = ::User.find(params[:user_id])
61
+ if user && user.password.blank? # is this the best way to decide of user has not logged in? Could also check status.
62
+ redirect_to :controller=>"users", :action=>"new", :email=>user.email, :ac=>params[:ac]
63
+ return
64
+ end
65
+ end
66
+ redirect_to :controller=>"sessions", :action=>"new", :ac=>params[:ac]
67
+ end
68
+
69
+ after_authenticate
70
+
71
+ end
72
+ def after_authenticate
73
+
74
+ end
75
+
76
+
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,119 @@
1
+ module Appoxy
2
+
3
+ module Sessions
4
+ module SessionsController
5
+
6
+ def new
7
+
8
+ end
9
+
10
+ def create
11
+ before_create
12
+
13
+ logout_keeping_session!
14
+
15
+ #puts 'params=' + params.inspect
16
+ @email = params[:email]
17
+ @has_password = params[:has_password]
18
+ #puts 'has_pass? ' + @has_password.inspect
19
+
20
+ if params[:has_password].blank?
21
+ flash[:error] = "Please click the radio button to let us know if you have a password or not."
22
+ render :action=>"new"
23
+ return
24
+ end
25
+
26
+ if @has_password == "true"
27
+ user = ::User.find_by_email(@email)
28
+ # user = User.authenticate(@email, params[:password])
29
+ if user && user.authenticate(params[:password])
30
+ self.current_user = user
31
+ flash[:info] = "Logged in successfully."
32
+ orig_url = session[:return_to]
33
+ puts 'orig_url = ' + orig_url.to_s
34
+ session[:return_to] = nil
35
+ if !orig_url.nil?
36
+ redirect_to orig_url # if entered via a different url
37
+ else
38
+ after_create
39
+ end
40
+ user.last_login = Time.now
41
+ user.save(:dirty=>true)
42
+ else
43
+ flash[:info] = "Invalid email or password. Please try again."
44
+ render :action => 'new'
45
+ end
46
+ else
47
+ # new user
48
+
49
+ redirect_to (new_user_path + "?email=#{@email}")
50
+ end
51
+
52
+ end
53
+
54
+ def before_create
55
+
56
+ end
57
+ def after_create
58
+
59
+ end
60
+
61
+
62
+ def reset_password
63
+ before_reset_password
64
+
65
+ unless verify_recaptcha
66
+ flash[:error] = "You are not human! Please try again."
67
+ render :action=>"forgot_password"
68
+ return
69
+ end
70
+
71
+ @email = params[:email]
72
+ unless User.email_is_valid? @email
73
+ flash[:error] = "You must enter a valid email."
74
+ render :action=>"forgot_password"
75
+ return
76
+ end
77
+
78
+ @user = ::User.find_by_email(@email)
79
+ unless @user
80
+ flash[:error] = "Email not found."
81
+ render :action=>"forgot_password"
82
+ return
83
+ end
84
+
85
+ @newpass = random_string(8)
86
+
87
+ @user.password = @newpass
88
+ @user.save(:dirty=>true)
89
+
90
+ flash[:success] = "Password reset. You should receive an email shortly with a new password."
91
+ redirect_to :action=>"new"
92
+
93
+ after_reset_password
94
+ end
95
+
96
+ def before_reset_password
97
+
98
+ end
99
+
100
+ # This is a great spot to send an email with the new password (the only spot actually).
101
+ def after_reset_password
102
+
103
+ end
104
+
105
+ def destroy
106
+ logout
107
+ end
108
+
109
+ def logout
110
+ @current_user = nil
111
+ reset_session
112
+ flash[:info] = "You have been logged out."
113
+ redirect_to('/')
114
+ end
115
+
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,206 @@
1
+ require 'aws'
2
+ require 'simple_record'
3
+
4
+ module Appoxy
5
+ module Sessions
6
+ module Shareable
7
+
8
+ # Call this method on your Sharable object to share it with the person.
9
+ # returns: a hash with :user (the user that the item was shared with), :ac (activation code that should be sent to the user)
10
+ # or false if couldn't be shared.
11
+ # You can check for errors by looking at the errors array of the object.
12
+ # Eg:
13
+ # if my_ob.share_with(x)
14
+ # # all good
15
+ # Mail the user a link that contains user_id and ac, this gem will take care of the rest.
16
+ # else
17
+ # # not all good, check errors
18
+ # errors = my_ob.errors
19
+ # end
20
+
21
+ def share_with(email, access_rights={}, options={})
22
+
23
+ access_rights = {} if access_rights.nil?
24
+
25
+ @email = email.strip
26
+
27
+ if @email == self.user.email
28
+ self.errors.add_to_base("User already owns this item.")
29
+ return false
30
+ end
31
+
32
+ user = ::User.find_by_email(@email)
33
+ if user.nil?
34
+ # lets create the user and send them an invite.
35
+ user = ::User.new(:email=>@email, :status=>"invited")
36
+ user.set_activation_code # todo: this shouldn't be on user anymore
37
+ if user.save
38
+
39
+ else
40
+ self.errors = user.errors
41
+ return false
42
+ end
43
+ end
44
+ activation_code = user.activation_code
45
+
46
+ # check if exists
47
+ share_domain = self.share_domain
48
+ item_id_name = self.item_id_name
49
+ # puts 'share_domain = ' + share_domain.inspect
50
+ @sdb = SimpleRecord::Base.connection
51
+ # @shared_with = share_class.find(:first, :conditions=>["user_id = ? and item_id = ?", user.id, @item.id])
52
+ @project_user = Shareable.get_results(:first, ["select * from #{share_domain} where user_id=? and #{item_id_name} = ?", user.id, self.id])
53
+ puts 'sharing user=' + @project_user.inspect
54
+ unless @project_user.nil?
55
+ self.errors.add_to_base("This item is already shared with #{email}.")
56
+ return false
57
+ end
58
+
59
+ now = Time.now
60
+ id = share_id(user)
61
+ @sdb.put_attributes(share_domain, id, {:new_share=>true,
62
+ :id=>id,
63
+ :created=>SimpleRecord::Translations.pad_and_offset(now),
64
+ :updated=>SimpleRecord::Translations.pad_and_offset(now),
65
+ :user_id => user.id,
66
+ :activation_code=>activation_code,
67
+ :status=>"invited",
68
+ item_id_name => self.id}.merge(access_rights),
69
+ true,
70
+ :create_domain=>true)
71
+
72
+ # ret = {
73
+ # :user=>user,
74
+ # :ac=>activation_code
75
+ # }
76
+ # return ret
77
+ return user
78
+
79
+ end
80
+
81
+ def item_id_name
82
+ return self.class.name.foreign_key
83
+ end
84
+
85
+ def common_attributes
86
+ ["new_share", "id", "created", "updated", "user_id", item_id_name]
87
+ end
88
+
89
+ # Returns a list of users that this item is shared with.
90
+ def shared_with
91
+ project_users = Shareable.get_results(:all, ["select * from #{share_domain} where #{item_id_name} = ?", self.id])
92
+ user_ids = []
93
+ options_hash = {}
94
+ project_users.each do |puhash|
95
+ puhash.each_pair do |k, v|
96
+ puhash[k] = v[0]
97
+ end
98
+ puts 'puhash=' + puhash.inspect
99
+ user_ids << puhash["user_id"]
100
+ options_hash[puhash["user_id"]] = puhash
101
+ end
102
+ ret = ::User.find(:all, :conditions=>["id in ('#{user_ids.join("','")}')"]).collect do |u|
103
+ def u.share_options=(options=nil)
104
+ instance_variable_set(:@share_options, options)
105
+ end
106
+
107
+ def u.share_options
108
+ instance_variable_get(:@share_options)
109
+ end
110
+
111
+ u.share_options=options_hash[u.id]
112
+ u
113
+ end
114
+ ret
115
+ end
116
+
117
+ # this unshares by the
118
+ def unshare_by_id(id)
119
+ # @project_user = ProjectUser.find(params[:pu_id])
120
+ # @project_user.delete
121
+ # puts 'unsharing ' + id.to_s
122
+ @sdb = SimpleRecord::Base.connection
123
+ puts "delete_attributes=" + @sdb.delete_attributes(share_domain, id.to_s).inspect
124
+ # puts 'deleted?'
125
+ end
126
+
127
+ # Unshare by user.
128
+ def unshare(user)
129
+ @sdb = SimpleRecord::Base.connection
130
+ @sdb.delete_attributes(share_domain, share_id(user))
131
+ # @project_user = Shareable.get_results(:first, ["select * from #{share_domain} where user_id=? and #{item_id_name} = ?", user.id, self.id])
132
+ # @project_user.each do |pu|
133
+ # @sdb.delete_attributes(share_domain, pu["id"])
134
+ # end
135
+ end
136
+
137
+ def update_sharing_options(user, options={})
138
+ options={} if options.nil?
139
+ # puts 'options=' + ({ :updated=>Time.now }.merge(options)).inspect
140
+ @sdb = SimpleRecord::Base.connection
141
+ @project_user = Shareable.get_results(:first, ["select * from #{share_domain} where user_id=? and #{item_id_name} = ?", user.id, self.id])
142
+ # compare values
143
+ to_delete = []
144
+ @project_user.each_pair do |k, v|
145
+ if !common_attributes.include?(k) && !options.include?(k)
146
+ to_delete << k
147
+ end
148
+ end
149
+ if to_delete.size > 0
150
+ puts 'to_delete=' + to_delete.inspect
151
+ @sdb.delete_attributes(share_domain, share_id(user), to_delete)
152
+ end
153
+ @sdb.put_attributes(share_domain, share_id(user), {:updated=>Time.now}.merge(options), true)
154
+
155
+ end
156
+
157
+ def share_id(user)
158
+ "#{self.id}_#{user.id}"
159
+ end
160
+
161
+ def share_domain
162
+ # puts 'instance share_domain'
163
+ ret = self.class.name + "User"
164
+ # puts 'SHARE_NAME=' + ret
165
+ ret = ret.tableize
166
+ # puts 'ret=' + ret
167
+ ret
168
+ end
169
+
170
+
171
+ def self.get_results(which, q)
172
+ @sdb = SimpleRecord::Base.connection
173
+ next_token = nil
174
+ ret = []
175
+ begin
176
+ begin
177
+ response = @sdb.select(q, next_token)
178
+ rs = response[:items]
179
+ rs.each_with_index do |i, index|
180
+ puts 'i=' + i.inspect
181
+ i.each_key do |k|
182
+ puts 'key=' + k.inspect
183
+ if which == :first
184
+ return i[k].update("id"=>k)
185
+ end
186
+ ret << i[k]
187
+ end
188
+ # break if index > 100
189
+ end
190
+ next_token = response[:next_token]
191
+ end until next_token.nil?
192
+ rescue Aws::AwsError, Aws::ActiveSdb::ActiveSdbError
193
+ if ($!.message().index("NoSuchDomain") != nil)
194
+ puts 'NO SUCH DOMAIN!!!'
195
+ # this is ok
196
+ else
197
+ raise $!
198
+ end
199
+ end
200
+ which == :first ? nil : ret
201
+ end
202
+
203
+ end
204
+ end
205
+ end
206
+
@@ -0,0 +1,76 @@
1
+ module Appoxy
2
+
3
+ module Sessions
4
+
5
+ class User < SimpleRecord::Base
6
+
7
+ def self.included(base)
8
+ puts self.name + " included in " + base.name
9
+ end
10
+
11
+
12
+ has_strings :email,
13
+ {:name => :password, :hashed=>true},
14
+ :first_name,
15
+ :last_name,
16
+ :remember_me,
17
+ :activation_code,
18
+ :status # invited, active
19
+
20
+ has_dates :last_login
21
+
22
+
23
+ def validate
24
+ errors.add("email", "is not valid") unless User.email_is_valid?(email)
25
+
26
+ if status == "invited"
27
+ # doesn't need password
28
+ else
29
+ errors.add("password", "must be at least 6 characters long.") if password.blank?
30
+ end
31
+ end
32
+
33
+
34
+ def self.email_is_valid?(email)
35
+ return email.present? && email =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
36
+ end
37
+
38
+
39
+ def is_active?
40
+ status == "active"
41
+ end
42
+
43
+
44
+
45
+ def set_activation_code
46
+ self.activation_code=Digest::SHA1.hexdigest(email.to_s+Time.now.to_s)
47
+ end
48
+
49
+
50
+ def activate!
51
+ self.activation_code=nil
52
+ self.status = "active"
53
+ end
54
+
55
+
56
+
57
+ def authenticate(password)
58
+
59
+ return nil if attributes["password"].blank? # if the user has no password (will this happen? maybe for invites...)
60
+
61
+ # This is a normal unencrypted password, temporary
62
+ if attributes["password"][0].length < 100
63
+ self.password = attributes["password"][0]
64
+ self.save
65
+ end
66
+
67
+ (self.password == password) ? self : nil
68
+ end
69
+
70
+
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
@@ -0,0 +1,122 @@
1
+ module Appoxy
2
+
3
+ module Sessions
4
+ module UsersController
5
+
6
+
7
+ def new
8
+ before_new
9
+ if params[:id]
10
+ @user = ::User.find params[:id]
11
+ else
12
+ @user = ::User.new
13
+ @user.email = params[:email] if params[:email]
14
+ end
15
+ @user.activation_code = params[:ac] if params[:ac]
16
+ after_new
17
+ end
18
+
19
+ def before_new
20
+
21
+ end
22
+
23
+ def after_new
24
+
25
+ end
26
+
27
+ def create
28
+
29
+ before_create
30
+
31
+ @user = ::User.new(params[:user])
32
+
33
+ if @user.password != params[:password_confirmation]
34
+ flash[:error] = "Confirmation password does not match. Please try again."
35
+ render :action=>"new"
36
+ return
37
+ end
38
+
39
+ if params[:user][:password].length < 6
40
+ flash[:error] = "Password can not be less than 6 characters."
41
+ render :action=>"new"
42
+ return
43
+ end
44
+
45
+ existing_user = ::User.find_by_email(@user.email)
46
+
47
+ if existing_user
48
+ if params[:ac]
49
+
50
+ end
51
+ # todo: remove activation_code on user
52
+ if @user.activation_code.present?
53
+ # hasn't logged in yet, probably invited, need to check access key
54
+ if existing_user.activation_code == @user.activation_code
55
+ existing_user.activate!
56
+ existing_user.password = @user.password
57
+ @user = existing_user
58
+ end
59
+ else
60
+ flash[:error] = "The email you entered already exists in our system. You might want to try logging in if you already have an account."
61
+ render :action=>"new"
62
+ return
63
+ end
64
+ else
65
+ @user.status = "active"
66
+ end
67
+
68
+ before_save_in_create
69
+ if @user.save
70
+ self.current_user = @user
71
+ flash[:success] = "Your account was created successfully."
72
+ after_save_in_create
73
+ after_create
74
+ else
75
+ render :action => "new"
76
+ end
77
+
78
+ end
79
+
80
+ def before_create
81
+
82
+ end
83
+
84
+ def before_save_in_create
85
+
86
+ end
87
+
88
+ def after_save_in_create
89
+
90
+ end
91
+
92
+ def after_create
93
+
94
+ end
95
+
96
+
97
+ # Usually a user gets here via an activation link in email.
98
+ def activate
99
+ logout_keeping_session!
100
+ @user = ::User.find_by_activation_code(params[:ac]) unless params[:ac].blank?
101
+ case
102
+ when (!params[:ac].blank?) && @user && !@user.is_active?
103
+ flash[:info] = "Account activated. please login."
104
+ @user.activate!
105
+ redirect_to login_url
106
+ when params[:ac].blank?
107
+ flash[:error] = "The activation code was missing. Please follow the URL from your email."
108
+ redirect_to(root_url)
109
+ else
110
+ flash[:error] = "We couldn't find a user with that activation code -- check your email? Or maybe you've already activated -- try signing in."
111
+ redirect_to(root_url)
112
+ end
113
+ end
114
+
115
+ end
116
+
117
+
118
+ end
119
+
120
+
121
+ end
122
+
@@ -0,0 +1,35 @@
1
+ module Appoxy
2
+
3
+ module UI
4
+
5
+ module ApplicationHelper
6
+
7
+ def self.included(base)
8
+ # puts self.class.name + " included in " + base.class.name
9
+ end
10
+
11
+
12
+ def current_url
13
+ request.url
14
+ end
15
+
16
+ def flash_messages
17
+ s = ""
18
+ flash.each_pair do |type, msg|
19
+ if msg.is_a?(Array)
20
+ msg.each do |m|
21
+ s << content_tag(:div, m, :class => type)
22
+ end
23
+ else
24
+ s << content_tag(:div, msg, :class => type)
25
+ end
26
+ end
27
+ s.html_safe
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: appoxy_rails
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 6
9
+ version: 0.0.6
10
+ platform: ruby
11
+ authors:
12
+ - Travis Reeder
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-23 00:00:00 -08:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rest-client
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: Appoxy API Helper gem description...
34
+ email: travis@appoxy.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - README.markdown
41
+ files:
42
+ - lib/api/api_controller.rb
43
+ - lib/api/client.rb
44
+ - lib/api/client_helper.rb
45
+ - lib/api/signatures.rb
46
+ - lib/appoxy_api.rb
47
+ - lib/appoxy_sessions.rb
48
+ - lib/appoxy_ui.rb
49
+ - lib/sessions/application_controller.rb
50
+ - lib/sessions/sessions_controller.rb
51
+ - lib/sessions/shareable.rb
52
+ - lib/sessions/user.rb
53
+ - lib/sessions/users_controller.rb
54
+ - lib/ui/application_helper.rb
55
+ - README.markdown
56
+ has_rdoc: true
57
+ homepage: http://www.appoxy.com
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options: []
62
+
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project:
84
+ rubygems_version: 1.3.7
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Appoxy Rails Helper gem
88
+ test_files: []
89
+