diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3708fd8..9f0f59c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,13 +9,21 @@ class ApplicationController < ActionController::Base rescue_from Pundit::NotAuthorizedError, with: :record_not_authorized end - helper_method :nobody_signed_in?, :current_user_id, :is_my?, :isnt_my?, :set_event + helper_method :nobody_signed_in?, :current_user_id, :set_event, :custom_authorization def set_event @event = Event.friendly.find_by_friendly_id(params[:event_id] || params[:id]) raise ActiveRecord::RecordNotFound unless @event end + def custom_authorization + skip_authorization + # manually authenticate certain methods, Pundit can't + unless @event.users.include?(current_user) || current_user.admin? + raise Pundit::NotAuthorizedError, 'not allowed to view this action' + end + end + # Keep the current user id in memory def current_user_id return unless current_user diff --git a/app/controllers/attendee_fields_controller.rb b/app/controllers/attendee_fields_controller.rb index 871cd98..2fc72b5 100644 --- a/app/controllers/attendee_fields_controller.rb +++ b/app/controllers/attendee_fields_controller.rb @@ -1,4 +1,5 @@ class AttendeeFieldsController < ApplicationController + before_action :please_sign_in before_action :set_event before_action :set_attendee_field, only: %i[show edit update destroy] before_action -> { authorize @attendee_field }, only: %i[show edit update destroy] diff --git a/app/controllers/attendees_controller.rb b/app/controllers/attendees_controller.rb index 7de5cab..5a531dc 100644 --- a/app/controllers/attendees_controller.rb +++ b/app/controllers/attendees_controller.rb @@ -28,14 +28,6 @@ def index end end - def custom_authorization - skip_authorization - # manually authenticate certain methods, Pundit can't - unless @event.users.include?(current_user) || current_user.admin? - raise Pundit::NotAuthorizedError, 'not allowed to view this action' - end - end - def show @attendee_fields = @event.fields end diff --git a/app/controllers/emails_controller.rb b/app/controllers/emails_controller.rb new file mode 100644 index 0000000..ceb5fa0 --- /dev/null +++ b/app/controllers/emails_controller.rb @@ -0,0 +1,57 @@ +class EmailsController < ApplicationController + before_action :please_sign_in + before_action :set_event + before_action :set_email, only: %i[show] + before_action :custom_authorization, only: %i[index settings configure] + + def index + end + + def show + authorize @email + end + + def new + @email = @event.emails.new + authorize @email + end + + def create + @email = @event.emails.new(email_params) + authorize @email + + if @email.save + redirect_to event_emails_path(@event) + flash[:success] = 'Email will be sent shortly.' + else + render :new + end + end + + def settings + @email_config = @event.email_config + end + + def configure + if @event.email_config.update(email_config_params) + redirect_to event_emails_path(@event) + flash[:success] = 'Email sending has been configured.' + else + render :edit + end + end + + private + + def set_email + @email = @event.emails.find(params[:id]) + end + + def email_params + params.require(:email).permit(:recipient, :sender_email, :subject, :body) + end + + def email_config_params + params.require(:email_config).permit(:smtp_url, :smtp_port, :authentication, :domain, :sender_email, :username, :password) + end +end diff --git a/app/models/email.rb b/app/models/email.rb new file mode 100644 index 0000000..aad87f8 --- /dev/null +++ b/app/models/email.rb @@ -0,0 +1,3 @@ +class Email < ApplicationRecord + belongs_to :event +end diff --git a/app/models/email_config.rb b/app/models/email_config.rb new file mode 100644 index 0000000..40b0c98 --- /dev/null +++ b/app/models/email_config.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class EmailConfig < ApplicationRecord + belongs_to :event + + def enabled? + true unless [ + smtp_url, smtp_port, authentication, domain, sender_email, username, password + ].any?(&:nil?) + end +end diff --git a/app/models/event.rb b/app/models/event.rb index 8240a27..63a6950 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -3,6 +3,8 @@ class Event < ApplicationRecord default_scope { order(id: :asc) } + has_one :email_config, dependent: :destroy + has_many :emails, dependent: :destroy has_many :attendees, dependent: :destroy has_many :fields, class_name: 'AttendeeField', dependent: :destroy has_many :organizer_positions, dependent: :destroy @@ -14,6 +16,12 @@ class Event < ApplicationRecord validates :name, :start_date, :end_date, :location, :user_id, presence: true validate :permitted_domains_cannot_have_trailing_slash + after_create do + create_email_config! + end + + private + def permitted_domains_cannot_have_trailing_slash permitted_domains.split(',').each do |domain| if domain[-1] == '/' diff --git a/app/policies/email_policy.rb b/app/policies/email_policy.rb new file mode 100644 index 0000000..5ef6c04 --- /dev/null +++ b/app/policies/email_policy.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class EmailPolicy < ApplicationPolicy + def show? + record.event.users.include?(user) || user.admin? + end + + def new? + record.event.users.include?(user) || user.admin? + end + + def create? + record.event.users.include?(user) || user.admin? + end +end diff --git a/app/views/emails/index.html.erb b/app/views/emails/index.html.erb new file mode 100644 index 0000000..655145f --- /dev/null +++ b/app/views/emails/index.html.erb @@ -0,0 +1,20 @@ +<% title "Emails on #{@event.name}" %> + + +

+ Emails + <% if @event.email_config.enabled? %> + <%= link_to 'Send an email', new_event_email_path, class: 'btn bg-success' %> + <%= link_to 'Edit settings', settings_event_emails_path, class: 'btn bg-info' %> + <% else %> + <%= link_to 'Configure email sending', settings_event_emails_path, class: 'btn bg-info' %> + <% end %> +

+ +<% if @event.email_config.enabled? %> + a +<% else %> +

Email sending hasn’t been configured.

+<% end %> diff --git a/app/views/emails/settings.html.erb b/app/views/emails/settings.html.erb new file mode 100644 index 0000000..2fd9850 --- /dev/null +++ b/app/views/emails/settings.html.erb @@ -0,0 +1,63 @@ +<% title "Editing email settings on #{@event.name}" %> + +

Email Configuration

+ +<%= form_with(model: @email_config, local: true, url: configure_event_emails_path) do |form| %> + <% if @email_config.errors.any? %> +
+

<%= pluralize(@email_config.errors.count, "error") %> prohibited this event from being saved:

+ + +
+ <% end %> + +
+ <%= form.label :smtp_url %> + <%= form.text_field :smtp_url %> +
+ +
+ <%= form.label :smtp_port %> + <%= form.text_field :smtp_port %> +
+ +
+ <%= form.label :authentication %> + <%= form.text_field :authentication, placeholder: 'PLAIN' %> +
+ +
+ <%= form.label :smtp_url %> + <%= form.text_field :smtp_url %> +
+ +
+ <%= form.label :domain %> + <%= form.text_field :domain %> +
+ +
+ <%= form.label :sender_email %> + <%= form.text_field :sender_email %> +
+ +
+ <%= form.label :username %> + <%= form.text_field :username %> +
+ +
+ <%= form.label :password %> + <%= form.password_field :password %> +
+ +
+ <%= form.submit 'Configure' %> +
+<% end %> diff --git a/app/views/events/show.html.erb b/app/views/events/show.html.erb index 03ac0d7..ef8a1b8 100644 --- a/app/views/events/show.html.erb +++ b/app/views/events/show.html.erb @@ -35,6 +35,11 @@ Hardware<%= @event.hardwares.count %> <% end %> + <%= link_to event_emails_path(@event) do %> +
  • + Emails<%= @event.email_config.enabled? ? @event.emails.count : 'Disabled' %> +
  • + <% end %>
    diff --git a/config/routes.rb b/config/routes.rb index 0231c26..24f56ca 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -18,6 +18,12 @@ end end resources :attendee_fields, path: 'fields' + resources :emails do + collection do + get 'settings', to: 'emails#settings', as: :settings + patch 'configure', to: 'emails#configure', as: :configure + end + end resources :organizer_position_invites, path: 'invites' do post 'accept' diff --git a/db/migrate/20181213014752_create_email_configs.rb b/db/migrate/20181213014752_create_email_configs.rb new file mode 100644 index 0000000..c2454e6 --- /dev/null +++ b/db/migrate/20181213014752_create_email_configs.rb @@ -0,0 +1,16 @@ +class CreateEmailConfigs < ActiveRecord::Migration[5.2] + def change + create_table :email_configs do |t| + t.string :smtp_url + t.string :smtp_port + t.string :authentication + t.string :domain + t.string :sender_email + t.string :username + t.string :password + t.belongs_to :event, index: true + + t.timestamps + end + end +end diff --git a/db/migrate/20181213030449_create_emails.rb b/db/migrate/20181213030449_create_emails.rb new file mode 100644 index 0000000..e33408f --- /dev/null +++ b/db/migrate/20181213030449_create_emails.rb @@ -0,0 +1,15 @@ +class CreateEmails < ActiveRecord::Migration[5.2] + def change + create_table :emails do |t| + t.string :recipient + t.string :sender_email + t.text :subject + t.text :body + t.string :read_receipt_img_url + t.string :read_receipt_stats_url + t.belongs_to :event, index: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 869560e..05305f2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_12_04_044905) do +ActiveRecord::Schema.define(version: 2018_12_13_030449) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -74,6 +74,33 @@ t.index ["event_id"], name: "index_attendees_on_event_id" end + create_table "email_configs", force: :cascade do |t| + t.string "smtp_url" + t.string "smtp_port" + t.string "authentication" + t.string "domain" + t.string "sender_email" + t.string "username" + t.string "password" + t.bigint "event_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["event_id"], name: "index_email_configs_on_event_id" + end + + create_table "emails", force: :cascade do |t| + t.string "recipient" + t.string "sender_email" + t.text "subject" + t.text "body" + t.string "read_receipt_img_url" + t.string "read_receipt_stats_url" + t.bigint "event_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["event_id"], name: "index_emails_on_event_id" + end + create_table "events", force: :cascade do |t| t.string "name" t.datetime "start_date" diff --git a/test/fixtures/email_configs.yml b/test/fixtures/email_configs.yml new file mode 100644 index 0000000..64e678a --- /dev/null +++ b/test/fixtures/email_configs.yml @@ -0,0 +1,21 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + enabled: false + smtp_url: MyString + smtp_port: MyString + authentication: MyString + domain: MyString + sender_email: MyString + username: MyString + password: MyString + +two: + enabled: false + smtp_url: MyString + smtp_port: MyString + authentication: MyString + domain: MyString + sender_email: MyString + username: MyString + password: MyString diff --git a/test/fixtures/emails.yml b/test/fixtures/emails.yml new file mode 100644 index 0000000..ba5c94d --- /dev/null +++ b/test/fixtures/emails.yml @@ -0,0 +1,17 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + recipient: MyString + sender_email: MyString + subject: MyText + body: MyText + read_receipt_img_url: MyString + read_receipt_stats_url: MyString + +two: + recipient: MyString + sender_email: MyString + subject: MyText + body: MyText + read_receipt_img_url: MyString + read_receipt_stats_url: MyString diff --git a/test/models/email_config_test.rb b/test/models/email_config_test.rb new file mode 100644 index 0000000..bd2ab00 --- /dev/null +++ b/test/models/email_config_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class EmailConfigTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/email_test.rb b/test/models/email_test.rb new file mode 100644 index 0000000..dc054e5 --- /dev/null +++ b/test/models/email_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class EmailTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end