atomic_admin 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +16 -0
- data/Rakefile +8 -0
- data/app/controllers/atomic_admin/application_controller.rb +23 -0
- data/app/controllers/atomic_admin/atomic_lti_install_controller.rb +36 -0
- data/app/controllers/atomic_admin/atomic_lti_platform_controller.rb +43 -0
- data/app/controllers/atomic_admin/atomic_tenant_client_id_strategy_controller.rb +54 -0
- data/app/controllers/atomic_admin/atomic_tenant_deployment_controller.rb +76 -0
- data/app/controllers/atomic_admin/atomic_tenant_platform_guid_strategy_controller.rb +54 -0
- data/app/jobs/atomic_admin/application_job.rb +4 -0
- data/app/mailers/atomic_admin/application_mailer.rb +6 -0
- data/app/models/atomic_admin/application_record.rb +5 -0
- data/config/routes.rb +13 -0
- data/lib/atomic_admin/engine.rb +6 -0
- data/lib/atomic_admin/jwt_token.rb +81 -0
- data/lib/atomic_admin/version.rb +3 -0
- data/lib/atomic_admin.rb +7 -0
- data/lib/tasks/atomic_admin_tasks.rake +4 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8ed8016c6474ebe66207d09ec1c66e42da12989c862dd1b7cdab433f8556b717
|
4
|
+
data.tar.gz: f6e57e1aa7917a06ce6854c2edcf77310526a402f5f709d43462bd45936e2e6e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 106d1dd8d2682945e602ac85eb5eab431f8fff57f83f9849e36a99c50b0cd462e50607afef5e2eb9889683b8009eef30db0ce6dca61bada38edd7f83d20983d0
|
7
|
+
data.tar.gz: 8ddda300ce1e5d949349c8ac20802153236a3742bff41cff35ea31500fb5b5502606f0df544e2dfe006b766ba02e847d85fd2d74c845565cf135e3b32f890a82
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2022 Atomic Jolt
|
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,16 @@
|
|
1
|
+
# atomic_admin
|
2
|
+
Engine to provide apis that power the atomic jolt admin app
|
3
|
+
|
4
|
+
# Usage
|
5
|
+
|
6
|
+
Add the gem to your project:
|
7
|
+
gem 'atomic_admin', git: 'https://github.com/atomicjolt/atomic_admin.git', tag: '0.1.0'
|
8
|
+
|
9
|
+
Add the following to routes.rb:
|
10
|
+
```
|
11
|
+
namespace :api do
|
12
|
+
namespace :admin do
|
13
|
+
mount AtomicAdmin::Engine => "/"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module AtomicAdmin
|
2
|
+
class ApplicationController < ActionController::API
|
3
|
+
include AtomicAdmin::JwtToken
|
4
|
+
# before_action :authenticate_user! # Use validate_token instead for now
|
5
|
+
before_action :validate_admin_app_token
|
6
|
+
before_action :validate_token
|
7
|
+
before_action :only_admins!
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def only_admins!
|
12
|
+
return if @admin_app_validated
|
13
|
+
|
14
|
+
user_not_authorized unless current_user.admin?
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def user_not_authorized(message = "Not Authorized")
|
19
|
+
render json: { message: message, }, status: 401
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module AtomicAdmin
|
2
|
+
class AtomicLtiInstallController < ApplicationController
|
3
|
+
def install_params
|
4
|
+
params.permit(:iss, :client_id)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find_install
|
8
|
+
AtomicLti::Install.find_by(id: params[:id])
|
9
|
+
end
|
10
|
+
|
11
|
+
def index
|
12
|
+
render json: AtomicLti::Install.all.order(:id).paginate(page: params[:page], per_page: 30)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
AtomicLti::Install.create!(install_params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def show
|
20
|
+
install = find_install
|
21
|
+
render json: install
|
22
|
+
end
|
23
|
+
|
24
|
+
def update
|
25
|
+
install = find_install
|
26
|
+
result = install.update!(install_params)
|
27
|
+
render json: result
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy
|
31
|
+
install = find_install
|
32
|
+
install.destroy
|
33
|
+
render json: install
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module AtomicAdmin
|
2
|
+
class AtomicLtiPlatformController < ApplicationController
|
3
|
+
def platform_params
|
4
|
+
params.permit(:iss, :jwks_url, :token_url, :oidc_url)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find_platform
|
8
|
+
AtomicLti::Platform.find_by(id: params[:id])
|
9
|
+
end
|
10
|
+
|
11
|
+
def index
|
12
|
+
page = AtomicLti::Platform.all.order(:id).paginate(page: params[:page], per_page: 30)
|
13
|
+
|
14
|
+
render json: {
|
15
|
+
platforms: page,
|
16
|
+
page: params[:page],
|
17
|
+
total_pages: page.total_pages
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
platform = AtomicLti::Platform.create!(platform_params)
|
23
|
+
render json: { platform: platform }
|
24
|
+
end
|
25
|
+
|
26
|
+
def show
|
27
|
+
platform = find_platform
|
28
|
+
render json: platform
|
29
|
+
end
|
30
|
+
|
31
|
+
def update
|
32
|
+
platform = find_platform
|
33
|
+
platform.update!(platform_params)
|
34
|
+
render json: { platform: find_platform }
|
35
|
+
end
|
36
|
+
|
37
|
+
def destroy
|
38
|
+
platform = find_platform
|
39
|
+
platform.destroy
|
40
|
+
render json: platform
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module AtomicAdmin
|
2
|
+
class AtomicTenantClientIdStrategyController < ApplicationController
|
3
|
+
def pinned_client_id_params
|
4
|
+
params.permit(:iss, :client_id, :application_instance_id)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find_pinned_client_id
|
8
|
+
AtomicTenant::PinnedClientId.find_by(id: params[:id])
|
9
|
+
end
|
10
|
+
|
11
|
+
def search
|
12
|
+
page = AtomicTenant::PinnedClientId
|
13
|
+
.where(application_instance_id: params[:application_instance_id])
|
14
|
+
.order(:id).paginate(page: params[:page], per_page: 30)
|
15
|
+
render json: {
|
16
|
+
pinned_client_ids: page,
|
17
|
+
page: params[:page],
|
18
|
+
total_pages: page.total_pages
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# def index
|
23
|
+
# page = AtomicTenant::PinnedClientId.all.order(:id).paginate(page: params[:page], per_page: 30)
|
24
|
+
# render json: {
|
25
|
+
# pinned_client_ids: page,
|
26
|
+
# page: params[:page],
|
27
|
+
# total_pages: page.total_pages
|
28
|
+
# }
|
29
|
+
# end
|
30
|
+
|
31
|
+
def create
|
32
|
+
result = AtomicTenant::PinnedClientId.create!(pinned_client_id_params)
|
33
|
+
render json: { pinned_client_id: result }
|
34
|
+
end
|
35
|
+
|
36
|
+
def show
|
37
|
+
pinned_client_id = find_pinned_client_id
|
38
|
+
render json: {pinned_client_id: pinned_client_id}
|
39
|
+
end
|
40
|
+
|
41
|
+
# def update
|
42
|
+
# pinned_client_id = find_pinned_client_id
|
43
|
+
# pinned_client_id.update!(pinned_client_id_params)
|
44
|
+
|
45
|
+
# render json: {pinned_client_id: find_pinned_client_id}
|
46
|
+
# end
|
47
|
+
|
48
|
+
def destroy
|
49
|
+
pinned_client_id = find_pinned_client_id
|
50
|
+
pinned_client_id.destroy
|
51
|
+
render json: { pinned_client_id: pinned_client_id }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module AtomicAdmin
|
2
|
+
class AtomicTenantDeploymentController < ApplicationController
|
3
|
+
def deployment_params
|
4
|
+
params.permit(:iss, :deployment_id, :application_instance_id)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find_deployment
|
8
|
+
AtomicTenant::LtiDeployment.find_by(id: params[:id])
|
9
|
+
end
|
10
|
+
|
11
|
+
def search
|
12
|
+
tenant_deployments = AtomicTenant::LtiDeployment
|
13
|
+
.where(application_instance_id: params[:application_instance_id])
|
14
|
+
.order(:id)
|
15
|
+
.paginate(page: params[:page], per_page: 30)
|
16
|
+
|
17
|
+
page_ids = tenant_deployments.pluck(:iss, :deployment_id)
|
18
|
+
|
19
|
+
pairs = page_ids.reduce({}) do |acc, c|
|
20
|
+
iss = c[0]
|
21
|
+
deployment_id = c[1]
|
22
|
+
|
23
|
+
acc[iss] = [] if acc[iss].nil?
|
24
|
+
|
25
|
+
acc[iss].push(deployment_id)
|
26
|
+
acc
|
27
|
+
end
|
28
|
+
|
29
|
+
page = pairs.reduce([]) do |acc, pair|
|
30
|
+
iss = pair[0]
|
31
|
+
deployment_ids = pair[1]
|
32
|
+
|
33
|
+
deployments = AtomicLti.get_deployments(iss: iss, deployment_ids: deployment_ids)
|
34
|
+
acc.concat(deployments)
|
35
|
+
end
|
36
|
+
|
37
|
+
render json: {
|
38
|
+
deployments: page,
|
39
|
+
page: params[:page],
|
40
|
+
total_pages: tenant_deployments.total_pages
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
# def index
|
45
|
+
# page = AtomicTenant::LtiDeployment.all.order(:id).paginate(page: params[:page], per_page: 30)
|
46
|
+
# render json: {
|
47
|
+
# deployments: page,
|
48
|
+
# page: params[:page],
|
49
|
+
# total_pages: page.total_pages
|
50
|
+
# }
|
51
|
+
# end
|
52
|
+
|
53
|
+
def create
|
54
|
+
result = AtomicTenant::LtiDeployment.create!(deployment_params)
|
55
|
+
render json: { deployment: result }
|
56
|
+
end
|
57
|
+
|
58
|
+
def show
|
59
|
+
deployment = find_deployment
|
60
|
+
render json: { deployment: deployment }
|
61
|
+
end
|
62
|
+
|
63
|
+
# def update
|
64
|
+
# deployment = find_deployment
|
65
|
+
# deployment.update!(deployment_params)
|
66
|
+
|
67
|
+
# render json: {deployment: find_deployment}
|
68
|
+
# end
|
69
|
+
|
70
|
+
def destroy
|
71
|
+
deployment = find_deployment
|
72
|
+
deployment.destroy
|
73
|
+
render json: { deployment: deployment }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module AtomicAdmin
|
2
|
+
class AtomicTenantPlatformGuidStrategyController < ApplicationController
|
3
|
+
def pinned_platform_guid_params
|
4
|
+
params.permit(:iss, :platform_guid, :application_id, :application_instance_id)
|
5
|
+
end
|
6
|
+
|
7
|
+
def find_pinned_platform_guid
|
8
|
+
AtomicTenant::PinnedPlatformGuid.find(params[:id])
|
9
|
+
end
|
10
|
+
|
11
|
+
def search
|
12
|
+
page = AtomicTenant::PinnedPlatformGuid
|
13
|
+
.where(application_instance_id: params[:application_instance_id])
|
14
|
+
.order(:id).paginate(page: params[:page], per_page: 30)
|
15
|
+
render json: {
|
16
|
+
pinned_platform_guids: page,
|
17
|
+
page: params[:page],
|
18
|
+
total_pages: page.total_pages
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# def index
|
23
|
+
# page = AtomicTenant::PinnedPlatformGuid.all.order(:id).paginate(page: params[:page], per_page: 30)
|
24
|
+
# render json: {
|
25
|
+
# pinned_platform_guids: page,
|
26
|
+
# page: params[:page],
|
27
|
+
# total_pages: page.total_pages
|
28
|
+
# }
|
29
|
+
# end
|
30
|
+
|
31
|
+
def create
|
32
|
+
result = AtomicTenant::PinnedPlatformGuid.create!(pinned_platform_guid_params)
|
33
|
+
render json: { pinned_platform_guid: result }
|
34
|
+
end
|
35
|
+
|
36
|
+
def show
|
37
|
+
pinned_platform_guid = find_pinned_platform_guid
|
38
|
+
render json: {pinned_platform_guid: pinned_platform_guid}
|
39
|
+
end
|
40
|
+
|
41
|
+
def update
|
42
|
+
pinned_platform_guid = find_pinned_platform_guid
|
43
|
+
pinned_platform_guid.update!(pinned_platform_guid_params)
|
44
|
+
|
45
|
+
render json: {pinned_platform_guid: find_pinned_platform_guid}
|
46
|
+
end
|
47
|
+
|
48
|
+
def destroy
|
49
|
+
pinned_platform_guid = find_pinned_platform_guid
|
50
|
+
pinned_platform_guid.destroy
|
51
|
+
render json: { pinned_platform_guid: pinned_platform_guid }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
AtomicAdmin::Engine.routes.draw do
|
2
|
+
# namespace :lti do
|
3
|
+
resources :atomic_lti_platform
|
4
|
+
resources :atomic_lti_install
|
5
|
+
resources :atomic_tenant_deployment
|
6
|
+
post '/atomic_tenant_deployment/search', to: 'atomic_tenant_deployment#search'
|
7
|
+
|
8
|
+
resources :atomic_tenant_platform_guid_strategy
|
9
|
+
post '/atomic_tenant_platform_guid_strategy/search', to: 'atomic_tenant_platform_guid_strategy#search'
|
10
|
+
post '/atomic_tenant_client_id_strategy/search', to: 'atomic_tenant_client_id_strategy#search'
|
11
|
+
|
12
|
+
resources :atomic_tenant_client_id_strategy
|
13
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
## Note: This code is basically copied out of the starter app to authenticate
|
2
|
+
## admin app api calls. Lives at /app/controllers/concerns/jwt_token.rb in
|
3
|
+
## starter app
|
4
|
+
module AtomicAdmin
|
5
|
+
module JwtToken
|
6
|
+
|
7
|
+
ALGORITHM = "HS512".freeze
|
8
|
+
|
9
|
+
class InvalidTokenError < StandardError; end
|
10
|
+
|
11
|
+
def self.valid?(token, secret = nil, algorithm = ALGORITHM)
|
12
|
+
decode(token, secret, true, algorithm)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.decode(token, secret = nil, validate = true, algorithm = ALGORITHM)
|
16
|
+
JWT.decode(
|
17
|
+
token,
|
18
|
+
secret || Rails.application.secrets.auth0_client_secret,
|
19
|
+
validate,
|
20
|
+
{ algorithm: algorithm },
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
def decoded_jwt_token(req, secret = nil)
|
25
|
+
token = AtomicAdmin::JwtToken.valid?(encoded_token(req), secret)
|
26
|
+
raise InvalidTokenError, "Unable to decode jwt token" if token.blank?
|
27
|
+
raise InvalidTokenError, "Invalid token payload" if token.empty?
|
28
|
+
|
29
|
+
token[0]
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate_token
|
33
|
+
return if @admin_app_validated
|
34
|
+
|
35
|
+
token = decoded_jwt_token(request)
|
36
|
+
raise InvalidTokenError if Rails.application.secrets.auth0_client_id != token["aud"]
|
37
|
+
|
38
|
+
current_application_instance_id = request.env['atomic.validated.application_instance_id']
|
39
|
+
if current_application_instance_id && current_application_instance_id != token["application_instance_id"]
|
40
|
+
raise InvalidTokenError
|
41
|
+
end
|
42
|
+
|
43
|
+
@user_tenant = token["user_tenant"] if token["user_tenant"].present?
|
44
|
+
@user = User.find(token["user_id"])
|
45
|
+
|
46
|
+
sign_in(@user, event: :authentication, store: false)
|
47
|
+
rescue JWT::DecodeError, InvalidTokenError => e
|
48
|
+
Rails.logger.error "JWT Error occured #{e.inspect}"
|
49
|
+
begin
|
50
|
+
render json: { error: "Unauthorized: Invalid token." }, status: :unauthorized
|
51
|
+
rescue NoMethodError
|
52
|
+
raise GraphQL::ExecutionError, "Unauthorized: Invalid token."
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_admin_app_token
|
57
|
+
_bearer, jwt = request.headers['Authorization'].split(' ')
|
58
|
+
@atomic_admin_params = AtomicAdmin::JwtToken.decode(jwt, Rails.application.secrets.atomic_admin_shared_key)
|
59
|
+
@admin_app_validated = true
|
60
|
+
rescue JWT::DecodeError, InvalidTokenError => e
|
61
|
+
# fall back to regular app jwt
|
62
|
+
Rails.logger.error "JWT Error occured with admin app token #{e.inspect}"
|
63
|
+
@admin_app_validated = false
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
def encoded_token(req)
|
69
|
+
return req.params[:jwt] if req.params[:jwt]
|
70
|
+
|
71
|
+
header = req.headers["Authorization"] || req.headers[:authorization]
|
72
|
+
raise InvalidTokenError, "No authorization header found" if header.nil?
|
73
|
+
|
74
|
+
token = header.split(" ").last
|
75
|
+
raise InvalidTokenError, "Invalid authorization header string" if token.nil?
|
76
|
+
|
77
|
+
token
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
data/lib/atomic_admin.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: atomic_admin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nick Benoit
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-08-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '7.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '7.0'
|
27
|
+
description: Engine to provide apis that power the atomic jolt admin app
|
28
|
+
email:
|
29
|
+
- nick.benoit@atomicjolt.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- MIT-LICENSE
|
35
|
+
- README.md
|
36
|
+
- Rakefile
|
37
|
+
- app/controllers/atomic_admin/application_controller.rb
|
38
|
+
- app/controllers/atomic_admin/atomic_lti_install_controller.rb
|
39
|
+
- app/controllers/atomic_admin/atomic_lti_platform_controller.rb
|
40
|
+
- app/controllers/atomic_admin/atomic_tenant_client_id_strategy_controller.rb
|
41
|
+
- app/controllers/atomic_admin/atomic_tenant_deployment_controller.rb
|
42
|
+
- app/controllers/atomic_admin/atomic_tenant_platform_guid_strategy_controller.rb
|
43
|
+
- app/jobs/atomic_admin/application_job.rb
|
44
|
+
- app/mailers/atomic_admin/application_mailer.rb
|
45
|
+
- app/models/atomic_admin/application_record.rb
|
46
|
+
- config/routes.rb
|
47
|
+
- lib/atomic_admin.rb
|
48
|
+
- lib/atomic_admin/engine.rb
|
49
|
+
- lib/atomic_admin/jwt_token.rb
|
50
|
+
- lib/atomic_admin/version.rb
|
51
|
+
- lib/tasks/atomic_admin_tasks.rake
|
52
|
+
homepage: https://github.com/atomicjolt/atomic_admin/
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata:
|
56
|
+
homepage_uri: https://github.com/atomicjolt/atomic_admin/
|
57
|
+
source_code_uri: https://github.com/atomicjolt/atomic_admin/
|
58
|
+
changelog_uri: https://github.com/atomicjolt/atomic_admin/
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubygems_version: 3.4.15
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Engine to provide apis that power the atomic jolt admin app
|
78
|
+
test_files: []
|