dm_newsletter 4.2.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +33 -0
- data/Rakefile +30 -0
- data/app/assets/stylesheets/dm_newsletter/application.css +13 -0
- data/app/controllers/dm_newsletter/admin/admin_controller.rb +16 -0
- data/app/controllers/dm_newsletter/admin/newsletters_controller.rb +81 -0
- data/app/controllers/dm_newsletter/application_controller.rb +3 -0
- data/app/controllers/dm_newsletter/newsletters_controller.rb +50 -0
- data/app/helpers/dm_newsletter/newsletters_helper.rb +8 -0
- data/app/models/dm_newsletter/concerns/ability.rb +37 -0
- data/app/models/dm_newsletter/permitted_params.rb +20 -0
- data/app/models/mailchimp_newsletter.rb +217 -0
- data/app/models/mailchimp_newsletter_subscriber.rb +43 -0
- data/app/models/newsletter.rb +46 -0
- data/app/models/newsletter_subscriber.rb +257 -0
- data/app/models/standard_newsletter.rb +19 -0
- data/app/views/dm_newsletter/admin/newsletters/_form.html.erb +17 -0
- data/app/views/dm_newsletter/admin/newsletters/edit.html.erb +2 -0
- data/app/views/dm_newsletter/admin/newsletters/index.html.erb +32 -0
- data/app/views/dm_newsletter/admin/newsletters/new.html.erb +2 -0
- data/app/views/dm_newsletter/admin/newsletters/show.html.erb +46 -0
- data/config/locales/nms.cs.yml +15 -0
- data/config/locales/nms.de.yml +15 -0
- data/config/locales/nms.en.yml +15 -0
- data/config/locales/nms.fi.yml +15 -0
- data/config/locales/nms.ja.yml +15 -0
- data/config/routes.rb +15 -0
- data/db/20130730120724_create_subscribers.rb +32 -0
- data/db/migrate/20130729075442_create_newsletter.rb +24 -0
- data/lib/dm_newsletter.rb +4 -0
- data/lib/dm_newsletter/engine.rb +8 -0
- data/lib/tasks/dm_newsletter_tasks.rake +4 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/ability.rb +12 -0
- data/spec/dummy/app/models/user.rb +6 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +82 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/assets.rb +8 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +12 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20141114170927_add_globalize_countries.dm_core.rb +50 -0
- data/spec/dummy/db/migrate/20141114170928_devise_create_users.dm_core.rb +46 -0
- data/spec/dummy/db/migrate/20141114170929_add_user_fields.dm_core.rb +14 -0
- data/spec/dummy/db/migrate/20141114170930_rolify_create_roles.dm_core.rb +20 -0
- data/spec/dummy/db/migrate/20141114170931_add_last_access.dm_core.rb +10 -0
- data/spec/dummy/db/migrate/20141114170932_create_versions.dm_core.rb +19 -0
- data/spec/dummy/db/migrate/20141114170933_add_object_changes_column_to_versions.dm_core.rb +12 -0
- data/spec/dummy/db/migrate/20141114170934_create_dm_core_accounts.dm_core.rb +13 -0
- data/spec/dummy/db/migrate/20141114170935_add_account_to_users.dm_core.rb +9 -0
- data/spec/dummy/db/migrate/20141114170936_create_preferences.dm_core.rb +13 -0
- data/spec/dummy/db/migrate/20141114170937_create_comments.dm_core.rb +22 -0
- data/spec/dummy/db/migrate/20141114170938_add_activity.dm_core.rb +21 -0
- data/spec/dummy/db/migrate/20141114170939_add_type_to_comments.dm_core.rb +9 -0
- data/spec/dummy/db/migrate/20141114170940_add_category.dm_core.rb +28 -0
- data/spec/dummy/db/migrate/20141114170941_create_email_table.dm_core.rb +26 -0
- data/spec/dummy/db/migrate/20141114170942_add_user_profile.dm_core.rb +46 -0
- data/spec/dummy/db/migrate/20141114170943_add_profile_email.dm_core.rb +14 -0
- data/spec/dummy/db/migrate/20141114170944_create_payment_history.dm_core.rb +37 -0
- data/spec/dummy/db/migrate/20141114170945_change_anchor_field.dm_core.rb +10 -0
- data/spec/dummy/db/migrate/20141114170946_create_user_site_profile.dm_core.rb +27 -0
- data/spec/dummy/db/migrate/20141114170947_add_avatar.dm_core.rb +12 -0
- data/spec/dummy/db/migrate/20141114170948_add_notify_to_payment_history.dm_core.rb +8 -0
- data/spec/dummy/db/migrate/20141114170949_acts_as_votable_migration.dm_core.rb +28 -0
- data/spec/dummy/db/migrate/20141114170950_add_user_site_profile_uuid.dm_core.rb +19 -0
- data/spec/dummy/db/migrate/20141114170951_add_invoice_id.dm_core.rb +7 -0
- data/spec/dummy/db/migrate/20141114170952_acts_as_follower_migration.dm_core.rb +18 -0
- data/spec/dummy/db/migrate/20141114170953_rename_invoice_id.dm_core.rb +12 -0
- data/spec/dummy/db/migrate/20141114170954_add_core_addresses.dm_core.rb +18 -0
- data/spec/dummy/db/migrate/20141114170955_papertrail_increase_column.dm_core.rb +9 -0
- data/spec/dummy/db/migrate/20141114170956_acts_as_taggable_on_migration.dm_core.rb +32 -0
- data/spec/dummy/db/migrate/20141114170957_add_missing_unique_indices.dm_core.rb +23 -0
- data/spec/dummy/db/migrate/20141114170958_add_taggings_counter_cache_to_tags.dm_core.rb +16 -0
- data/spec/dummy/db/migrate/20141114170959_create_custom_fields.dm_core.rb +40 -0
- data/spec/dummy/db/migrate/20141114170960_add_missing_taggable_index.dm_core.rb +11 -0
- data/spec/dummy/db/migrate/20141119112030_create_cms.dm_cms.rb +92 -0
- data/spec/dummy/db/migrate/20141119112031_add_account_to_cms.dm_cms.rb +11 -0
- data/spec/dummy/db/migrate/20141119112032_create_blog.dm_cms.rb +62 -0
- data/spec/dummy/db/migrate/20141119112033_add_notification_sent.dm_cms.rb +6 -0
- data/spec/dummy/db/migrate/20141119112034_add_blog_comment.dm_cms.rb +8 -0
- data/spec/dummy/db/migrate/20141119112035_add_blog_image.dm_cms.rb +6 -0
- data/spec/dummy/db/migrate/20141119112036_rename_snippet_slug.dm_cms.rb +14 -0
- data/spec/dummy/db/migrate/20141119112037_add_requires_subscription_blog.dm_cms.rb +8 -0
- data/spec/dummy/db/migrate/20141119112038_add_pages_ranked_model.dm_cms.rb +23 -0
- data/spec/dummy/db/migrate/20141119112039_add_blog_owner.dm_cms.rb +7 -0
- data/spec/dummy/db/migrate/20141119112040_create_media_files.dm_cms.rb +30 -0
- data/spec/dummy/db/migrate/20141119112041_add_cmspage_summary.dm_cms.rb +7 -0
- data/spec/dummy/db/migrate/20141119112042_add_blog_image_email_header.dm_cms.rb +6 -0
- data/spec/dummy/db/migrate/20141119112043_add_header_image.dm_cms.rb +10 -0
- data/spec/dummy/db/migrate/20160128145239_add_favored_locale.dm_core.rb +17 -0
- data/spec/dummy/db/migrate/20160128145240_update_papertrail_v4.dm_core.rb +41 -0
- data/spec/dummy/db/schema.rb +593 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/accounts.rb +9 -0
- data/spec/factories/user_profiles.rb +10 -0
- data/spec/factories/users.rb +19 -0
- data/spec/models/newsletter_spec.rb +9 -0
- data/spec/rails_helper.rb +70 -0
- data/spec/spec_helper.rb +85 -0
- data/spec/support/accounts.rb +17 -0
- data/spec/support/devise.rb +44 -0
- data/spec/support/fix_locale.rb +57 -0
- metadata +296 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9a3b03f31653026403d126ca9b3abf692aac4819
|
4
|
+
data.tar.gz: 90255c7249b1d731919e056aaab344ae76f62442
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c260c52c8739df5137ebb2f7cb7484326d699a101a307a207270162658db99b4ec1042a6146858b715e17fb69b99146f1ac3ff7f69c74e3a408e64c48905aa00
|
7
|
+
data.tar.gz: bf3be1368f65dbc081072d03345b36975f6c0e659dbbbc4a9061af33e57c9549025e1e038b4acde530def16438d9ea2b70d92c7d1e1de8037625064a883ca62f
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 digitalMoksha
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# dm_newsletter
|
2
|
+
|
3
|
+
**dm_newsletter** provides the newsletter management system for the MokshaCMS collection of gems.
|
4
|
+
|
5
|
+
_The MokshaCMS collection of gems provides an integrated system of services for content, event, forum, learning, and newsletter management. It supports sites with multiple languages and mutliple distinct sites per installation. Administration is built in. Additional services/engines can be written to provide additional functionality._
|
6
|
+
|
7
|
+
- core foundation ([dm_core](https://github.com/digitalmoksha/dm_core))
|
8
|
+
- content management ([dm_cms](https://github.com/digitalmoksha/dm_cms))
|
9
|
+
- event management ([dm_event](https://github.com/digitalmoksha/dm_event))
|
10
|
+
- forum management ([dm_forum](https://github.com/digitalmoksha/dm_forum))
|
11
|
+
- learning management ([dm_lms](https://github.com/digitalmoksha/dm_lms))
|
12
|
+
- newsletter management ([dm_newsletter](https://github.com/digitalmoksha/dm_newsletter))
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add the following to your Gem file:
|
17
|
+
|
18
|
+
```
|
19
|
+
gem 'dm_preferences', '~> 1.0'
|
20
|
+
gem 'dm_core', git: 'https://github.com/digitalmoksha/dm_core.git', branch: '4-2-stable'
|
21
|
+
gem 'dm_cms', git: 'https://github.com/digitalmoksha/dm_cms.git', branch: '4-2-stable'
|
22
|
+
gem 'dm_newsletter', git: 'https://github.com/digitalmoksha/dm_newsletter.git', branch: '4-2-stable'
|
23
|
+
gem 'themes_for_rails', git: 'git://github.com/digitalmoksha/themes_for_rails.git'
|
24
|
+
gem 'aced_rails', git: 'git://github.com/digitalmoksha/aced_rails.git'
|
25
|
+
```
|
26
|
+
|
27
|
+
After running `bundle install`, run
|
28
|
+
|
29
|
+
```
|
30
|
+
rake dm_core:install:migrations
|
31
|
+
rake dm_cms:install:migrations
|
32
|
+
rake dm_newsletter:install:migrations
|
33
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'DmNewsletter'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
Bundler::GemHelper.install_tasks
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
|
24
|
+
require 'rspec/core'
|
25
|
+
require 'rspec/core/rake_task'
|
26
|
+
|
27
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
28
|
+
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
29
|
+
|
30
|
+
task :default => :spec
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class DmNewsletter::Admin::AdminController < DmCore::Admin::AdminController
|
2
|
+
include DmNewsletter::NewslettersHelper
|
3
|
+
helper 'dm_newsletter/newsletters'
|
4
|
+
|
5
|
+
before_filter :authorize_access
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
#------------------------------------------------------------------------------
|
10
|
+
def authorize_access
|
11
|
+
unless can?(:manage_newsletters, :all)
|
12
|
+
flash[:alert] = "Unauthorized Access!"
|
13
|
+
redirect_to current_account.index_path
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
class DmNewsletter::Admin::NewslettersController < DmNewsletter::Admin::AdminController
|
2
|
+
include DmNewsletter::PermittedParams
|
3
|
+
|
4
|
+
#before_filter :mailchimp_guard, only: [:new, :edit, :create, :update]
|
5
|
+
before_filter :newsletter_lookup, except: [:index, :new, :create, :synchronize_lists]
|
6
|
+
|
7
|
+
#------------------------------------------------------------------------------
|
8
|
+
def index
|
9
|
+
@newsletters = using_mailchimp? ? MailchimpNewsletter.all : StandardNewsletter.all
|
10
|
+
@newsletters.each { |newsletter| newsletter.update_list_stats }
|
11
|
+
end
|
12
|
+
|
13
|
+
#------------------------------------------------------------------------------
|
14
|
+
def new
|
15
|
+
@newsletter = using_mailchimp? ? MailchimpNewsletter.new : StandardNewsletter.new
|
16
|
+
end
|
17
|
+
|
18
|
+
#------------------------------------------------------------------------------
|
19
|
+
def edit
|
20
|
+
end
|
21
|
+
|
22
|
+
#------------------------------------------------------------------------------
|
23
|
+
def create
|
24
|
+
@newsletter = using_mailchimp? ? MailchimpNewsletter.new(mailchimp_newsletter_params) : StandardNewsletter.new(standard_newsletter_params)
|
25
|
+
if @newsletter.save
|
26
|
+
redirect_to admin_newsletters_url, notice: 'Newsletter was successfully created.'
|
27
|
+
else
|
28
|
+
render action: :new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#------------------------------------------------------------------------------
|
33
|
+
def update
|
34
|
+
if @newsletter.update_attributes(newsletter_params)
|
35
|
+
redirect_to admin_newsletters_url, notice: 'Newsletter was successfully updated.'
|
36
|
+
else
|
37
|
+
render action: :edit
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#------------------------------------------------------------------------------
|
42
|
+
def destroy
|
43
|
+
@newsletter.destroy
|
44
|
+
|
45
|
+
redirect_to admin_newsletters_url
|
46
|
+
end
|
47
|
+
|
48
|
+
#------------------------------------------------------------------------------
|
49
|
+
def show
|
50
|
+
# @subscriptions = @newsletter.subscriptions
|
51
|
+
@folder_list = @newsletter.folder_list
|
52
|
+
end
|
53
|
+
|
54
|
+
#------------------------------------------------------------------------------
|
55
|
+
def synchronize_lists
|
56
|
+
if using_mailchimp?
|
57
|
+
MailchimpNewsletter.synchronize
|
58
|
+
redirect_to(admin_newsletters_url, notice: 'Synchronized with Mailchimp') and return
|
59
|
+
else
|
60
|
+
redirect_to(admin_newsletters_url) and return
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
#------------------------------------------------------------------------------
|
67
|
+
def newsletter_lookup
|
68
|
+
@newsletter = Newsletter.find(params[:id])
|
69
|
+
end
|
70
|
+
|
71
|
+
# Protects certain actions from being run if we're using mailchimp integration
|
72
|
+
#------------------------------------------------------------------------------
|
73
|
+
def mailchimp_guard
|
74
|
+
if using_mailchimp?
|
75
|
+
redirect_to(admin_newsletters_url, error: 'Action not supported when using Mailchimp') and return false
|
76
|
+
else
|
77
|
+
true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class DmNewsletter::NewslettersController < DmNewsletter::ApplicationController
|
2
|
+
|
3
|
+
# Handle a newsletter signup. By submitting using a Rails form
|
4
|
+
# and then adding via the MailChimp API, it should cut out automated signups
|
5
|
+
# from spam bots, because the authenticity token will be validated first.
|
6
|
+
#------------------------------------------------------------------------------
|
7
|
+
def subscribe_to_newsletter
|
8
|
+
subscription_params = params['subscription'] || {}
|
9
|
+
user_or_email = current_user ? current_user : subscription_params['email']
|
10
|
+
@newsletter = Newsletter.find_newsletter(params['token'])
|
11
|
+
|
12
|
+
if @newsletter
|
13
|
+
result = @newsletter.subscribe(user_or_email, subscription_params)
|
14
|
+
respond_to do |format|
|
15
|
+
if result[:success]
|
16
|
+
msg = I18n.t('nms.subscription_successful')
|
17
|
+
format.html { redirect_to (request.env['HTTP_REFERER'].blank? ? main_app.index_url : :back), notice: msg }
|
18
|
+
format.json { render json: { success: true, msg: msg } }
|
19
|
+
else
|
20
|
+
msg = I18n.t(@newsletter.map_error_to_msg(result[:code]))
|
21
|
+
format.html { redirect_to :back, alert: msg }
|
22
|
+
format.json { render json: { success: false, msg: msg } }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Unsubscribe current user from newsletter. We only support direct unsubscribing
|
29
|
+
# for a logged in user
|
30
|
+
#------------------------------------------------------------------------------
|
31
|
+
def unsubscribe_from_newsletter
|
32
|
+
email = current_user ? current_user.email : ''
|
33
|
+
@newsletter = Newsletter.find_newsletter(params['token'])
|
34
|
+
|
35
|
+
if (@newsletter)
|
36
|
+
result = @newsletter.unsubscribe(email)
|
37
|
+
respond_to do |format|
|
38
|
+
if result
|
39
|
+
msg = I18n.t('nms.unsubscribe_successuful')
|
40
|
+
format.html { redirect_to (request.env['HTTP_REFERER'].blank? ? main_app.index_url : :back), notice: msg }
|
41
|
+
format.js { render json: { success: true, msg: msg } }
|
42
|
+
else
|
43
|
+
msg = I18n.t('nms.Email_NotExists')
|
44
|
+
format.html { redirect_to :back, alert: msg }
|
45
|
+
format.js { render json: { success: false, msg: msg } }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Wrap lms specific CanCan rules. Should be included in the main app's
|
2
|
+
# Ability class.
|
3
|
+
# NOTE: When checking abilities, don't check for Class level abilities,
|
4
|
+
# unless you don't care about the instance level. For example, don't
|
5
|
+
# use both styles
|
6
|
+
# can? :moderate, Forum
|
7
|
+
# can? :moderate, @forum
|
8
|
+
# In this case, if you need to check the class level, then use specific
|
9
|
+
# current_user.has_role? :moderator, Forum
|
10
|
+
#------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
module DmNewsletter
|
13
|
+
module Concerns
|
14
|
+
module Ability
|
15
|
+
def dm_newsletter_abilities(user)
|
16
|
+
#--- Admin
|
17
|
+
if user && user.has_role?(:newsletter_manager)
|
18
|
+
can :manage_newsletters, :all
|
19
|
+
can :access_admin, :all
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#------------------------------------------------------------------------------
|
27
|
+
# The abilities get basically compiled. So if you use
|
28
|
+
#
|
29
|
+
# can :moderate, Forum, :id => Forum.with_role(:moderator, user).map(&:id)
|
30
|
+
#
|
31
|
+
# this will execute the Forum.with_role query once during Ability.new. However
|
32
|
+
#
|
33
|
+
# can :moderate, Forum do |forum|
|
34
|
+
# user.has_role? :moderator, forum
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# this will execute the has_role? block on each call to can?
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DmNewsletter
|
2
|
+
module PermittedParams
|
3
|
+
|
4
|
+
#------------------------------------------------------------------------------
|
5
|
+
def newsletter_params
|
6
|
+
params.require(:newsletter).permit! if can? :manage_newsletters, :all
|
7
|
+
end
|
8
|
+
|
9
|
+
#------------------------------------------------------------------------------
|
10
|
+
def standard_newsletter_params
|
11
|
+
params.require(:standard_newsletter).permit! if can? :manage_newsletters, :all
|
12
|
+
end
|
13
|
+
|
14
|
+
#------------------------------------------------------------------------------
|
15
|
+
def mailchimp_newsletter_params
|
16
|
+
params.require(:mailchimp_newsletter).permit! if can? :manage_newsletters, :all
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# Integrates MailChimp into our system. Using the 'gibbon' gem to interface
|
2
|
+
# with MailChimp API V2
|
3
|
+
#------------------------------------------------------------------------------
|
4
|
+
class MailchimpNewsletter < Newsletter
|
5
|
+
|
6
|
+
MAILCHIMP_ERRORS = { 200 => 'List_DoesNotExist',
|
7
|
+
214 => 'List_AlreadySubscribed',
|
8
|
+
232 => 'Email_NotExists'
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
validate :validate_list_id
|
12
|
+
after_create :update_list_stats
|
13
|
+
|
14
|
+
#------------------------------------------------------------------------------
|
15
|
+
def self.signup_information(token, options = {})
|
16
|
+
information = { newsletter: self.find_newsletter(token, options) }
|
17
|
+
if information[:newsletter]
|
18
|
+
information[:grouping] = information[:newsletter].groupings[0]
|
19
|
+
if options[:current_user]
|
20
|
+
subscriber = MailchimpNewsletterSubscriber.subscriber_info(information[:newsletter], options[:current_user].email)
|
21
|
+
information[:subscriber] = (subscriber && subscriber.subscribed? ? subscriber : nil)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
return information
|
25
|
+
end
|
26
|
+
|
27
|
+
# Make sure list id is specified, and it's valid with MailChimp
|
28
|
+
#------------------------------------------------------------------------------
|
29
|
+
def validate_list_id
|
30
|
+
unless self.mc_id.blank?
|
31
|
+
api = MailchimpNewsletter.api
|
32
|
+
list_info = api.lists.list(filters: {list_id: self.mc_id, exact: true})
|
33
|
+
if !list_info['errors'].empty?
|
34
|
+
errors[:mc_id] << (list_info['errors'][0]['error'])
|
35
|
+
end
|
36
|
+
else
|
37
|
+
errors[:mc_id] << ("list id must be provided")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Retrieve list of groupings from Mailchimp
|
42
|
+
#------------------------------------------------------------------------------
|
43
|
+
def groupings
|
44
|
+
begin
|
45
|
+
api = MailchimpNewsletter.api
|
46
|
+
groupings = api.lists.interest_groupings(id: self.mc_id)
|
47
|
+
rescue Gibbon::MailChimpError => exception
|
48
|
+
#--- groupings are not enabled for this list
|
49
|
+
return []
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# subscribe user or email to the newsletter
|
54
|
+
# Setting the Accept-Language will cause MC to send the confirmation in the users
|
55
|
+
# language if the list auto-translate is turned on
|
56
|
+
#------------------------------------------------------------------------------
|
57
|
+
def subscribe(user_or_email, options = {FNAME: '', LNAME: ''})
|
58
|
+
return { success: false, code: 232 } if user_or_email.blank?
|
59
|
+
api = MailchimpNewsletter.api
|
60
|
+
headers = {'Accept-Language' => I18n.locale.to_s}
|
61
|
+
|
62
|
+
#--- update data if user logged in. Don't for an unprotected subscribe. but honor value if passed in
|
63
|
+
options.reverse_merge! update_existing: user_or_email.is_a?(User)
|
64
|
+
|
65
|
+
#--- remove any invalid merge vars or other options
|
66
|
+
merge_vars = options.except('new-email', :email, :optin_ip, :optin_time, :mc_location, :mc_notes,
|
67
|
+
:update_existing, :mc_language, :headers)
|
68
|
+
|
69
|
+
#--- groupings needs to be an Array, but the form usually sends it as a Hash
|
70
|
+
merge_vars['GROUPINGS'] = [merge_vars['GROUPINGS']] if merge_vars['GROUPINGS'] && !merge_vars['GROUPINGS'].is_a?(Array)
|
71
|
+
|
72
|
+
if user_or_email.is_a?(User)
|
73
|
+
email = {email: user_or_email.email}
|
74
|
+
merge_vars[:FNAME] = user_or_email.first_name
|
75
|
+
merge_vars[:LNAME] = user_or_email.last_name
|
76
|
+
merge_vars[:COUNTRY] = user_or_email.country.english_name if user_or_email.country
|
77
|
+
else
|
78
|
+
email = {email: user_or_email}
|
79
|
+
end
|
80
|
+
merge_vars[:SPAMAPI] = 1
|
81
|
+
merge_vars[:MC_LANGUAGE] = I18n.locale # set the language to the current locale they are using
|
82
|
+
api.lists.subscribe(id: self.mc_id, email: email, merge_vars: merge_vars,
|
83
|
+
double_optin: true, update_existing: options[:update_existing], replace_interests: true,
|
84
|
+
headers: headers)
|
85
|
+
return { success: true, code: 0 }
|
86
|
+
rescue Gibbon::MailChimpError => exception
|
87
|
+
Rails.logger.info "=== Error Subscribing #{email} : #{exception.to_s}"
|
88
|
+
return { success: false, code: exception.code }
|
89
|
+
end
|
90
|
+
|
91
|
+
# unsubscribe email from the newsletter
|
92
|
+
#------------------------------------------------------------------------------
|
93
|
+
def unsubscribe(email)
|
94
|
+
return false if email.blank?
|
95
|
+
|
96
|
+
api = MailchimpNewsletter.api
|
97
|
+
api.lists.unsubscribe(id: self.mc_id, email: {email: email}, delete_member: false, send_goodbye: true, send_notify: true)
|
98
|
+
return true
|
99
|
+
rescue Gibbon::MailChimpError => exception
|
100
|
+
Rails.logger.info "=== Error Unsubscribing #{email} : #{exception.to_s}"
|
101
|
+
return false
|
102
|
+
end
|
103
|
+
|
104
|
+
#------------------------------------------------------------------------------
|
105
|
+
def update_list_stats
|
106
|
+
api = MailchimpNewsletter.api
|
107
|
+
list_info = api.lists.list(filters: {list_id: self.mc_id, exact: true})
|
108
|
+
|
109
|
+
#--- update the newsletter
|
110
|
+
if list_info['errors'].empty?
|
111
|
+
self.update_attributes(
|
112
|
+
name: list_info['data'][0]['name'],
|
113
|
+
subscribed_count: list_info['data'][0]['stats']['member_count'],
|
114
|
+
unsubscribed_count: list_info['data'][0]['stats']['unsubscribe_count'],
|
115
|
+
cleaned_count: list_info['data'][0]['stats']['cleaned_count'],
|
116
|
+
created_at: list_info['data'][0]['date_created'])
|
117
|
+
else
|
118
|
+
#--- looks like the list was deleted at MailChimp, mark as deleted
|
119
|
+
self.update_attribute(:deleted, true)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# get a list of sent campaigns. Can specify :folder_id to get only those
|
124
|
+
# in a specfic folder
|
125
|
+
#------------------------------------------------------------------------------
|
126
|
+
def sent_campaign_list(options = {start: 0, limit: 100})
|
127
|
+
api = MailchimpNewsletter.api
|
128
|
+
list_params = {sort_field: 'send_time', sort_dir: 'DESC',
|
129
|
+
filters: {list_id: self.mc_id}}
|
130
|
+
list_params[:start] = options[:start] ? options[:start] : 0
|
131
|
+
list_params[:limit] = options[:limit] ? options[:limit] : 100
|
132
|
+
list_params[:filters][:folder_id] = options[:folder_id] if options[:folder_id]
|
133
|
+
|
134
|
+
campaigns = api.campaigns.list(list_params)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Get simplified list of sent campaigns. Useful for showing archived
|
138
|
+
# campaigns on the front end
|
139
|
+
#------------------------------------------------------------------------------
|
140
|
+
def sent_campaign_list_simple(options = {start: 0, limit: 100})
|
141
|
+
list = sent_campaign_list(options)
|
142
|
+
campaigns = list['data'].map {|item| {subject: item['subject'],
|
143
|
+
sent_on: item['send_time'].to_datetime,
|
144
|
+
archive_url: item['archive_url']} }
|
145
|
+
end
|
146
|
+
|
147
|
+
#------------------------------------------------------------------------------
|
148
|
+
def folder_list(type = 'campaign')
|
149
|
+
api = MailchimpNewsletter.api
|
150
|
+
folder_list = api.folders.list(type: type)
|
151
|
+
folder_list.sort! {|x, y| x['name'] <=> y['name']}
|
152
|
+
end
|
153
|
+
|
154
|
+
#------------------------------------------------------------------------------
|
155
|
+
def map_error_to_msg(code)
|
156
|
+
return MAILCHIMP_ERRORS[code] ? "nms.#{MAILCHIMP_ERRORS[code]}" : 'nms.mc_unknown_error'
|
157
|
+
end
|
158
|
+
|
159
|
+
# Grab an API object to work with
|
160
|
+
#------------------------------------------------------------------------------
|
161
|
+
def self.api
|
162
|
+
if !Account.current.preferred_nms_api_key.blank?
|
163
|
+
Gibbon::API.new(Account.current.preferred_nms_api_key)
|
164
|
+
else
|
165
|
+
nil
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# is the email already subscribed to this list
|
170
|
+
#------------------------------------------------------------------------------
|
171
|
+
def email_subscribed?(email)
|
172
|
+
subscriber = MailchimpNewsletterSubscriber.subscriber_info(self, email)
|
173
|
+
return subscriber.present? && subscriber.subscribed?
|
174
|
+
end
|
175
|
+
|
176
|
+
# Query the lists in MailChimp, and create / update what we have in the database.
|
177
|
+
# If a list no longer exists, we will delete it and any attached information
|
178
|
+
# Note: [todo] This function is currently not used. Still determining if it's needed.
|
179
|
+
# Keep here until final decision.
|
180
|
+
#------------------------------------------------------------------------------
|
181
|
+
# def self.synchronize
|
182
|
+
# newsletters = MailchimpNewsletter.all
|
183
|
+
# api = MailchimpNewsletter.api
|
184
|
+
# lists = api.lists.list
|
185
|
+
#
|
186
|
+
# unless lists['data'].nil?
|
187
|
+
# lists['data'].each do |list|
|
188
|
+
# index = newsletters.find_index { |item| item.mc_id == list['id'] }
|
189
|
+
# if index
|
190
|
+
# #--- update the newsletter
|
191
|
+
# newsletters[index].update_attributes(
|
192
|
+
# name: list['name'],
|
193
|
+
# subscribed_count: list['stats']['member_count'],
|
194
|
+
# unsubscribed_count: list['stats']['unsubscribe_count'],
|
195
|
+
# cleaned_count: list['stats']['cleaned_count'])
|
196
|
+
# newsletters.delete_at(index)
|
197
|
+
# else
|
198
|
+
# #--- create a new newsletter
|
199
|
+
# MailchimpNewsletter.create!(
|
200
|
+
# name: list['name'],
|
201
|
+
# mc_id: list['id'],
|
202
|
+
# created_at: list['date_created'])
|
203
|
+
# end
|
204
|
+
# end
|
205
|
+
#
|
206
|
+
# #--- if any left, then mark them as deleted
|
207
|
+
# newsletters.each { |old_list| old_list.update_attribute(:deleted, true) }
|
208
|
+
#
|
209
|
+
# #--- update the lists_synced_on time
|
210
|
+
# account = Account.current
|
211
|
+
# account.preferred_nms_lists_synced_on = Time.now
|
212
|
+
# account.save
|
213
|
+
# end
|
214
|
+
# rescue Gibbon::MailChimpError
|
215
|
+
# end
|
216
|
+
|
217
|
+
end
|