appoxy_rails 0.0.6

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/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
+