ditty 0.10.2 → 0.11.1
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/Readme.md +1 -1
- data/ditty.gemspec +5 -5
- data/lib/ditty/cli.rb +1 -1
- data/lib/ditty/components/ditty.rb +3 -2
- data/lib/ditty/controllers/component_controller.rb +3 -5
- data/lib/ditty/controllers/users_controller.rb +10 -10
- data/lib/ditty/db.rb +2 -2
- data/lib/ditty/generators/project_generator.rb +3 -3
- data/lib/ditty/helpers/authentication.rb +4 -0
- data/lib/ditty/helpers/pundit.rb +2 -2
- data/lib/ditty/helpers/response.rb +6 -6
- data/lib/ditty/helpers/views.rb +9 -0
- data/lib/ditty/listener.rb +4 -1
- data/lib/ditty/models/identity.rb +4 -4
- data/lib/ditty/models/user.rb +1 -15
- data/lib/ditty/services/pagination_wrapper.rb +1 -1
- data/lib/ditty/services/settings.rb +5 -1
- data/lib/ditty/tasks/ditty.rake +26 -4
- data/lib/ditty/templates/views/index.haml.tt +26 -24
- data/lib/ditty/version.rb +1 -1
- data/views/audit_logs/index.haml +33 -31
- data/views/auth/identity.haml +2 -2
- data/views/layout.haml +7 -4
- data/views/partials/actions.haml +7 -9
- data/views/roles/index.haml +24 -22
- data/views/user_login_traits/index.haml +26 -23
- data/views/users/index.haml +32 -30
- data/views/users/profile.haml +1 -1
- metadata +18 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0ecdd202f458e55d205e3e77b295a3c8908f7d3ecaf3d894fa9ae09c62d8b4fd
|
|
4
|
+
data.tar.gz: bcc5967235a668d896cee25228130b1ab2d98761dc2fb2125d5f7f2d2912881b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 45c0c4fb7acb614ce8cbfda366908fcaee02482d9601c26fe797ff5012a7bbeff0e81897141a33ce2c3d31064529401ea0c35f194852969262b263a306760b3c
|
|
7
|
+
data.tar.gz: c471989b26228ad7a08f933e8c1c747a8f5fd9ec21fd0fc1515a496c63d98446a2a7505802d01c4110bbcb514d6876e85b0c611dc4c438750aaff4e507948f64
|
data/.travis.yml
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
sudo: false
|
|
2
2
|
language: ruby
|
|
3
3
|
rvm:
|
|
4
|
+
- 3.2
|
|
5
|
+
- 3.1
|
|
4
6
|
- 3.0
|
|
5
7
|
- 2.7
|
|
6
|
-
- 2.6
|
|
7
8
|
gemfile: Gemfile.ci
|
|
8
9
|
env:
|
|
9
10
|
matrix:
|
|
@@ -17,7 +18,7 @@ before_script:
|
|
|
17
18
|
- bundle exec rake ditty:prep
|
|
18
19
|
script:
|
|
19
20
|
- bundle exec rake
|
|
20
|
-
- bundle exec rubocop --fail-level W lib views spec
|
|
21
|
+
- bundle exec rubocop -c .rubocop.yml --fail-level W lib views spec
|
|
21
22
|
after_script:
|
|
22
23
|
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
|
23
24
|
after_success:
|
data/Readme.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://app.travis-ci.com/github/EagerELK/ditty)
|
|
2
2
|
[](https://codeclimate.com/github/EagerELK/ditty)
|
|
3
3
|
[](https://codeclimate.com/github/EagerELK/ditty/coverage)
|
|
4
4
|
[](http://inch-ci.org/github/EagerELK/ditty)
|
data/ditty.gemspec
CHANGED
|
@@ -41,13 +41,13 @@ Gem::Specification.new do |spec|
|
|
|
41
41
|
spec.add_dependency 'bcrypt', '>= 3.1'
|
|
42
42
|
spec.add_dependency 'browser', '>= 5.3'
|
|
43
43
|
spec.add_dependency 'dotenv', '>= 2'
|
|
44
|
-
spec.add_dependency 'haml', '>= 5.1.2'
|
|
44
|
+
spec.add_dependency 'haml', '~> 5.1', '>= 5.1.2' # Going to 6 creates a `undefined method capture_html` and breaks a lot of other stuff
|
|
45
45
|
spec.add_dependency 'logger', '>= 1.0'
|
|
46
46
|
spec.add_dependency 'mail', '>= 1.7'
|
|
47
47
|
spec.add_dependency 'oga', '>= 2.14'
|
|
48
|
-
spec.add_dependency 'omniauth', '
|
|
49
|
-
spec.add_dependency 'omniauth-identity', '
|
|
50
|
-
spec.add_dependency 'pundit', '
|
|
48
|
+
spec.add_dependency 'omniauth', '>= 1.0'
|
|
49
|
+
spec.add_dependency 'omniauth-identity', '>= 1.0'
|
|
50
|
+
spec.add_dependency 'pundit', '>= 2.0'
|
|
51
51
|
spec.add_dependency 'rack-contrib', '>= 2.0'
|
|
52
52
|
spec.add_dependency 'rack_csrf', '>= 2.0'
|
|
53
53
|
spec.add_dependency 'rake', '>= 13.0'
|
|
@@ -59,5 +59,5 @@ Gem::Specification.new do |spec|
|
|
|
59
59
|
spec.add_dependency 'thor', '>= 0.20'
|
|
60
60
|
spec.add_dependency 'tilt', '>= 2'
|
|
61
61
|
spec.add_dependency 'will_paginate', '>= 3.1'
|
|
62
|
-
spec.add_dependency 'wisper', '
|
|
62
|
+
spec.add_dependency 'wisper', '>= 2.0'
|
|
63
63
|
end
|
data/lib/ditty/cli.rb
CHANGED
|
@@ -66,8 +66,9 @@ module Ditty
|
|
|
66
66
|
load
|
|
67
67
|
|
|
68
68
|
sa = ::Ditty::Role.find_or_create(name: 'super_admin')
|
|
69
|
-
admin = ::Ditty::Role.find_or_create(name: 'admin') { |
|
|
70
|
-
::Ditty::Role.find_or_create(name: 'user') { |
|
|
69
|
+
admin = ::Ditty::Role.find_or_create(name: 'admin') { |rec| rec.parent = sa }
|
|
70
|
+
::Ditty::Role.find_or_create(name: 'user') { |rec| rec.parent = admin }
|
|
71
|
+
::Ditty::Role.find_or_create(name: 'anonymous')
|
|
71
72
|
end
|
|
72
73
|
end
|
|
73
74
|
|
|
@@ -39,9 +39,7 @@ module Ditty
|
|
|
39
39
|
after do
|
|
40
40
|
return if settings.environment == 'production'
|
|
41
41
|
|
|
42
|
-
if (response.successful? || response.redirection?) && @skip_verify == false
|
|
43
|
-
verify_authorized
|
|
44
|
-
end
|
|
42
|
+
verify_authorized if (response.successful? || response.redirection?) && @skip_verify == false
|
|
45
43
|
end
|
|
46
44
|
|
|
47
45
|
after '/' do
|
|
@@ -67,7 +65,7 @@ module Ditty
|
|
|
67
65
|
|
|
68
66
|
entity = settings.model_class.new(permitted_parameters(settings.model_class, :create))
|
|
69
67
|
haml :"#{view_location}/new",
|
|
70
|
-
locals: { entity: entity, title: heading(:new) },
|
|
68
|
+
locals: { entity: entity, title: heading(:new), actions: actions(action: :new) },
|
|
71
69
|
layout: layout
|
|
72
70
|
end
|
|
73
71
|
|
|
@@ -100,7 +98,7 @@ module Ditty
|
|
|
100
98
|
|
|
101
99
|
flash[:redirect_to] = "#{base_path}/#{entity.display_id}" unless flash.keep(:redirect_to)
|
|
102
100
|
haml :"#{view_location}/edit",
|
|
103
|
-
locals: { entity: entity, title: heading(:edit) },
|
|
101
|
+
locals: { entity: entity, title: heading(:edit), actions: actions(entity: entity, action: :edit) },
|
|
104
102
|
layout: layout
|
|
105
103
|
end
|
|
106
104
|
|
|
@@ -15,10 +15,10 @@ module Ditty
|
|
|
15
15
|
set track_actions: true
|
|
16
16
|
|
|
17
17
|
# New
|
|
18
|
-
get '/new' do
|
|
18
|
+
get '/new/?' do
|
|
19
19
|
authorize settings.model_class, :create
|
|
20
20
|
|
|
21
|
-
locals = { title: heading(:new), entity: User.new, identity: Identity.new }
|
|
21
|
+
locals = { title: heading(:new), entity: User.new, identity: Identity.new, actions: actions(action: :new) }
|
|
22
22
|
haml :"#{view_location}/new", locals: locals
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -60,7 +60,7 @@ module Ditty
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
# Update
|
|
63
|
-
put '/:id' do |id|
|
|
63
|
+
put '/:id/?' do |id|
|
|
64
64
|
entity = dataset.first(settings.model_class.primary_key => id)
|
|
65
65
|
halt 404 unless entity
|
|
66
66
|
authorize entity, :update
|
|
@@ -80,7 +80,7 @@ module Ditty
|
|
|
80
80
|
update_response(entity)
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
put '/:id/identity' do |id|
|
|
83
|
+
put '/:id/identity/?' do |id|
|
|
84
84
|
entity = dataset.first(settings.model_class.primary_key => id)
|
|
85
85
|
halt 404 unless entity
|
|
86
86
|
authorize entity, :update
|
|
@@ -88,13 +88,13 @@ module Ditty
|
|
|
88
88
|
identity = entity.identity.first
|
|
89
89
|
identity_params = params['identity']
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
if (current_user.super_admin? == false || current_user_id == entity.id) && identity.authenticate(identity_params['old_password']) == false
|
|
92
92
|
broadcast(:identity_update_password_failed, target: self)
|
|
93
93
|
flash[:danger] = 'Old Password didn\'t match'
|
|
94
|
-
return redirect back
|
|
94
|
+
return redirect(with_layout(params[:redirect_to] || flash[:redirect_to] || back))
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
values = permitted_parameters(Identity, :
|
|
97
|
+
values = permitted_parameters(Identity, :update)
|
|
98
98
|
identity.set values
|
|
99
99
|
if identity.valid?
|
|
100
100
|
identity.save_changes
|
|
@@ -111,7 +111,7 @@ module Ditty
|
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
# Delete
|
|
114
|
-
delete '/:id', provides: %i[html json] do |id|
|
|
114
|
+
delete '/:id/?', provides: %i[html json] do |id|
|
|
115
115
|
entity = dataset.first(settings.model_class.primary_key => id)
|
|
116
116
|
halt 404 unless entity
|
|
117
117
|
authorize entity, :delete
|
|
@@ -125,13 +125,13 @@ module Ditty
|
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
# Profile
|
|
128
|
-
get '/profile' do
|
|
128
|
+
get '/profile/?' do
|
|
129
129
|
entity = current_user
|
|
130
130
|
halt 404 unless entity
|
|
131
131
|
authorize entity, :read
|
|
132
132
|
|
|
133
133
|
flash[:redirect_to] = request.path
|
|
134
|
-
haml :"#{view_location}/profile", locals: { entity: entity, identity: entity.identity.first, title: 'My Account' }
|
|
134
|
+
haml :"#{view_location}/profile", locals: { entity: entity, identity: entity.identity.first, title: 'My Account', actions: actions(entity: entity, action: :read) }
|
|
135
135
|
end
|
|
136
136
|
end
|
|
137
137
|
end
|
data/lib/ditty/db.rb
CHANGED
|
@@ -8,7 +8,7 @@ require 'active_support/core_ext/object/blank'
|
|
|
8
8
|
pool_timeout = (ENV['DB_POOL_TIMEOUT'] || 5).to_i
|
|
9
9
|
|
|
10
10
|
if defined? DB
|
|
11
|
-
::Ditty::Services::Logger.warn 'Database connection already set up'
|
|
11
|
+
::Ditty::Services::Logger.warn '** Database connection already set up **'
|
|
12
12
|
elsif ENV['DATABASE_URL'].blank? == false
|
|
13
13
|
# Delete DATABASE_URL from the environment, so it isn't accidently
|
|
14
14
|
# passed to subprocesses. DATABASE_URL may contain passwords.
|
|
@@ -29,5 +29,5 @@ elsif ENV['DATABASE_URL'].blank? == false
|
|
|
29
29
|
Sequel::Model.plugin :update_or_create
|
|
30
30
|
Sequel::Model.plugin :validation_helpers
|
|
31
31
|
else
|
|
32
|
-
::Ditty::Services::Logger.error '
|
|
32
|
+
::Ditty::Services::Logger.error '*** NO DATABASE CONNECTION SET UP ***'
|
|
33
33
|
end
|
|
@@ -41,9 +41,9 @@ module Ditty
|
|
|
41
41
|
copy_file 'sidekiq.rb', './config/sidekiq.rb'
|
|
42
42
|
copy_file 'sidekiq.yml', './config/sidekiq.yml'
|
|
43
43
|
|
|
44
|
-
copy_file 'spec_helper.rb', './
|
|
45
|
-
copy_file '../../../spec/support/api_shared_examples.rb', './
|
|
46
|
-
copy_file '../../../spec/support/crud_shared_examples.rb', './
|
|
44
|
+
copy_file 'spec_helper.rb', './spec/spec_helper.rb'
|
|
45
|
+
copy_file '../../../spec/support/api_shared_examples.rb', './spec/support/api_shared_examples.rb'
|
|
46
|
+
copy_file '../../../spec/support/crud_shared_examples.rb', './spec/support/crud_shared_examples.rb'
|
|
47
47
|
|
|
48
48
|
template 'settings.yml.erb', './config/settings.yml'
|
|
49
49
|
end
|
|
@@ -9,6 +9,10 @@ module Ditty
|
|
|
9
9
|
return nil if current_user_id.nil?
|
|
10
10
|
|
|
11
11
|
@current_user ||= User[current_user_id]
|
|
12
|
+
rescue Sequel::DatabaseError => e
|
|
13
|
+
Services::Logger.warn "Could not fetch current user: #{e.message} / #{current_user_id}"
|
|
14
|
+
Services::Logger.debug e
|
|
15
|
+
nil
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
def current_user=(user)
|
data/lib/ditty/helpers/pundit.rb
CHANGED
|
@@ -5,7 +5,7 @@ require 'pundit'
|
|
|
5
5
|
module Ditty
|
|
6
6
|
module Helpers
|
|
7
7
|
module Pundit
|
|
8
|
-
include ::Pundit
|
|
8
|
+
include ::Pundit::Authorization
|
|
9
9
|
|
|
10
10
|
def authorize(record, query)
|
|
11
11
|
query = :"#{query}?" unless query[-1] == '?'
|
|
@@ -24,7 +24,7 @@ module Ditty
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def permitted_parameters(record, action = nil)
|
|
27
|
-
param_key = PolicyFinder.new(record).param_key
|
|
27
|
+
param_key = ::Pundit::PolicyFinder.new(record).param_key
|
|
28
28
|
policy_fields = permitted_attributes(record, action)
|
|
29
29
|
request.params.fetch(param_key, {}).select do |key, _value|
|
|
30
30
|
policy_fields.include? key.to_sym
|
|
@@ -6,10 +6,9 @@ module Ditty
|
|
|
6
6
|
module Helpers
|
|
7
7
|
module Response
|
|
8
8
|
def list_response(result, view: 'index')
|
|
9
|
+
actions = actions(action: :list)
|
|
9
10
|
respond_to do |format|
|
|
10
11
|
format.html do
|
|
11
|
-
actions = {}
|
|
12
|
-
actions["#{base_path}/new"] = "New #{heading}" if policy(settings.model_class).create?
|
|
13
12
|
haml :"#{view_location}/#{view}",
|
|
14
13
|
locals: { list: result, title: heading(:list), actions: actions },
|
|
15
14
|
layout: layout
|
|
@@ -49,15 +48,16 @@ module Ditty
|
|
|
49
48
|
end
|
|
50
49
|
end
|
|
51
50
|
|
|
52
|
-
def actions(entity
|
|
51
|
+
def actions(entity: nil, action: nil)
|
|
53
52
|
actions = {}
|
|
54
|
-
actions["#{base_path}/#{entity.display_id}/edit"] = "Edit #{heading}" if entity && policy(entity).update?
|
|
55
|
-
actions[
|
|
53
|
+
actions["#{base_path}/#{entity.display_id}/edit"] = "Edit #{heading}" if entity && policy(entity).update? && action != :edit
|
|
54
|
+
actions[base_path] = "List #{heading(:list)}" if policy(entity || settings.model_class).list? && action != :list
|
|
55
|
+
actions["#{base_path}/new"] = "New #{heading}" if policy(entity || settings.model_class).create? && action != :new
|
|
56
56
|
actions
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def read_response(entity)
|
|
60
|
-
actions = actions(entity)
|
|
60
|
+
actions = actions(entity: entity, action: :read)
|
|
61
61
|
respond_to do |format|
|
|
62
62
|
format.html do
|
|
63
63
|
title = heading(:read) + (entity.respond_to?(:name) ? ": #{entity.name}" : '')
|
data/lib/ditty/helpers/views.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'ditty/services/pagination_wrapper'
|
|
4
|
+
require 'digest/sha2'
|
|
4
5
|
|
|
5
6
|
module Ditty
|
|
6
7
|
module Helpers
|
|
@@ -156,6 +157,14 @@ module Ditty
|
|
|
156
157
|
|
|
157
158
|
'fa-sort-down'
|
|
158
159
|
end
|
|
160
|
+
|
|
161
|
+
def static_headers(view)
|
|
162
|
+
view_path = "views/#{view}.haml"
|
|
163
|
+
return unless File.exist?(view_path)
|
|
164
|
+
|
|
165
|
+
last_modified File.mtime(view_path)
|
|
166
|
+
etag Digest::SHA2.hexdigest(File.read(view_path))
|
|
167
|
+
end
|
|
159
168
|
end
|
|
160
169
|
end
|
|
161
170
|
end
|
data/lib/ditty/listener.rb
CHANGED
|
@@ -70,11 +70,14 @@ module Ditty
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def log_action(values)
|
|
73
|
-
|
|
73
|
+
require 'ditty/models/audit_log'
|
|
74
|
+
|
|
75
|
+
values[:user] ||= values[:target].current_user if values[:target] && values[:target].respond_to?(:current_user)
|
|
74
76
|
@mutex.synchronize { ::Ditty::AuditLog.create values }
|
|
75
77
|
end
|
|
76
78
|
|
|
77
79
|
def user_traits(target)
|
|
80
|
+
return {} unless target.respond_to?(:current_user) && target.respond_to?(:browser)
|
|
78
81
|
{
|
|
79
82
|
user_id: target.current_user&.id,
|
|
80
83
|
platform: target.browser.platform.name,
|
|
@@ -21,9 +21,9 @@ module Ditty
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def authenticate(unencrypted)
|
|
24
|
-
return false if crypted_password.blank?
|
|
24
|
+
return false if crypted_password.blank? || ::BCrypt::Password.new(crypted_password) != unencrypted
|
|
25
25
|
|
|
26
|
-
self
|
|
26
|
+
self
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def persisted?
|
|
@@ -69,7 +69,7 @@ module Ditty
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# Callbacks
|
|
72
|
-
def
|
|
72
|
+
def before_validation
|
|
73
73
|
super
|
|
74
74
|
encrypt_password unless password == '' || password.nil?
|
|
75
75
|
end
|
|
@@ -81,7 +81,7 @@ module Ditty
|
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
def password_required
|
|
84
|
-
crypted_password.blank? ||
|
|
84
|
+
crypted_password.blank? || password.present?
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
end
|
data/lib/ditty/models/user.rb
CHANGED
|
@@ -4,6 +4,7 @@ require 'ditty/models/base'
|
|
|
4
4
|
require 'digest/md5'
|
|
5
5
|
require 'active_support'
|
|
6
6
|
require 'active_support/core_ext/object/blank'
|
|
7
|
+
require 'ditty/models/role'
|
|
7
8
|
|
|
8
9
|
# Why not store this in Elasticsearch?
|
|
9
10
|
module Ditty
|
|
@@ -88,20 +89,5 @@ module Ditty
|
|
|
88
89
|
def display_name
|
|
89
90
|
name || username
|
|
90
91
|
end
|
|
91
|
-
|
|
92
|
-
class << self
|
|
93
|
-
def anonymous_user
|
|
94
|
-
role = ::Ditty::Role.find_or_create(name: 'anonymous')
|
|
95
|
-
::Ditty::User.where(roles: role).first
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def create_anonymous_user(email = 'anonymous@ditty.io')
|
|
99
|
-
return if anonymous_user
|
|
100
|
-
|
|
101
|
-
user = ::Ditty::User.find_or_create(email: email)
|
|
102
|
-
user.remove_role ::Ditty::Role.find_or_create(name: 'user')
|
|
103
|
-
user.add_role ::Ditty::Role.find_or_create(name: 'anonymous') unless user.role?('anonymous')
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
92
|
end
|
|
107
93
|
end
|
|
@@ -75,7 +75,7 @@ module Ditty
|
|
|
75
75
|
else
|
|
76
76
|
return (0..0) if list.current_page > page_count
|
|
77
77
|
|
|
78
|
-
a = 1 + (list.current_page - 1) * page_size
|
|
78
|
+
a = 1 + ((list.current_page - 1) * page_size)
|
|
79
79
|
b = a + page_size - 1
|
|
80
80
|
b = pagination_record_count if b > pagination_record_count
|
|
81
81
|
a..b
|
|
@@ -55,7 +55,11 @@ module Ditty
|
|
|
55
55
|
attr_writer :values
|
|
56
56
|
|
|
57
57
|
def read(filename)
|
|
58
|
-
base =
|
|
58
|
+
base = if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
|
|
59
|
+
::YAML.safe_load(ERB.new(File.read(filename)).result, permitted_classes: [Symbol])
|
|
60
|
+
else
|
|
61
|
+
::YAML.safe_load(ERB.new(File.read(filename)).result, [Symbol])
|
|
62
|
+
end.deep_symbolize_keys
|
|
59
63
|
base.deep_merge!(base[ENV['APP_ENV'].to_sym]) unless ENV['APP_ENV'].nil? || base[ENV['APP_ENV'].to_sym].nil?
|
|
60
64
|
base
|
|
61
65
|
end
|
data/lib/ditty/tasks/ditty.rake
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
3
5
|
namespace :ditty do
|
|
4
6
|
desc 'Run the ditty console'
|
|
5
7
|
task :console do
|
|
@@ -34,17 +36,37 @@ namespace :ditty do
|
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
namespace :prep do
|
|
39
|
+
desc 'Create a user'
|
|
40
|
+
task :user, [:email, :password] do |_t, args|
|
|
41
|
+
require 'ditty/listener'
|
|
42
|
+
|
|
43
|
+
identity = Ditty::Identity.new(username: args[:email], password: args[:password])
|
|
44
|
+
identity.password_confirmation = identity.password
|
|
45
|
+
user = Ditty::User.new(email: identity.username)
|
|
46
|
+
begin
|
|
47
|
+
identity.valid?
|
|
48
|
+
DB.transaction do
|
|
49
|
+
user.save_changes
|
|
50
|
+
user.add_identity identity
|
|
51
|
+
Ditty::Listener.new.user_register(target: self, values: { user: user })
|
|
52
|
+
end
|
|
53
|
+
rescue StandardError => e
|
|
54
|
+
Ditty::Services::Logger.error "Could not regster super user: #{e.message}"
|
|
55
|
+
Ditty::Services::Logger.debug e
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
37
59
|
desc 'Check that the required Ditty folders are present'
|
|
38
60
|
task :folders do
|
|
39
61
|
puts 'Prepare the Ditty folders'
|
|
40
|
-
|
|
41
|
-
|
|
62
|
+
FileUtils.mkdir_p 'pids'
|
|
63
|
+
FileUtils.mkdir_p 'logs'
|
|
42
64
|
end
|
|
43
65
|
|
|
44
66
|
desc 'Check that the public folder is present and populated'
|
|
45
67
|
task :public do
|
|
46
68
|
puts 'Preparing the Ditty public folder'
|
|
47
|
-
|
|
69
|
+
FileUtils.mkdir_p 'public'
|
|
48
70
|
::Ditty::Components.public_folder.each do |path|
|
|
49
71
|
puts "Checking #{path}"
|
|
50
72
|
path = "#{path}/."
|
|
@@ -55,7 +77,7 @@ namespace :ditty do
|
|
|
55
77
|
desc 'Check that the migrations folder is present and populated'
|
|
56
78
|
task :migrations do
|
|
57
79
|
puts 'Preparing the Ditty migrations folder'
|
|
58
|
-
|
|
80
|
+
FileUtils.mkdir_p 'migrations'
|
|
59
81
|
::Ditty::Components.migrations.each do |path|
|
|
60
82
|
path = "#{path}/."
|
|
61
83
|
FileUtils.cp_r path, 'migrations' unless File.expand_path(path).eql? File.expand_path('migrations')
|
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
.row
|
|
2
2
|
.col-md-12
|
|
3
3
|
= haml :'partials/search'
|
|
4
|
-
|
|
5
|
-
%
|
|
6
|
-
%
|
|
7
|
-
<%- columns.each do |col| -%>
|
|
8
|
-
%th <%= col.to_s.titleize %>
|
|
9
|
-
<%- end %>
|
|
10
|
-
%th
|
|
11
|
-
%tbody
|
|
12
|
-
- if list.count > 0
|
|
13
|
-
- list.all.each do |entity|
|
|
14
|
-
%tr
|
|
15
|
-
<%- columns.each do |col| -%>
|
|
16
|
-
%td= entity.<%= col %>
|
|
17
|
-
<%- end %>
|
|
18
|
-
%td
|
|
19
|
-
%a{ href: "#{base_path}/#{entity.display_id}", title: 'Show' }
|
|
20
|
-
%i.fa.fa-search
|
|
21
|
-
- if policy(entity).update?
|
|
22
|
-
%a{ href: "#{base_path}/#{entity.display_id}/edit", title: 'Edit' }
|
|
23
|
-
%i.fa.fa-edit
|
|
24
|
-
- else
|
|
4
|
+
.card.card-default.shadow.table-responsive
|
|
5
|
+
%table.table.table-striped.table-bordered.table-hover.mb-0
|
|
6
|
+
%thead.thead-dark
|
|
25
7
|
%tr
|
|
26
|
-
|
|
8
|
+
<%- columns.each do |col| -%>
|
|
9
|
+
%th <%= col.to_s.titleize %>
|
|
10
|
+
<%- end %>
|
|
11
|
+
%th
|
|
12
|
+
%tbody
|
|
13
|
+
- if list.count > 0
|
|
14
|
+
- list.all.each do |entity|
|
|
15
|
+
%tr
|
|
16
|
+
<%- columns.each do |col| -%>
|
|
17
|
+
%td= entity.<%= col %>
|
|
18
|
+
<%- end %>
|
|
19
|
+
%td
|
|
20
|
+
%a{ href: "#{base_path}/#{entity.display_id}", title: 'Show' }
|
|
21
|
+
%i.fa.fa-search
|
|
22
|
+
- if policy(entity).update?
|
|
23
|
+
%a{ href: "#{base_path}/#{entity.display_id}/edit", title: 'Edit' }
|
|
24
|
+
%i.fa.fa-edit
|
|
25
|
+
- else
|
|
26
|
+
%tr
|
|
27
|
+
%td.text-center{ colspan: <%= columns.count + 1 %> } No <%= model_name.pluralize %>
|
|
27
28
|
|
|
28
|
-
- if list.count > 0
|
|
29
|
-
|
|
29
|
+
- if list.count > 0
|
|
30
|
+
.card-body
|
|
31
|
+
= pagination(list, base_path)
|
data/lib/ditty/version.rb
CHANGED
data/views/audit_logs/index.haml
CHANGED
|
@@ -1,36 +1,38 @@
|
|
|
1
1
|
.row
|
|
2
2
|
.col-md-12
|
|
3
3
|
= haml :'partials/search'
|
|
4
|
-
|
|
5
|
-
%
|
|
6
|
-
%
|
|
7
|
-
%th= "User #{sort_ui(:user)}"
|
|
8
|
-
%th= "Action #{sort_ui(:action)}"
|
|
9
|
-
%th= "Details #{sort_ui(:details)}"
|
|
10
|
-
%th= "IP Address #{sort_ui(:ip_address)}"
|
|
11
|
-
%th= "Browser #{sort_ui(:browser)}"
|
|
12
|
-
%th= "Device #{sort_ui(:device)}"
|
|
13
|
-
%th= "Platform #{sort_ui(:platform)}"
|
|
14
|
-
%th= "Created At #{sort_ui(:created_at)}"
|
|
15
|
-
%tbody
|
|
16
|
-
- if list.count > 0
|
|
17
|
-
- list.all.each do |entity|
|
|
18
|
-
%tr
|
|
19
|
-
%td
|
|
20
|
-
-if entity.user
|
|
21
|
-
%a{ href: "#{settings.map_path}/users/#{entity.user.id}" }= entity.user.email
|
|
22
|
-
-else
|
|
23
|
-
None
|
|
24
|
-
%td= entity.action
|
|
25
|
-
%td= entity.details
|
|
26
|
-
%td= entity.ip_address || 'Unknown'
|
|
27
|
-
%td= entity.browser || 'Unknown'
|
|
28
|
-
%td= entity.device || 'Unknown'
|
|
29
|
-
%td= entity.platform || 'Unknown'
|
|
30
|
-
%td= entity.created_at&.strftime('%Y-%m-%d %H:%M:%S') || 'Unknown'
|
|
31
|
-
- else
|
|
4
|
+
.card.card-default.shadow.table-responsive
|
|
5
|
+
%table.table.table-striped.table-bordered.table-hover.mb-0
|
|
6
|
+
%thead.thead-dark
|
|
32
7
|
%tr
|
|
33
|
-
%
|
|
8
|
+
%th= "User #{sort_ui(:user)}"
|
|
9
|
+
%th= "Action #{sort_ui(:action)}"
|
|
10
|
+
%th= "Details #{sort_ui(:details)}"
|
|
11
|
+
%th= "IP Address #{sort_ui(:ip_address)}"
|
|
12
|
+
%th= "Browser #{sort_ui(:browser)}"
|
|
13
|
+
%th= "Device #{sort_ui(:device)}"
|
|
14
|
+
%th= "Platform #{sort_ui(:platform)}"
|
|
15
|
+
%th= "Created At #{sort_ui(:created_at)}"
|
|
16
|
+
%tbody
|
|
17
|
+
- if list.count > 0
|
|
18
|
+
- list.all.each do |entity|
|
|
19
|
+
%tr
|
|
20
|
+
%td
|
|
21
|
+
-if entity.user
|
|
22
|
+
%a{ href: "#{settings.map_path}/users/#{entity.user.id}" }= entity.user.email
|
|
23
|
+
-else
|
|
24
|
+
None
|
|
25
|
+
%td= entity.action
|
|
26
|
+
%td= entity.details
|
|
27
|
+
%td= entity.ip_address || 'Unknown'
|
|
28
|
+
%td= entity.browser || 'Unknown'
|
|
29
|
+
%td= entity.device || 'Unknown'
|
|
30
|
+
%td= entity.platform || 'Unknown'
|
|
31
|
+
%td= entity.created_at&.strftime('%Y-%m-%d %H:%M:%S') || 'Unknown'
|
|
32
|
+
- else
|
|
33
|
+
%tr
|
|
34
|
+
%td.text-center{ colspan: 4 } No records
|
|
34
35
|
|
|
35
|
-
- if list.count > 0
|
|
36
|
-
|
|
36
|
+
- if list.count > 0
|
|
37
|
+
.card-body
|
|
38
|
+
= pagination(list, base_path)
|
data/views/auth/identity.haml
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
= form_tag("#{settings.map_path}/auth/identity/callback", attributes: { class: 'user' }) do
|
|
2
2
|
.form-group
|
|
3
|
-
%input.form-control.form-control-user{ name: 'username', type: 'email', 'aria-describedby': 'emailHelp', placeholder: 'Enter Email Address...' }
|
|
3
|
+
%input.form-control.form-control-user{ name: 'username', type: 'email', 'aria-describedby': 'emailHelp', placeholder: 'Enter Email Address...', required: true }
|
|
4
4
|
.form-group
|
|
5
|
-
%input.form-control.form-control-user{ name: 'password', type: 'password', placeholder: 'Password' }
|
|
5
|
+
%input.form-control.form-control-user{ name: 'password', type: 'password', placeholder: 'Password', required: true }
|
|
6
6
|
/ .form-group
|
|
7
7
|
/ .custom-control.custom-checkbox.small
|
|
8
8
|
/ <input type="checkbox" class="custom-control-input" id="customCheck">
|
data/views/layout.haml
CHANGED
|
@@ -45,11 +45,14 @@
|
|
|
45
45
|
|
|
46
46
|
#content-wrapper.d-flex.flex-column
|
|
47
47
|
#content
|
|
48
|
-
= haml :'partials/topbar'
|
|
48
|
+
= haml :'partials/topbar', locals: { title: (defined?(title) ? title : nil) }
|
|
49
49
|
.container-fluid
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
- if (defined?(hide_title).nil? || hide_title == false) && defined?(title)
|
|
51
|
+
.row.mb-2
|
|
52
|
+
.col-md-9.my-auto
|
|
53
|
+
%h1.text-dark= title
|
|
54
|
+
.col.md-3.text-right.my-auto
|
|
55
|
+
= haml :'partials/actions', locals: { actions: defined?(actions) ? actions : {} }
|
|
53
56
|
= haml :'partials/notifications'
|
|
54
57
|
|
|
55
58
|
= yield
|
data/views/partials/actions.haml
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
- if defined?(actions)
|
|
1
|
+
- if defined?(actions) && actions != nil
|
|
2
2
|
- if actions.count > 1
|
|
3
3
|
- link, text = actions.shift
|
|
4
4
|
.btn-group.text-right
|
|
5
5
|
%a.btn.btn-primary{ href: link }= text
|
|
6
|
-
%button.btn.btn-primary.dropdown-toggle{ type: 'button', id: 'actions-toggle', data: { toggle: 'dropdown' } }
|
|
6
|
+
%button.btn.btn-primary.dropdown-toggle{ type: 'button', id: 'actions-toggle', data: { toggle: 'dropdown' }, 'aria-haspopup': 'true', 'aria-expanded': 'false' }
|
|
7
7
|
%span.caret
|
|
8
8
|
%span.sr-only Toggle Dropdown
|
|
9
|
-
|
|
10
|
-
-actions.each do |k, v|
|
|
11
|
-
%
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-actions.each do |k, v|
|
|
15
|
-
%a.btn.btn-primary{ href: k }= v
|
|
9
|
+
.dropdown-menu
|
|
10
|
+
- actions.each do |k, v|
|
|
11
|
+
%a.dropdown-item{ href: k }= v
|
|
12
|
+
- elsif actions.count == 1
|
|
13
|
+
%a.btn.btn-primary{ href: actions.keys.first }= actions.values.first
|
data/views/roles/index.haml
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
.row
|
|
2
2
|
.col-md-12
|
|
3
3
|
= haml :'partials/search'
|
|
4
|
-
|
|
5
|
-
%
|
|
6
|
-
%
|
|
7
|
-
%th= "Name#{sort_ui(:name)}"
|
|
8
|
-
%th Parent
|
|
9
|
-
%th
|
|
10
|
-
%tbody
|
|
11
|
-
- if list.count > 0
|
|
12
|
-
- list.all.each do |entity|
|
|
13
|
-
%tr
|
|
14
|
-
%td
|
|
15
|
-
%a{ href: "#{base_path}/#{entity.display_id}" }= entity.name
|
|
16
|
-
%td
|
|
17
|
-
%a{ href: "#{base_path}/#{entity.parent_id}" }= entity.parent&.name || '(None)'
|
|
18
|
-
%td
|
|
19
|
-
- if policy(entity).update?
|
|
20
|
-
%a{ href: "#{base_path}/#{entity.display_id}/edit", title: 'Edit' }
|
|
21
|
-
%i.fa.fa-edit
|
|
22
|
-
- else
|
|
4
|
+
.card.card-default.shadow.table-responsive
|
|
5
|
+
%table.table.table-striped.table-bordered.table-hover.mb-0
|
|
6
|
+
%thead.thead-dark
|
|
23
7
|
%tr
|
|
24
|
-
%
|
|
8
|
+
%th= "Name#{sort_ui(:name)}"
|
|
9
|
+
%th Parent
|
|
10
|
+
%th
|
|
11
|
+
%tbody
|
|
12
|
+
- if list.count > 0
|
|
13
|
+
- list.all.each do |entity|
|
|
14
|
+
%tr
|
|
15
|
+
%td
|
|
16
|
+
%a{ href: "#{base_path}/#{entity.display_id}" }= entity.name
|
|
17
|
+
%td
|
|
18
|
+
%a{ href: "#{base_path}/#{entity.parent_id}" }= entity.parent&.name || '(None)'
|
|
19
|
+
%td
|
|
20
|
+
- if policy(entity).update?
|
|
21
|
+
%a{ href: "#{base_path}/#{entity.display_id}/edit", title: 'Edit' }
|
|
22
|
+
%i.fa.fa-edit
|
|
23
|
+
- else
|
|
24
|
+
%tr
|
|
25
|
+
%td.text-center{ colspan: 3 } No Roles
|
|
25
26
|
|
|
26
|
-
- if list.count > 0
|
|
27
|
-
|
|
27
|
+
- if list.count > 0
|
|
28
|
+
.card-body
|
|
29
|
+
= pagination(list, base_path)
|
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
.row
|
|
2
2
|
.col-md-12
|
|
3
3
|
= haml :'partials/search'
|
|
4
|
-
|
|
5
|
-
%
|
|
6
|
-
%
|
|
7
|
-
%th= "User #{sort_ui(:user_id)}"
|
|
8
|
-
%th= "IP Address #{sort_ui(:ip_address)}"
|
|
9
|
-
%th= "Device #{sort_ui(:device)}"
|
|
10
|
-
%th= "Platform #{sort_ui(:platform)}"
|
|
11
|
-
%th= "Browser #{sort_ui(:browser)}"
|
|
12
|
-
%th= "Last Seen #{sort_ui(:updated_at)}"
|
|
13
|
-
%tbody
|
|
14
|
-
- if list.count.positive?
|
|
15
|
-
- list.all.each do |entity|
|
|
16
|
-
%tr
|
|
17
|
-
%td= entity.user&.email || 'Unknown'
|
|
18
|
-
%td
|
|
19
|
-
%a{ href: "#{base_path}/#{entity.display_id}" }= entity.ip_address || 'Unknown'
|
|
20
|
-
%td= entity.device || 'Unknown'
|
|
21
|
-
%td= entity.platform || 'Unknown'
|
|
22
|
-
%td= entity.browser || 'Unknown'
|
|
23
|
-
%td= entity.updated_at
|
|
24
|
-
- else
|
|
4
|
+
.card.card-default.shadow.table-responsive
|
|
5
|
+
%table.table.table-striped.table-bordered.table-hover.mb-0
|
|
6
|
+
%thead.thead-dark
|
|
25
7
|
%tr
|
|
26
|
-
%
|
|
8
|
+
%th= "User #{sort_ui(:user_id)}"
|
|
9
|
+
%th= "IP Address #{sort_ui(:ip_address)}"
|
|
10
|
+
%th= "Device #{sort_ui(:device)}"
|
|
11
|
+
%th= "Platform #{sort_ui(:platform)}"
|
|
12
|
+
%th= "Browser #{sort_ui(:browser)}"
|
|
13
|
+
%th= "Last Seen #{sort_ui(:updated_at)}"
|
|
14
|
+
%tbody
|
|
15
|
+
- if list.count.positive?
|
|
16
|
+
- list.all.each do |entity|
|
|
17
|
+
%tr
|
|
18
|
+
%td= entity.user&.email || 'Unknown'
|
|
19
|
+
%td
|
|
20
|
+
%a{ href: "#{base_path}/#{entity.display_id}" }= entity.ip_address || 'Unknown'
|
|
21
|
+
%td= entity.device || 'Unknown'
|
|
22
|
+
%td= entity.platform || 'Unknown'
|
|
23
|
+
%td= entity.browser || 'Unknown'
|
|
24
|
+
%td= entity.updated_at
|
|
25
|
+
- else
|
|
26
|
+
%tr
|
|
27
|
+
%td.text-center{ colspan: 6 } No records
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
- if list.count > 0
|
|
30
|
+
.card-body
|
|
31
|
+
= pagination(list, base_path)
|
data/views/users/index.haml
CHANGED
|
@@ -1,35 +1,37 @@
|
|
|
1
1
|
.row
|
|
2
2
|
.col-md-12
|
|
3
3
|
= haml :'partials/search'
|
|
4
|
-
|
|
5
|
-
%
|
|
6
|
-
%
|
|
7
|
-
%th= "Email #{sort_ui(:email)}"
|
|
8
|
-
%th= "Name #{sort_ui(:name)}"
|
|
9
|
-
%th= "Surname #{sort_ui(:surname)}"
|
|
10
|
-
%th Roles
|
|
11
|
-
%th= "Signed Up #{sort_ui(:created_at)}"
|
|
12
|
-
%th
|
|
13
|
-
%tbody
|
|
14
|
-
- if list.count > 0
|
|
15
|
-
- list.all.each do |entity|
|
|
16
|
-
%tr
|
|
17
|
-
%td
|
|
18
|
-
- if policy(entity).read?
|
|
19
|
-
%a{ href: "#{base_path}/#{entity.display_id}" }= entity.email
|
|
20
|
-
- else
|
|
21
|
-
= entity.email
|
|
22
|
-
%td= entity.name
|
|
23
|
-
%td= entity.surname
|
|
24
|
-
%td= entity.all_roles.map(&:name).map(&:titlecase).join(', ')
|
|
25
|
-
%td= entity.created_at.strftime('%Y-%m-%d')
|
|
26
|
-
%td
|
|
27
|
-
- if policy(entity).update?
|
|
28
|
-
%a{ href: "#{base_path}/#{entity.display_id}/edit", title: 'Edit' }
|
|
29
|
-
%i.fa.fa-edit
|
|
30
|
-
- else
|
|
4
|
+
.card.card-default.shadow.table-responsive
|
|
5
|
+
%table.table.table-striped.table-bordered.table-hover.mb-0
|
|
6
|
+
%thead.thead-dark
|
|
31
7
|
%tr
|
|
32
|
-
%
|
|
8
|
+
%th= "Email #{sort_ui(:email)}"
|
|
9
|
+
%th= "Name #{sort_ui(:name)}"
|
|
10
|
+
%th= "Surname #{sort_ui(:surname)}"
|
|
11
|
+
%th Roles
|
|
12
|
+
%th= "Signed Up #{sort_ui(:created_at)}"
|
|
13
|
+
%th
|
|
14
|
+
%tbody
|
|
15
|
+
- if list.count > 0
|
|
16
|
+
- list.all.each do |entity|
|
|
17
|
+
%tr
|
|
18
|
+
%td
|
|
19
|
+
- if policy(entity).read?
|
|
20
|
+
%a{ href: "#{base_path}/#{entity.display_id}" }= entity.email
|
|
21
|
+
- else
|
|
22
|
+
= entity.email
|
|
23
|
+
%td= entity.name
|
|
24
|
+
%td= entity.surname
|
|
25
|
+
%td= entity.all_roles.map(&:name).map(&:titlecase).join(', ')
|
|
26
|
+
%td= entity.created_at.strftime('%Y-%m-%d')
|
|
27
|
+
%td
|
|
28
|
+
- if policy(entity).update?
|
|
29
|
+
%a{ href: "#{base_path}/#{entity.display_id}/edit", title: 'Edit' }
|
|
30
|
+
%i.fa.fa-edit
|
|
31
|
+
- else
|
|
32
|
+
%tr
|
|
33
|
+
%td.text-center{ colspan: 6 } No records
|
|
33
34
|
|
|
34
|
-
- if list.count > 0
|
|
35
|
-
|
|
35
|
+
- if list.count > 0
|
|
36
|
+
.card-body
|
|
37
|
+
= pagination(list, base_path)
|
data/views/users/profile.haml
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
.card-body
|
|
38
38
|
%h4.card-title Change Password
|
|
39
39
|
= edit_form_tag("#{base_path}/#{entity.display_id}/identity") do
|
|
40
|
-
- if current_user.super_admin? == false
|
|
40
|
+
- if current_user.super_admin? == false || current_user_id == entity.id
|
|
41
41
|
= form_control(:old_password, identity, type: 'password', placeholder: 'Your current password', value: '')
|
|
42
42
|
= form_control(:password, identity, type: 'password', placeholder: 'Your new password')
|
|
43
43
|
= form_control(:password_confirmation, identity, type: 'password', label: 'Confirm Password', placeholder: 'Confirm your password')
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ditty
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jurgens du Toit
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-01-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -294,6 +294,9 @@ dependencies:
|
|
|
294
294
|
name: haml
|
|
295
295
|
requirement: !ruby/object:Gem::Requirement
|
|
296
296
|
requirements:
|
|
297
|
+
- - "~>"
|
|
298
|
+
- !ruby/object:Gem::Version
|
|
299
|
+
version: '5.1'
|
|
297
300
|
- - ">="
|
|
298
301
|
- !ruby/object:Gem::Version
|
|
299
302
|
version: 5.1.2
|
|
@@ -301,6 +304,9 @@ dependencies:
|
|
|
301
304
|
prerelease: false
|
|
302
305
|
version_requirements: !ruby/object:Gem::Requirement
|
|
303
306
|
requirements:
|
|
307
|
+
- - "~>"
|
|
308
|
+
- !ruby/object:Gem::Version
|
|
309
|
+
version: '5.1'
|
|
304
310
|
- - ">="
|
|
305
311
|
- !ruby/object:Gem::Version
|
|
306
312
|
version: 5.1.2
|
|
@@ -350,44 +356,44 @@ dependencies:
|
|
|
350
356
|
name: omniauth
|
|
351
357
|
requirement: !ruby/object:Gem::Requirement
|
|
352
358
|
requirements:
|
|
353
|
-
- - "
|
|
359
|
+
- - ">="
|
|
354
360
|
- !ruby/object:Gem::Version
|
|
355
361
|
version: '1.0'
|
|
356
362
|
type: :runtime
|
|
357
363
|
prerelease: false
|
|
358
364
|
version_requirements: !ruby/object:Gem::Requirement
|
|
359
365
|
requirements:
|
|
360
|
-
- - "
|
|
366
|
+
- - ">="
|
|
361
367
|
- !ruby/object:Gem::Version
|
|
362
368
|
version: '1.0'
|
|
363
369
|
- !ruby/object:Gem::Dependency
|
|
364
370
|
name: omniauth-identity
|
|
365
371
|
requirement: !ruby/object:Gem::Requirement
|
|
366
372
|
requirements:
|
|
367
|
-
- - "
|
|
373
|
+
- - ">="
|
|
368
374
|
- !ruby/object:Gem::Version
|
|
369
375
|
version: '1.0'
|
|
370
376
|
type: :runtime
|
|
371
377
|
prerelease: false
|
|
372
378
|
version_requirements: !ruby/object:Gem::Requirement
|
|
373
379
|
requirements:
|
|
374
|
-
- - "
|
|
380
|
+
- - ">="
|
|
375
381
|
- !ruby/object:Gem::Version
|
|
376
382
|
version: '1.0'
|
|
377
383
|
- !ruby/object:Gem::Dependency
|
|
378
384
|
name: pundit
|
|
379
385
|
requirement: !ruby/object:Gem::Requirement
|
|
380
386
|
requirements:
|
|
381
|
-
- - "
|
|
387
|
+
- - ">="
|
|
382
388
|
- !ruby/object:Gem::Version
|
|
383
|
-
version: '
|
|
389
|
+
version: '2.0'
|
|
384
390
|
type: :runtime
|
|
385
391
|
prerelease: false
|
|
386
392
|
version_requirements: !ruby/object:Gem::Requirement
|
|
387
393
|
requirements:
|
|
388
|
-
- - "
|
|
394
|
+
- - ">="
|
|
389
395
|
- !ruby/object:Gem::Version
|
|
390
|
-
version: '
|
|
396
|
+
version: '2.0'
|
|
391
397
|
- !ruby/object:Gem::Dependency
|
|
392
398
|
name: rack-contrib
|
|
393
399
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -546,14 +552,14 @@ dependencies:
|
|
|
546
552
|
name: wisper
|
|
547
553
|
requirement: !ruby/object:Gem::Requirement
|
|
548
554
|
requirements:
|
|
549
|
-
- - "
|
|
555
|
+
- - ">="
|
|
550
556
|
- !ruby/object:Gem::Version
|
|
551
557
|
version: '2.0'
|
|
552
558
|
type: :runtime
|
|
553
559
|
prerelease: false
|
|
554
560
|
version_requirements: !ruby/object:Gem::Requirement
|
|
555
561
|
requirements:
|
|
556
|
-
- - "
|
|
562
|
+
- - ">="
|
|
557
563
|
- !ruby/object:Gem::Version
|
|
558
564
|
version: '2.0'
|
|
559
565
|
description: Sinatra Based Application Framework
|