punk 0.1.2 → 0.3.2
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/.editorconfig +9 -0
- data/.github/workflows/ship.yml +3 -1
- data/.github/workflows/test.yml +26 -1
- data/.rdoc_options +23 -0
- data/.rgignore +1 -0
- data/.rspec +2 -0
- data/Gemfile +7 -8
- data/Gemfile.lock +28 -41
- data/README.md +7 -1
- data/Rakefile +0 -1
- data/VERSION +1 -1
- data/app/migrations/001_lets_punk.rb +3 -0
- data/app/routes/hello.rb +4 -0
- data/env/.gitignore +3 -0
- data/env/spec/test.sh +3 -0
- data/lib/punk/actions/.keep +0 -0
- data/lib/punk/actions/groups/list.rb +24 -0
- data/lib/punk/actions/sessions/clear.rb +21 -0
- data/lib/punk/actions/sessions/create.rb +64 -0
- data/lib/punk/actions/sessions/list.rb +18 -0
- data/lib/punk/actions/sessions/verify.rb +24 -0
- data/lib/punk/actions/tenants/list.rb +18 -0
- data/lib/punk/actions/users/list_group.rb +18 -0
- data/lib/punk/actions/users/list_tenant.rb +18 -0
- data/lib/punk/actions/users/show.rb +18 -0
- data/lib/punk/commands/list.rb +12 -6
- data/lib/punk/config/defaults.json +3 -0
- data/lib/punk/config/schema.json +3 -0
- data/lib/punk/core/app.rb +4 -6
- data/lib/punk/core/commander.rb +12 -7
- data/lib/punk/core/exec.rb +2 -0
- data/lib/punk/core/load.rb +0 -1
- data/lib/punk/framework/command.rb +5 -1
- data/lib/punk/framework/plugins/validation.rb +0 -14
- data/lib/punk/helpers/loggable.rb +1 -1
- data/lib/punk/migrations/001_punk.rb +103 -0
- data/lib/punk/models/.keep +0 -0
- data/lib/punk/models/group.rb +20 -0
- data/lib/punk/models/group_user_metadata.rb +17 -0
- data/lib/punk/models/identity.rb +29 -0
- data/lib/punk/models/session.rb +89 -0
- data/lib/punk/models/tenant.rb +19 -0
- data/lib/punk/models/tenant_user_metadata.rb +17 -0
- data/lib/punk/models/user.rb +31 -0
- data/lib/punk/routes/groups.rb +31 -0
- data/lib/punk/routes/plivo.rb +4 -0
- data/lib/punk/routes/sessions.rb +108 -0
- data/lib/punk/routes/swagger.rb +9 -0
- data/lib/punk/routes/tenants.rb +29 -0
- data/lib/punk/routes/users.rb +36 -0
- data/lib/punk/services/.keep +0 -0
- data/lib/punk/services/challenge_claim.rb +46 -0
- data/lib/punk/services/create_identities.rb +25 -0
- data/lib/punk/services/generate_swagger.rb +25 -0
- data/lib/punk/services/prove_claim.rb +29 -0
- data/lib/punk/services/secret.rb +9 -0
- data/lib/punk/templates/groups/list.jbuilder +7 -0
- data/lib/punk/templates/plivo.slim +16 -0
- data/lib/punk/templates/sessions/list.jbuilder +6 -0
- data/lib/punk/templates/sessions/pending.jbuilder +4 -0
- data/lib/punk/templates/tenants/list.jbuilder +7 -0
- data/lib/punk/templates/tenants/list.slim +8 -0
- data/lib/punk/templates/users/list.jbuilder +7 -0
- data/lib/punk/templates/users/list.rcsv +4 -0
- data/lib/punk/templates/users/show.jbuilder +5 -0
- data/lib/punk/views/groups/list.rb +22 -0
- data/lib/punk/views/plivo_store.rb +15 -0
- data/lib/punk/views/sessions/list.rb +22 -0
- data/lib/punk/views/sessions/pending.rb +28 -0
- data/lib/punk/views/tenants/list.rb +22 -0
- data/lib/punk/views/users/list.rb +22 -0
- data/lib/punk/views/users/show.rb +22 -0
- data/lib/punk/workers/.keep +0 -0
- data/lib/punk/workers/expire_sessions.rb +9 -0
- data/lib/punk/workers/geocode_session_worker.rb +48 -0
- data/lib/punk/workers/identify_session_worker.rb +45 -0
- data/lib/punk/workers/secret.rb +18 -0
- data/lib/punk/workers/send_email_worker.rb +51 -0
- data/lib/punk/workers/send_sms_worker.rb +40 -0
- data/punk.gemspec +147 -21
- data/schema.psql +345 -0
- data/spec/actions/groups/punk/list_groups_action_spec.rb +36 -0
- data/spec/actions/sessions/punk/clear_session_action_spec.rb +29 -0
- data/spec/actions/sessions/punk/create_session_action_spec.rb +33 -0
- data/spec/actions/sessions/punk/list_sessions_action_spec.rb +26 -0
- data/spec/actions/sessions/punk/verify_session_action_spec.rb +59 -0
- data/spec/actions/tenants/punk/list_tenants_action_spec.rb +25 -0
- data/spec/actions/users/punk/list_group_users_action_spec.rb +26 -0
- data/spec/actions/users/punk/list_tenant_users_action_spec.rb +26 -0
- data/spec/factories/group.rb +12 -0
- data/spec/factories/group_user_metadata.rb +10 -0
- data/spec/factories/identity.rb +19 -0
- data/spec/factories/session.rb +12 -0
- data/spec/factories/tenant.rb +10 -0
- data/spec/factories/tenant_user_metadata.rb +10 -0
- data/spec/factories/user.rb +12 -0
- data/spec/lib/commands/auth_spec.rb +11 -0
- data/spec/lib/commands/generate_spec.rb +7 -0
- data/spec/lib/commands/http_spec.rb +23 -0
- data/spec/lib/commands/list_spec.rb +7 -0
- data/spec/lib/commands/swagger_spec.rb +7 -0
- data/spec/lib/engine/punk_env_spec.rb +13 -0
- data/spec/lib/engine/punk_exec_spec.rb +9 -0
- data/spec/lib/engine/punk_init_spec.rb +9 -0
- data/spec/lib/engine/punk_store_spec.rb +10 -0
- data/spec/lib/punk.env +7 -0
- data/spec/models/punk/group_spec.rb +50 -0
- data/spec/models/punk/group_user_metadata_spec.rb +61 -0
- data/spec/models/punk/identity_spec.rb +61 -0
- data/spec/models/punk/session_spec.rb +156 -0
- data/spec/models/punk/tenant_spec.rb +51 -0
- data/spec/models/punk/tenant_user_metadata_spec.rb +61 -0
- data/spec/models/punk/user_spec.rb +115 -0
- data/spec/routes/groups/get_groups_spec.rb +33 -0
- data/spec/routes/plivo/get_plivo_spec.rb +11 -0
- data/spec/routes/sessions/delete_session_spec.rb +11 -0
- data/spec/routes/sessions/get_sessions_spec.rb +30 -0
- data/spec/routes/sessions/patch_session_spec.rb +11 -0
- data/spec/routes/sessions/post_session_spec.rb +11 -0
- data/spec/routes/swagger/get_swagger_spec.rb +12 -0
- data/spec/routes/tenants/get_tenants_spec.rb +31 -0
- data/spec/routes/users/get_users_spec.rb +60 -0
- data/spec/services/punk/challenge_claim_service_spec.rb +7 -0
- data/spec/services/punk/create_identities_service_spec.rb +14 -0
- data/spec/services/punk/generate_swagger_service_spec.rb +7 -0
- data/spec/services/punk/prove_claim_service_spec.rb +7 -0
- data/spec/services/punk/secret_service_spec.rb +7 -0
- data/spec/spec_helper.rb +122 -0
- data/spec/vcr_cassettes/PUNK_GeocodeSessionWorker/updates_the_session_data.yml +57 -0
- data/spec/vcr_cassettes/PUNK_IdentifySessionWorker/updates_the_session_data.yml +112 -0
- data/spec/views/punk/plivo_store_spec.rb +7 -0
- data/spec/views/sessions/punk/list_sessions_view_spec.rb +7 -0
- data/spec/views/sessions/punk/pending_session_view_spec.rb +7 -0
- data/spec/views/tenants/punk/list_tenants_view_spec.rb +7 -0
- data/spec/views/users/punk/list_groups_view_spec.rb +7 -0
- data/spec/views/users/punk/list_users_view_spec.rb +7 -0
- data/spec/workers/punk/expire_sessions_worker_spec.rb +31 -0
- data/spec/workers/punk/geocode_session_worker_spec.rb +14 -0
- data/spec/workers/punk/identify_session_worker_spec.rb +15 -0
- data/spec/workers/punk/secret_worker_spec.rb +20 -0
- data/spec/workers/punk/send_email_worker_spec.rb +46 -0
- data/spec/workers/punk/send_sms_worker_spec.rb +33 -0
- metadata +154 -16
- data/lib/punk/views/all.rb +0 -4
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PUNK
|
|
4
|
+
class ClearSessionAction < Action
|
|
5
|
+
args :session
|
|
6
|
+
|
|
7
|
+
def validate
|
|
8
|
+
validates_not_null :session
|
|
9
|
+
validates_not_empty :session
|
|
10
|
+
return if session.blank?
|
|
11
|
+
validates_type Session, :session
|
|
12
|
+
validates_state :session, :active
|
|
13
|
+
validates_event :session, :clear
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def process
|
|
17
|
+
session.clear!
|
|
18
|
+
present Info, message: "You have been logged out."
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
require 'phony'
|
|
5
|
+
|
|
6
|
+
module PUNK
|
|
7
|
+
class CreateSessionAction < Action
|
|
8
|
+
args :claim, :remote_addr, :user_agent
|
|
9
|
+
|
|
10
|
+
def validate
|
|
11
|
+
validates_not_null :claim
|
|
12
|
+
validates_not_empty :claim
|
|
13
|
+
validates_not_null :claim_type, message: "is not an email address or phone number"
|
|
14
|
+
validates_email :claim if claim_type == :email
|
|
15
|
+
validates_phone :claim if claim_type == :phone
|
|
16
|
+
validates_not_null :remote_addr
|
|
17
|
+
validates_not_empty :remote_addr
|
|
18
|
+
validates_not_null :user_agent
|
|
19
|
+
validates_not_empty :user_agent
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def process
|
|
23
|
+
PUNK.db.transaction do
|
|
24
|
+
identity =
|
|
25
|
+
Identity.find_or_create(claim: _normalize_claim) do |i|
|
|
26
|
+
i.claim_type = claim_type
|
|
27
|
+
end
|
|
28
|
+
session = Session.create(identity: identity, remote_addr: remote_addr, user_agent: user_agent)
|
|
29
|
+
ChallengeClaimService.run(session: session)
|
|
30
|
+
IdentifySessionWorker.perform_async(session_id: session.id)
|
|
31
|
+
message =
|
|
32
|
+
case identity.claim_type
|
|
33
|
+
when :email
|
|
34
|
+
"We have sent a verification code to your email address. Please enter it to verify your identity."
|
|
35
|
+
when :phone
|
|
36
|
+
"We have sent a verification code to your phone number by SMS. Please enter it to verify your identity."
|
|
37
|
+
end
|
|
38
|
+
present PendingSessionView, session: session, message: message, status: 201
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def claim_type
|
|
43
|
+
@claim_type ||= _guess_claim_type
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def _guess_claim_type
|
|
49
|
+
return :email if URI::MailTo::EMAIL_REGEXP.match(claim)
|
|
50
|
+
return :phone if Phony.plausible?(claim)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def _normalize_claim
|
|
54
|
+
case claim_type
|
|
55
|
+
when :email
|
|
56
|
+
claim.downcase.strip
|
|
57
|
+
when :phone
|
|
58
|
+
phone = claim.strip
|
|
59
|
+
phone = "+1#{phone}" if phone !~ /^[+]/
|
|
60
|
+
"+#{Phony.normalize(phone)}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PUNK
|
|
4
|
+
class ListSessionsAction < Action
|
|
5
|
+
args :user
|
|
6
|
+
|
|
7
|
+
def validate
|
|
8
|
+
validates_not_null :user
|
|
9
|
+
validates_not_empty :user
|
|
10
|
+
return if user.blank?
|
|
11
|
+
validates_type User, :user
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
present ListSessionsView, sessions: user.active_sessions.all
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PUNK
|
|
4
|
+
class VerifySessionAction < Action
|
|
5
|
+
args :session, :secret
|
|
6
|
+
|
|
7
|
+
def validate
|
|
8
|
+
validates_not_null :session
|
|
9
|
+
validates_not_empty :session
|
|
10
|
+
return if session.blank?
|
|
11
|
+
validates_not_null :secret
|
|
12
|
+
return if secret.blank?
|
|
13
|
+
validates_type Session, :session
|
|
14
|
+
validates_state :session, :pending
|
|
15
|
+
validates_event :session, :verify
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def process
|
|
19
|
+
verify = ProveClaimService.run(session: session, secret: secret)
|
|
20
|
+
raise BadRequest, 'Secret is incorrect' unless verify.result == true
|
|
21
|
+
present Info, message: 'We have succesfully verified your identity. Welcome to GroupFire!'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PUNK
|
|
4
|
+
class ListTenantsAction < Action
|
|
5
|
+
args :user
|
|
6
|
+
|
|
7
|
+
def validate
|
|
8
|
+
validates_not_null :user
|
|
9
|
+
validates_not_empty :user
|
|
10
|
+
return if user.blank?
|
|
11
|
+
validates_type User, :user
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
present ListTenantsView, tenants: user.tenants_dataset.order(:name).all
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PUNK
|
|
4
|
+
class ListGroupUsersAction < Action
|
|
5
|
+
args :group
|
|
6
|
+
|
|
7
|
+
def validate
|
|
8
|
+
validates_not_null :group
|
|
9
|
+
validates_not_empty :group
|
|
10
|
+
return if group.blank?
|
|
11
|
+
validates_type Group, :group
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
present ListUsersView, users: group.users
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PUNK
|
|
4
|
+
class ListTenantUsersAction < Action
|
|
5
|
+
args :tenant
|
|
6
|
+
|
|
7
|
+
def validate
|
|
8
|
+
validates_not_null :tenant
|
|
9
|
+
validates_not_empty :tenant
|
|
10
|
+
return if tenant.blank?
|
|
11
|
+
validates_type Tenant, :tenant
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
present ListUsersView, users: tenant.users
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PUNK
|
|
4
|
+
class ShowUserAction < Action
|
|
5
|
+
args :user
|
|
6
|
+
|
|
7
|
+
def validate
|
|
8
|
+
validates_not_null :user
|
|
9
|
+
validates_not_empty :user
|
|
10
|
+
return if user.blank?
|
|
11
|
+
validates_type User, :user
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process
|
|
15
|
+
present ShowUserView, user: user
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/punk/commands/list.rb
CHANGED
|
@@ -4,25 +4,31 @@ PUNK::Command.create "list" do
|
|
|
4
4
|
shortcut 'l'
|
|
5
5
|
description "List routes, actions, models, views, services or workers"
|
|
6
6
|
|
|
7
|
+
option shortcut: :a, name: :all, description: "Include Punk!", type: nil
|
|
8
|
+
|
|
7
9
|
def process
|
|
8
10
|
case args.join(' ')
|
|
9
11
|
when 'routes'
|
|
10
12
|
PUNK.app
|
|
11
|
-
PUNK::App.route_list
|
|
13
|
+
PUNK::App.route_list # TODO: exclude PUNK routes by default
|
|
12
14
|
when 'actions'
|
|
13
|
-
ObjectSpace.each_object(PUNK::Action.singleton_class).map(&:name).reject { |name|
|
|
15
|
+
ObjectSpace.each_object(PUNK::Action.singleton_class).map(&:name).reject { |name| _hide?(name) }
|
|
14
16
|
when 'models'
|
|
15
|
-
ObjectSpace.each_object(PUNK::Model.singleton_class).map(&:name).reject { |name|
|
|
17
|
+
ObjectSpace.each_object(PUNK::Model.singleton_class).map(&:name).reject { |name| _hide?(name) }
|
|
16
18
|
when 'views'
|
|
17
|
-
ObjectSpace.each_object(PUNK::View.singleton_class).map(&:name).reject { |name|
|
|
19
|
+
ObjectSpace.each_object(PUNK::View.singleton_class).map(&:name).reject { |name| _hide?(name) }
|
|
18
20
|
when 'services'
|
|
19
|
-
ObjectSpace.each_object(PUNK::Service.singleton_class).select { |klass| klass.superclass == PUNK::Service }.map(&:name).reject { |name|
|
|
21
|
+
ObjectSpace.each_object(PUNK::Service.singleton_class).select { |klass| klass.superclass == PUNK::Service }.map(&:name).reject { |name| _hide?(name) }
|
|
20
22
|
when 'workers'
|
|
21
|
-
ObjectSpace.each_object(PUNK::Worker.singleton_class).select { |klass| klass.superclass == PUNK::Worker }.map(&:name).reject { |name|
|
|
23
|
+
ObjectSpace.each_object(PUNK::Worker.singleton_class).select { |klass| klass.superclass == PUNK::Worker }.map(&:name).reject { |name| _hide?(name) }
|
|
22
24
|
when '', 'help'
|
|
23
25
|
"? specify one of: routes, actions, models, views, services, workers"
|
|
24
26
|
else
|
|
25
27
|
"? unkown arguments: #{args.join(',')}"
|
|
26
28
|
end
|
|
27
29
|
end
|
|
30
|
+
|
|
31
|
+
def _hide?(name)
|
|
32
|
+
name.nil? || (name =~ /^PUNK/) && !opts[:all]
|
|
33
|
+
end
|
|
28
34
|
end
|
data/lib/punk/config/schema.json
CHANGED
data/lib/punk/core/app.rb
CHANGED
|
@@ -23,7 +23,7 @@ module PUNK
|
|
|
23
23
|
|
|
24
24
|
ROUTES = Tempfile.new("routes.json").path
|
|
25
25
|
PUNK.profile_info("generate", path: ROUTES) do
|
|
26
|
-
system "roda-parse_routes -f #{ROUTES} #{File.expand_path(File.join(PUNK.get.app.path, 'routes', '*'))}"
|
|
26
|
+
system "roda-parse_routes -f #{ROUTES} #{File.expand_path(File.join(PUNK.get.app.path, 'routes', '*'))} #{File.expand_path(File.join(__dir__, '..', 'routes', '*'))}"
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
class App < Roda
|
|
@@ -88,8 +88,7 @@ module PUNK
|
|
|
88
88
|
|
|
89
89
|
def require_session!
|
|
90
90
|
begin
|
|
91
|
-
|
|
92
|
-
@_current_session = nil # Session[request.session['session_id']]
|
|
91
|
+
@_current_session = Session[request.session['session_id']]
|
|
93
92
|
if @_current_session&.active?
|
|
94
93
|
@_current_session.touch
|
|
95
94
|
else
|
|
@@ -192,9 +191,8 @@ module PUNK
|
|
|
192
191
|
name = "#{request.request_method} #{request.path}"
|
|
193
192
|
logger.info "Started #{name} for #{request.ip}", params.deep_symbolize_keys.sanitize.inspect
|
|
194
193
|
logger.trace request.env['HTTP_USER_AGENT']
|
|
195
|
-
#
|
|
196
|
-
|
|
197
|
-
# logger.trace request.env['HTTP_USER_AGENT'] || Session.default_values[:user_agent]
|
|
194
|
+
logger.info "Started #{name} for #{request.ip || Session.default_values[:remote_addr].to_s}", params.deep_symbolize_keys.sanitize.inspect
|
|
195
|
+
logger.trace request.env['HTTP_USER_AGENT'] || Session.default_values[:user_agent]
|
|
198
196
|
logger.trace request.env['HTTP_COOKIE']
|
|
199
197
|
logger.push_tags(name)
|
|
200
198
|
_set_cookie(request.env)
|
data/lib/punk/core/commander.rb
CHANGED
|
@@ -10,7 +10,7 @@ command :test do |c|
|
|
|
10
10
|
end
|
|
11
11
|
ENV.delete_if { |name, _value| name =~ /^PUNK_/ }
|
|
12
12
|
system('rubocop') &&
|
|
13
|
-
# system('quasar build -m pwa') &&
|
|
13
|
+
# system('quasar build -m pwa') &&
|
|
14
14
|
system('PUNK_ENV=test rspec')
|
|
15
15
|
exit $CHILD_STATUS.exitstatus # rubocop:disable Rails/Exit
|
|
16
16
|
end
|
|
@@ -74,12 +74,17 @@ command 'db migrate' do |c|
|
|
|
74
74
|
say('Migrating db...')
|
|
75
75
|
PUNK.boot
|
|
76
76
|
Sequel.extension :migration
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
migrations_path = File.join(PUNK.get.app.path, 'migrations')
|
|
78
|
+
if File.exist?(migrations_path)
|
|
79
|
+
if options.relative.nil?
|
|
80
|
+
Sequel::Migrator.run(PUNK.db, migrations_path)
|
|
81
|
+
else
|
|
82
|
+
Sequel::Migrator.run(PUNK.db, migrations_path, relative: options.relative)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
if PUNK.env.development?
|
|
86
|
+
database = File.basename(PUNK.get.db.url)
|
|
87
|
+
`pg_dump #{database} --schema-only > schema.psql`
|
|
81
88
|
end
|
|
82
|
-
database = File.basename(PUNK.get.db.url)
|
|
83
|
-
`pg_dump #{database} --schema-only > schema.psql`
|
|
84
89
|
end
|
|
85
90
|
end
|
data/lib/punk/core/exec.rb
CHANGED
|
@@ -23,6 +23,7 @@ end
|
|
|
23
23
|
|
|
24
24
|
PUNK::Interface.register(:app) do
|
|
25
25
|
require_relative 'app'
|
|
26
|
+
PUNK.require_all(File.join(__dir__, '..', 'routes'))
|
|
26
27
|
PUNK.require_all(File.join(PUNK.get.app.path, 'routes'))
|
|
27
28
|
retval = PUNK.get.app.reloadable ? PUNK.loader : PUNK::App.freeze.app
|
|
28
29
|
SemanticLogger.flush
|
|
@@ -32,6 +33,7 @@ end
|
|
|
32
33
|
PUNK.inject :loader, :app
|
|
33
34
|
|
|
34
35
|
['actions', 'models', 'views', 'services', 'workers'].each do |dir|
|
|
36
|
+
PUNK.require_all(File.join(__dir__, '..', dir))
|
|
35
37
|
PUNK.require_all(File.join(PUNK.get.app.path, dir))
|
|
36
38
|
end
|
|
37
39
|
|
data/lib/punk/core/load.rb
CHANGED
|
@@ -71,7 +71,11 @@ module PUNK
|
|
|
71
71
|
define_method(:options) do |opt|
|
|
72
72
|
punk_command = PUNK.store.commands[match]
|
|
73
73
|
punk_command.instance_variable_get(:@options).each_value do |option|
|
|
74
|
-
|
|
74
|
+
if option[:type].present?
|
|
75
|
+
opt.on option[:shortcut], option[:name], option[:description], argument: true, as: option[:type]
|
|
76
|
+
else
|
|
77
|
+
opt.on option[:shortcut], option[:name], option[:description]
|
|
78
|
+
end
|
|
75
79
|
end
|
|
76
80
|
end
|
|
77
81
|
define_method(:process) do
|
|
@@ -28,20 +28,6 @@ module PUNK
|
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def validates_parse_id(atts, opts={})
|
|
32
|
-
default = { message: "is not a Parse ID" }
|
|
33
|
-
validatable_attributes(atts, default.merge(opts)) do |_name, value, message|
|
|
34
|
-
message unless /^[[:alnum:]]{10}$/.match(value)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def validates_subdomain(atts, opts={})
|
|
39
|
-
default = { message: "is not a subdomain" }
|
|
40
|
-
validatable_attributes(atts, default.merge(opts)) do |_name, value, message|
|
|
41
|
-
message unless /^[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?$/.match(value)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
31
|
def validates_state(name, state)
|
|
46
32
|
errors.add(name, "is not in #{state} state") unless self[name].send("#{state}?")
|
|
47
33
|
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
def _tenants
|
|
4
|
+
create_table :tenants do
|
|
5
|
+
uuid :id, primary_key: true, default: Sequel.function(:gen_random_uuid)
|
|
6
|
+
punk_state :state, null: false, default: 'created'
|
|
7
|
+
String :name, null: false, text: true
|
|
8
|
+
String :icon, text: true
|
|
9
|
+
jsonb :data, default: '{}'
|
|
10
|
+
DateTime :created_at
|
|
11
|
+
DateTime :updated_at
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def _users
|
|
16
|
+
create_table :users do
|
|
17
|
+
uuid :id, primary_key: true, default: Sequel.function(:gen_random_uuid)
|
|
18
|
+
punk_state :state, null: false, default: 'created'
|
|
19
|
+
String :name, null: false, text: true
|
|
20
|
+
String :icon, text: true
|
|
21
|
+
String :email, text: true, unique: true
|
|
22
|
+
String :phone, text: true, unique: true
|
|
23
|
+
jsonb :data, default: '{}'
|
|
24
|
+
DateTime :created_at
|
|
25
|
+
DateTime :updated_at
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def _tenants_users
|
|
30
|
+
create_table :tenants_users do
|
|
31
|
+
primary_key [:tenant_id, :user_id]
|
|
32
|
+
foreign_key :tenant_id, :tenants, null: false, type: :uuid
|
|
33
|
+
foreign_key :user_id, :users, null: false, type: :uuid
|
|
34
|
+
index [:tenant_id, :user_id]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def _groups
|
|
39
|
+
create_table :groups do
|
|
40
|
+
uuid :id, primary_key: true, default: Sequel.function(:gen_random_uuid)
|
|
41
|
+
punk_state :state, null: false, default: 'created'
|
|
42
|
+
String :name, null: false, text: true
|
|
43
|
+
String :icon, text: true
|
|
44
|
+
jsonb :data, default: '{}'
|
|
45
|
+
DateTime :created_at
|
|
46
|
+
DateTime :updated_at
|
|
47
|
+
foreign_key :tenant_id, :tenants, null: false, type: :uuid
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def _groups_users
|
|
52
|
+
create_table :groups_users do
|
|
53
|
+
primary_key [:group_id, :user_id]
|
|
54
|
+
foreign_key :group_id, :groups, null: false, type: :uuid
|
|
55
|
+
foreign_key :user_id, :users, null: false, type: :uuid
|
|
56
|
+
index [:group_id, :user_id]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def _identities
|
|
61
|
+
create_enum(:claim_type, %w[email phone])
|
|
62
|
+
create_table :identities do
|
|
63
|
+
uuid :id, primary_key: true, default: Sequel.function(:gen_random_uuid)
|
|
64
|
+
punk_state :state, null: false, default: 'created'
|
|
65
|
+
claim_type :claim_type, null: false
|
|
66
|
+
String :claim, text: true, null: false, unique: true
|
|
67
|
+
jsonb :data, default: '{}'
|
|
68
|
+
DateTime :created_at
|
|
69
|
+
DateTime :updated_at
|
|
70
|
+
foreign_key :user_id, :users, null: true, type: :uuid
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def _sessions
|
|
75
|
+
create_enum(:session_state, %w[pending created active deleted expired])
|
|
76
|
+
create_table :sessions do
|
|
77
|
+
uuid :id, primary_key: true, default: Sequel.function(:gen_random_uuid)
|
|
78
|
+
uuid :slug, default: Sequel.function(:gen_random_uuid)
|
|
79
|
+
session_state :state, null: false, default: 'created'
|
|
80
|
+
File :salt, text: true
|
|
81
|
+
File :hash, text: true
|
|
82
|
+
Integer :attempt_count, null: false, default: 0
|
|
83
|
+
cidr :remote_addr, null: false, default: '127.0.0.1'
|
|
84
|
+
String :user_agent, text: true, null: false, default: 'Mozilla/5.0 (compatible; Punk!; +https://punk.kranzky.com)'
|
|
85
|
+
jsonb :data, default: '{}'
|
|
86
|
+
DateTime :created_at
|
|
87
|
+
DateTime :updated_at
|
|
88
|
+
foreign_key :identity_id, :identities, null: false, type: :uuid
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
PUNK.migration do
|
|
93
|
+
change do
|
|
94
|
+
create_enum(:punk_state, %w[created active deleted])
|
|
95
|
+
_tenants
|
|
96
|
+
_users
|
|
97
|
+
_tenants_users
|
|
98
|
+
_groups
|
|
99
|
+
_groups_users
|
|
100
|
+
_identities
|
|
101
|
+
_sessions
|
|
102
|
+
end
|
|
103
|
+
end
|