model_driven_api 3.1.10 → 3.1.12

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 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