symphonia 2.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +16 -0
- data/Rakefile +44 -0
- data/app/assets/images/bg-checker.png +0 -0
- data/app/assets/images/bullet.gif +0 -0
- data/app/assets/images/close.png +0 -0
- data/app/assets/images/loading.gif +0 -0
- data/app/assets/images/next.png +0 -0
- data/app/assets/images/prev.png +0 -0
- data/app/assets/javascripts/ckeditor/plugins/autogrow/plugin.js +232 -0
- data/app/assets/javascripts/ckeditor/plugins/autogrow/samples/autogrow.html +102 -0
- data/app/assets/javascripts/ckeditor/plugins/image_chooser/icons/addimage.png +0 -0
- data/app/assets/javascripts/ckeditor/plugins/image_chooser/plugin.js +15 -0
- data/app/assets/javascripts/symphonia/Sortable.js +1249 -0
- data/app/assets/javascripts/symphonia/_core.js +45 -0
- data/app/assets/javascripts/symphonia/application.js.erb +147 -0
- data/app/assets/javascripts/symphonia/filters.js +44 -0
- data/app/assets/javascripts/symphonia/symphonia_bootstrap_dialog.js +136 -0
- data/app/assets/javascripts/symphonia/symphonia_ckeditor.js +55 -0
- data/app/assets/stylesheets/symphonia/application.css +4 -0
- data/app/assets/stylesheets/symphonia/basic.scss +218 -0
- data/app/assets/stylesheets/symphonia/filters.scss +19 -0
- data/app/assets/stylesheets/symphonia/symphonia_bootstrap.scss +56 -0
- data/app/channels/application_cable/channel.rb +5 -0
- data/app/controllers/symphonia/accounts_controller.rb +169 -0
- data/app/controllers/symphonia/admin_controller.rb +22 -0
- data/app/controllers/symphonia/api_controller.rb +64 -0
- data/app/controllers/symphonia/application_controller.rb +8 -0
- data/app/controllers/symphonia/attachments_controller.rb +37 -0
- data/app/controllers/symphonia/filters_controller.rb +23 -0
- data/app/controllers/symphonia/images_controller.rb +16 -0
- data/app/controllers/symphonia/login_controller.rb +80 -0
- data/app/controllers/symphonia/roles_controller.rb +100 -0
- data/app/controllers/symphonia/user_sessions_controller.rb +16 -0
- data/app/controllers/symphonia/users_controller.rb +168 -0
- data/app/helpers/symphonia/application_helper.rb +422 -0
- data/app/helpers/symphonia/bootstrap_modal_helper.rb +59 -0
- data/app/helpers/symphonia/form_helper.rb +50 -0
- data/app/helpers/symphonia/renderer_helper.rb +85 -0
- data/app/mailers/symphonia/application_mailer.rb +6 -0
- data/app/mailers/symphonia/notifier.rb +42 -0
- data/app/models/symphonia/admin_module.rb +18 -0
- data/app/models/symphonia/application_record.rb +14 -0
- data/app/models/symphonia/attachment.rb +16 -0
- data/app/models/symphonia/common_file.rb +9 -0
- data/app/models/symphonia/email_preference.rb +5 -0
- data/app/models/symphonia/image.rb +46 -0
- data/app/models/symphonia/preference.rb +12 -0
- data/app/models/symphonia/role.rb +55 -0
- data/app/models/symphonia/swagger/error_model.rb +19 -0
- data/app/models/symphonia/swagger/responses.rb +27 -0
- data/app/models/symphonia/user.rb +141 -0
- data/app/models/symphonia/user_session.rb +19 -0
- data/app/views/common/403.html.erb +5 -0
- data/app/views/common/404.html.erb +2 -0
- data/app/views/layouts/symphonia/_modal.html.erb +19 -0
- data/app/views/layouts/symphonia/_query.html.erb +51 -0
- data/app/views/layouts/symphonia/application.html.erb +45 -0
- data/app/views/layouts/symphonia/application.pdf.erb +15 -0
- data/app/views/layouts/symphonia/mailer.html.erb +13 -0
- data/app/views/symphonia/accounts/_detail.html.erb +65 -0
- data/app/views/symphonia/accounts/_form.html.erb +14 -0
- data/app/views/symphonia/accounts/edit.html.erb +9 -0
- data/app/views/symphonia/accounts/edit.js.erb +5 -0
- data/app/views/symphonia/accounts/lost_password.html.erb +6 -0
- data/app/views/symphonia/accounts/lost_password.js.erb +3 -0
- data/app/views/symphonia/accounts/new_activation.html.erb +11 -0
- data/app/views/symphonia/accounts/new_activation.js.erb +6 -0
- data/app/views/symphonia/accounts/register.html.erb +20 -0
- data/app/views/symphonia/accounts/reset_password.html.erb +18 -0
- data/app/views/symphonia/accounts/update.js.erb +1 -0
- data/app/views/symphonia/admin/index.html.erb +15 -0
- data/app/views/symphonia/attachments/destroy.js.erb +1 -0
- data/app/views/symphonia/common/_editable_images_grid.html.erb +12 -0
- data/app/views/symphonia/common/_filters.html.erb +23 -0
- data/app/views/symphonia/common/_locale_chooser.html.erb +16 -0
- data/app/views/symphonia/common/_share_links.html.erb +5 -0
- data/app/views/symphonia/filters/options.html.erb +36 -0
- data/app/views/symphonia/filters/options.js.erb +9 -0
- data/app/views/symphonia/filters/table.html.erb +21 -0
- data/app/views/symphonia/login/_form.html.erb +19 -0
- data/app/views/symphonia/login/new.html.erb +11 -0
- data/app/views/symphonia/login_sessions/new.html.erb +1 -0
- data/app/views/symphonia/notifier/activation_user.html.erb +7 -0
- data/app/views/symphonia/notifier/activation_user.text.erb +3 -0
- data/app/views/symphonia/notifier/reset_password_user.html.erb +7 -0
- data/app/views/symphonia/notifier/reset_password_user.text.erb +3 -0
- data/app/views/symphonia/notifier/test_mail.html.erb +2 -0
- data/app/views/symphonia/notifier/test_mail.text.erb +3 -0
- data/app/views/symphonia/notifier/user_change_to_active.html.erb +3 -0
- data/app/views/symphonia/notifier/user_change_to_active.text.erb +1 -0
- data/app/views/symphonia/notifier/user_registered.html.erb +13 -0
- data/app/views/symphonia/notifier/user_registered.text.erb +8 -0
- data/app/views/symphonia/roles/_form.html.erb +30 -0
- data/app/views/symphonia/roles/edit.html.erb +5 -0
- data/app/views/symphonia/roles/index.html.erb +6 -0
- data/app/views/symphonia/roles/new.html.erb +4 -0
- data/app/views/symphonia/roles/show.html.erb +5 -0
- data/app/views/symphonia/users/_form.html.erb +13 -0
- data/app/views/symphonia/users/edit.html.erb +26 -0
- data/app/views/symphonia/users/edit.js.erb +3 -0
- data/app/views/symphonia/users/edit_current.html.erb +7 -0
- data/app/views/symphonia/users/index.html.erb +5 -0
- data/app/views/symphonia/users/new.html.erb +8 -0
- data/app/views/symphonia/users/show.html.erb +63 -0
- data/config/locales/cs.yml +233 -0
- data/config/locales/en.yml +47 -0
- data/config/routes.rb +52 -0
- data/db/migrate/20130714140500_create_users.rb +49 -0
- data/db/migrate/20130714140501_create_roles.rb +16 -0
- data/db/migrate/20130714140502_create_preferences.rb +26 -0
- data/db/migrate/20130828175114_create_attachments.rb +20 -0
- data/db/migrate/20141213204351_create_admin_modules.rb +20 -0
- data/db/seeds.rb +12 -0
- data/lib/generators/symphonia/entity_controller/entity_controller_generator.rb +48 -0
- data/lib/generators/symphonia/entity_controller/templates/controller.rb +100 -0
- data/lib/generators/symphonia/query/query_generator.rb +37 -0
- data/lib/generators/symphonia/setup/setup_generator.rb +52 -0
- data/lib/generators/symphonia/setup/templates/404.html +26 -0
- data/lib/generators/symphonia/setup/templates/500.html +37 -0
- data/lib/generators/symphonia/setup/templates/Gemfile +18 -0
- data/lib/generators/symphonia/setup/templates/base_layout.html.erb +46 -0
- data/lib/generators/symphonia/setup/templates/design.scss +4 -0
- data/lib/generators/symphonia/setup/templates/settings.rb +65 -0
- data/lib/generators/symphonia/setup/templates/spec_helper.rb +18 -0
- data/lib/symphonia/action_cable/connection.rb +31 -0
- data/lib/symphonia/admin_constraint.rb +9 -0
- data/lib/symphonia/attachable.rb +35 -0
- data/lib/symphonia/base_controller.rb +96 -0
- data/lib/symphonia/bootstrap_link_render.rb +69 -0
- data/lib/symphonia/controller_extensions.rb +200 -0
- data/lib/symphonia/engine.rb +137 -0
- data/lib/symphonia/form_builder.rb +137 -0
- data/lib/symphonia/menu_manager.rb +23 -0
- data/lib/symphonia/model_attributes/attribute.rb +137 -0
- data/lib/symphonia/model_attributes.rb +102 -0
- data/lib/symphonia/model_filters/base.rb +82 -0
- data/lib/symphonia/model_filters/boolean_filter.rb +26 -0
- data/lib/symphonia/model_filters/date_filter.rb +81 -0
- data/lib/symphonia/model_filters/integer_filter.rb +18 -0
- data/lib/symphonia/model_filters/select_filter.rb +48 -0
- data/lib/symphonia/model_filters/string_filter.rb +18 -0
- data/lib/symphonia/model_filters.rb +10 -0
- data/lib/symphonia/object.rb +31 -0
- data/lib/symphonia/permissions.rb +93 -0
- data/lib/symphonia/query.rb +275 -0
- data/lib/symphonia/query_columns/attribute_column.rb +43 -0
- data/lib/symphonia/query_columns/generic_column.rb +165 -0
- data/lib/symphonia/query_columns.rb +8 -0
- data/lib/symphonia/spec_helper.rb +4 -0
- data/lib/symphonia/user_management.rb +58 -0
- data/lib/symphonia/version.rb +4 -0
- data/lib/symphonia.rb +20 -0
- data/spec/controllers/account_controller_spec.rb +90 -0
- data/spec/controllers/admin_controller_spec.rb +35 -0
- data/spec/controllers/api_controller_spec.rb +9 -0
- data/spec/controllers/filters_controller_spec.rb +35 -0
- data/spec/controllers/images_controller_spec.rb +5 -0
- data/spec/controllers/login_controller_spec.rb +20 -0
- data/spec/controllers/roles_controller_spec.rb +12 -0
- data/spec/controllers/users_controller_spec.rb +47 -0
- data/spec/factories/factories.rb +52 -0
- data/spec/helpers/symphonia/application_helper_spec.rb +62 -0
- data/spec/mailers/previews/symphonia/notifier_preview.rb +27 -0
- data/spec/mailers/symphonia/notifier_spec.rb +76 -0
- data/spec/models/attachment_spec.rb +22 -0
- data/spec/models/query/attribute_spec.rb +8 -0
- data/spec/models/query/symphonia_query_spec.rb +70 -0
- data/spec/models/role_spec.rb +13 -0
- data/spec/models/user_spec.rb +10 -0
- data/spec/rails_helper.rb +13 -0
- data/spec/requests/accounts_spec.rb +118 -0
- data/spec/requests/attachments_controller_spec.rb +23 -0
- data/spec/requests/login_spec.rb +26 -0
- data/spec/requests/roles_spec.rb +10 -0
- data/spec/requests/users_spec.rb +50 -0
- data/spec/spec_helper.rb +101 -0
- data/spec/support/common_file.txt +2 -0
- data/spec/support/query.rb +36 -0
- data/spec/support/shared.rb +62 -0
- data/spec/support/shared_controllers.rb +31 -0
- data/spec/support/stub_users.rb +32 -0
- data/spec/support/symphonia.jpg +0 -0
- data/spec/support/wait_for_ajax.rb +15 -0
- data/spec/version_spec.rb +5 -0
- data/spec/views/filters/options.html.erb_spec.rb +14 -0
- metadata +697 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
module Symphonia
|
2
|
+
module RendererHelper
|
3
|
+
|
4
|
+
def render_symphonia_table(*args, &block)
|
5
|
+
options = args.extract_options!
|
6
|
+
query = args[0]
|
7
|
+
entities = args[1] || @entities
|
8
|
+
r = QueryRender.new(self, query, options)
|
9
|
+
r.summarize = options.delete(:show_summarize_row)
|
10
|
+
unless block_given?
|
11
|
+
block = proc { |renderer, entity| renderer.default_buttons(entity) }
|
12
|
+
end
|
13
|
+
render(layout: 'layouts/symphonia/query', locals: { renderer: r, entities: entities, options: options }, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
class QueryRender
|
17
|
+
|
18
|
+
attr_reader :query
|
19
|
+
attr_accessor :summarize
|
20
|
+
OPTIONS = [:without_pagination, :show_checkboxes, :show_radios, :table_css_classes]
|
21
|
+
attr_accessor *OPTIONS
|
22
|
+
|
23
|
+
def initialize(helper, query, options = {})
|
24
|
+
@_c = helper
|
25
|
+
@query = query
|
26
|
+
OPTIONS.each do |key|
|
27
|
+
send("#{key}=", options[key])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def show_summarize?
|
32
|
+
!!summarize
|
33
|
+
end
|
34
|
+
|
35
|
+
def show_checkboxes?
|
36
|
+
!!@show_checkboxes
|
37
|
+
end
|
38
|
+
|
39
|
+
def show_radios?
|
40
|
+
!!@show_radios
|
41
|
+
end
|
42
|
+
|
43
|
+
def show_link(entity)
|
44
|
+
@_c.link_to(@_c.icon('info-circle', t(:button_show)), entity)
|
45
|
+
end
|
46
|
+
|
47
|
+
def edit_link(entity)
|
48
|
+
@_c.link_to(@_c.icon('edit', t(:button_edit)), @_c.edit_polymorphic_path(entity, back_url: @_c.polymorphic_path(@_c.controller_name, page: @_c.params[:page])))
|
49
|
+
end
|
50
|
+
|
51
|
+
def delete_link(entity)
|
52
|
+
@_c.link_to(@_c.icon('del', t(:button_delete)), entity, method: 'DELETE', data: { remote: true, confirm: t(:text_are_you_sure) })
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_buttons(entity)
|
56
|
+
edit_link(entity) + delete_link(entity)
|
57
|
+
end
|
58
|
+
|
59
|
+
def header_tag(column, options = {})
|
60
|
+
return '' unless column.header?
|
61
|
+
|
62
|
+
title = column.title
|
63
|
+
return title unless column.sort?
|
64
|
+
|
65
|
+
current_column = query.sort_column || SortableTable::SortColumn.new(nil, nil)
|
66
|
+
prefix = options.delete(:prefix)
|
67
|
+
is_current_column = column.sort_definition.column == current_column.column
|
68
|
+
options_class = options.delete(:class)
|
69
|
+
css_class = is_current_column ? "current #{current_column.direction} #{options_class}" : options_class
|
70
|
+
direction = is_current_column && current_column.direction == 'asc' ? 'desc' : 'asc'
|
71
|
+
sort_params = { "#{prefix}sort" => column.sort_definition.column,
|
72
|
+
"#{prefix}direction" => direction,
|
73
|
+
"#{prefix}page" => nil }
|
74
|
+
@_c.link_to title, query.to_params.merge(sort_params), options.merge({ class: css_class })
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def t(*args)
|
80
|
+
@_c.t(*args)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Symphonia
|
3
|
+
class Notifier < ApplicationMailer
|
4
|
+
# default from: "noreply@host.cz", :host => 'host.cz'
|
5
|
+
|
6
|
+
helper :application
|
7
|
+
helper Symphonia::ApplicationHelper
|
8
|
+
|
9
|
+
def mail(headers={}, &block)
|
10
|
+
I18n.locale = Symphonia.config[:backend_locale]
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def activation_user(user)
|
15
|
+
@user = user
|
16
|
+
mail({ to: @user.mail, subject: t(:subject_activation_mail) })
|
17
|
+
end
|
18
|
+
|
19
|
+
def user_change_to_active(user)
|
20
|
+
@user = user
|
21
|
+
mail({ to: @user.mail, subject: 'Váš účet je aktivován' })
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset_password_user(user)
|
25
|
+
@user = user
|
26
|
+
mail({ to: @user.mail, subject: t(:subject_reset_password_mail) })
|
27
|
+
end
|
28
|
+
|
29
|
+
def user_registered(user)
|
30
|
+
@user = user
|
31
|
+
@recipients = Symphonia::User.recipients_for(:notify_after_user_registered).pluck(:mail).uniq
|
32
|
+
mail({ to: @recipients, subject: t(:subject_user_registered) }) if @recipients.any?
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_mail(user_id = nil)
|
36
|
+
@user = Symphonia::User.find_by(id: user_id) || Symphonia::User.active.where(admin: true).first
|
37
|
+
mail(to: @user.mail, subject: 'Symphonia testing mail')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Symphonia
|
2
|
+
class AdminModule < ApplicationRecord
|
3
|
+
self.table_name = 'admin_modules'
|
4
|
+
|
5
|
+
belongs_to :user
|
6
|
+
store :settings, coder: JSON
|
7
|
+
|
8
|
+
validates :title, presence: true
|
9
|
+
validates :panel_type, inclusion: { in: %w(default primary success info warning danger) }
|
10
|
+
|
11
|
+
|
12
|
+
def body_path
|
13
|
+
# override me
|
14
|
+
self.description
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'acts_as_list'
|
2
|
+
module Symphonia
|
3
|
+
class Attachment < ApplicationRecord
|
4
|
+
self.table_name = 'attachments'
|
5
|
+
|
6
|
+
belongs_to :attachable, polymorphic: true, touch: true, optional: true
|
7
|
+
acts_as_list scope: :attachable
|
8
|
+
|
9
|
+
scope :like, proc {|q| where(arel_table[:description].matches("%#{q}%"))}
|
10
|
+
|
11
|
+
def name
|
12
|
+
attachment_file_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Symphonia
|
2
|
+
class Image < Attachment
|
3
|
+
|
4
|
+
class_attribute :paperclip_options
|
5
|
+
|
6
|
+
def self.image_styles
|
7
|
+
Symphonia.config[:paperclip_styles] || {
|
8
|
+
tiny_thumb: '120x120>', thumb: '200x200>', medium: '400x300>', large: '800x600>', original: '1280x800>'
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
has_attached_file(:attachment, {
|
13
|
+
styles: image_styles,
|
14
|
+
url: :paperclip_attachment_url,
|
15
|
+
convert_options: {
|
16
|
+
thumb: '-strip -quality 75',
|
17
|
+
tiny_thumb: '-strip -quality 75',
|
18
|
+
large: '-strip -quality 90'
|
19
|
+
}
|
20
|
+
})
|
21
|
+
|
22
|
+
before_post_process :transliterate_file_name
|
23
|
+
|
24
|
+
validates_attachment :attachment, presence: true, content_type: {
|
25
|
+
content_type: %w(image/jpeg image/jpg image/JPG image/png image/gif)}, size: {in: 0..5.megabytes}
|
26
|
+
|
27
|
+
|
28
|
+
def url(variant = :original)
|
29
|
+
attachment.url(variant)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def paperclip_attachment_url
|
35
|
+
paperclip_options.try(:[], :url) || Paperclip::Attachment.default_options[:url]
|
36
|
+
end
|
37
|
+
|
38
|
+
def transliterate_file_name
|
39
|
+
extension = File.extname(attachment_file_name).remove('.')
|
40
|
+
filename = File.basename(attachment_file_name, '.*')
|
41
|
+
self.attachment.instance_write(:file_name, "#{filename.parameterize}.#{extension}")
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Symphonia
|
2
|
+
class Preference < ApplicationRecord
|
3
|
+
self.table_name = 'preferences'
|
4
|
+
|
5
|
+
validates :name, uniqueness: true
|
6
|
+
# has_and_belongs_to_many :symphonia_units, association_foreign_key: 'user_id'
|
7
|
+
has_and_belongs_to_many :users, join_table: 'preferences_users', association_foreign_key: 'user_id', class_name: 'Symphonia::User'
|
8
|
+
|
9
|
+
scope :visible, ->(user = Symphonia::User.current) { user.admin? ? all : where(restrict: false)}
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Symphonia
|
2
|
+
class Role < ApplicationRecord
|
3
|
+
self.table_name = 'roles'
|
4
|
+
|
5
|
+
include ModelAttributes
|
6
|
+
|
7
|
+
register_query do
|
8
|
+
add_attribute :name, :link
|
9
|
+
end
|
10
|
+
|
11
|
+
validates :name, presence: true
|
12
|
+
|
13
|
+
serialize :permissions, Array
|
14
|
+
|
15
|
+
scope :active, -> {}
|
16
|
+
scope :sorted, -> { order(:name) }
|
17
|
+
|
18
|
+
# after_save :expire_cache
|
19
|
+
|
20
|
+
def allowed_to?(permission)
|
21
|
+
Rails.cache.fetch([self, permission]) do
|
22
|
+
!allowed_permissions.detect { |i| permission.to_sym == i.name }.nil?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def authorize?(controller, action)
|
27
|
+
Rails.cache.fetch([self, controller, action]) do
|
28
|
+
!allowed_permissions.detect { |p| p.allowed?(controller, action) }.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def allowed_permissions
|
33
|
+
return @allowed_permissions if @allowed_permissions
|
34
|
+
|
35
|
+
@allowed_permissions = permissions.collect do |i|
|
36
|
+
i.is_a?(Symphonia::Permissions::Permission) ? i : Symphonia::Permissions.get(i.to_sym)
|
37
|
+
end.compact
|
38
|
+
|
39
|
+
@allowed_permissions
|
40
|
+
end
|
41
|
+
|
42
|
+
def permission_names
|
43
|
+
permissions #.map(&:name)
|
44
|
+
end
|
45
|
+
|
46
|
+
# private
|
47
|
+
#
|
48
|
+
# def expire_cache
|
49
|
+
# Rails.cache.delete_matched("role_#{self.id}_*")
|
50
|
+
# Rails.cache.delete_matched('user_allowed_to*')
|
51
|
+
# end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Symphonia
|
2
|
+
module Swagger
|
3
|
+
class ErrorModel
|
4
|
+
include ::Swagger::Blocks
|
5
|
+
|
6
|
+
swagger_schema :ErrorModel do
|
7
|
+
key :required, %i[attribute messages]
|
8
|
+
property :attribute do
|
9
|
+
key :type, :string
|
10
|
+
key :example, "login"
|
11
|
+
end
|
12
|
+
property :messages do
|
13
|
+
key :type, :array
|
14
|
+
key :example, "[cannot be blank]"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Symphonia
|
2
|
+
module Swagger
|
3
|
+
module Responses
|
4
|
+
def self.extended(base)
|
5
|
+
base.response 401 do
|
6
|
+
key :description, 'not authorized'
|
7
|
+
end
|
8
|
+
base.response 404 do
|
9
|
+
key :description, 'not found'
|
10
|
+
end
|
11
|
+
base.response 406 do
|
12
|
+
key :description, 'not allowed'
|
13
|
+
end
|
14
|
+
base.response 422 do
|
15
|
+
key :description, 'unprocessable entity'
|
16
|
+
schema do
|
17
|
+
key :'$ref', :ErrorModel
|
18
|
+
end
|
19
|
+
end
|
20
|
+
base.response 500 do
|
21
|
+
key :description, 'internal server error'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Symphonia
|
2
|
+
class User < ApplicationRecord
|
3
|
+
self.table_name = 'users'
|
4
|
+
|
5
|
+
include ModelAttributes
|
6
|
+
|
7
|
+
register_query do
|
8
|
+
add_attribute :login, :link
|
9
|
+
add_attribute :name, :link, sort: %i(first_name last_name), default: true
|
10
|
+
add_attribute :first_name
|
11
|
+
add_attribute :last_name
|
12
|
+
add_attribute :email, :mail, default: true
|
13
|
+
add_attribute :status, :enum, filter: "select"
|
14
|
+
add_attribute :role, :reference
|
15
|
+
add_attribute :admin, :boolean
|
16
|
+
add_attribute :login_count
|
17
|
+
add_attribute :last_login_ip
|
18
|
+
add_attribute :last_login_at
|
19
|
+
end
|
20
|
+
|
21
|
+
acts_as_authentic do |config|
|
22
|
+
end
|
23
|
+
|
24
|
+
include UserManagement
|
25
|
+
|
26
|
+
include ::Swagger::Blocks
|
27
|
+
|
28
|
+
swagger_schema :User do
|
29
|
+
key :required, %i[id login email]
|
30
|
+
property :id do
|
31
|
+
key :type, :integer
|
32
|
+
key :format, :int64
|
33
|
+
end
|
34
|
+
property :fist_name do
|
35
|
+
key :type, :string
|
36
|
+
end
|
37
|
+
property :last_name do
|
38
|
+
key :type, :string
|
39
|
+
end
|
40
|
+
property :email do
|
41
|
+
key :type, :string
|
42
|
+
key :format, :email
|
43
|
+
end
|
44
|
+
property :status do
|
45
|
+
key :type, :string
|
46
|
+
key :enum, Symphonia::User.statuses.keys
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
has_and_belongs_to_many :preferences, foreign_key: 'user_id'
|
51
|
+
|
52
|
+
belongs_to :edited_by, class_name: 'Symphonia::User', required: false
|
53
|
+
belongs_to :role, required: false
|
54
|
+
|
55
|
+
accepts_nested_attributes_for :preferences
|
56
|
+
|
57
|
+
scope :recipients_for, ->(notification) { joins(:preferences).where(preferences: { name: notification, type: 'Symphonia::EmailPreference' }) }
|
58
|
+
|
59
|
+
scope :like, ->(q) { t = arel_table; where(t[:email].matches("%#{q}%").or(t[:first_name].matches("%#{q}%").or(t[:last_name].matches("%#{q}%")))) }
|
60
|
+
|
61
|
+
alias_attribute :mail, :email
|
62
|
+
|
63
|
+
|
64
|
+
before_save do |model|
|
65
|
+
Rails.cache.delete_matched('user_allowed_to*') if model.role_id_changed?
|
66
|
+
end
|
67
|
+
|
68
|
+
def allowed_to?(action)
|
69
|
+
return true if admin?
|
70
|
+
|
71
|
+
Rails.cache.fetch([:user_allowed_to, self, action]) do
|
72
|
+
role_id && role.allowed_to?(action)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def authorize?(controller, action)
|
77
|
+
return true if admin?
|
78
|
+
|
79
|
+
if role_id
|
80
|
+
role.authorize?(controller, action)
|
81
|
+
else
|
82
|
+
false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# def form_path
|
87
|
+
# 'symphonia/users/form'
|
88
|
+
# end
|
89
|
+
|
90
|
+
class Anonymous
|
91
|
+
|
92
|
+
def id
|
93
|
+
0
|
94
|
+
end
|
95
|
+
|
96
|
+
def name
|
97
|
+
'Anonymous'
|
98
|
+
end
|
99
|
+
|
100
|
+
def login
|
101
|
+
'anonymous'
|
102
|
+
end
|
103
|
+
|
104
|
+
def email
|
105
|
+
'anonym@nothing'
|
106
|
+
end
|
107
|
+
|
108
|
+
def allowed_to?(_action)
|
109
|
+
false
|
110
|
+
end
|
111
|
+
|
112
|
+
def authorize?(_controller, _action)
|
113
|
+
false
|
114
|
+
end
|
115
|
+
|
116
|
+
def save
|
117
|
+
false
|
118
|
+
end
|
119
|
+
|
120
|
+
def create
|
121
|
+
false
|
122
|
+
end
|
123
|
+
|
124
|
+
def admin
|
125
|
+
false
|
126
|
+
end
|
127
|
+
|
128
|
+
alias_method :admin?, :admin
|
129
|
+
|
130
|
+
def logged_in?
|
131
|
+
false
|
132
|
+
end
|
133
|
+
|
134
|
+
def persistence_token
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Symphonia
|
2
|
+
class UserSession < Authlogic::Session::Base
|
3
|
+
params_key :key
|
4
|
+
single_access_allowed_request_types %w(application/rss+xml application/xml application/json)
|
5
|
+
|
6
|
+
generalize_credentials_error_messages true
|
7
|
+
|
8
|
+
def self.validators_on(*args)
|
9
|
+
[]
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def params_credentials
|
15
|
+
super || ActionController::HttpAuthentication::Token.authenticate(controller) { |t, _o| t } || nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<div class="modal" tabindex="-1" role="dialog">
|
2
|
+
<div class="modal-dialog" role="document">
|
3
|
+
<div class="modal-content">
|
4
|
+
<div class="modal-header">
|
5
|
+
<h5 class="modal-title">Modal title</h5>
|
6
|
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
7
|
+
<span aria-hidden="true">×</span>
|
8
|
+
</button>
|
9
|
+
</div>
|
10
|
+
<div class="modal-body">
|
11
|
+
<%= yield %>
|
12
|
+
</div>
|
13
|
+
<div class="modal-footer">
|
14
|
+
<button type="button" class="btn btn-primary">Save changes</button>
|
15
|
+
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</div>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
<% if entities.any? %>
|
2
|
+
<div id="query_data" class="table-responsive">
|
3
|
+
<table class="table <%= renderer.query.entity.name.pluralize.underscore %> table-striped <%= renderer.table_css_classes %>">
|
4
|
+
<thead>
|
5
|
+
<tr>
|
6
|
+
<% if renderer.show_checkboxes? %>
|
7
|
+
<th class="px-0">
|
8
|
+
<a class="fa fa-check-square-o" href="javascript:void(0)" onclick="SymphoniaCheckboxes.toggleAll(document.getElementById('query_data'))"></a>
|
9
|
+
</th>
|
10
|
+
<% elsif renderer.show_radios? %>
|
11
|
+
<%= content_tag(:th) %>
|
12
|
+
<% end %>
|
13
|
+
<% renderer.query.columns.each do |c| %>
|
14
|
+
<th class="<%= c.css_classes %>"><%= renderer.header_tag(c) %></th>
|
15
|
+
<% end %>
|
16
|
+
<th class="buttons hidden-print"></th>
|
17
|
+
</tr>
|
18
|
+
<% if renderer.show_summarize? && renderer.query.columns.detect(&:summarize?) %>
|
19
|
+
<tr class="summarize-row">
|
20
|
+
<%= content_tag(:th) if renderer.show_checkboxes? || renderer.show_radios? %>
|
21
|
+
<% renderer.query.columns.each do |column| %>
|
22
|
+
<th class="<%= column.css_classes %>">
|
23
|
+
<% if column.summarize? %>
|
24
|
+
<%= column.sum_value(self) %>
|
25
|
+
<% end %>
|
26
|
+
</th>
|
27
|
+
<% end %>
|
28
|
+
<th class="hidden-print"></th>
|
29
|
+
</tr>
|
30
|
+
<% end %>
|
31
|
+
</thead>
|
32
|
+
<tbody>
|
33
|
+
<% entities.each do |entity| %>
|
34
|
+
<tr id="<%= dom_id(entity) %>" class="<%= cycle('odd', 'even') %> <%= entity.try(:css_classes) %>">
|
35
|
+
<%= content_tag(:td, check_box_tag('ids[]', entity.id), class: "px-0") if renderer.show_checkboxes? %>
|
36
|
+
<%= content_tag(:td, radio_button_tag('id', entity.id)) if renderer.show_radios? %>
|
37
|
+
<% renderer.query.columns.each do |column| %>
|
38
|
+
<%= content_tag(:td, column.format_value(self, entity), class: column.css_classes) %>
|
39
|
+
<% end %>
|
40
|
+
<td class="buttons hidden-print">
|
41
|
+
<%= yield renderer, entity %>
|
42
|
+
</td>
|
43
|
+
</tr>
|
44
|
+
<% end %>
|
45
|
+
</tbody>
|
46
|
+
</table>
|
47
|
+
<%= will_paginate(entities) if renderer.without_pagination.nil? %>
|
48
|
+
</div>
|
49
|
+
<% else %>
|
50
|
+
<%= render_no_data %>
|
51
|
+
<% end %>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="<%= I18n.locale %>">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<title><%= html_title %></title>
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
+
<%= yield :meta_tags %>
|
8
|
+
<%= stylesheet_link_tag 'application', :media => 'all', 'data-turbolinks-track' => true %>
|
9
|
+
<%= yield :stylesheet_tags %>
|
10
|
+
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
|
11
|
+
<script type="text/javascript">
|
12
|
+
Symphonia.routes.reorderImagesPath = '<%= symphonia.reorder_attachment_path %>';
|
13
|
+
</script>
|
14
|
+
<%= yield :javascript_tags %>
|
15
|
+
<%= csrf_meta_tags %>
|
16
|
+
</head>
|
17
|
+
<body class="controller-<%= controller_name %> action-<%= action_name %>" data-menu-item="<%= @menu_item.to_sym %>">
|
18
|
+
<header data-turbolinks-permanent>
|
19
|
+
<nav class="navbar navbar-expand-lg navbar-light bg-light fixed-top">
|
20
|
+
<!--<a class="navbar-brand" href="#">Navbar</a>-->
|
21
|
+
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
22
|
+
<%= fa_icon('bars') %>
|
23
|
+
</button>
|
24
|
+
|
25
|
+
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
26
|
+
<%= render_menu(:top_menu) %>
|
27
|
+
<%= render_menu(:top_menu_account, { container_class: 'mr-right' }) %>
|
28
|
+
</div>
|
29
|
+
</nav>
|
30
|
+
</header>
|
31
|
+
|
32
|
+
<div id="main" class="container">
|
33
|
+
<slot id="flash_messages" name="flash_messages"><%= render_flash_messages.html_safe -%></slot>
|
34
|
+
<%= yield %>
|
35
|
+
</div>
|
36
|
+
<footer class="footer">
|
37
|
+
<div class="container text-center">
|
38
|
+
© Lukáš Pokorný
|
39
|
+
<%= yield :footer %>
|
40
|
+
</div>
|
41
|
+
</footer>
|
42
|
+
|
43
|
+
<div id="ajax-indicator" style="display:none"><i class="fa fa-spinner fa-spin fa-large"></i></div>
|
44
|
+
</body>
|
45
|
+
</html>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="<%= I18n.locale %>">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<title><%= html_title %></title>
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
+
<%= wicked_pdf_stylesheet_link_tag('application') %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<section id="main" class="container-fluid">
|
11
|
+
<%= yield %>
|
12
|
+
</section>
|
13
|
+
|
14
|
+
</body>
|
15
|
+
</html>
|