apicasso 0.2.16 → 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 +5 -5
- data/README.md +176 -176
- data/Rakefile +32 -32
- data/app/controllers/apicasso/application_controller.rb +124 -124
- data/app/controllers/apicasso/crud_controller.rb +211 -211
- data/app/controllers/concerns/orderable.rb +45 -45
- data/app/models/apicasso/ability.rb +38 -40
- data/app/models/apicasso/application_record.rb +6 -6
- data/app/models/apicasso/key.rb +25 -25
- data/app/models/apicasso/request.rb +8 -8
- data/config/routes.rb +14 -14
- data/db/migrate/20180826141433_create_apicasso_tables.rb +17 -17
- data/lib/apicasso/engine.rb +6 -6
- data/lib/apicasso/version.rb +3 -3
- data/lib/apicasso.rb +9 -9
- data/lib/generators/apicasso/install/install_generator.rb +25 -25
- data/lib/generators/apicasso/install/templates/create_apicasso_tables.rb +17 -17
- data/lib/tasks/apicasso_tasks.rake +4 -4
- metadata +2 -2
@@ -1,45 +1,45 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# This concern is used to provide abstract ordering based on `params[:sort]`
|
4
|
-
module Orderable
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
SORT_ORDER = { '+' => :asc, '-' => :desc }.freeze
|
7
|
-
|
8
|
-
# A list of the param names that can be used for ordering the model list
|
9
|
-
def ordering_params(params)
|
10
|
-
# For example it retrieves a list of orders in descending order of total_value.
|
11
|
-
# Within a specific total_value, older orders are ordered first
|
12
|
-
#
|
13
|
-
# GET /orders?sort=-total_value,created_at
|
14
|
-
# ordering_params(params) # => { total_value: :desc, created_at: :asc }
|
15
|
-
#
|
16
|
-
# Usage:
|
17
|
-
# Order.order(ordering_params(params))
|
18
|
-
ordering = {}
|
19
|
-
params[:sort].try(:split, ',').try(:each) do |attr|
|
20
|
-
parsed_attr = parse_attr attr
|
21
|
-
if model.attribute_names.include?(parsed_attr)
|
22
|
-
ordering[parsed_attr] = SORT_ORDER[parse_sign attr]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
ordering
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
# Parsing of attributes to avoid empty starts in case browser passes "+" as " "
|
31
|
-
def parse_attr(attr)
|
32
|
-
return attr.gsub(/^\ (.*)/, '\1') if attr.starts_with?(' ')
|
33
|
-
return attr[1..-1] if attr.starts_with?('+') || attr.starts_with?('-')
|
34
|
-
attr
|
35
|
-
end
|
36
|
-
|
37
|
-
# Ordering sign parse, which separates
|
38
|
-
def parse_sign(attr)
|
39
|
-
attr =~ /\A[+-]/ ? attr.slice!(0) : '+'
|
40
|
-
end
|
41
|
-
|
42
|
-
def model
|
43
|
-
(params[:resource] || params[:nested] || controller_name).classify.constantize
|
44
|
-
end
|
45
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This concern is used to provide abstract ordering based on `params[:sort]`
|
4
|
+
module Orderable
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
SORT_ORDER = { '+' => :asc, '-' => :desc }.freeze
|
7
|
+
|
8
|
+
# A list of the param names that can be used for ordering the model list
|
9
|
+
def ordering_params(params)
|
10
|
+
# For example it retrieves a list of orders in descending order of total_value.
|
11
|
+
# Within a specific total_value, older orders are ordered first
|
12
|
+
#
|
13
|
+
# GET /orders?sort=-total_value,created_at
|
14
|
+
# ordering_params(params) # => { total_value: :desc, created_at: :asc }
|
15
|
+
#
|
16
|
+
# Usage:
|
17
|
+
# Order.order(ordering_params(params))
|
18
|
+
ordering = {}
|
19
|
+
params[:sort].try(:split, ',').try(:each) do |attr|
|
20
|
+
parsed_attr = parse_attr attr
|
21
|
+
if model.attribute_names.include?(parsed_attr)
|
22
|
+
ordering[parsed_attr] = SORT_ORDER[parse_sign attr]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
ordering
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Parsing of attributes to avoid empty starts in case browser passes "+" as " "
|
31
|
+
def parse_attr(attr)
|
32
|
+
return attr.gsub(/^\ (.*)/, '\1') if attr.starts_with?(' ')
|
33
|
+
return attr[1..-1] if attr.starts_with?('+') || attr.starts_with?('-')
|
34
|
+
attr
|
35
|
+
end
|
36
|
+
|
37
|
+
# Ordering sign parse, which separates
|
38
|
+
def parse_sign(attr)
|
39
|
+
attr =~ /\A[+-]/ ? attr.slice!(0) : '+'
|
40
|
+
end
|
41
|
+
|
42
|
+
def model
|
43
|
+
(params[:resource] || params[:nested] || controller_name).classify.constantize
|
44
|
+
end
|
45
|
+
end
|
@@ -1,40 +1,38 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Apicasso
|
4
|
-
# Ability to parse a scope object from Apicasso::Key
|
5
|
-
class Ability
|
6
|
-
include CanCan::Ability
|
7
|
-
|
8
|
-
def initialize(key)
|
9
|
-
key ||= Apicasso::Key.new
|
10
|
-
cannot :manage, :all
|
11
|
-
cannot :read, :all
|
12
|
-
key.scope.each do |permission, klasses_clearances|
|
13
|
-
klasses_clearances.each do |
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apicasso
|
4
|
+
# Ability to parse a scope object from Apicasso::Key
|
5
|
+
class Ability
|
6
|
+
include CanCan::Ability
|
7
|
+
|
8
|
+
def initialize(key)
|
9
|
+
key ||= Apicasso::Key.new
|
10
|
+
cannot :manage, :all
|
11
|
+
cannot :read, :all
|
12
|
+
key.scope.each do |permission, klasses_clearances|
|
13
|
+
klasses_clearances.each do |klass, clearance|
|
14
|
+
if clearance == true
|
15
|
+
# Usage:
|
16
|
+
# To have a key reading all channels and all accouts
|
17
|
+
# you would have a scope:
|
18
|
+
# => `{read: {channel: true, accout: true}}`
|
19
|
+
can permission.to_sym, klass.underscore.to_sym
|
20
|
+
can permission.to_sym, klass.classify.constantize
|
21
|
+
elsif clearance.class == Hash
|
22
|
+
# Usage:
|
23
|
+
# To have a key reading all banners from a channel with id 999
|
24
|
+
# you would have a scope:
|
25
|
+
# => `{read: {banner: {owner_id: [999]}}}`
|
26
|
+
can permission.to_sym,
|
27
|
+
klass.underscore.to_sym
|
28
|
+
clearance.each do |by_field, values|
|
29
|
+
can permission.to_sym,
|
30
|
+
klass.classify.constantize,
|
31
|
+
by_field.to_sym => values
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
module Apicasso
|
2
|
-
class ApplicationRecord < ActiveRecord::Base
|
3
|
-
self.abstract_class = true
|
4
|
-
self.table_name_prefix = 'apicasso_'
|
5
|
-
end
|
6
|
-
end
|
1
|
+
module Apicasso
|
2
|
+
class ApplicationRecord < ActiveRecord::Base
|
3
|
+
self.abstract_class = true
|
4
|
+
self.table_name_prefix = 'apicasso_'
|
5
|
+
end
|
6
|
+
end
|
data/app/models/apicasso/key.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'securerandom'
|
4
|
-
module Apicasso
|
5
|
-
# A model to abstract API access, with scope options, token generation, request limiting
|
6
|
-
class Key < ApplicationRecord
|
7
|
-
before_create :set_auth_token
|
8
|
-
|
9
|
-
private
|
10
|
-
|
11
|
-
# Method that generates `SecureRandom.uuid` as token until
|
12
|
-
# an unique one has been acquired
|
13
|
-
def set_auth_token
|
14
|
-
loop do
|
15
|
-
self.token = generate_auth_token
|
16
|
-
break unless self.class.exists?(token: token)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# RFC4122 style token
|
21
|
-
def generate_auth_token
|
22
|
-
SecureRandom.uuid.delete('-')
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
module Apicasso
|
5
|
+
# A model to abstract API access, with scope options, token generation, request limiting
|
6
|
+
class Key < ApplicationRecord
|
7
|
+
before_create :set_auth_token
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# Method that generates `SecureRandom.uuid` as token until
|
12
|
+
# an unique one has been acquired
|
13
|
+
def set_auth_token
|
14
|
+
loop do
|
15
|
+
self.token = generate_auth_token
|
16
|
+
break unless self.class.exists?(token: token)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# RFC4122 style token
|
21
|
+
def generate_auth_token
|
22
|
+
SecureRandom.uuid.delete('-')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Apicasso
|
4
|
-
# A model to abstract API access, with scope options, token generation, request limiting
|
5
|
-
class Request < ApplicationRecord
|
6
|
-
belongs_to :api_key, class_name: 'Apicasso::Key'
|
7
|
-
end
|
8
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apicasso
|
4
|
+
# A model to abstract API access, with scope options, token generation, request limiting
|
5
|
+
class Request < ApplicationRecord
|
6
|
+
belongs_to :api_key, class_name: 'Apicasso::Key'
|
7
|
+
end
|
8
|
+
end
|
data/config/routes.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
Apicasso::Engine.routes.draw do
|
2
|
-
scope module: :apicasso do
|
3
|
-
resources :apidocs, only: [:index]
|
4
|
-
get '/:resource/', to: 'crud#index', via: :get
|
5
|
-
match '/:resource/', to: 'crud#create', via: :post
|
6
|
-
get '/:resource/:id', to: 'crud#show', via: :get
|
7
|
-
match '/:resource/:id', to: 'crud#update', via: :patch
|
8
|
-
match '/:resource/:id', to: 'crud#destroy', via: :delete
|
9
|
-
match '/:resource/:id/:nested/', to: 'crud#nested_index', via: :get
|
10
|
-
match '/:resource/', to: 'crud#schema', via: :options
|
11
|
-
match '/:resource/:id', to: 'crud#schema', via: :options
|
12
|
-
match '/:resource/:id/:nested/', to: 'crud#schema', via: :options
|
13
|
-
end
|
14
|
-
end
|
1
|
+
Apicasso::Engine.routes.draw do
|
2
|
+
scope module: :apicasso do
|
3
|
+
resources :apidocs, only: [:index]
|
4
|
+
get '/:resource/', to: 'crud#index', via: :get
|
5
|
+
match '/:resource/', to: 'crud#create', via: :post
|
6
|
+
get '/:resource/:id', to: 'crud#show', via: :get
|
7
|
+
match '/:resource/:id', to: 'crud#update', via: :patch
|
8
|
+
match '/:resource/:id', to: 'crud#destroy', via: :delete
|
9
|
+
match '/:resource/:id/:nested/', to: 'crud#nested_index', via: :get
|
10
|
+
match '/:resource/', to: 'crud#schema', via: :options
|
11
|
+
match '/:resource/:id', to: 'crud#schema', via: :options
|
12
|
+
match '/:resource/:id/:nested/', to: 'crud#schema', via: :options
|
13
|
+
end
|
14
|
+
end
|
@@ -1,17 +1,17 @@
|
|
1
|
-
class CreateApicassoTables < ActiveRecord::Migration[5.0]
|
2
|
-
def change
|
3
|
-
create_table :apicasso_keys, id: :uuid do |t|
|
4
|
-
t.json :scope
|
5
|
-
t.integer :scope_type
|
6
|
-
t.json :request_limiting
|
7
|
-
t.text :token
|
8
|
-
t.datetime :deleted_at
|
9
|
-
t.timestamps null: false
|
10
|
-
end
|
11
|
-
create_table :apicasso_requests, id: :uuid do |t|
|
12
|
-
t.text :api_key_id
|
13
|
-
t.json :object
|
14
|
-
t.timestamps null: false
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
1
|
+
class CreateApicassoTables < ActiveRecord::Migration[5.0]
|
2
|
+
def change
|
3
|
+
create_table :apicasso_keys, id: :uuid do |t|
|
4
|
+
t.json :scope
|
5
|
+
t.integer :scope_type
|
6
|
+
t.json :request_limiting
|
7
|
+
t.text :token
|
8
|
+
t.datetime :deleted_at
|
9
|
+
t.timestamps null: false
|
10
|
+
end
|
11
|
+
create_table :apicasso_requests, id: :uuid do |t|
|
12
|
+
t.text :api_key_id
|
13
|
+
t.json :object
|
14
|
+
t.timestamps null: false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/apicasso/engine.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Apicasso
|
4
|
-
class Engine < ::Rails::Engine
|
5
|
-
end
|
6
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apicasso
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
end
|
6
|
+
end
|
data/lib/apicasso/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Apicasso
|
2
|
-
VERSION = '0.
|
3
|
-
end
|
1
|
+
module Apicasso
|
2
|
+
VERSION = '0.3.0'
|
3
|
+
end
|
data/lib/apicasso.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'apicasso/version'
|
4
|
-
require 'apicasso/engine'
|
5
|
-
require 'apicasso/active_record_extension'
|
6
|
-
|
7
|
-
module Apicasso
|
8
|
-
# Your code goes here...
|
9
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apicasso/version'
|
4
|
+
require 'apicasso/engine'
|
5
|
+
require 'apicasso/active_record_extension'
|
6
|
+
|
7
|
+
module Apicasso
|
8
|
+
# Your code goes here...
|
9
|
+
end
|
@@ -1,25 +1,25 @@
|
|
1
|
-
require 'rails/generators/migration'
|
2
|
-
|
3
|
-
module Apicasso
|
4
|
-
module Generators
|
5
|
-
class InstallGenerator < ::Rails::Generators::Base
|
6
|
-
include Rails::Generators::Migration
|
7
|
-
source_root File.expand_path('../templates', __FILE__)
|
8
|
-
desc 'Add the required migrations to run APIcasso'
|
9
|
-
|
10
|
-
def self.next_migration_number(path)
|
11
|
-
if @prev_migration_nr
|
12
|
-
@prev_migration_nr += 1
|
13
|
-
else
|
14
|
-
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
15
|
-
end
|
16
|
-
@prev_migration_nr.to_s
|
17
|
-
end
|
18
|
-
|
19
|
-
def copy_migrations
|
20
|
-
migration_template 'create_apicasso_tables.rb',
|
21
|
-
'db/migrate/create_apicasso_tables.rb'
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
1
|
+
require 'rails/generators/migration'
|
2
|
+
|
3
|
+
module Apicasso
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
desc 'Add the required migrations to run APIcasso'
|
9
|
+
|
10
|
+
def self.next_migration_number(path)
|
11
|
+
if @prev_migration_nr
|
12
|
+
@prev_migration_nr += 1
|
13
|
+
else
|
14
|
+
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
15
|
+
end
|
16
|
+
@prev_migration_nr.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def copy_migrations
|
20
|
+
migration_template 'create_apicasso_tables.rb',
|
21
|
+
'db/migrate/create_apicasso_tables.rb'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,17 +1,17 @@
|
|
1
|
-
class CreateApicassoTables < ActiveRecord::Migration[5.0]
|
2
|
-
def change
|
3
|
-
create_table :apicasso_keys, id: :uuid do |t|
|
4
|
-
t.json :scope
|
5
|
-
t.integer :scope_type
|
6
|
-
t.json :request_limiting
|
7
|
-
t.text :token
|
8
|
-
t.datetime :deleted_at
|
9
|
-
t.timestamps null: false
|
10
|
-
end
|
11
|
-
create_table :apicasso_requests, id: :uuid do |t|
|
12
|
-
t.text :api_key_id
|
13
|
-
t.json :object
|
14
|
-
t.timestamps null: false
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
1
|
+
class CreateApicassoTables < ActiveRecord::Migration[5.0]
|
2
|
+
def change
|
3
|
+
create_table :apicasso_keys, id: :uuid do |t|
|
4
|
+
t.json :scope
|
5
|
+
t.integer :scope_type
|
6
|
+
t.json :request_limiting
|
7
|
+
t.text :token
|
8
|
+
t.datetime :deleted_at
|
9
|
+
t.timestamps null: false
|
10
|
+
end
|
11
|
+
create_table :apicasso_requests, id: :uuid do |t|
|
12
|
+
t.text :api_key_id
|
13
|
+
t.json :object
|
14
|
+
t.timestamps null: false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# desc "Explaining what the task does"
|
2
|
-
# task :apicasso do
|
3
|
-
# # Task goes here
|
4
|
-
# end
|
1
|
+
# desc "Explaining what the task does"
|
2
|
+
# task :apicasso do
|
3
|
+
# # Task goes here
|
4
|
+
# end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apicasso
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fernando Bellincanta
|
@@ -134,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
134
|
version: '0'
|
135
135
|
requirements: []
|
136
136
|
rubyforge_project:
|
137
|
-
rubygems_version: 2.
|
137
|
+
rubygems_version: 2.6.14
|
138
138
|
signing_key:
|
139
139
|
specification_version: 4
|
140
140
|
summary: An abstract API design as a mountable engine
|