radiant-reader-extension 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.md +89 -0
- data/Rakefile +140 -0
- data/VERSION +1 -0
- data/app/controllers/admin/messages_controller.rb +20 -0
- data/app/controllers/admin/reader_settings_controller.rb +92 -0
- data/app/controllers/admin/readers_controller.rb +28 -0
- data/app/controllers/password_resets_controller.rb +64 -0
- data/app/controllers/reader_action_controller.rb +84 -0
- data/app/controllers/reader_activations_controller.rb +60 -0
- data/app/controllers/reader_sessions_controller.rb +56 -0
- data/app/controllers/readers_controller.rb +131 -0
- data/app/helpers/admin/reader_settings_helper.rb +36 -0
- data/app/models/message.rb +108 -0
- data/app/models/message_function.rb +37 -0
- data/app/models/message_reader.rb +13 -0
- data/app/models/reader.rb +146 -0
- data/app/models/reader_notifier.rb +34 -0
- data/app/models/reader_session.rb +3 -0
- data/app/views/admin/messages/_form.html.haml +29 -0
- data/app/views/admin/messages/_help.html.haml +41 -0
- data/app/views/admin/messages/_message_description.html.haml +3 -0
- data/app/views/admin/messages/edit.html.haml +16 -0
- data/app/views/admin/messages/new.html.haml +16 -0
- data/app/views/admin/reader_settings/_setting.html.haml +24 -0
- data/app/views/admin/reader_settings/edit.html.haml +10 -0
- data/app/views/admin/reader_settings/index.html.haml +35 -0
- data/app/views/admin/reader_settings/show.html.haml +1 -0
- data/app/views/admin/readers/_avatar.html.haml +3 -0
- data/app/views/admin/readers/_form.html.haml +50 -0
- data/app/views/admin/readers/_list_head.html.haml +9 -0
- data/app/views/admin/readers/_listed.html.haml +22 -0
- data/app/views/admin/readers/_password_fields.html.haml +18 -0
- data/app/views/admin/readers/edit.html.haml +8 -0
- data/app/views/admin/readers/index.html.haml +17 -0
- data/app/views/admin/readers/new.html.haml +7 -0
- data/app/views/admin/readers/remove.html.haml +18 -0
- data/app/views/admin/sites/_choose_reader_layout.html.haml +7 -0
- data/app/views/password_resets/create.html.haml +13 -0
- data/app/views/password_resets/edit.html.haml +71 -0
- data/app/views/password_resets/new.html.haml +31 -0
- data/app/views/reader_activations/_activation_required.html.haml +34 -0
- data/app/views/reader_activations/_on_activation.html.haml +4 -0
- data/app/views/reader_activations/show.html.haml +41 -0
- data/app/views/reader_notifier/message.html.haml +1 -0
- data/app/views/reader_sessions/_login_form.html.haml +59 -0
- data/app/views/reader_sessions/new.html.haml +38 -0
- data/app/views/readers/_contributions.html.haml +2 -0
- data/app/views/readers/_controls.html.haml +25 -0
- data/app/views/readers/_extra_controls.html.haml +0 -0
- data/app/views/readers/_flasher.html.haml +6 -0
- data/app/views/readers/_form.html.haml +73 -0
- data/app/views/readers/create.html.haml +28 -0
- data/app/views/readers/edit.html.haml +47 -0
- data/app/views/readers/index.html.haml +16 -0
- data/app/views/readers/login.html.haml +15 -0
- data/app/views/readers/new.html.haml +41 -0
- data/app/views/readers/permission_denied.html.haml +23 -0
- data/app/views/readers/show.html.haml +35 -0
- data/app/views/wrappers/_field_errors.html.haml +5 -0
- data/config/routes.rb +22 -0
- data/config/settings.rb +9 -0
- data/db/migrate/001_create_readers.rb +31 -0
- data/db/migrate/002_extend_sites.rb +17 -0
- data/db/migrate/003_reader_honorifics.rb +12 -0
- data/db/migrate/004_user_readers.rb +11 -0
- data/db/migrate/005_last_login.rb +15 -0
- data/db/migrate/007_adapt_for_authlogic.rb +27 -0
- data/db/migrate/20090921125653_reader_messages.rb +27 -0
- data/db/migrate/20090924164413_functional_messages.rb +9 -0
- data/db/migrate/20090925081225_standard_messages.rb +106 -0
- data/db/migrate/20091006102438_message_visibility.rb +9 -0
- data/db/migrate/20091010083503_registration_config.rb +10 -0
- data/db/migrate/20091019124021_message_functions.rb +9 -0
- data/db/migrate/20091020133533_forenames.rb +9 -0
- data/db/migrate/20091020135152_contacts.rb +23 -0
- data/db/migrate/20091111090819_ensure_functional_messages_visible.rb +9 -0
- data/db/migrate/20091119092936_messages_have_layout.rb +9 -0
- data/db/migrate/20100922152338_lock_versions.rb +9 -0
- data/db/migrate/20100927095703_default_settings.rb +14 -0
- data/db/migrate/20101004074945_unlock_version.rb +9 -0
- data/lib/config_extensions.rb +5 -0
- data/lib/controller_extensions.rb +77 -0
- data/lib/reader_admin_ui.rb +64 -0
- data/lib/reader_helper.rb +36 -0
- data/lib/reader_site.rb +10 -0
- data/lib/reader_tags.rb +297 -0
- data/lib/rfc822.rb +29 -0
- data/lib/tasks/reader_extension_tasks.rake +28 -0
- data/pkg/radiant-reader-extension-0.9.0.gem +0 -0
- data/public/images/admin/chk_off.png +0 -0
- data/public/images/admin/chk_on.png +0 -0
- data/public/images/admin/new-message.png +0 -0
- data/public/images/admin/new-reader.png +0 -0
- data/public/javascripts/admin/messages.js +13 -0
- data/public/stylesheets/sass/admin/reader.sass +95 -0
- data/radiant-reader-extension.gemspec +184 -0
- data/reader_extension.rb +55 -0
- data/spec/controllers/admin/messages_controller_spec.rb +38 -0
- data/spec/controllers/admin/readers_controller_spec.rb +14 -0
- data/spec/controllers/password_resets_controller_spec.rb +140 -0
- data/spec/controllers/reader_activations_controller_spec.rb +45 -0
- data/spec/controllers/readers_controller_spec.rb +193 -0
- data/spec/datasets/messages_dataset.rb +49 -0
- data/spec/datasets/reader_layouts_dataset.rb +26 -0
- data/spec/datasets/reader_sites_dataset.rb +10 -0
- data/spec/datasets/readers_dataset.rb +51 -0
- data/spec/lib/reader_admin_ui_spec.rb +35 -0
- data/spec/lib/reader_site_spec.rb +18 -0
- data/spec/matchers/reader_login_system_matcher.rb +35 -0
- data/spec/models/message_spec.rb +109 -0
- data/spec/models/reader_notifier_spec.rb +34 -0
- data/spec/models/reader_spec.rb +155 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +48 -0
- metadata +267 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
class ReaderActionController < ApplicationController
|
2
|
+
helper_method :current_site, :current_site=, :logged_in?, :logged_in_user?, :logged_in_admin?
|
3
|
+
|
4
|
+
no_login_required
|
5
|
+
before_filter :set_site_title
|
6
|
+
|
7
|
+
# reader session is normally required for modifying actions
|
8
|
+
before_filter :require_reader, :except => [:index, :show]
|
9
|
+
|
10
|
+
radiant_layout { |controller| Radiant::Config['reader.layout'] }
|
11
|
+
|
12
|
+
# authorisation helpers
|
13
|
+
|
14
|
+
def logged_in?
|
15
|
+
true if current_reader
|
16
|
+
end
|
17
|
+
|
18
|
+
def logged_in_user?
|
19
|
+
true if logged_in? && current_reader.is_user?
|
20
|
+
end
|
21
|
+
|
22
|
+
def logged_in_admin?
|
23
|
+
true if logged_in_user? && current_reader.admin?
|
24
|
+
end
|
25
|
+
|
26
|
+
def permission_denied
|
27
|
+
session[:return_to] ||= request.referer
|
28
|
+
@title = flash[:error] || "Sorry: permission denied"
|
29
|
+
render
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
# context-setters
|
35
|
+
|
36
|
+
def set_site_title
|
37
|
+
if defined? Site && current_site
|
38
|
+
@site_title = current_site.name
|
39
|
+
@short_site_title = current_site.abbreviation || @site_title
|
40
|
+
@site_url = current_site.base_domain
|
41
|
+
else
|
42
|
+
@site_title = Radiant::Config['site.title']
|
43
|
+
@short_site_title = Radiant::Config['site.abbreviation'] || @site_title
|
44
|
+
@site_url = request.host
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def require_reader
|
49
|
+
unless set_reader # set_reader is in ControllerExtension and sets Reader.current while checking for current_reader
|
50
|
+
store_location
|
51
|
+
respond_to do |format|
|
52
|
+
format.html { redirect_to reader_login_url }
|
53
|
+
format.js {
|
54
|
+
@inline = true
|
55
|
+
render :partial => 'reader_sessions/login_form'
|
56
|
+
}
|
57
|
+
end
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def require_activated_reader
|
63
|
+
unless current_reader && current_reader.activated?
|
64
|
+
respond_to do |format|
|
65
|
+
format.html { redirect_to reader_activation_url }
|
66
|
+
format.js {
|
67
|
+
@inline = true
|
68
|
+
render :partial => 'reader_activations/activation_required'
|
69
|
+
}
|
70
|
+
end
|
71
|
+
false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def require_no_reader
|
76
|
+
if set_reader
|
77
|
+
store_location
|
78
|
+
flash[:notice] = "Please log out first"
|
79
|
+
redirect_back_or_to url_for(current_reader)
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class ReaderActivationsController < ReaderActionController
|
2
|
+
|
3
|
+
no_login_required
|
4
|
+
skip_before_filter :require_reader
|
5
|
+
before_filter :authenticate_reader, :only => [:update]
|
6
|
+
before_filter :check_reader_inactive
|
7
|
+
|
8
|
+
radiant_layout { |controller| Radiant::Config['reader.layout'] }
|
9
|
+
|
10
|
+
# this is just fake REST: we're actually working on the reader, not an activation object, but in a usefully restricted way:
|
11
|
+
# .show sends out an activation message if we can identify the current reader
|
12
|
+
# .update activates the reader, if the token is correct
|
13
|
+
|
14
|
+
def show
|
15
|
+
render
|
16
|
+
end
|
17
|
+
|
18
|
+
def new
|
19
|
+
if current_reader
|
20
|
+
@reader = current_reader
|
21
|
+
@reader.send_activation_message
|
22
|
+
flash[:notice] = "Account activation instructions have been emailed to you."
|
23
|
+
end
|
24
|
+
render :action => 'show'
|
25
|
+
end
|
26
|
+
|
27
|
+
def update
|
28
|
+
if @reader
|
29
|
+
@reader.activate!
|
30
|
+
self.current_reader = @reader
|
31
|
+
flash[:notice] = "Thank you! Your account has been activated."
|
32
|
+
redirect_back_or_to default_activated_url
|
33
|
+
|
34
|
+
else
|
35
|
+
@error = "Sorry: something was wrong in that link. Please check your email message."
|
36
|
+
flash[:error] = "Activation failed."
|
37
|
+
render :action => 'show'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def authenticate_reader
|
44
|
+
# not using authlogic's find_using_perishable_token because I don't want the token to expire
|
45
|
+
@reader = Reader.find_by_id_and_perishable_token(params[:id], params[:activation_code])
|
46
|
+
end
|
47
|
+
|
48
|
+
def check_reader_inactive
|
49
|
+
if @reader && @reader.activated?
|
50
|
+
flash[:notice] = "Hello #{@reader.name}! Your account is already active."
|
51
|
+
redirect_back_or_to default_activated_url
|
52
|
+
false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def default_activated_url
|
57
|
+
reader_url(@reader)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class ReaderSessionsController < ReaderActionController
|
2
|
+
|
3
|
+
before_filter :require_reader, :only => :destroy
|
4
|
+
radiant_layout { |controller| Radiant::Config['reader.layout'] }
|
5
|
+
|
6
|
+
def new
|
7
|
+
@reader_session = ReaderSession.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def create
|
11
|
+
@reader_session = ReaderSession.new(params[:reader_session])
|
12
|
+
if @reader_session.save
|
13
|
+
if @reader_session.reader.activated? && @reader_session.reader.clear_password
|
14
|
+
@reader_session.reader.clear_password = "" # we forget the cleartext version on the first successful login after activation
|
15
|
+
@reader_session.reader.save(false)
|
16
|
+
end
|
17
|
+
respond_to do |format|
|
18
|
+
format.html {
|
19
|
+
flash[:notice] = "Hello #{@reader_session.reader.name}. Welcome back."
|
20
|
+
redirect_back_or_to default_loggedin_url
|
21
|
+
}
|
22
|
+
format.js {
|
23
|
+
redirect_back_with_format(:js)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
else
|
28
|
+
respond_to do |format|
|
29
|
+
format.html {
|
30
|
+
flash[:error] = "Sorry: that combination of login and password is not known here."
|
31
|
+
render :action => :new
|
32
|
+
}
|
33
|
+
format.js { render :action => :new, :layout => false }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy
|
39
|
+
current_reader_session.destroy
|
40
|
+
if current_user
|
41
|
+
cookies[:session_token] = { :expires => 1.day.ago }
|
42
|
+
current_user.forget_me
|
43
|
+
session['user_id'] = nil
|
44
|
+
current_user = nil
|
45
|
+
end
|
46
|
+
flash[:notice] = "You are logged out. Bye!"
|
47
|
+
redirect_back_or_to reader_login_url
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def default_loggedin_url
|
53
|
+
reader_url(@reader_session.reader)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
class ReadersController < ReaderActionController
|
2
|
+
@@extended_form_partials = []
|
3
|
+
cattr_accessor :extended_form_partials
|
4
|
+
|
5
|
+
before_filter :check_registration_allowed, :only => [:new, :create]
|
6
|
+
before_filter :initialize_form_partials, :only => [:new, :edit, :update, :create]
|
7
|
+
before_filter :i_am_me, :only => [:show]
|
8
|
+
before_filter :require_reader, :except => [:index, :new, :create, :activate]
|
9
|
+
before_filter :restrict_to_self, :only => [:edit, :update, :resend_activation]
|
10
|
+
before_filter :no_removing, :only => [:remove, :destroy]
|
11
|
+
before_filter :require_password, :only => [:update]
|
12
|
+
|
13
|
+
def index
|
14
|
+
@readers = Reader.paginate(:page => params[:page], :order => 'readers.created_at desc')
|
15
|
+
end
|
16
|
+
|
17
|
+
def show
|
18
|
+
@reader = Reader.find(params[:id])
|
19
|
+
respond_to do |format|
|
20
|
+
format.html {
|
21
|
+
if @reader.inactive? && @reader == current_reader
|
22
|
+
redirect_to reader_activation_url
|
23
|
+
else
|
24
|
+
render
|
25
|
+
end
|
26
|
+
}
|
27
|
+
format.js {
|
28
|
+
@inline = true
|
29
|
+
render :partial => 'readers/controls'
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def new
|
36
|
+
if current_reader
|
37
|
+
flash[:error] = "You're already logged in!"
|
38
|
+
redirect_to url_for(current_reader) and return
|
39
|
+
end
|
40
|
+
@reader = Reader.new
|
41
|
+
session[:return_to] = request.referer
|
42
|
+
session[:email_field] = @email_field = @reader.generate_email_field_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def edit
|
46
|
+
end
|
47
|
+
|
48
|
+
def create
|
49
|
+
@reader = Reader.new(params[:reader])
|
50
|
+
@reader.clear_password = params[:reader][:password]
|
51
|
+
|
52
|
+
unless @reader.email.blank?
|
53
|
+
flash[:error] = "Please don't fill in the spam trap field."
|
54
|
+
@reader.email = ''
|
55
|
+
@reader.errors.add(:trap, "must be empty")
|
56
|
+
render :action => 'new' and return
|
57
|
+
end
|
58
|
+
|
59
|
+
unless @email_field = session[:email_field]
|
60
|
+
flash[:error] = "Please use the registration form."
|
61
|
+
redirect_to new_reader_url and return
|
62
|
+
end
|
63
|
+
|
64
|
+
@reader.email = params[@email_field.intern]
|
65
|
+
if (@reader.valid?)
|
66
|
+
@reader.save!
|
67
|
+
@reader.send_activation_message
|
68
|
+
self.current_reader = @reader
|
69
|
+
redirect_to reader_activation_url
|
70
|
+
else
|
71
|
+
render :action => 'new'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def update
|
76
|
+
@reader.attributes = params[:reader]
|
77
|
+
@reader.clear_password = params[:reader][:password] if params[:reader][:password]
|
78
|
+
if @reader.save
|
79
|
+
flash[:notice] = "Your account has been updated"
|
80
|
+
redirect_to url_for(@reader)
|
81
|
+
else
|
82
|
+
render :action => 'edit'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def i_am_me
|
89
|
+
params[:id] = current_reader.id if params[:id] == 'me' && current_reader
|
90
|
+
end
|
91
|
+
|
92
|
+
def restrict_to_self
|
93
|
+
flash[:error] = "Sorry. You are not allowed to edit other people's accounts." if params[:id] && params[:id] != current_reader.id
|
94
|
+
@reader = current_reader
|
95
|
+
end
|
96
|
+
|
97
|
+
def require_password
|
98
|
+
return true if @reader.valid_password?(params[:reader][:current_password])
|
99
|
+
|
100
|
+
# might as well get any other validation messages while we're at it
|
101
|
+
@reader.attributes = params[:reader]
|
102
|
+
@reader.valid?
|
103
|
+
|
104
|
+
flash[:error] = 'Sorry. Wrong password.'
|
105
|
+
@reader.errors.add(:current_password, "was not correct")
|
106
|
+
render :action => 'edit' and return false
|
107
|
+
end
|
108
|
+
|
109
|
+
def no_removing
|
110
|
+
flash[:error] = "You can't delete readers here. Please log in to the admin interface."
|
111
|
+
redirect_to admin_readers_url
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_registration_allowed
|
115
|
+
unless Radiant::Config['reader.allow_registration?']
|
116
|
+
flash[:error] = "Sorry. This site does not allow public registration."
|
117
|
+
redirect_to reader_login_url
|
118
|
+
false
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.add_form_partial(path)
|
123
|
+
extended_form_partials.push(path)
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
def initialize_form_partials
|
128
|
+
@form_partials = extended_form_partials
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Admin::ReaderSettingsHelper
|
2
|
+
|
3
|
+
def editable_setting(setting)
|
4
|
+
setting = Radiant::Config.find_by_key(setting) unless setting.is_a? Radiant::Config
|
5
|
+
domkey = setting.key.gsub('?', '_')
|
6
|
+
containerid = "set_#{domkey}"
|
7
|
+
link = link_to_remote setting.value,
|
8
|
+
:url => edit_admin_reader_setting_url(setting.id),
|
9
|
+
:method => 'get',
|
10
|
+
:update => containerid,
|
11
|
+
:loading => "$('#{containerid}').addClassName('waiting');",
|
12
|
+
:loaded => "$('#{containerid}').removeClassName('waiting');"
|
13
|
+
%{
|
14
|
+
#{link}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def checkbox_for_setting(setting, label)
|
19
|
+
setting = Radiant::Config.find_by_key(setting) unless setting.is_a? Radiant::Config
|
20
|
+
domkey = setting.key.gsub('?', '_')
|
21
|
+
containerid = "set_#{domkey}"
|
22
|
+
checkbox = check_box_tag setting.key.to_sym, 1, setting.value, :class => 'fancy', :id => domkey, :onchange => remote_function(
|
23
|
+
:url => admin_reader_setting_path(setting.id),
|
24
|
+
:with => %{'value=' + (this.checked ? 'true' : 'false')},
|
25
|
+
:method => 'put',
|
26
|
+
:loading => "$('#{containerid}').addClassName('waiting');",
|
27
|
+
:success => "$('#{containerid}').removeClassName('waiting').toggleClassName('true').toggleClassName('false');"
|
28
|
+
)
|
29
|
+
%{
|
30
|
+
#{checkbox}
|
31
|
+
<label for="#{domkey}">#{label}</label>
|
32
|
+
}
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class Message < ActiveRecord::Base
|
2
|
+
|
3
|
+
is_site_scoped if defined? ActiveRecord::SiteNotFound
|
4
|
+
|
5
|
+
belongs_to :layout
|
6
|
+
belongs_to :created_by, :class_name => 'User'
|
7
|
+
belongs_to :updated_by, :class_name => 'User'
|
8
|
+
|
9
|
+
has_many :message_readers
|
10
|
+
has_many :readers, :through => :message_readers
|
11
|
+
|
12
|
+
has_many :deliveries, :class_name => 'MessageReader', :conditions => ["message_readers.sent_at IS NOT NULL and message_readers.sent_at <= ?", Time.now.to_s(:db)]
|
13
|
+
has_many :recipients, :through => :deliveries, :source => :reader
|
14
|
+
|
15
|
+
validates_presence_of :subject
|
16
|
+
validates_presence_of :body
|
17
|
+
|
18
|
+
object_id_attr :filter, TextFilter
|
19
|
+
|
20
|
+
default_scope :order => 'updated_at DESC, created_at DESC'
|
21
|
+
named_scope :for_function, lambda { |f| {:conditions => ["function_id = ?", f.to_s]} }
|
22
|
+
named_scope :administrative, { :conditions => "function_id IS NOT NULL" }
|
23
|
+
named_scope :ordinary, { :conditions => "function_id IS NULL" }
|
24
|
+
named_scope :published, { :conditions => "status_id >= 100" }
|
25
|
+
|
26
|
+
def filtered_body
|
27
|
+
filter.filter(body)
|
28
|
+
end
|
29
|
+
|
30
|
+
# has to return a named_scope for chainability
|
31
|
+
def possible_readers
|
32
|
+
Reader.active
|
33
|
+
end
|
34
|
+
|
35
|
+
def undelivered_readers
|
36
|
+
possible_readers - recipients
|
37
|
+
end
|
38
|
+
|
39
|
+
def inactive_readers
|
40
|
+
possible_readers.inactive
|
41
|
+
end
|
42
|
+
|
43
|
+
def active_readers
|
44
|
+
possible_readers.active
|
45
|
+
end
|
46
|
+
|
47
|
+
def delivered?
|
48
|
+
deliveries.any?
|
49
|
+
end
|
50
|
+
|
51
|
+
def delivered_to?(reader)
|
52
|
+
recipients.include?(reader)
|
53
|
+
end
|
54
|
+
|
55
|
+
def preview(reader=nil)
|
56
|
+
reader ||= possible_readers.first || Reader.find_or_create_for_user(created_by)
|
57
|
+
ReaderNotifier.create_message(reader, self)
|
58
|
+
end
|
59
|
+
|
60
|
+
def function
|
61
|
+
MessageFunction[self.function_id]
|
62
|
+
end
|
63
|
+
def self.functional(function)
|
64
|
+
for_function(MessageFunction[function]).first
|
65
|
+
end
|
66
|
+
def has_function?
|
67
|
+
!function.nil?
|
68
|
+
end
|
69
|
+
def administrative?
|
70
|
+
has_function?
|
71
|
+
end
|
72
|
+
|
73
|
+
def status
|
74
|
+
Status.find(self.status_id)
|
75
|
+
end
|
76
|
+
def status=(value)
|
77
|
+
self.status_id = value.id
|
78
|
+
end
|
79
|
+
def published?
|
80
|
+
status == Status[:published]
|
81
|
+
end
|
82
|
+
def published!
|
83
|
+
status = Status[:published]
|
84
|
+
end
|
85
|
+
|
86
|
+
def deliver(readers)
|
87
|
+
failures = []
|
88
|
+
readers.each do |reader|
|
89
|
+
failures.push(reader) unless deliver_to(reader)
|
90
|
+
end
|
91
|
+
self.published!
|
92
|
+
failures
|
93
|
+
end
|
94
|
+
|
95
|
+
def deliver_to(reader, sender=nil)
|
96
|
+
ReaderNotifier.deliver_message(reader, self, sender)
|
97
|
+
record_delivery(reader)
|
98
|
+
true
|
99
|
+
rescue => e
|
100
|
+
logger.warn "@@ delivery failed: #{e.inspect}"
|
101
|
+
raise
|
102
|
+
end
|
103
|
+
|
104
|
+
def record_delivery(reader)
|
105
|
+
MessageReader.find_or_create_by_message_id_and_reader_id(self.id, reader.id).update_attribute(:sent_at, Time.now)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|