model_driven_api 3.1.10 → 3.1.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0afb3dc1dca5b7277c7ea2bfd601669765d5227fe68ede17fa6fbfc3de19d36f
4
- data.tar.gz: 02c3ece69e6237b42f8f04de6660469d528c81a84cf392a34a743360b765d832
3
+ metadata.gz: 9d01d90d7ec2ea3620ce94fe7343c78b4a410b1a36be50727eee2eeeeaeef4c2
4
+ data.tar.gz: 5dfdd6800dba34d112febcdfc2e292f6c3b499fe8dcb886c24a8506baeb0b9a4
5
5
  SHA512:
6
- metadata.gz: 92c3d537101cb23123ce34564eaac4fe1d767770628dddcd1cc94487253bb82c880e07721a78c2be3dc571c370020b12e13ab30e9981d035c7766634dccdeb7b
7
- data.tar.gz: 69385bf1c20fe26e8168be63da529edb847002984084e133e431aef6b07815bb88edf1f42ed43d65dc0ef5194a28ede011c29f05aca3de0176dd11a119da3a8a
6
+ metadata.gz: 5a00471f793e5cd7a829ddfedd4c2e947c63a7ecc727900f4b41bf4e6bb336aa19a2fcf504ecd81b3e2b861882924573a94e548592b8e0aae294e070db6a4177
7
+ data.tar.gz: bb79bf086d32464868aa24ee9508f5f9f14be291bab9ffadd5d7c307ebb3ab83eb7554804db505312464a1aefdd6afbab45a8ada6d3585813a5ec273d2f1ce7b
@@ -139,7 +139,7 @@ class Api::V2::InfoController < Api::V2::ApplicationController
139
139
  "post": {
140
140
  "summary": "Authenticate",
141
141
  "tags": ["Authentication"],
142
- "description": "Authenticate the user and return a JWT token in the header and the current user as body",
142
+ "description": "Authenticate the user and return a JWT token in the header and the current user as body.",
143
143
  "security": [
144
144
  "basicAuth": []
145
145
  ],
@@ -414,7 +414,7 @@ class Api::V2::InfoController < Api::V2::ApplicationController
414
414
  "/info/swagger": {
415
415
  "get": {
416
416
  "summary": "Swagger",
417
- "description": "Returns the Swagger",
417
+ "description": "Returns the self generated Swagger for all the models in the App.",
418
418
  "tags": ["Info"],
419
419
  "responses": {
420
420
  "200": {
@@ -515,49 +515,17 @@ class Api::V2::InfoController < Api::V2::ApplicationController
515
515
  }
516
516
  }
517
517
  # Non CRUD or Search, but custom, usually bulk operations endpoints
518
- custom_actions = d.methods(false).select do |m| m.to_s.starts_with?("custom_action_") end
519
- # Add also custom actions created using th enew Endpoints Interface
520
- custom_actions += "Endpoints::#{d.model_name.name}".constantize.methods(false) rescue []
521
- custom_actions.each do |action|
522
- custom_action_name = action.to_s.gsub("custom_action_", "")
523
- pivot["/#{model}/custom_action/#{custom_action_name}"] = {
524
- "get": {
525
- "summary": "Custom Action #{custom_action_name.titleize}",
526
- "description": "This is just an example of a custom action, they can accept a wide range of payloads and response with a wide range of responses, also all verbs are valid. Please refer to the documentation for more information.",
527
- "tags": [model.classify],
528
- "security": [
529
- "bearerAuth": []
530
- ],
531
- "responses": {
532
- "200": {
533
- "description": "Custom Action",
534
- "content": {
535
- "application/json": {
536
- "schema": {
537
- "type": "object",
538
- "properties": {
539
- "id": {
540
- "type": "integer"
541
- },
542
- "created_at": {
543
- "type": "string",
544
- "format": "date-time"
545
- },
546
- "updated_at": {
547
- "type": "string",
548
- "format": "date-time"
549
- }
550
- }
551
- }
552
- }
553
- }
554
- },
555
- "404": {
556
- "description": "No #{model} found"
557
- }
558
- }
559
- }
560
- }
518
+ new_custom_actions = ("Endpoints::#{d.model_name.name}".constantize.instance_methods(false) rescue [])
519
+ # Rails.logger.debug "New Custom Actions (#{d.model_name.name}): #{new_custom_actions}"
520
+ new_custom_actions.each do |action|
521
+ openapi_definition = "Endpoints::#{d.model_name.name}".constantize.definitions[action.to_sym] rescue false
522
+
523
+ # Add the tag to the openapi definition
524
+ openapi_definition.each do |k, v|
525
+ v[:tags] = [ d.model_name.name ]
526
+ end
527
+
528
+ pivot["/#{model}/custom_action/#{action}"] = openapi_definition if openapi_definition
561
529
  end
562
530
  pivot["/#{model}/search"] = {
563
531
  # Complex queries are made using ranskac search via a post endpoint
@@ -1,56 +1,78 @@
1
1
  class Endpoints::TestApi < NonCrudEndpoints
2
- def test(params)
3
- # Define an explain var to be used to validate and document the action behavior when using ?explain=true in query string
4
- explain = {
5
- verbs: ["GET", "POST"],
6
- body: {
7
- messages: {
8
- type: :array,
9
- optional: true,
10
- items: {
11
- type: :string,
12
- optional: false
2
+ self.desc :test, {
3
+ # Define the action name using openapi swagger format
4
+ get: {
5
+ summary: "Test API Custom Action",
6
+ description: "This is a test API custom action",
7
+ operationId: "test",
8
+ tags: ["Test"],
9
+ parameters: [
10
+ {
11
+ name: "explain",
12
+ in: "query",
13
+ description: "Explain the action by returning this openapi schema",
14
+ required: true,
15
+ schema: {
16
+ type: "boolean"
13
17
  }
14
- },
15
- is_connected: {
16
- type: :boolean,
17
- optional: false
18
- },
19
- user: {
20
- type: :object,
21
- optional: true,
22
- properties: {
23
- name: {
24
- type: :string,
25
- optional: false
26
- },
27
- age: {
28
- type: :integer,
29
- optional: true
18
+ }
19
+ ],
20
+ responses: {
21
+ 200 => {
22
+ description: "The openAPI json schema for this action",
23
+ content: {
24
+ "application/json": {
25
+ schema: {
26
+ type: "object",
27
+ additionalProperties: true
28
+ }
30
29
  }
31
30
  }
31
+ },
32
+ 501 => {
33
+ error: :string,
32
34
  }
33
- },
34
- query: {
35
- explain: {
36
- type: :boolean,
37
- optional: true
35
+ }
36
+ },
37
+ post: {
38
+ summary: "Test API Custom Action",
39
+ description: "This is a test API custom action",
40
+ operationId: "test",
41
+ tags: ["Test"],
42
+ requestBody: {
43
+ required: true,
44
+ content: {
45
+ "application/json": {}
38
46
  }
39
47
  },
40
48
  responses: {
41
49
  200 => {
42
- message: :string,
43
- params: {},
50
+ description: "The openAPI json schema for this action",
51
+ # This will return the object with a message string and a params object
52
+ content: {
53
+ "application/json": {
54
+ schema: {
55
+ type: "object",
56
+ properties: {
57
+ message: {
58
+ type: "string"
59
+ },
60
+ params: {
61
+ type: "object",
62
+ additionalProperties: true
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
44
68
  },
45
69
  501 => {
46
70
  error: :string,
47
- },
48
- },
71
+ }
72
+ }
49
73
  }
50
- return explain, 200 if params[:explain].to_s == "true" && !explain.blank?
51
-
52
-
74
+ }
75
+ def test(params)
53
76
  return { message: "Hello World From Test API Custom Action called test", params: params }, 200
54
77
  end
55
78
  end
56
- # end
@@ -1,3 +1,3 @@
1
1
  module ModelDrivenApi
2
- VERSION = "3.1.10".freeze
2
+ VERSION = "3.1.12".freeze
3
3
  end
@@ -1,37 +1,34 @@
1
1
  class NonCrudEndpoints
2
2
  attr_accessor :result
3
+ cattr_accessor :definitions
4
+ self.definitions = {}
3
5
  # Add a validation method which will be inherited by all the instances, and automatically run before any method call
4
6
  def initialize(m, params)
5
7
  # Check if self hase the m method, if not, raise a NoMethodError
6
- raise NoMethodError, "The method #{m} does not exist in #{self.class}" unless self.respond_to? m
7
- definition = self.send(m, { explain: true }) rescue []
8
- validate_request(definition.first.presence || {}, params)
8
+ raise NoMethodError, "The method #{m} does not exist in #{self.class.name}" unless self.respond_to? m
9
+ @definition = self.definitions[m.to_sym].with_indifferent_access
10
+
11
+ # self.send(m, { explain: true }) rescue []
12
+ validate_request(params)
9
13
  @result = self.send(m, params)
10
14
  end
11
15
 
12
- def validate_request(definition, params)
16
+ def validate_request(params)
13
17
  # If there is no definition, return
14
- return if definition.blank?
15
- # puts "Called Class is: #{self.class}"
16
- # puts "Which is son of: #{self.class.superclass}"
17
- body_mandatory_keys = definition[:body].select { |k, v| v[:optional] == false }.keys
18
- query_mandatory_keys = definition[:query].select { |k, v| v[:optional] == false }.keys
19
- # Raise a ValidationError if the request does not match the definition
20
- raise EndpointValidationError, "The verb \"#{params[:request_verb].presence || "No Verb Provided"}\" is not present in #{definition[:verbs].join(", ")}." if definition[:verbs].exclude? params[:request_verb]
21
- # Raise an exception if the verb is put or post and the body keys in definition are not all present as params keys, both params and definition[:body] can have nested objects
22
- raise EndpointValidationError, "The request body does not match the definition: in #{params[:request_verb]} requests all of the params must be present in definition. The body definition is #{definition[:body]}." if params[:request_verb] != "GET" && (body_mandatory_keys & params.keys) != body_mandatory_keys
23
- # Raise an exception if the verb is put or post and the body keys in definition are not all present as params keys, both params and definition[:body] can have nested objects
24
- raise EndpointValidationError, "The request query does not match the definition. The query definition is: #{definition[:query]}." if (query_mandatory_keys & params.keys) != query_mandatory_keys
25
- # Rais if the type of the param is not the same as the definition
26
- definition[:body].each do |k, v|
27
- next if params[k].nil?
28
- computed_type = get_type(params[k])
29
- raise EndpointValidationError, "The type of the param #{k} is not the same as the definition. The definition is #{v[:type]} and the param is #{computed_type}." if v[:type] != computed_type
30
- end
18
+ return if @definition.blank?
19
+
20
+ # Raise a ValidationError if the request does not match the definition of the verbs expected in the @definition hash
21
+ #raise EndpointValidationError, "The verb \"#{params[:request_verb].presence || "No Verb Provided"}\" is not present in #{@definition.keys.join(", ")}." if @definition.keys.exclude? params[:request_verb]
22
+ # Assuming @definition follows the openapi schema, we can check the request body and query parameters are correct
23
+
31
24
  end
32
25
 
33
26
  private
34
27
 
28
+ def self.desc(key, definition)
29
+ self.definitions[key] = definition
30
+ end
31
+
35
32
  def get_type(type)
36
33
  case type
37
34
  when String
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: model_driven_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.10
4
+ version: 3.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriele Tassoni
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-18 00:00:00.000000000 Z
11
+ date: 2024-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thecore_backend_commons