symphonia 2.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +16 -0
  4. data/Rakefile +44 -0
  5. data/app/assets/images/bg-checker.png +0 -0
  6. data/app/assets/images/bullet.gif +0 -0
  7. data/app/assets/images/close.png +0 -0
  8. data/app/assets/images/loading.gif +0 -0
  9. data/app/assets/images/next.png +0 -0
  10. data/app/assets/images/prev.png +0 -0
  11. data/app/assets/javascripts/ckeditor/plugins/autogrow/plugin.js +232 -0
  12. data/app/assets/javascripts/ckeditor/plugins/autogrow/samples/autogrow.html +102 -0
  13. data/app/assets/javascripts/ckeditor/plugins/image_chooser/icons/addimage.png +0 -0
  14. data/app/assets/javascripts/ckeditor/plugins/image_chooser/plugin.js +15 -0
  15. data/app/assets/javascripts/symphonia/Sortable.js +1249 -0
  16. data/app/assets/javascripts/symphonia/_core.js +45 -0
  17. data/app/assets/javascripts/symphonia/application.js.erb +147 -0
  18. data/app/assets/javascripts/symphonia/filters.js +44 -0
  19. data/app/assets/javascripts/symphonia/symphonia_bootstrap_dialog.js +136 -0
  20. data/app/assets/javascripts/symphonia/symphonia_ckeditor.js +55 -0
  21. data/app/assets/stylesheets/symphonia/application.css +4 -0
  22. data/app/assets/stylesheets/symphonia/basic.scss +218 -0
  23. data/app/assets/stylesheets/symphonia/filters.scss +19 -0
  24. data/app/assets/stylesheets/symphonia/symphonia_bootstrap.scss +56 -0
  25. data/app/channels/application_cable/channel.rb +5 -0
  26. data/app/controllers/symphonia/accounts_controller.rb +169 -0
  27. data/app/controllers/symphonia/admin_controller.rb +22 -0
  28. data/app/controllers/symphonia/api_controller.rb +64 -0
  29. data/app/controllers/symphonia/application_controller.rb +8 -0
  30. data/app/controllers/symphonia/attachments_controller.rb +37 -0
  31. data/app/controllers/symphonia/filters_controller.rb +23 -0
  32. data/app/controllers/symphonia/images_controller.rb +16 -0
  33. data/app/controllers/symphonia/login_controller.rb +80 -0
  34. data/app/controllers/symphonia/roles_controller.rb +100 -0
  35. data/app/controllers/symphonia/user_sessions_controller.rb +16 -0
  36. data/app/controllers/symphonia/users_controller.rb +168 -0
  37. data/app/helpers/symphonia/application_helper.rb +422 -0
  38. data/app/helpers/symphonia/bootstrap_modal_helper.rb +59 -0
  39. data/app/helpers/symphonia/form_helper.rb +50 -0
  40. data/app/helpers/symphonia/renderer_helper.rb +85 -0
  41. data/app/mailers/symphonia/application_mailer.rb +6 -0
  42. data/app/mailers/symphonia/notifier.rb +42 -0
  43. data/app/models/symphonia/admin_module.rb +18 -0
  44. data/app/models/symphonia/application_record.rb +14 -0
  45. data/app/models/symphonia/attachment.rb +16 -0
  46. data/app/models/symphonia/common_file.rb +9 -0
  47. data/app/models/symphonia/email_preference.rb +5 -0
  48. data/app/models/symphonia/image.rb +46 -0
  49. data/app/models/symphonia/preference.rb +12 -0
  50. data/app/models/symphonia/role.rb +55 -0
  51. data/app/models/symphonia/swagger/error_model.rb +19 -0
  52. data/app/models/symphonia/swagger/responses.rb +27 -0
  53. data/app/models/symphonia/user.rb +141 -0
  54. data/app/models/symphonia/user_session.rb +19 -0
  55. data/app/views/common/403.html.erb +5 -0
  56. data/app/views/common/404.html.erb +2 -0
  57. data/app/views/layouts/symphonia/_modal.html.erb +19 -0
  58. data/app/views/layouts/symphonia/_query.html.erb +51 -0
  59. data/app/views/layouts/symphonia/application.html.erb +45 -0
  60. data/app/views/layouts/symphonia/application.pdf.erb +15 -0
  61. data/app/views/layouts/symphonia/mailer.html.erb +13 -0
  62. data/app/views/symphonia/accounts/_detail.html.erb +65 -0
  63. data/app/views/symphonia/accounts/_form.html.erb +14 -0
  64. data/app/views/symphonia/accounts/edit.html.erb +9 -0
  65. data/app/views/symphonia/accounts/edit.js.erb +5 -0
  66. data/app/views/symphonia/accounts/lost_password.html.erb +6 -0
  67. data/app/views/symphonia/accounts/lost_password.js.erb +3 -0
  68. data/app/views/symphonia/accounts/new_activation.html.erb +11 -0
  69. data/app/views/symphonia/accounts/new_activation.js.erb +6 -0
  70. data/app/views/symphonia/accounts/register.html.erb +20 -0
  71. data/app/views/symphonia/accounts/reset_password.html.erb +18 -0
  72. data/app/views/symphonia/accounts/update.js.erb +1 -0
  73. data/app/views/symphonia/admin/index.html.erb +15 -0
  74. data/app/views/symphonia/attachments/destroy.js.erb +1 -0
  75. data/app/views/symphonia/common/_editable_images_grid.html.erb +12 -0
  76. data/app/views/symphonia/common/_filters.html.erb +23 -0
  77. data/app/views/symphonia/common/_locale_chooser.html.erb +16 -0
  78. data/app/views/symphonia/common/_share_links.html.erb +5 -0
  79. data/app/views/symphonia/filters/options.html.erb +36 -0
  80. data/app/views/symphonia/filters/options.js.erb +9 -0
  81. data/app/views/symphonia/filters/table.html.erb +21 -0
  82. data/app/views/symphonia/login/_form.html.erb +19 -0
  83. data/app/views/symphonia/login/new.html.erb +11 -0
  84. data/app/views/symphonia/login_sessions/new.html.erb +1 -0
  85. data/app/views/symphonia/notifier/activation_user.html.erb +7 -0
  86. data/app/views/symphonia/notifier/activation_user.text.erb +3 -0
  87. data/app/views/symphonia/notifier/reset_password_user.html.erb +7 -0
  88. data/app/views/symphonia/notifier/reset_password_user.text.erb +3 -0
  89. data/app/views/symphonia/notifier/test_mail.html.erb +2 -0
  90. data/app/views/symphonia/notifier/test_mail.text.erb +3 -0
  91. data/app/views/symphonia/notifier/user_change_to_active.html.erb +3 -0
  92. data/app/views/symphonia/notifier/user_change_to_active.text.erb +1 -0
  93. data/app/views/symphonia/notifier/user_registered.html.erb +13 -0
  94. data/app/views/symphonia/notifier/user_registered.text.erb +8 -0
  95. data/app/views/symphonia/roles/_form.html.erb +30 -0
  96. data/app/views/symphonia/roles/edit.html.erb +5 -0
  97. data/app/views/symphonia/roles/index.html.erb +6 -0
  98. data/app/views/symphonia/roles/new.html.erb +4 -0
  99. data/app/views/symphonia/roles/show.html.erb +5 -0
  100. data/app/views/symphonia/users/_form.html.erb +13 -0
  101. data/app/views/symphonia/users/edit.html.erb +26 -0
  102. data/app/views/symphonia/users/edit.js.erb +3 -0
  103. data/app/views/symphonia/users/edit_current.html.erb +7 -0
  104. data/app/views/symphonia/users/index.html.erb +5 -0
  105. data/app/views/symphonia/users/new.html.erb +8 -0
  106. data/app/views/symphonia/users/show.html.erb +63 -0
  107. data/config/locales/cs.yml +233 -0
  108. data/config/locales/en.yml +47 -0
  109. data/config/routes.rb +52 -0
  110. data/db/migrate/20130714140500_create_users.rb +49 -0
  111. data/db/migrate/20130714140501_create_roles.rb +16 -0
  112. data/db/migrate/20130714140502_create_preferences.rb +26 -0
  113. data/db/migrate/20130828175114_create_attachments.rb +20 -0
  114. data/db/migrate/20141213204351_create_admin_modules.rb +20 -0
  115. data/db/seeds.rb +12 -0
  116. data/lib/generators/symphonia/entity_controller/entity_controller_generator.rb +48 -0
  117. data/lib/generators/symphonia/entity_controller/templates/controller.rb +100 -0
  118. data/lib/generators/symphonia/query/query_generator.rb +37 -0
  119. data/lib/generators/symphonia/setup/setup_generator.rb +52 -0
  120. data/lib/generators/symphonia/setup/templates/404.html +26 -0
  121. data/lib/generators/symphonia/setup/templates/500.html +37 -0
  122. data/lib/generators/symphonia/setup/templates/Gemfile +18 -0
  123. data/lib/generators/symphonia/setup/templates/base_layout.html.erb +46 -0
  124. data/lib/generators/symphonia/setup/templates/design.scss +4 -0
  125. data/lib/generators/symphonia/setup/templates/settings.rb +65 -0
  126. data/lib/generators/symphonia/setup/templates/spec_helper.rb +18 -0
  127. data/lib/symphonia/action_cable/connection.rb +31 -0
  128. data/lib/symphonia/admin_constraint.rb +9 -0
  129. data/lib/symphonia/attachable.rb +35 -0
  130. data/lib/symphonia/base_controller.rb +96 -0
  131. data/lib/symphonia/bootstrap_link_render.rb +69 -0
  132. data/lib/symphonia/controller_extensions.rb +200 -0
  133. data/lib/symphonia/engine.rb +137 -0
  134. data/lib/symphonia/form_builder.rb +137 -0
  135. data/lib/symphonia/menu_manager.rb +23 -0
  136. data/lib/symphonia/model_attributes/attribute.rb +137 -0
  137. data/lib/symphonia/model_attributes.rb +102 -0
  138. data/lib/symphonia/model_filters/base.rb +82 -0
  139. data/lib/symphonia/model_filters/boolean_filter.rb +26 -0
  140. data/lib/symphonia/model_filters/date_filter.rb +81 -0
  141. data/lib/symphonia/model_filters/integer_filter.rb +18 -0
  142. data/lib/symphonia/model_filters/select_filter.rb +48 -0
  143. data/lib/symphonia/model_filters/string_filter.rb +18 -0
  144. data/lib/symphonia/model_filters.rb +10 -0
  145. data/lib/symphonia/object.rb +31 -0
  146. data/lib/symphonia/permissions.rb +93 -0
  147. data/lib/symphonia/query.rb +275 -0
  148. data/lib/symphonia/query_columns/attribute_column.rb +43 -0
  149. data/lib/symphonia/query_columns/generic_column.rb +165 -0
  150. data/lib/symphonia/query_columns.rb +8 -0
  151. data/lib/symphonia/spec_helper.rb +4 -0
  152. data/lib/symphonia/user_management.rb +58 -0
  153. data/lib/symphonia/version.rb +4 -0
  154. data/lib/symphonia.rb +20 -0
  155. data/spec/controllers/account_controller_spec.rb +90 -0
  156. data/spec/controllers/admin_controller_spec.rb +35 -0
  157. data/spec/controllers/api_controller_spec.rb +9 -0
  158. data/spec/controllers/filters_controller_spec.rb +35 -0
  159. data/spec/controllers/images_controller_spec.rb +5 -0
  160. data/spec/controllers/login_controller_spec.rb +20 -0
  161. data/spec/controllers/roles_controller_spec.rb +12 -0
  162. data/spec/controllers/users_controller_spec.rb +47 -0
  163. data/spec/factories/factories.rb +52 -0
  164. data/spec/helpers/symphonia/application_helper_spec.rb +62 -0
  165. data/spec/mailers/previews/symphonia/notifier_preview.rb +27 -0
  166. data/spec/mailers/symphonia/notifier_spec.rb +76 -0
  167. data/spec/models/attachment_spec.rb +22 -0
  168. data/spec/models/query/attribute_spec.rb +8 -0
  169. data/spec/models/query/symphonia_query_spec.rb +70 -0
  170. data/spec/models/role_spec.rb +13 -0
  171. data/spec/models/user_spec.rb +10 -0
  172. data/spec/rails_helper.rb +13 -0
  173. data/spec/requests/accounts_spec.rb +118 -0
  174. data/spec/requests/attachments_controller_spec.rb +23 -0
  175. data/spec/requests/login_spec.rb +26 -0
  176. data/spec/requests/roles_spec.rb +10 -0
  177. data/spec/requests/users_spec.rb +50 -0
  178. data/spec/spec_helper.rb +101 -0
  179. data/spec/support/common_file.txt +2 -0
  180. data/spec/support/query.rb +36 -0
  181. data/spec/support/shared.rb +62 -0
  182. data/spec/support/shared_controllers.rb +31 -0
  183. data/spec/support/stub_users.rb +32 -0
  184. data/spec/support/symphonia.jpg +0 -0
  185. data/spec/support/wait_for_ajax.rb +15 -0
  186. data/spec/version_spec.rb +5 -0
  187. data/spec/views/filters/options.html.erb_spec.rb +14 -0
  188. 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,6 @@
1
+ module Symphonia
2
+ class ApplicationMailer < ActionMailer::Base
3
+ # default from: 'symphonia@luk4s.cz'
4
+ layout 'symphonia/mailer'
5
+ end
6
+ 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,14 @@
1
+ module Symphonia
2
+ class ApplicationRecord < ::ActiveRecord::Base
3
+ self.abstract_class = true
4
+
5
+ def to_s
6
+ if respond_to?(:name)
7
+ name
8
+ else
9
+ super
10
+ end
11
+ end
12
+
13
+ end
14
+ 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,9 @@
1
+ module Symphonia
2
+ class CommonFile < Attachment
3
+ class_attribute :paperclip_options
4
+ has_attached_file :attachment
5
+
6
+ validates_attachment :attachment, presence: true, size: {in: 0..2.megabytes}
7
+ do_not_validate_attachment_file_type :attachment
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module Symphonia
2
+ class EmailPreference < Preference
3
+
4
+ end
5
+ 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,5 @@
1
+ <i class="fa fa-hand-stop-o fa-5x pull-left"></i> <%= page_header 403 %>
2
+ <p class="clearfix">
3
+ <%= t :text_access_deny %>
4
+ </p>
5
+ <%= link_to icon('back', t(:button_back)), :back, class: 'btn btn-link' %>
@@ -0,0 +1,2 @@
1
+ <%= page_header 404 %>
2
+ <%= link_to t(:button_back), :back, :class => 'fa fa-back' %>
@@ -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">&times;</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
+ &copy; 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>