shrine-lambda 0.0.1 → 0.1.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/CHANGELOG.md +20 -3
- data/README.md +2 -2
- data/lib/shrine/plugins/shrine-lambda.rb +83 -62
- data/shrine-lambda.gemspec +9 -7
- metadata +63 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: de0b2ec23b85a7b74eab35936b6f031abc89251d1bfa487de9b6d3b8890f1ac1
|
4
|
+
data.tar.gz: 89969c5aa88c8793c24dec44f2434acf604b6e0fda20688c1e01e96e1b4a8d23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96593e09066a0600ef0669d6be98a040764f646899ffac2c2f18a72491b39bcd9ebd5b47c930f8454d9ab99f4779263dd48d8cd2b26410ba84fb1211ea9b087e
|
7
|
+
data.tar.gz: 47d53b565d9dcf0783630e42674e24761c9311a7f59048794aea7f7ab46e48f25e5ef7a98f39ad377874ae4f0370a5341c778dedd84561a10f5916dd1585286e
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,21 @@
|
|
1
|
-
#
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [0.1.0](https://github.com/texpert/shrine-lambda/tree/0.1.0) (2020-05-25)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/texpert/shrine-lambda/compare/v0.0.1...0.1.0)
|
6
|
+
|
7
|
+
**Breaking changes:**
|
8
|
+
|
9
|
+
- BREAKING CHANGE: Uploader's `:lambda\_process` method renamed to `:lambda\_process\_versions` [\#14](https://github.com/texpert/shrine-lambda/pull/14) ([texpert](https://github.com/texpert))
|
10
|
+
|
11
|
+
**Implemented enhancements:**
|
12
|
+
|
13
|
+
- Rubocop tuning and offences fixing [\#12](https://github.com/texpert/shrine-lambda/pull/12) ([texpert](https://github.com/texpert))
|
2
14
|
|
3
|
-
## [0.0.1](https://github.com/texpert/shrine-lambda/tree/0.0.1) (2018-02-12)
|
4
15
|
**Merged pull requests:**
|
5
16
|
|
17
|
+
- Added github\_changelog\_generator as a development dependency [\#15](https://github.com/texpert/shrine-lambda/pull/15) ([texpert](https://github.com/texpert))
|
18
|
+
- Release v. 0.0.1 [\#11](https://github.com/texpert/shrine-lambda/pull/11) ([texpert](https://github.com/texpert))
|
6
19
|
- Prepairing for release. [\#10](https://github.com/texpert/shrine-lambda/pull/10) ([texpert](https://github.com/texpert))
|
7
20
|
- Plugin documentation. [\#9](https://github.com/texpert/shrine-lambda/pull/9) ([texpert](https://github.com/texpert))
|
8
21
|
- Comply with Shrine's `upload\_options` plugin to be able to set ACL's … [\#8](https://github.com/texpert/shrine-lambda/pull/8) ([texpert](https://github.com/texpert))
|
@@ -14,6 +27,10 @@
|
|
14
27
|
- Fix of `:configure` and implementation of client and `:lambda\_function\_list` methods. [\#2](https://github.com/texpert/shrine-lambda/pull/2) ([texpert](https://github.com/texpert))
|
15
28
|
- Initial gem and plugin config [\#1](https://github.com/texpert/shrine-lambda/pull/1) ([texpert](https://github.com/texpert))
|
16
29
|
|
30
|
+
## [v0.0.1](https://github.com/texpert/shrine-lambda/tree/v0.0.1) (2018-02-12)
|
31
|
+
|
32
|
+
[Full Changelog](https://github.com/texpert/shrine-lambda/compare/803b40a03817943e5032c653742f90d811cdaff8...v0.0.1)
|
33
|
+
|
17
34
|
|
18
35
|
|
19
|
-
\* *This
|
36
|
+
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
data/README.md
CHANGED
@@ -171,7 +171,7 @@ the Lambda function's `:access_key_id` received in the request authorization hea
|
|
171
171
|
|
172
172
|
#### Usage
|
173
173
|
|
174
|
-
Shrine-Lambda assemblies are built inside the `#
|
174
|
+
Shrine-Lambda assemblies are built inside the `#lambda_process_versions` method in the `LambdaUploader` class:
|
175
175
|
|
176
176
|
```
|
177
177
|
# app/uploaders/lambda_uploader.rb:
|
@@ -191,7 +191,7 @@ class LambdaUploader < Uploader
|
|
191
191
|
|
192
192
|
plugin :versions
|
193
193
|
|
194
|
-
def
|
194
|
+
def lambda_process_versions(io, context)
|
195
195
|
assembly = { function: 'ImageResizeOnDemand' } # Here the AWS Lambda function name is specified
|
196
196
|
|
197
197
|
# Check if the original file format is a image format supported by the Sharp.js library
|
@@ -5,35 +5,45 @@ require 'aws-sdk-lambda'
|
|
5
5
|
class Shrine
|
6
6
|
module Plugins
|
7
7
|
module Lambda
|
8
|
-
SETTINGS = { access_key_id:
|
9
|
-
callback_url:
|
10
|
-
convert_params:
|
11
|
-
endpoint:
|
12
|
-
log_formatter:
|
13
|
-
log_level:
|
14
|
-
logger:
|
15
|
-
profile:
|
16
|
-
region:
|
17
|
-
retry_limit:
|
8
|
+
SETTINGS = { access_key_id: :optional,
|
9
|
+
callback_url: :required,
|
10
|
+
convert_params: :optional,
|
11
|
+
endpoint: :optional,
|
12
|
+
log_formatter: :optional,
|
13
|
+
log_level: :optional,
|
14
|
+
logger: :optional,
|
15
|
+
profile: :optional,
|
16
|
+
region: :optional,
|
17
|
+
retry_limit: :optional,
|
18
18
|
secret_access_key: :optional,
|
19
|
-
session_token:
|
20
|
-
stub_responses:
|
21
|
-
validate_params:
|
19
|
+
session_token: :optional,
|
20
|
+
stub_responses: :optional,
|
21
|
+
validate_params: :optional }.freeze
|
22
22
|
|
23
23
|
Error = Class.new(Shrine::Error)
|
24
24
|
|
25
25
|
# If promoting was not yet overridden, it is set to automatically trigger
|
26
26
|
# Lambda processing defined in `Shrine#lambda_process`.
|
27
27
|
def self.configure(uploader, settings = {})
|
28
|
-
|
29
|
-
raise Error, "The :#{key} is
|
30
|
-
|
31
|
-
|
32
|
-
raise Error, "The :#{key} is required for Lambda plugin"
|
33
|
-
end
|
28
|
+
SETTINGS.each do |key, value|
|
29
|
+
raise Error, "The :#{key} option is required for Lambda plugin" if value == :required && settings[key].nil?
|
30
|
+
|
31
|
+
uploader.opts[key] = settings.delete(key) if settings[key]
|
34
32
|
end
|
35
33
|
|
36
|
-
|
34
|
+
@logger = if Shrine.respond_to?(:logger)
|
35
|
+
Shrine.logger
|
36
|
+
elsif uploader.respond_to?(:logger)
|
37
|
+
uploader.logger
|
38
|
+
end
|
39
|
+
|
40
|
+
uploader.opts[:backgrounding_promote] = proc { lambda_process }
|
41
|
+
|
42
|
+
return unless @logger
|
43
|
+
|
44
|
+
settings.each do |key, _value|
|
45
|
+
@logger.info "The :#{key} option is not supported by the Lambda plugin"
|
46
|
+
end
|
37
47
|
end
|
38
48
|
|
39
49
|
# It loads the backgrounding plugin, so that it can override promoting.
|
@@ -56,26 +66,35 @@ class Shrine
|
|
56
66
|
# received from Lambda request. Then it compares the calculated and received signatures, returning an error if
|
57
67
|
# the signatures mismatch.
|
58
68
|
#
|
59
|
-
# If the signatures are equal, it returns the attacher and the hash of the parsed result from Lambda
|
69
|
+
# If the signatures are equal, it returns the attacher and the hash of the parsed result from Lambda, else -
|
70
|
+
# it returns false.
|
60
71
|
# @param [Hash] headers from the Lambda request
|
72
|
+
# @option headers [String] 'User-Agent' The AWS Lambda function user agent
|
73
|
+
# @option headers [String] 'Content-Type' 'application/json'
|
74
|
+
# @option headers [String] 'Host'
|
75
|
+
# @option headers [String] 'X-Amz-Date' The AWS Lambda function user agent
|
76
|
+
# @option headers [String] 'Authorization' The AWS authorization string
|
61
77
|
# @param [String] body of the Lambda request
|
62
|
-
# @return [Array] Shrine Attacher and the Lambda result (the request body parsed to a hash)
|
78
|
+
# @return [Array] Shrine Attacher and the Lambda result (the request body parsed to a hash) if signature in
|
79
|
+
# received headers matches locally computed AWS signature
|
80
|
+
# @return [false] if signature in received headers does't match locally computed AWS signature
|
63
81
|
def lambda_authorize(headers, body)
|
64
82
|
result = JSON.parse(body)
|
65
83
|
attacher = load(result.delete('context'))
|
66
84
|
incoming_auth_header = auth_header_hash(headers['Authorization'])
|
67
85
|
|
68
|
-
signer = build_signer(
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
http_method: 'PUT',
|
73
|
-
url: Shrine.opts[:callback_url],
|
74
|
-
headers: { 'X-Amz-Date' => headers['X-Amz-Date'] },
|
75
|
-
body: body
|
86
|
+
signer = build_signer(
|
87
|
+
incoming_auth_header['Credential'].split('/'),
|
88
|
+
JSON.parse(attacher.record.__send__(:"#{attacher.data_attribute}") || '{}').dig('metadata', 'key') || 'key',
|
89
|
+
headers['x-amz-security-token']
|
76
90
|
)
|
91
|
+
signature = signer.sign_request(http_method: 'PUT',
|
92
|
+
url: Shrine.opts[:callback_url],
|
93
|
+
headers: { 'X-Amz-Date' => headers['X-Amz-Date'] },
|
94
|
+
body: body)
|
77
95
|
calculated_signature = auth_header_hash(signature.headers['authorization'])['Signature']
|
78
96
|
return false if incoming_auth_header['Signature'] != calculated_signature
|
97
|
+
|
79
98
|
[attacher, result]
|
80
99
|
end
|
81
100
|
|
@@ -83,13 +102,13 @@ class Shrine
|
|
83
102
|
|
84
103
|
def build_signer(headers, secret_access_key, security_token = nil)
|
85
104
|
Aws::Sigv4::Signer.new(
|
86
|
-
service:
|
87
|
-
region:
|
88
|
-
access_key_id:
|
89
|
-
secret_access_key:
|
90
|
-
session_token:
|
105
|
+
service: headers[3],
|
106
|
+
region: headers[2],
|
107
|
+
access_key_id: headers[0],
|
108
|
+
secret_access_key: secret_access_key,
|
109
|
+
session_token: security_token,
|
91
110
|
apply_checksum_header: false,
|
92
|
-
unsigned_headers:
|
111
|
+
unsigned_headers: %w[content-length user-agent x-amzn-trace-id]
|
93
112
|
)
|
94
113
|
end
|
95
114
|
|
@@ -110,27 +129,28 @@ class Shrine
|
|
110
129
|
# function for signing the request.
|
111
130
|
#
|
112
131
|
# Stores the DB record class and name, attacher data atribute and uploader class names, into the context
|
113
|
-
# attribute of the Lambda function invokation payload. Also stores the
|
114
|
-
# into the payload.
|
132
|
+
# attribute of the Lambda function invokation payload. Also stores the cached file hash object and the
|
133
|
+
# generated path into the payload.
|
115
134
|
#
|
116
|
-
# After the AWS Lambda function
|
117
|
-
# No more response analysis is performed, because Lambda is invoked asynchronously (note the
|
135
|
+
# After the AWS Lambda function invocation, a `Shrine::Error` will be raised if the response is containing
|
136
|
+
# errors. No more response analysis is performed, because Lambda is invoked asynchronously (note the
|
118
137
|
# `invocation_type`: 'Event' in the `invoke` call). The results will be sent by Lambda by HTTP requests to
|
119
138
|
# the specified `callbackUrl`.
|
120
139
|
def lambda_process(data)
|
121
140
|
cached_file = uploaded_file(data['attachment'])
|
122
|
-
assembly =
|
123
|
-
assembly.merge!(store.
|
141
|
+
assembly = lambda_default_values
|
142
|
+
assembly.merge!(store.lambda_process_versions(cached_file, context))
|
124
143
|
function = assembly.delete(:function)
|
125
144
|
raise Error, 'No Lambda function specified!' unless function
|
126
145
|
raise Error, "Function #{function} not available on Lambda!" unless function_available?(function)
|
127
146
|
|
128
147
|
prepare_assembly(assembly, cached_file, context)
|
129
148
|
assembly[:context] = data.except('attachment', 'action', 'phase')
|
130
|
-
response = lambda_client.invoke(function_name:
|
149
|
+
response = lambda_client.invoke(function_name: function,
|
131
150
|
invocation_type: 'Event',
|
132
|
-
payload:
|
151
|
+
payload: assembly.to_json)
|
133
152
|
raise Error, "#{response.function_error}: #{response.payload.read}" if response.function_error
|
153
|
+
|
134
154
|
swap(cached_file) || _set(cached_file)
|
135
155
|
end
|
136
156
|
|
@@ -141,7 +161,7 @@ class Shrine
|
|
141
161
|
# Deletes the signing key, if it is present in the original file's metadata, converts the result to a JSON
|
142
162
|
# string, and writes this string into the `data_attribute` of the Shrine attacher's record.
|
143
163
|
#
|
144
|
-
# Chooses the `
|
164
|
+
# Chooses the `save_method` either for the ActiveRecord or for Sequel, and saves the record.
|
145
165
|
# @param [Hash] result
|
146
166
|
def lambda_save(result)
|
147
167
|
versions = result['versions']
|
@@ -165,6 +185,20 @@ class Shrine
|
|
165
185
|
|
166
186
|
private
|
167
187
|
|
188
|
+
def lambda_default_values
|
189
|
+
{ callbackURL: Shrine.opts[:callback_url],
|
190
|
+
copy_original: true,
|
191
|
+
storages: buckets_to_use(%i[cache store]),
|
192
|
+
target_storage: :store }
|
193
|
+
end
|
194
|
+
|
195
|
+
# @param [Array] buckets that will be sent to Lambda function for use
|
196
|
+
def buckets_to_use(buckets)
|
197
|
+
buckets.map do |b|
|
198
|
+
{ b.to_s => { name: Shrine.storages[b].bucket.name, prefix: Shrine.storages[b].prefix } }
|
199
|
+
end.inject(:merge!)
|
200
|
+
end
|
201
|
+
|
168
202
|
# A cached instance of an AWS Lambda client.
|
169
203
|
def lambda_client
|
170
204
|
@lambda_client ||= Shrine.lambda_client
|
@@ -213,24 +247,11 @@ class Shrine
|
|
213
247
|
def lambda_function_list(master_region: nil, function_version: 'ALL', marker: nil, items: 100, force: false)
|
214
248
|
fl = opts[:lambda_function_list]
|
215
249
|
return fl unless force || fl.nil? || fl.empty?
|
216
|
-
opts[:lambda_function_list] = lambda_client.list_functions(master_region: master_region,
|
217
|
-
function_version: function_version,
|
218
|
-
marker: marker,
|
219
|
-
max_items: items).functions
|
220
|
-
end
|
221
250
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
end.inject(:merge!)
|
227
|
-
end
|
228
|
-
|
229
|
-
def lambda_default_values
|
230
|
-
{ callbackURL: Shrine.opts[:callback_url],
|
231
|
-
copy_original: true,
|
232
|
-
storages: Shrine.buckets_to_use(%i[cache store]),
|
233
|
-
target_storage: :store }
|
251
|
+
opts[:lambda_function_list] = lambda_client.list_functions(master_region: master_region,
|
252
|
+
function_version: function_version,
|
253
|
+
marker: marker,
|
254
|
+
max_items: items).functions
|
234
255
|
end
|
235
256
|
end
|
236
257
|
end
|
data/shrine-lambda.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |gem|
|
4
4
|
gem.name = 'shrine-lambda'
|
5
|
-
gem.version = '0.0
|
5
|
+
gem.version = '0.1.0'
|
6
6
|
|
7
7
|
gem.required_ruby_version = '>= 2.3'
|
8
8
|
|
@@ -19,17 +19,19 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.files = Dir['CHANGELOG.md', 'README.md', 'LICENSE', 'lib/**/*.rb', '*.gemspec']
|
20
20
|
gem.require_path = 'lib/shrine/plugins'
|
21
21
|
|
22
|
-
gem.metadata = {
|
23
|
-
|
24
|
-
|
25
|
-
"source_code_uri" => "https://github.com/texpert/shrine-lambda"
|
26
|
-
}
|
22
|
+
gem.metadata = { 'bug_tracker_uri' => 'https://github.com/texpert/shrine-lambda/issues',
|
23
|
+
'changelog_uri' => 'https://github.com/texpert/shrine-lambda/CHANGELOG.md',
|
24
|
+
'source_code_uri' => 'https://github.com/texpert/shrine-lambda' }
|
27
25
|
|
28
26
|
gem.add_dependency 'aws-sdk-lambda', '~> 1.0'
|
29
27
|
gem.add_dependency 'aws-sdk-s3', '~> 1.2'
|
30
28
|
gem.add_dependency 'shrine', '~> 2.6'
|
31
29
|
|
30
|
+
gem.add_development_dependency 'activerecord', '>= 4.2.0'
|
32
31
|
gem.add_development_dependency 'dotenv'
|
32
|
+
gem.add_development_dependency 'github_changelog_generator'
|
33
33
|
gem.add_development_dependency 'rake'
|
34
|
-
gem.add_development_dependency '
|
34
|
+
gem.add_development_dependency 'rspec'
|
35
|
+
gem.add_development_dependency 'rubocop', '0.81'
|
36
|
+
gem.add_development_dependency 'sqlite3' unless RUBY_ENGINE == 'jruby'
|
35
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shrine-lambda
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aurel Branzeanu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-lambda
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activerecord
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 4.2.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 4.2.0
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: dotenv
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,20 @@ dependencies:
|
|
66
80
|
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: github_changelog_generator
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: rake
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,20 +108,48 @@ dependencies:
|
|
80
108
|
- - ">="
|
81
109
|
- !ruby/object:Gem::Version
|
82
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
126
|
name: rubocop
|
85
127
|
requirement: !ruby/object:Gem::Requirement
|
86
128
|
requirements:
|
87
|
-
- -
|
129
|
+
- - '='
|
88
130
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0.
|
131
|
+
version: '0.81'
|
90
132
|
type: :development
|
91
133
|
prerelease: false
|
92
134
|
version_requirements: !ruby/object:Gem::Requirement
|
93
135
|
requirements:
|
94
|
-
- -
|
136
|
+
- - '='
|
95
137
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0.
|
138
|
+
version: '0.81'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sqlite3
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
97
153
|
description: |2
|
98
154
|
AWS Lambda integration plugin for Shrine File Attachment toolkit for Ruby applications.
|
99
155
|
Used for invoking AWS Lambda functions for processing files already stored in some AWS S3 bucket.
|
@@ -130,8 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
186
|
- !ruby/object:Gem::Version
|
131
187
|
version: '0'
|
132
188
|
requirements: []
|
133
|
-
|
134
|
-
rubygems_version: 2.6.13
|
189
|
+
rubygems_version: 3.0.8
|
135
190
|
signing_key:
|
136
191
|
specification_version: 4
|
137
192
|
summary: AWS Lambda integration plugin for Shrine.
|