fcid 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +22 -0
- data/app/controllers/fcid/feeds_controller.rb +22 -0
- data/app/controllers/fcid/friendships_controller.rb +74 -0
- data/app/controllers/fcid/messages_controller.rb +24 -0
- data/app/controllers/fcid/session_controller.rb +80 -0
- data/app/controllers/fcid/users_controller.rb +25 -0
- data/app/views/fcid/_ajax_new.html.erb +3 -0
- data/app/views/fcid/_announce.html.erb +5 -0
- data/app/views/fcid/_footer.html.erb +0 -0
- data/app/views/fcid/_navigation.html.erb +0 -0
- data/app/views/fcid/create.html.erb +6 -0
- data/app/views/fcid/feeds/_feed.html.erb +29 -0
- data/app/views/fcid/feeds/index.html.erb +4 -0
- data/app/views/fcid/feeds/show.html.erb +0 -0
- data/app/views/fcid/friendships/index.html.erb +5 -0
- data/app/views/fcid/friendships/new.html.erb +22 -0
- data/app/views/fcid/messages/_message.html.erb +0 -0
- data/app/views/fcid/messages/_message_tr.html.erb +8 -0
- data/app/views/fcid/messages/index.html.erb +20 -0
- data/app/views/fcid/new.html.erb +30 -0
- data/app/views/fcid/session/new.html.erb +40 -0
- data/app/views/fcid/users/_ajax_new.html.erb +3 -0
- data/app/views/fcid/users/create.html.erb +6 -0
- data/app/views/fcid/users/new.html.erb +33 -0
- data/app/views/friendships/new.html.erb +22 -0
- data/app/views/session/new.html.erb +20 -0
- data/config/routes.rb +29 -0
- data/lib/fcid/active_resource/exceptions.rb +7 -0
- data/lib/fcid/active_resource/extra_params.rb +66 -0
- data/lib/fcid/active_resource/session.rb +45 -0
- data/lib/fcid/base.rb +7 -0
- data/lib/fcid/config.rb +88 -0
- data/lib/fcid/consumer.rb +51 -0
- data/lib/fcid/controller.rb +46 -0
- data/lib/fcid/email.rb +9 -0
- data/lib/fcid/engine.rb +5 -0
- data/lib/fcid/feed.rb +17 -0
- data/lib/fcid/friendship.rb +5 -0
- data/lib/fcid/helpers.rb +49 -0
- data/lib/fcid/message.rb +5 -0
- data/lib/fcid/notification.rb +5 -0
- data/lib/fcid/publisher/base.rb +398 -0
- data/lib/fcid/session.rb +5 -0
- data/lib/fcid/user.rb +50 -0
- data/lib/fcid/user_methods.rb +39 -0
- data/lib/fcid/version.rb +3 -0
- data/lib/fcid.rb +12 -0
- data/lib/fcid_client.rb +14 -0
- data/lib/tasks/fcid_tasks.rake +4 -0
- data/lib/vendor/authenticated_system.rb +153 -0
- data/lib/vendor/authenticated_test_helper.rb +11 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/fcid_test.rb +9 -0
- data/test/test_helper.rb +15 -0
- metadata +169 -0
@@ -0,0 +1,398 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'action_mailer/adv_attr_accessor'
|
3
|
+
module Fcid
|
4
|
+
module Publisher #:nodoc:
|
5
|
+
class Base
|
6
|
+
class Controller #:nodoc: we need this let the url helpers to work
|
7
|
+
include ActionController::UrlWriter
|
8
|
+
def self.default_url_options
|
9
|
+
#ActionMailer::Base.default_url_options
|
10
|
+
Fcid::Publisher::Base.default_url_options
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
include ActionMailer::AdvAttrAccessor
|
15
|
+
cattr_accessor :default_url_options
|
16
|
+
if Object.const_defined?(:ActionController)
|
17
|
+
include ActionController::UrlWriter
|
18
|
+
include ActionController::Layout
|
19
|
+
end
|
20
|
+
include ActionView::Helpers
|
21
|
+
|
22
|
+
# setting for host
|
23
|
+
=begin
|
24
|
+
def self.default_url_options
|
25
|
+
{:host=>"uc.powerapple.com",:only_path=>false}
|
26
|
+
end
|
27
|
+
=end
|
28
|
+
|
29
|
+
private_class_method :new #:nodoc:
|
30
|
+
|
31
|
+
class_inheritable_accessor :view_paths
|
32
|
+
cattr_accessor :logger
|
33
|
+
self.logger = Rails.logger
|
34
|
+
|
35
|
+
@@raise_delivery_errors = true
|
36
|
+
cattr_accessor :raise_delivery_errors
|
37
|
+
|
38
|
+
|
39
|
+
@@perform_deliveries = true
|
40
|
+
cattr_accessor :perform_deliveries
|
41
|
+
|
42
|
+
@@deliveries = []
|
43
|
+
cattr_accessor :deliveries
|
44
|
+
|
45
|
+
@@default_charset = "utf-8"
|
46
|
+
cattr_accessor :default_charset
|
47
|
+
|
48
|
+
|
49
|
+
cattr_reader :protected_instance_variables
|
50
|
+
@@protected_instance_variables = %w(@body)
|
51
|
+
|
52
|
+
adv_attr_accessor :delivery_method
|
53
|
+
|
54
|
+
# Define the body of the message. This is either a Hash (in which case it
|
55
|
+
# specifies the variables to pass to the template when it is rendered),
|
56
|
+
# or a string, in which case it specifies the actual text of the message.
|
57
|
+
adv_attr_accessor :body
|
58
|
+
|
59
|
+
# Specify the from address for the message.
|
60
|
+
adv_attr_accessor :from
|
61
|
+
|
62
|
+
# The recipient addresses for the message, either as a string (for a single
|
63
|
+
# address) or an array (for multiple addresses).
|
64
|
+
adv_attr_accessor :recipients
|
65
|
+
|
66
|
+
# The date on which the message was sent. If not set (the default), the
|
67
|
+
# header will be set by the delivery agent.
|
68
|
+
adv_attr_accessor :sent_on
|
69
|
+
|
70
|
+
# Specify the subject of the message.
|
71
|
+
adv_attr_accessor :subject
|
72
|
+
|
73
|
+
# Specify the template name to use for current message. This is the "base"
|
74
|
+
# template name, without the extension or directory, and may be used to
|
75
|
+
# have multiple publisher methods share the same template.
|
76
|
+
adv_attr_accessor :template
|
77
|
+
|
78
|
+
# we use this to show an image in activities
|
79
|
+
adv_attr_accessor :activitable
|
80
|
+
|
81
|
+
adv_attr_accessor :feed_type
|
82
|
+
|
83
|
+
|
84
|
+
adv_attr_accessor :body_data
|
85
|
+
adv_attr_accessor :title_data
|
86
|
+
|
87
|
+
adv_attr_accessor :title_template
|
88
|
+
adv_attr_accessor :body_template
|
89
|
+
|
90
|
+
# popup text
|
91
|
+
adv_attr_accessor :popup_text
|
92
|
+
|
93
|
+
# popup url
|
94
|
+
adv_attr_accessor :popup_url
|
95
|
+
|
96
|
+
# for notification
|
97
|
+
adv_attr_accessor :buttons
|
98
|
+
|
99
|
+
# Override the publisher name, which defaults to an inflected version of the
|
100
|
+
# publisher's class name. If you want to use a template in a non-standard
|
101
|
+
# location, you can use this to specify that location.
|
102
|
+
def publisher_name(value = nil)
|
103
|
+
if value
|
104
|
+
self.publisher_name = value
|
105
|
+
else
|
106
|
+
self.class.publisher_name
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def publisher_name=(value)
|
111
|
+
self.class.publisher_name = value
|
112
|
+
end
|
113
|
+
|
114
|
+
# The mail object instance referenced by this publisher.
|
115
|
+
attr_reader :feed
|
116
|
+
attr_reader :template_name, :default_template_name, :action_name
|
117
|
+
|
118
|
+
class << self
|
119
|
+
attr_writer :publisher_name
|
120
|
+
|
121
|
+
def publisher_name
|
122
|
+
@publisher_name ||= name.underscore
|
123
|
+
end
|
124
|
+
|
125
|
+
# for ActionView compatibility
|
126
|
+
alias_method :controller_name, :publisher_name
|
127
|
+
alias_method :controller_path, :publisher_name
|
128
|
+
|
129
|
+
def respond_to?(method_symbol, include_private = false) #:nodoc:
|
130
|
+
matches_dynamic_method?(method_symbol) || super
|
131
|
+
end
|
132
|
+
|
133
|
+
def method_missing(method_symbol, *parameters) #:nodoc:
|
134
|
+
match = matches_dynamic_method?(method_symbol)
|
135
|
+
case match[1]
|
136
|
+
when 'create' then new(match[2], *parameters).feed
|
137
|
+
when 'deliver' then new(match[2], *parameters).deliver!
|
138
|
+
when 'register' then new(match[2], *parameters).register!
|
139
|
+
when 'new' then nil
|
140
|
+
else super
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
def register(name)
|
147
|
+
logger.debug "registering template: #{name}" if logger
|
148
|
+
content = new.send(name + "_template")
|
149
|
+
oneline = story = ""
|
150
|
+
case content
|
151
|
+
when String
|
152
|
+
oneline = content
|
153
|
+
when Array
|
154
|
+
oneline,story = content.first,content.last
|
155
|
+
when Hash
|
156
|
+
oneline = content[:oneline]
|
157
|
+
stroy = content[:story]
|
158
|
+
end
|
159
|
+
ActivityTemplate.register("#{self.name}.#{name}",oneline,story)
|
160
|
+
end
|
161
|
+
|
162
|
+
def register_all
|
163
|
+
publisher_instance_methods = self.public_instance_methods - UC::Publisher::Base.public_instance_methods
|
164
|
+
publisher_instance_methods.grep(/_action$/).each do |action|
|
165
|
+
register(action)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def deliver(feed)
|
170
|
+
new.deliver!(feed)
|
171
|
+
end
|
172
|
+
|
173
|
+
def template_root
|
174
|
+
self.view_paths && self.view_paths.first
|
175
|
+
end
|
176
|
+
|
177
|
+
def template_root=(root)
|
178
|
+
self.view_paths = ActionView::Base.process_view_paths(root)
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
private
|
184
|
+
def matches_dynamic_method?(method_name) #:nodoc:
|
185
|
+
method_name = method_name.to_s
|
186
|
+
/(create|deliver|register)_([_a-z]\w*)/.match(method_name) || /^(new)$/.match(method_name)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Instantiate a new publisher object. If +method_name+ is not +nil+, the publisher
|
191
|
+
# will be initialized according to the named method. If not, the publisher will
|
192
|
+
# remain uninitialized (useful when you only need to invoke the "receive"
|
193
|
+
# method, for instance).
|
194
|
+
def initialize(method_name=nil, *parameters) #:nodoc:
|
195
|
+
@controller = Controller.new
|
196
|
+
create!(method_name, *parameters) if method_name
|
197
|
+
end
|
198
|
+
|
199
|
+
def images(src,url=nil)
|
200
|
+
@images << [src,url]
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
def create!(method_name, *parameters) #:nodoc:
|
205
|
+
initialize_defaults(method_name)
|
206
|
+
__send__(method_name, *parameters)
|
207
|
+
|
208
|
+
delivery_method case method_name
|
209
|
+
when /_action$/,/_feed$/
|
210
|
+
:action
|
211
|
+
when /_notification$/
|
212
|
+
:notification
|
213
|
+
when /_email$/
|
214
|
+
:email
|
215
|
+
when /_activity$/
|
216
|
+
:activity
|
217
|
+
when /_popup$/
|
218
|
+
:popup
|
219
|
+
else
|
220
|
+
raise "unknow delivery method"
|
221
|
+
end if delivery_method.nil?
|
222
|
+
|
223
|
+
# notification will be sent
|
224
|
+
delivery_method :test if Rails.env == "test" && delivery_method != :notification
|
225
|
+
|
226
|
+
# If an explicit, textual body has not been set, we check assumptions.
|
227
|
+
unless String === @body_template
|
228
|
+
template_exists ||= template_root["#{publisher_name}/#{@template}"]
|
229
|
+
@body_template = render_message(@template, @body_data.merge(@body)) if template_exists
|
230
|
+
end
|
231
|
+
|
232
|
+
# build the feed object itself
|
233
|
+
@feed = create_feed
|
234
|
+
end
|
235
|
+
|
236
|
+
def deliver!(feed = @feed)
|
237
|
+
raise "no feed object available for delivery!" unless feed
|
238
|
+
unless logger.nil?
|
239
|
+
logger.info "Sent feed to #{Array(recipients).join(', ')}"
|
240
|
+
logger.debug "\n#{feed.inspect}"
|
241
|
+
end
|
242
|
+
|
243
|
+
begin
|
244
|
+
m = "perform_delivery_#{delivery_method}"
|
245
|
+
# raise m
|
246
|
+
__send__(m, feed) if perform_deliveries
|
247
|
+
rescue Exception => e # Net::SMTP errors or sendmail pipe errors
|
248
|
+
raise e if raise_delivery_errors
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
private
|
253
|
+
# Set up the default values for the various instance variables of this
|
254
|
+
# publisher. Subclasses may override this method to provide different
|
255
|
+
# defaults.
|
256
|
+
def initialize_defaults(method_name)
|
257
|
+
@charset ||= @@default_charset.dup
|
258
|
+
@template ||= method_name
|
259
|
+
@default_template_name = @action_name = @template
|
260
|
+
@template = @template + ".html" if @template # set default extension name
|
261
|
+
@publisher_name ||= self.class.name.underscore
|
262
|
+
@body_template = nil
|
263
|
+
@title_template = nil
|
264
|
+
@body_data ||= {}
|
265
|
+
@body ||= {}
|
266
|
+
@title_data ||= {}
|
267
|
+
@images = []
|
268
|
+
end
|
269
|
+
|
270
|
+
def render_message(method_name, body)
|
271
|
+
render :file => method_name, :body => body
|
272
|
+
end
|
273
|
+
|
274
|
+
def render(opts)
|
275
|
+
body = opts.delete(:body)
|
276
|
+
if opts[:file] && (opts[:file] !~ /\// && !opts[:file].respond_to?(:render))
|
277
|
+
opts[:file] = "#{publisher_name}/#{opts[:file]}"
|
278
|
+
end
|
279
|
+
|
280
|
+
begin
|
281
|
+
old_template, @template = @template, initialize_template_class(body)
|
282
|
+
layout = respond_to?(:pick_layout, true) ? pick_layout(opts) : false
|
283
|
+
@template.render(opts.merge(:layout => layout))
|
284
|
+
ensure
|
285
|
+
@template = old_template
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def default_template_format
|
290
|
+
:html
|
291
|
+
end
|
292
|
+
|
293
|
+
def default_template(action)
|
294
|
+
|
295
|
+
end
|
296
|
+
=begin
|
297
|
+
def candidate_for_layout?(options)
|
298
|
+
!@template.send(:exempt_from_layout?, default_template_name)
|
299
|
+
end
|
300
|
+
=end
|
301
|
+
|
302
|
+
def template_root
|
303
|
+
self.class.template_root
|
304
|
+
end
|
305
|
+
|
306
|
+
def template_root=(root)
|
307
|
+
self.class.template_root = root
|
308
|
+
end
|
309
|
+
|
310
|
+
def template_path
|
311
|
+
"#{template_root}/#{publisher_name}"
|
312
|
+
end
|
313
|
+
|
314
|
+
def initialize_template_class(assigns)
|
315
|
+
ActionView::Base.new(view_paths, assigns, self)
|
316
|
+
end
|
317
|
+
|
318
|
+
def create_feed
|
319
|
+
return self
|
320
|
+
feed = Feed.new
|
321
|
+
feed.popup_text = popup_text
|
322
|
+
feed.popup_url = popup_url
|
323
|
+
feed.user_id = from
|
324
|
+
feed.feed_type = feed_type
|
325
|
+
feed.title_data = title_data
|
326
|
+
feed.body_data = body_data
|
327
|
+
feed.title_template = title_template
|
328
|
+
feed.body_template = body_template
|
329
|
+
@images.each_with_index do |image,index|
|
330
|
+
feed.send("image_#{index + 1}=",image.first)
|
331
|
+
feed.send("image_#{index + 1}_link=",image.last) if image.last
|
332
|
+
end
|
333
|
+
feed
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
# 发送为action
|
338
|
+
def perform_delivery_action(feed)
|
339
|
+
logger.debug "send as action: #{feed.inspect}" if logger
|
340
|
+
logger.debug "from #{from.inspect}" if logger
|
341
|
+
Fcid::Feed.with_session feed.recipients do
|
342
|
+
fcid_feed = Fcid::Feed.new
|
343
|
+
fcid_feed.title_template = feed.title_template
|
344
|
+
fcid_feed.title_data = feed.title_data
|
345
|
+
fcid_feed.body_template = feed.body_template
|
346
|
+
fcid_feed.body_data = feed.body_data
|
347
|
+
images = feed.instance_variable_get(:@images)
|
348
|
+
images.each_with_index do |image,index|
|
349
|
+
fcid_feed.send(:"picture#{index + 1}_url=",image[0])
|
350
|
+
fcid_feed.send(:"picture#{index + 1}_link=",image[1])
|
351
|
+
end
|
352
|
+
fcid_feed.save
|
353
|
+
fcid_feed
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def perform_delivery_email(feed)
|
358
|
+
email = Fcid::Email.new :user_id=>recipients,:body=>body_template,:subject=>subject
|
359
|
+
email.save
|
360
|
+
end
|
361
|
+
|
362
|
+
# 发送为notification
|
363
|
+
def perform_delivery_notification(feed)
|
364
|
+
logger.debug "send as notification: #{feed.inspect}" if logger
|
365
|
+
# replace as real send notfication
|
366
|
+
notification = Notification.new :type=>feed.feed_type
|
367
|
+
notification.user_id = feed.user_id || recipients
|
368
|
+
notification.message = feed.body_template
|
369
|
+
notification.buttons = [buttons].flatten.compact
|
370
|
+
notification.save!
|
371
|
+
end
|
372
|
+
|
373
|
+
def perform_delivery_popup(feed)
|
374
|
+
if feed.popup_text
|
375
|
+
SessionClient.instance.drb.popup(feed.recipients,feed.popup_text,feed.popup_url,:to=>:self)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
|
380
|
+
def perform_delivery_test(feed)
|
381
|
+
deliveries << feed
|
382
|
+
end
|
383
|
+
|
384
|
+
|
385
|
+
include ActionMailer::Helpers
|
386
|
+
Dir.glob(File.join(RAILS_ROOT,"app","helpers","*_helper.rb")) do |file|
|
387
|
+
# load all helpers
|
388
|
+
helper_name = File.basename(file).gsub(/_helper.rb$/,'')
|
389
|
+
helper helper_name.to_sym
|
390
|
+
include ActionView::Helpers
|
391
|
+
include "#{helper_name}_helper".classify.constantize
|
392
|
+
end
|
393
|
+
|
394
|
+
self.template_root = [File.join(RAILS_ROOT,"app","views")]
|
395
|
+
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
data/lib/fcid/session.rb
ADDED
data/lib/fcid/user.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#这里似乎有个奇怪的问题 指定model的功能将被禁用
|
3
|
+
module Fcid
|
4
|
+
class User < Base
|
5
|
+
|
6
|
+
def self.sub_domain?(domain)
|
7
|
+
a = domain.split(".").reverse[0,2]
|
8
|
+
b = Fcid.host.split(".").reverse[0,2]
|
9
|
+
return b == a
|
10
|
+
rescue
|
11
|
+
false
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.config
|
15
|
+
Fcid.config
|
16
|
+
end
|
17
|
+
|
18
|
+
#通过auto_token来验证用户,成功返回用户,失败返回 false
|
19
|
+
def self.authenticate_by_auth_token(token)
|
20
|
+
user = get(:info,:token=>token)
|
21
|
+
rsync(user['username'])
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.authenticate(username_or_email,password)
|
25
|
+
get(:authenticate,:email=>username_or_email,:password=>password)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def self.columns
|
30
|
+
Fcid.columns
|
31
|
+
end
|
32
|
+
|
33
|
+
def avatar(style = "thumb")
|
34
|
+
avatar_url
|
35
|
+
end
|
36
|
+
|
37
|
+
[:username,:email,:password,:password_confirmation].each do |column|
|
38
|
+
define_method "#{column}" do
|
39
|
+
attributes[column.to_s]
|
40
|
+
end
|
41
|
+
|
42
|
+
define_method "#{column}=" do
|
43
|
+
attributes[column.to_s] = column
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method :name,:username
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Fcid
|
3
|
+
module UserMethods
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
end
|
7
|
+
base.send(:include,InstanceMethods)
|
8
|
+
base.send(:extend,ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
module InstanceMethods
|
13
|
+
def avatar
|
14
|
+
read_attribute(:avatar).blank? ? "/assets/avatar.gif" : read_attribute(:avatar)
|
15
|
+
end
|
16
|
+
|
17
|
+
def sync
|
18
|
+
self.class.sync id
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
|
25
|
+
def sync(id)
|
26
|
+
user_res = Fcid::User.find(id)
|
27
|
+
user = find_or_initialize_by_id(id)
|
28
|
+
Fcid.columns.each do |key,value|
|
29
|
+
user.send(:write_attribute,key,user_res.send(value))
|
30
|
+
end
|
31
|
+
user.after_sync if user.respond_to?(:after_sync) # can add other initialize code
|
32
|
+
user.save!
|
33
|
+
user
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/fcid/version.rb
ADDED
data/lib/fcid.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "fcid/engine"
|
3
|
+
require "fcid/config"
|
4
|
+
require "fcid/controller"
|
5
|
+
require "fcid/helpers"
|
6
|
+
|
7
|
+
ActionController::Base.send(:include,Fcid::Controller)
|
8
|
+
|
9
|
+
ActionView::Base.send(:include,Fcid::Helpers)
|
10
|
+
|
11
|
+
require "fcid/user"
|
12
|
+
require "fcid/session"
|
data/lib/fcid_client.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "oauth_active_resource"
|
3
|
+
module FcidClient
|
4
|
+
|
5
|
+
def self.register(options = {})
|
6
|
+
OAuthActiveResource.register(self.ancestors.first,self.ancestors.first.const_get('Models'),options)
|
7
|
+
end
|
8
|
+
|
9
|
+
module Models
|
10
|
+
class User < OAuthActiveResource::Resource
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module AuthenticatedSystem
|
3
|
+
protected
|
4
|
+
# Returns true or false if the user is logged in.
|
5
|
+
# Preloads @current_user with the user model if they're logged in.
|
6
|
+
def logged_in?
|
7
|
+
!!current_user
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
# Accesses the current user from the session. Set it to :false if login fails
|
13
|
+
# so that future calls do not hit the database.
|
14
|
+
def current_user
|
15
|
+
#@current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie || login_from_url )
|
16
|
+
@current_user ||= (login_from_session || login_from_basic_auth || login_from_url )
|
17
|
+
end
|
18
|
+
|
19
|
+
# Store the given user in the session.
|
20
|
+
def current_user=(new_user)
|
21
|
+
session[:user] = (new_user.nil? || new_user.is_a?(Symbol)) ? nil : new_user.id
|
22
|
+
@current_user = new_user
|
23
|
+
end
|
24
|
+
|
25
|
+
# Check if the user is authorized
|
26
|
+
#
|
27
|
+
# Override this method in your controllers if you want to restrict access
|
28
|
+
# to only a few actions or if you want to check if the user
|
29
|
+
# has the correct rights.
|
30
|
+
#
|
31
|
+
# Example:
|
32
|
+
#
|
33
|
+
# # only allow nonbobs
|
34
|
+
# def authorized?
|
35
|
+
# current_user.login != "bob"
|
36
|
+
# end
|
37
|
+
def authorized?
|
38
|
+
logged_in?
|
39
|
+
end
|
40
|
+
|
41
|
+
# Filter method to enforce a login requirement.
|
42
|
+
#
|
43
|
+
# To require logins for all actions, use this in your controllers:
|
44
|
+
#
|
45
|
+
# before_filter :login_required
|
46
|
+
#
|
47
|
+
# To require logins for specific actions, use this in your controllers:
|
48
|
+
#
|
49
|
+
# before_filter :login_required, :only => [ :edit, :update ]
|
50
|
+
#
|
51
|
+
# To skip this in a subclassed controller:
|
52
|
+
#
|
53
|
+
# skip_before_filter :login_required
|
54
|
+
#
|
55
|
+
def login_required
|
56
|
+
authorized? || access_denied
|
57
|
+
end
|
58
|
+
|
59
|
+
# Redirect as appropriate when an access request fails.
|
60
|
+
#
|
61
|
+
# The default action is to redirect to the login screen.
|
62
|
+
#
|
63
|
+
# Override this method in your controllers if you want to have special
|
64
|
+
# behavior in case the user is not authorized
|
65
|
+
# to access the requested action. For example, a popup window might
|
66
|
+
# simply close itself.
|
67
|
+
def access_denied
|
68
|
+
respond_to do |accepts|
|
69
|
+
accepts.html do
|
70
|
+
store_location
|
71
|
+
redirect_to :controller => '/fcid/session', :action => 'new'
|
72
|
+
end
|
73
|
+
accepts.xml do
|
74
|
+
headers["Status"] = "Unauthorized"
|
75
|
+
headers["WWW-Authenticate"] = %(Basic realm="Web Password")
|
76
|
+
render :text => "Could't authenticate you", :status => '401 Unauthorized'
|
77
|
+
end
|
78
|
+
|
79
|
+
#added by aotianlong
|
80
|
+
accepts.js do
|
81
|
+
render :update do |page|
|
82
|
+
page << "try{"
|
83
|
+
page.login_dialog.show
|
84
|
+
page << "} catch(e){}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
# Store the URI of the current request in the session.
|
92
|
+
#
|
93
|
+
# We can return to this location by calling #redirect_back_or_default.
|
94
|
+
def store_location
|
95
|
+
session[:return_to] = request.request_uri
|
96
|
+
end
|
97
|
+
|
98
|
+
# Redirect to the URI stored by the most recent store_location call or
|
99
|
+
# to the passed default.
|
100
|
+
def redirect_back_or_default(default)
|
101
|
+
redirect_to(session[:return_to] || default)
|
102
|
+
session[:return_to] = nil
|
103
|
+
end
|
104
|
+
|
105
|
+
# Inclusion hook to make #current_user and #logged_in?
|
106
|
+
# available as ActionView helper methods.
|
107
|
+
def self.included(base)
|
108
|
+
base.send :helper_method, :current_user, :logged_in?
|
109
|
+
end
|
110
|
+
|
111
|
+
# Called from #current_user. First attempt to login by the user id stored in the session.
|
112
|
+
def login_from_session
|
113
|
+
self.current_user = User.find_by_id(session[:user]) if session[:user]
|
114
|
+
end
|
115
|
+
|
116
|
+
# Called from #current_user. Now, attempt to login by basic authentication information.
|
117
|
+
def login_from_basic_auth
|
118
|
+
username, passwd = get_auth_data
|
119
|
+
self.current_user = User.authenticate(username, passwd) if username && passwd
|
120
|
+
end
|
121
|
+
|
122
|
+
# Called from #current_user. Finaly, attempt to login by an expiring token in the cookie.
|
123
|
+
def login_from_cookie
|
124
|
+
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
|
125
|
+
if user && user.remember_token?
|
126
|
+
user.remember_me
|
127
|
+
cookies[:auth_token] = { :value => user.remember_token, :expires => user.remember_token_expires_at }
|
128
|
+
self.current_user = user
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def login_from_url
|
133
|
+
fcid_auth_token = params[:fcid_auth_token]
|
134
|
+
if fcid_auth_token
|
135
|
+
user = Fcid::User.get(:authenticate,:fcid_auth_token=>fcid_auth_token)
|
136
|
+
if user
|
137
|
+
user_id = user["id"]
|
138
|
+
User.sync(user_id)
|
139
|
+
self.current_user = User.find(user_id)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
@@http_auth_headers = %w(Authorization HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION)
|
146
|
+
|
147
|
+
# gets BASIC auth info
|
148
|
+
def get_auth_data
|
149
|
+
auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
|
150
|
+
auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
|
151
|
+
return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil]
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module AuthenticatedTestHelper
|
3
|
+
# Sets the current user in the session from the user fixtures.
|
4
|
+
def login_as(user)
|
5
|
+
@request.session[:user] = user ? users(user).id : nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def authorize_as(user)
|
9
|
+
@request.env["HTTP_AUTHORIZATION"] = user ? "Basic #{Base64.encode64("#{users(user).login}:test")}" : nil
|
10
|
+
end
|
11
|
+
end
|