command_tower 0.3.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +59 -0
- data/Rakefile +32 -0
- data/app/controllers/command_tower/admin_controller.rb +104 -0
- data/app/controllers/command_tower/application_controller.rb +81 -0
- data/app/controllers/command_tower/auth/plain_text_controller.rb +132 -0
- data/app/controllers/command_tower/inbox/message_blast_controller.rb +89 -0
- data/app/controllers/command_tower/inbox/message_controller.rb +79 -0
- data/app/controllers/command_tower/user_controller.rb +49 -0
- data/app/controllers/command_tower/username_controller.rb +26 -0
- data/app/helpers/command_tower/application_helper.rb +4 -0
- data/app/helpers/command_tower/schema_helper.rb +29 -0
- data/app/jobs/command_tower/application_job.rb +4 -0
- data/app/mailers/command_tower/application_mailer.rb +8 -0
- data/app/mailers/command_tower/email_verification_mailer.rb +12 -0
- data/app/models/command_tower/application_record.rb +45 -0
- data/app/models/message.rb +30 -0
- data/app/models/message_blast.rb +27 -0
- data/app/models/user.rb +61 -0
- data/app/models/user_secret.rb +72 -0
- data/app/services/command_tower/README.md +49 -0
- data/app/services/command_tower/argument_validation/README.md +192 -0
- data/app/services/command_tower/argument_validation/class_methods.rb +178 -0
- data/app/services/command_tower/argument_validation/instance_methods.rb +148 -0
- data/app/services/command_tower/argument_validation.rb +11 -0
- data/app/services/command_tower/authorize/validate.rb +49 -0
- data/app/services/command_tower/inbox_service/blast/delete.rb +23 -0
- data/app/services/command_tower/inbox_service/blast/metadata.rb +26 -0
- data/app/services/command_tower/inbox_service/blast/new_user_blaster.rb +24 -0
- data/app/services/command_tower/inbox_service/blast/retrieve.rb +30 -0
- data/app/services/command_tower/inbox_service/blast/upsert.rb +67 -0
- data/app/services/command_tower/inbox_service/message/metadata.rb +35 -0
- data/app/services/command_tower/inbox_service/message/modify.rb +44 -0
- data/app/services/command_tower/inbox_service/message/retrieve.rb +36 -0
- data/app/services/command_tower/inbox_service/message/send.rb +33 -0
- data/app/services/command_tower/jwt/authenticate_user.rb +86 -0
- data/app/services/command_tower/jwt/decode.rb +21 -0
- data/app/services/command_tower/jwt/encode.rb +15 -0
- data/app/services/command_tower/jwt/login_create.rb +21 -0
- data/app/services/command_tower/jwt/time_delay_token.rb +17 -0
- data/app/services/command_tower/login_strategy/plain_text/create.rb +43 -0
- data/app/services/command_tower/login_strategy/plain_text/email_verification/generate.rb +29 -0
- data/app/services/command_tower/login_strategy/plain_text/email_verification/required.rb +20 -0
- data/app/services/command_tower/login_strategy/plain_text/email_verification/send.rb +23 -0
- data/app/services/command_tower/login_strategy/plain_text/email_verification/verify.rb +24 -0
- data/app/services/command_tower/login_strategy/plain_text/login.rb +50 -0
- data/app/services/command_tower/secrets/cleanse.rb +14 -0
- data/app/services/command_tower/secrets/generate.rb +62 -0
- data/app/services/command_tower/secrets/verify.rb +27 -0
- data/app/services/command_tower/secrets.rb +15 -0
- data/app/services/command_tower/service_base.rb +89 -0
- data/app/services/command_tower/service_logging.rb +41 -0
- data/app/services/command_tower/user_attributes/modify.rb +68 -0
- data/app/services/command_tower/user_attributes/roles.rb +27 -0
- data/app/services/command_tower/username/available.rb +64 -0
- data/app/views/command_tower/email_verification_mailer/verify_email.html.erb +26 -0
- data/config/routes.rb +55 -0
- data/db/migrate/20241117043720_create_command_tower_users.rb +42 -0
- data/db/migrate/20241204065708_create_command_tower_user_secrets.rb +16 -0
- data/db/migrate/20250223023306_create_command_tower_messages.rb +12 -0
- data/db/migrate/20250223023313_create_command_tower_message_blasts.rb +14 -0
- data/lib/command_tower/authorization/default.yml +42 -0
- data/lib/command_tower/authorization/entity.rb +101 -0
- data/lib/command_tower/authorization/role.rb +101 -0
- data/lib/command_tower/authorization.rb +85 -0
- data/lib/command_tower/configuration/admin/config.rb +18 -0
- data/lib/command_tower/configuration/application/config.rb +40 -0
- data/lib/command_tower/configuration/authorization/config.rb +24 -0
- data/lib/command_tower/configuration/base.rb +11 -0
- data/lib/command_tower/configuration/config.rb +77 -0
- data/lib/command_tower/configuration/email/config.rb +87 -0
- data/lib/command_tower/configuration/jwt/config.rb +22 -0
- data/lib/command_tower/configuration/login/config.rb +18 -0
- data/lib/command_tower/configuration/login/strategy/plain_text/config.rb +57 -0
- data/lib/command_tower/configuration/login/strategy/plain_text/email_verify.rb +50 -0
- data/lib/command_tower/configuration/login/strategy/plain_text/lockable.rb +27 -0
- data/lib/command_tower/configuration/otp/config.rb +54 -0
- data/lib/command_tower/configuration/user/config.rb +56 -0
- data/lib/command_tower/configuration/username/check.rb +31 -0
- data/lib/command_tower/configuration/username/config.rb +41 -0
- data/lib/command_tower/engine.rb +53 -0
- data/lib/command_tower/error.rb +5 -0
- data/lib/command_tower/schema/admin/users.rb +15 -0
- data/lib/command_tower/schema/error/base.rb +15 -0
- data/lib/command_tower/schema/error/invalid_argument.rb +15 -0
- data/lib/command_tower/schema/error/invalid_argument_response.rb +17 -0
- data/lib/command_tower/schema/inbox/blast_request.rb +15 -0
- data/lib/command_tower/schema/inbox/blast_response.rb +16 -0
- data/lib/command_tower/schema/inbox/message_blast_entity.rb +16 -0
- data/lib/command_tower/schema/inbox/message_blast_metadata.rb +16 -0
- data/lib/command_tower/schema/inbox/message_entity.rb +14 -0
- data/lib/command_tower/schema/inbox/metadata.rb +18 -0
- data/lib/command_tower/schema/inbox/modified.rb +13 -0
- data/lib/command_tower/schema/page.rb +14 -0
- data/lib/command_tower/schema/plain_text/create_user_request.rb +18 -0
- data/lib/command_tower/schema/plain_text/create_user_response.rb +17 -0
- data/lib/command_tower/schema/plain_text/email_verify_request.rb +11 -0
- data/lib/command_tower/schema/plain_text/email_verify_response.rb +11 -0
- data/lib/command_tower/schema/plain_text/email_verify_send_request.rb +9 -0
- data/lib/command_tower/schema/plain_text/email_verify_send_response.rb +11 -0
- data/lib/command_tower/schema/plain_text/login_request.rb +15 -0
- data/lib/command_tower/schema/plain_text/login_response.rb +13 -0
- data/lib/command_tower/schema/user.rb +28 -0
- data/lib/command_tower/schema.rb +38 -0
- data/lib/command_tower/spec_helper.rb +19 -0
- data/lib/command_tower/version.rb +5 -0
- data/lib/command_tower.rb +33 -0
- data/lib/generators/api_engine_base/configure/USAGE +8 -0
- data/lib/generators/api_engine_base/configure/configure_generator.rb +12 -0
- data/lib/tasks/auto_annotate_models.rake +60 -0
- metadata +255 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cf20c74b952fc6ca7dc2c7a67212ce9e5e8eb96a93bcb6173bd40564d28ceecc
|
4
|
+
data.tar.gz: 1e6d03692209feecdad59b05f8296792ab5ccc0b62f301dc80bc5d88afe4a091
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a6aeb3aa6c47f3b253b26bc0778c8862e80b78601bd495acea69709a4b0f39f830d3b236c1ed3385b0ad8457598dde34203a200ff809aa86e839c02706c10abd
|
7
|
+
data.tar.gz: a3d9687e594904270b83b2c033cb1c83abe38c9ebceeef3b4c8c3b482e95b86b5423cb05f5d6598aa3659f1cca7d3996514a39d9fdbe4b67f975e2910f996b60
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# CommandTower
|
2
|
+
This is an API only base engine to build on top of. This Engine takes care of all Authentication, Token Refresh, and RBAC Roles so that you do not have to! For all applications, you can get right to work on implementing the code directly related to your project rather than dealing with the administrative overhead.
|
3
|
+
|
4
|
+
While this gem is heavily opinionated, everything can be configured to your liking.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem "command_tower"
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
```bash
|
15
|
+
$ bundle
|
16
|
+
```
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
```bash
|
20
|
+
$ gem install command_tower
|
21
|
+
```
|
22
|
+
|
23
|
+
## Initializing CommandTower
|
24
|
+
Please follow all steps in [Initializing CommandTower](docs/initializing.md)
|
25
|
+
|
26
|
+
|
27
|
+
## Available Routes
|
28
|
+
|
29
|
+
For more info, check out [Controllers ReadMe](docs/controllers.md)
|
30
|
+
|
31
|
+
Additionally, You can check out [RSpec Integration Testing](/spec/integration_test)
|
32
|
+
|
33
|
+
## Available Models
|
34
|
+
|
35
|
+
CommandTower provides several Models at the in the root namespace. Core Models like `User` and `UserSecret` are readily available. Don't forget! You can add additional methods to these classes by opening them back up.
|
36
|
+
|
37
|
+
For more info, check out [Models ReadMe](doc/models.md)
|
38
|
+
|
39
|
+
## Authentication (JWT BearerToken)
|
40
|
+
Authentication ensures that we know which user is requesting the action. When the Engine is unable to authenticate, a `401` status code is returned.
|
41
|
+
|
42
|
+
For more info, check out [Authentication ReadMe](docs/authentication.md)
|
43
|
+
|
44
|
+
## Authorization (RBAC)
|
45
|
+
Authorization is only done after authentication. This is the act of ensuring that the user can perform the action it is requesting. Put differently, I know who you are, but I need to validate you have permissions to complete the action. When the engine is unable to authorize the user, a `403` status code is returned.
|
46
|
+
|
47
|
+
For more info, check out [Authentication ReadMe](docs/authorization.md)
|
48
|
+
|
49
|
+
## Sensitive Changes
|
50
|
+
|
51
|
+
For more info, check out [Sensitive Routes](docs/sensitive_routes.md)
|
52
|
+
|
53
|
+
## ServiceBase
|
54
|
+
ServiceBase is built on top of Interactor. The ServiceBase is the heart of all logic for CommandTower. It includes Logging and enhanced ArgumentValidation that can directly return back to the API request.
|
55
|
+
|
56
|
+
For more info, check out [ServiceBase ReadMe](app/services/command_tower/README.md)
|
57
|
+
|
58
|
+
## License
|
59
|
+
The engine is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'CommandTower'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("rails_app/Rakefile", __dir__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: :test
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CommandTower
|
4
|
+
class AdminController < ::CommandTower::ApplicationController
|
5
|
+
include CommandTower::SchemaHelper
|
6
|
+
|
7
|
+
before_action :authenticate_user!
|
8
|
+
before_action :authorize_user!
|
9
|
+
before_action :user!, only: [:modify, :modify_role]
|
10
|
+
|
11
|
+
# Pagination is needed here
|
12
|
+
def show
|
13
|
+
schemafied_users = User.all.map { CommandTower::Schema::User.convert_user_object(user: _1) }
|
14
|
+
schema = CommandTower::Schema::Admin::Users.new(users: schemafied_users)
|
15
|
+
schema_succesful!(status: 200, schema:)
|
16
|
+
end
|
17
|
+
|
18
|
+
def modify
|
19
|
+
result = CommandTower::UserAttributes::Modify.(user:, admin_user:, **modify_params)
|
20
|
+
if result.success?
|
21
|
+
schema = CommandTower::Schema::User.convert_user_object(user: user.reload)
|
22
|
+
status = 201
|
23
|
+
schema_succesful!(status:, schema:)
|
24
|
+
else
|
25
|
+
if result.invalid_arguments
|
26
|
+
invalid_arguments!(
|
27
|
+
status: 400,
|
28
|
+
message: result.msg,
|
29
|
+
argument_object: result.invalid_argument_hash,
|
30
|
+
schema: CommandTower::Schema::PlainText::LoginRequest
|
31
|
+
)
|
32
|
+
else
|
33
|
+
server_error!(result:)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def modify_role
|
39
|
+
result = CommandTower::UserAttributes::Roles.(user:, admin_user:, roles: params[:roles] || [])
|
40
|
+
if result.success?
|
41
|
+
schema = CommandTower::Schema::User.convert_user_object(user: user.reload)
|
42
|
+
status = 201
|
43
|
+
schema_succesful!(status:, schema:)
|
44
|
+
else
|
45
|
+
if result.invalid_arguments
|
46
|
+
invalid_arguments!(
|
47
|
+
status: 400,
|
48
|
+
message: result.msg,
|
49
|
+
argument_object: result.invalid_argument_hash,
|
50
|
+
schema: CommandTower::Schema::PlainText::LoginRequest
|
51
|
+
)
|
52
|
+
else
|
53
|
+
server_error!(result:)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def impersonate
|
59
|
+
# TODO: @matt-taylor
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def server_error!(result:)
|
65
|
+
status = 500
|
66
|
+
schema = CommandTower::Schema::Error::Base.new(status:, message: result.msg)
|
67
|
+
render(json: schema.to_h, status:)
|
68
|
+
end
|
69
|
+
|
70
|
+
def modify_params
|
71
|
+
{
|
72
|
+
email: params[:email],
|
73
|
+
email_validated: safe_boolean(value: params[:email_validated]),
|
74
|
+
first_name: params[:first_name],
|
75
|
+
last_name: params[:last_name],
|
76
|
+
username: params[:username],
|
77
|
+
verifier_token: safe_boolean(value: params[:verifier_token]),
|
78
|
+
}.compact
|
79
|
+
end
|
80
|
+
|
81
|
+
def admin_user
|
82
|
+
# current_user is defined via authenticate_user! before action
|
83
|
+
current_user
|
84
|
+
end
|
85
|
+
|
86
|
+
def user!
|
87
|
+
_user = User.where(id: params[:user_id]).first
|
88
|
+
if _user
|
89
|
+
@user = _user
|
90
|
+
return true
|
91
|
+
end
|
92
|
+
|
93
|
+
status = 400
|
94
|
+
schema = CommandTower::Schema::Error::Base.new(status:, message: "Invalid user")
|
95
|
+
render(json: schema.to_h, status:)
|
96
|
+
# Must return false so callbacks know to halt propagation
|
97
|
+
false
|
98
|
+
end
|
99
|
+
|
100
|
+
def user
|
101
|
+
@user ||= nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CommandTower
|
4
|
+
class ApplicationController < ActionController::API
|
5
|
+
AUTHENTICATION_HEADER = "Authentication"
|
6
|
+
AUTHENTICATION_EXPIRE_HEADER = "X-Authentication-Expire"
|
7
|
+
AUTHENTICATION_WITH_RESET = "X-Authentication-Reset"
|
8
|
+
|
9
|
+
def safe_boolean(value:)
|
10
|
+
return nil unless [true, false, "true", "false", "0", "1", 0, 1].include?(value)
|
11
|
+
|
12
|
+
ActiveModel::Type::Boolean.new.cast(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
###
|
16
|
+
# Authenticate user via the passed in header
|
17
|
+
# AUTHENTICATION_HEADER="Bearer: {token value}"
|
18
|
+
def authenticate_user!(bypass_email_validation: false)
|
19
|
+
raw_token = request.headers[AUTHENTICATION_HEADER]
|
20
|
+
if raw_token.nil?
|
21
|
+
status = 401
|
22
|
+
schema = CommandTower::Schema::Error::Base.new(status:, message: "Bearer token missing")
|
23
|
+
render(json: schema.to_h, status:)
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
|
27
|
+
token = raw_token.split("Bearer:")[1].strip
|
28
|
+
with_reset = safe_boolean(value: request.headers[AUTHENTICATION_WITH_RESET])
|
29
|
+
result = CommandTower::Jwt::AuthenticateUser.(token:, bypass_email_validation:, with_reset:)
|
30
|
+
if result.success?
|
31
|
+
@current_user = result.user
|
32
|
+
response.set_header(AUTHENTICATION_EXPIRE_HEADER, result.expires_at)
|
33
|
+
if with_reset
|
34
|
+
response.set_header(AUTHENTICATION_WITH_RESET, result.generated_token)
|
35
|
+
end
|
36
|
+
true
|
37
|
+
else
|
38
|
+
status = 401
|
39
|
+
schema = CommandTower::Schema::Error::Base.new(status:, message: result.msg)
|
40
|
+
render(json: schema.to_h, status:)
|
41
|
+
# Must return false so callbacks know to halt propagation
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
###
|
47
|
+
# Authenticate user via the passed in header without validating email
|
48
|
+
def authenticate_user_without_email_verification!
|
49
|
+
authenticate_user!(bypass_email_validation: true)
|
50
|
+
end
|
51
|
+
|
52
|
+
###
|
53
|
+
# After Authenticating user, see if the user needs authorization on the route
|
54
|
+
def authorize_user!
|
55
|
+
if current_user.nil?
|
56
|
+
Rails.logger.error { "Current User is not defined. This means that authenticate_user! was not called" }
|
57
|
+
status = 401
|
58
|
+
schema = CommandTower::Schema::Error::Base.new(status:, message: "Bearer token missing")
|
59
|
+
render(json: schema.to_h, status:)
|
60
|
+
return false
|
61
|
+
end
|
62
|
+
result = CommandTower::Authorize::Validate.(user: current_user, controller: self.class, method: params[:action])
|
63
|
+
|
64
|
+
if result.success?
|
65
|
+
@current_user = result.user
|
66
|
+
true
|
67
|
+
else
|
68
|
+
# Current user is not authorized for the current Controller#action
|
69
|
+
status = 403
|
70
|
+
schema = CommandTower::Schema::Error::Base.new(status:, message: result.msg)
|
71
|
+
render(json: schema.to_h, status:)
|
72
|
+
# Must return false so callbacks know to halt propagation
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def current_user
|
78
|
+
@current_user ||= nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module CommandTower
|
2
|
+
module Auth
|
3
|
+
class PlainTextController < ::CommandTower::ApplicationController
|
4
|
+
include CommandTower::SchemaHelper
|
5
|
+
|
6
|
+
before_action :authenticate_user_without_email_verification!, only: [:email_verify_post, :email_verify_resend_post]
|
7
|
+
|
8
|
+
# POST /auth/login
|
9
|
+
# Login to the application and create/set the JWT token
|
10
|
+
def login_post
|
11
|
+
result = CommandTower::LoginStrategy::PlainText::Login.(**login_params)
|
12
|
+
if result.success?
|
13
|
+
schema = CommandTower::Schema::PlainText::LoginResponse.new(
|
14
|
+
token: result.token,
|
15
|
+
header_name: AUTHENTICATION_HEADER,
|
16
|
+
message: "Successfully logged user in"
|
17
|
+
)
|
18
|
+
status = 201
|
19
|
+
schema_succesful!(status:, schema:)
|
20
|
+
else
|
21
|
+
if result.invalid_arguments
|
22
|
+
invalid_arguments!(
|
23
|
+
status: 401,
|
24
|
+
message: result.msg,
|
25
|
+
argument_object: result.invalid_argument_hash,
|
26
|
+
schema: CommandTower::Schema::PlainText::LoginRequest
|
27
|
+
)
|
28
|
+
else
|
29
|
+
json_result = { msg: result.msg }
|
30
|
+
status = 400
|
31
|
+
render(json: schema.to_h, status:)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# POST /auth/create
|
37
|
+
# New PlainText user creation
|
38
|
+
def create_post
|
39
|
+
result = CommandTower::LoginStrategy::PlainText::Create.(**create_params)
|
40
|
+
if result.success?
|
41
|
+
schema = CommandTower::Schema::PlainText::CreateUserResponse.new(
|
42
|
+
full_name: result.user.full_name,
|
43
|
+
first_name: result.first_name,
|
44
|
+
last_name: result.last_name,
|
45
|
+
username: result.username,
|
46
|
+
email: result.email,
|
47
|
+
msg: "Successfully created new User",
|
48
|
+
)
|
49
|
+
status = 201
|
50
|
+
schema_succesful!(status:, schema:)
|
51
|
+
else
|
52
|
+
if result.invalid_arguments
|
53
|
+
invalid_arguments!(
|
54
|
+
status: 400,
|
55
|
+
message: result.msg,
|
56
|
+
argument_object: result.invalid_argument_hash,
|
57
|
+
schema: CommandTower::Schema::PlainText::CreateUserRequest
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# POST /auth/email/verify
|
64
|
+
# Verifies a logged in users email verification code when enabled
|
65
|
+
def email_verify_post
|
66
|
+
if current_user.email_validated
|
67
|
+
schema = CommandTower::Schema::PlainText::EmailVerifyResponse.new(message: "Email is already verified.")
|
68
|
+
status = 200
|
69
|
+
schema_succesful!(status:, schema:)
|
70
|
+
else
|
71
|
+
result = CommandTower::LoginStrategy::PlainText::EmailVerification::Verify.(user: current_user, code: params[:code])
|
72
|
+
if result.success?
|
73
|
+
schema = CommandTower::Schema::PlainText::EmailVerifyResponse.new(message: "Successfully verified email")
|
74
|
+
status = 201
|
75
|
+
schema_succesful!(status:, schema:)
|
76
|
+
else
|
77
|
+
if result.invalid_arguments
|
78
|
+
invalid_arguments!(
|
79
|
+
status: result.status || 403,
|
80
|
+
message: result.msg,
|
81
|
+
argument_object: result.invalid_argument_hash,
|
82
|
+
schema: CommandTower::Schema::PlainText::EmailVerifyRequest
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# POST /auth/email/send
|
90
|
+
# Sends a logged in users email verification code
|
91
|
+
def email_verify_resend_post
|
92
|
+
if current_user.email_validated
|
93
|
+
schema = CommandTower::Schema::PlainText::EmailVerifyResponse.new(message: "Email is already verified. No code required")
|
94
|
+
status = 200
|
95
|
+
schema_succesful!(status:, schema:)
|
96
|
+
else
|
97
|
+
result = CommandTower::LoginStrategy::PlainText::EmailVerification::Send.(user: current_user)
|
98
|
+
if result.success?
|
99
|
+
schema = CommandTower::Schema::PlainText::EmailVerifyResponse.new(message: "Successfully sent Email verification code")
|
100
|
+
status = 201
|
101
|
+
schema_succesful!(status:, schema:)
|
102
|
+
else
|
103
|
+
schema = CommandTower::Schema::Error::Base.new(status:, message: result.msg)
|
104
|
+
status = result.status || 401
|
105
|
+
render(json: schema.to_h, status:)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def login_params
|
113
|
+
{
|
114
|
+
username: params[:username],
|
115
|
+
email: params[:email],
|
116
|
+
password: params[:password],
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
def create_params
|
121
|
+
{
|
122
|
+
first_name: params[:first_name],
|
123
|
+
last_name: params[:last_name],
|
124
|
+
username: params[:username],
|
125
|
+
email: params[:email],
|
126
|
+
password: params[:password],
|
127
|
+
password_confirmation: params[:password_confirmation],
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CommandTower
|
4
|
+
module Inbox
|
5
|
+
class MessageBlastController < ::CommandTower::ApplicationController
|
6
|
+
include CommandTower::SchemaHelper
|
7
|
+
|
8
|
+
before_action :authenticate_user!
|
9
|
+
before_action :authorize_user!
|
10
|
+
|
11
|
+
# GET /inbox/blast
|
12
|
+
def metadata
|
13
|
+
result = CommandTower::InboxService::Blast::Metadata.(id: params[:id].to_i)
|
14
|
+
schema_succesful!(status: 200, schema: result.metadata)
|
15
|
+
end
|
16
|
+
|
17
|
+
# GET /inbox/blast/:id
|
18
|
+
def blast
|
19
|
+
result = CommandTower::InboxService::Blast::Retrieve.(id: params[:id].to_i)
|
20
|
+
if result.success?
|
21
|
+
schema = result.message_blast
|
22
|
+
status = 200
|
23
|
+
schema_succesful!(status:, schema:)
|
24
|
+
else
|
25
|
+
invalid_arguments!(
|
26
|
+
status: 400,
|
27
|
+
message: result.msg,
|
28
|
+
argument_object: result.invalid_argument_hash,
|
29
|
+
schema: CommandTower::Schema::PlainText::LoginRequest,
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# POST /inbox/blast
|
35
|
+
def create
|
36
|
+
upsert
|
37
|
+
end
|
38
|
+
|
39
|
+
# PATCH /inbox/blast/:id
|
40
|
+
def modify
|
41
|
+
upsert(id: params[:id].to_i)
|
42
|
+
end
|
43
|
+
|
44
|
+
# DELETE /inbox/blast/:id
|
45
|
+
def delete
|
46
|
+
result = CommandTower::InboxService::Blast::Delete.(id: params[:id].to_i)
|
47
|
+
if result.success?
|
48
|
+
schema = result.message
|
49
|
+
status = 200
|
50
|
+
render :json, { id: params[:id], msg: "Message Blast message deleted" }
|
51
|
+
else
|
52
|
+
invalid_arguments!(
|
53
|
+
status: 400,
|
54
|
+
message: result.msg,
|
55
|
+
argument_object: result.invalid_argument_hash,
|
56
|
+
schema: CommandTower::Schema::PlainText::LoginRequest,
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def upsert(id: nil)
|
64
|
+
upsert_params = {
|
65
|
+
user: current_user,
|
66
|
+
existing_users: safe_boolean(value: params[:existing_users]),
|
67
|
+
new_users: safe_boolean(value: params[:new_users]),
|
68
|
+
text: params[:text],
|
69
|
+
title: params[:title],
|
70
|
+
id:,
|
71
|
+
}.compact
|
72
|
+
result = CommandTower::InboxService::Blast::Upsert.(**upsert_params)
|
73
|
+
|
74
|
+
if result.success?
|
75
|
+
schema = result.blast
|
76
|
+
status = 200
|
77
|
+
schema_succesful!(status:, schema:)
|
78
|
+
else
|
79
|
+
invalid_arguments!(
|
80
|
+
status: 400,
|
81
|
+
message: result.msg,
|
82
|
+
argument_object: result.invalid_argument_hash,
|
83
|
+
schema: CommandTower::Schema::Inbox::BlastRequest
|
84
|
+
)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CommandTower
|
4
|
+
module Inbox
|
5
|
+
class MessageController < ::CommandTower::ApplicationController
|
6
|
+
include CommandTower::SchemaHelper
|
7
|
+
|
8
|
+
before_action :authenticate_user!
|
9
|
+
|
10
|
+
# GET: /inbox/messages
|
11
|
+
def metadata
|
12
|
+
result = CommandTower::InboxService::Message::Metadata.(user: current_user)
|
13
|
+
if result.success?
|
14
|
+
schema = result.metadata
|
15
|
+
status = 200
|
16
|
+
schema_succesful!(status:, schema:)
|
17
|
+
else
|
18
|
+
invalid_arguments!(
|
19
|
+
status: 400,
|
20
|
+
message: result.msg,
|
21
|
+
argument_object: result.invalid_argument_hash,
|
22
|
+
schema: CommandTower::Schema::PlainText::LoginRequest
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET: /inbox/messages/:id
|
28
|
+
def message
|
29
|
+
result = CommandTower::InboxService::Message::Retrieve.(user: current_user, id: params[:id].to_i)
|
30
|
+
if result.success?
|
31
|
+
schema = result.message
|
32
|
+
status = 200
|
33
|
+
schema_succesful!(status:, schema:)
|
34
|
+
else
|
35
|
+
invalid_arguments!(
|
36
|
+
status: 400,
|
37
|
+
message: result.msg,
|
38
|
+
argument_object: result.invalid_argument_hash,
|
39
|
+
schema: CommandTower::Schema::PlainText::LoginRequest
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# POST: /inbox/messages/ack
|
45
|
+
# Body { ids: [<list of ids to ack>] }
|
46
|
+
def ack
|
47
|
+
modify(type: CommandTower::InboxService::Message::Modify::VIEWED)
|
48
|
+
end
|
49
|
+
|
50
|
+
# POST: /inbox/messages/delete
|
51
|
+
# Body { ids: [<list of ids to delete>] }
|
52
|
+
def delete
|
53
|
+
modify(type: CommandTower::InboxService::Message::Modify::DELETE)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def modify(type:)
|
59
|
+
result = CommandTower::InboxService::Message::Modify.(
|
60
|
+
user: current_user,
|
61
|
+
ids: params[:ids],
|
62
|
+
type:,
|
63
|
+
)
|
64
|
+
if result.success?
|
65
|
+
schema = result.modified
|
66
|
+
status = 200
|
67
|
+
schema_succesful!(status:, schema:)
|
68
|
+
else
|
69
|
+
invalid_arguments!(
|
70
|
+
status: 400,
|
71
|
+
message: result.msg,
|
72
|
+
argument_object: result.invalid_argument_hash,
|
73
|
+
schema: CommandTower::Schema::PlainText::LoginRequest
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CommandTower
|
4
|
+
class UserController < ::CommandTower::ApplicationController
|
5
|
+
include CommandTower::SchemaHelper
|
6
|
+
|
7
|
+
before_action :authenticate_user!
|
8
|
+
|
9
|
+
def show
|
10
|
+
schema = CommandTower::Schema::User.convert_user_object(user: current_user)
|
11
|
+
schema_succesful!(status: 200, schema:)
|
12
|
+
end
|
13
|
+
|
14
|
+
def modify
|
15
|
+
result = CommandTower::UserAttributes::Modify.(user: current_user, **modify_params)
|
16
|
+
if result.success?
|
17
|
+
schema = CommandTower::Schema::User.convert_user_object(user: current_user.reload)
|
18
|
+
status = 201
|
19
|
+
schema_succesful!(status:, schema:)
|
20
|
+
else
|
21
|
+
if result.invalid_arguments
|
22
|
+
invalid_arguments!(
|
23
|
+
status: 400,
|
24
|
+
message: result.msg,
|
25
|
+
argument_object: result.invalid_argument_hash,
|
26
|
+
schema: CommandTower::Schema::PlainText::LoginRequest
|
27
|
+
)
|
28
|
+
else
|
29
|
+
status = 500
|
30
|
+
schema = CommandTower::Schema::Error::Base.new(status:, message: result.msg)
|
31
|
+
render(json: schema.to_h, status:)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def modify_params
|
39
|
+
{
|
40
|
+
email: params[:email],
|
41
|
+
email_validated: safe_boolean(value: params[:email_validated]),
|
42
|
+
first_name: params[:first_name],
|
43
|
+
last_name: params[:last_name],
|
44
|
+
username: params[:username],
|
45
|
+
verifier_token: safe_boolean(value: params[:verifier_token]),
|
46
|
+
}.compact
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module CommandTower
|
2
|
+
class UsernameController < ::CommandTower::ApplicationController
|
3
|
+
|
4
|
+
# GET /username/available/:username
|
5
|
+
def username_availability
|
6
|
+
result = CommandTower::Username::Available.(username: params[:username])
|
7
|
+
|
8
|
+
if result.success?
|
9
|
+
json_result = {
|
10
|
+
username: {
|
11
|
+
available: result.available,
|
12
|
+
valid: result.valid,
|
13
|
+
description: CommandTower.config.username.username_failure_message
|
14
|
+
}
|
15
|
+
}
|
16
|
+
status = 200
|
17
|
+
else
|
18
|
+
json_result = { msg: result.msg }
|
19
|
+
json_result[:invalid_arguments] = true if result.invalid_arguments
|
20
|
+
status = 401
|
21
|
+
end
|
22
|
+
|
23
|
+
render json: json_result, status: status
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|