noresponse 2.1.13 → 2.1.15
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 +4 -4
- data/lib/no_response/assessments.rb +288 -0
- data/lib/no_response/late_results.rb +114 -14
- data/lib/no_response/models/operations/deleteassessment_request.rb +33 -0
- data/lib/no_response/models/operations/deleteassessment_request.rbi +14 -0
- data/lib/no_response/models/operations/deleteassessment_response.rb +32 -0
- data/lib/no_response/models/operations/deleteassessment_response.rbi +20 -0
- data/lib/no_response/models/operations.rb +2 -0
- data/lib/no_response/models/shared/assessmentdeletion.rb +78 -0
- data/lib/no_response/models/shared/assessmentdeletion.rbi +38 -0
- data/lib/no_response/models/shared/assessmentdeletionaccount.rb +37 -0
- data/lib/no_response/models/shared/assessmentdeletionaccount.rbi +20 -0
- data/lib/no_response/models/shared.rb +2 -0
- data/lib/no_response/sdkconfiguration.rb +2 -2
- metadata +9 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2469d4f72cf85b77dbd86ca8a05136ff313081e86be235d86cc5190ba9141639
|
|
4
|
+
data.tar.gz: 4368344ab696f56ae59f9dc2b932f25f5e66183f6e57a3ebf398f79a0146e965
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 70c09610fdb41378166092d7af4693538817762093e6ff73df8b6333c341e0bbee290b3b8b6156140361131ac1ef716d4277aa88b75ce30fa4f3e92814810688
|
|
7
|
+
data.tar.gz: 6f120c6191d655a540ffeb3d78f9c8c093c0cb6f42eb3641f0c2c9fb35076edf4d958af2965e6f517c380500c77b562795a09928ec5e095ecf0b959b4a286577
|
|
@@ -628,6 +628,294 @@ module NoResponse
|
|
|
628
628
|
end
|
|
629
629
|
end
|
|
630
630
|
|
|
631
|
+
sig {
|
|
632
|
+
params(
|
|
633
|
+
assessment_id: ::String,
|
|
634
|
+
retries: T.nilable(Utils::RetryConfig),
|
|
635
|
+
timeout_ms: T.nilable(Integer),
|
|
636
|
+
http_headers: T.nilable(T::Hash[T.any(String, Symbol), String])
|
|
637
|
+
)
|
|
638
|
+
.returns(Models::Operations::DeleteAssessmentResponse)
|
|
639
|
+
}
|
|
640
|
+
def delete(assessment_id:, retries: nil, timeout_ms: nil, http_headers: nil)
|
|
641
|
+
# delete - Delete one assessment.
|
|
642
|
+
# Deletes one assessment in the environment of your key, with its versions, evidence and outcomes and the identity-graph marks its outcomes set, and scores its account again from what remains. Afterwards the assessment answers 404 and leaves the account's history. The answer names the account and the assessment its current risk now comes from; current_assessment_id is absent when the account has no assessment with a decision left. Requires the history scope. An unknown, expired or already deleted assessment answers 404, so a repeat answers 404; to erase a whole account idempotently, use accounts.delete.
|
|
643
|
+
request = Models::Operations::DeleteAssessmentRequest.new(
|
|
644
|
+
assessment_id: assessment_id
|
|
645
|
+
)
|
|
646
|
+
url, params = @sdk_configuration.get_server_details
|
|
647
|
+
base_url = Utils.template_url(url, params)
|
|
648
|
+
url = Utils.generate_url(
|
|
649
|
+
Models::Operations::DeleteAssessmentRequest,
|
|
650
|
+
base_url,
|
|
651
|
+
"/v1/assessments/{assessment_id}",
|
|
652
|
+
request
|
|
653
|
+
)
|
|
654
|
+
headers = {}
|
|
655
|
+
headers = T.cast(headers, T::Hash[String, String])
|
|
656
|
+
headers["Accept"] = "application/json"
|
|
657
|
+
headers["user-agent"] = @sdk_configuration.user_agent
|
|
658
|
+
retries ||= @sdk_configuration.retry_config
|
|
659
|
+
retries ||= Utils::RetryConfig.new(
|
|
660
|
+
backoff: Utils::BackoffStrategy.new(
|
|
661
|
+
exponent: 2.0,
|
|
662
|
+
initial_interval: 500,
|
|
663
|
+
max_elapsed_time: 30_000,
|
|
664
|
+
max_interval: 8000
|
|
665
|
+
),
|
|
666
|
+
retry_connection_errors: true,
|
|
667
|
+
strategy: "backoff"
|
|
668
|
+
)
|
|
669
|
+
retry_options = retries.to_faraday_retry_options(initial_time: Time.now)
|
|
670
|
+
retry_options[:retry_statuses] = [408, 429, 500, 501, 502, 503, 504, 505]
|
|
671
|
+
|
|
672
|
+
security = @sdk_configuration.security_source&.call
|
|
673
|
+
|
|
674
|
+
timeout = (timeout_ms.to_f / 1000) unless timeout_ms.nil?
|
|
675
|
+
timeout ||= @sdk_configuration.timeout
|
|
676
|
+
|
|
677
|
+
connection = @sdk_configuration.client.dup
|
|
678
|
+
connection.use(Utils::RetryMiddleware, retry_options)
|
|
679
|
+
|
|
680
|
+
hook_ctx = SDKHooks::HookContext.new(
|
|
681
|
+
config: @sdk_configuration,
|
|
682
|
+
base_url: base_url,
|
|
683
|
+
oauth2_scopes: nil,
|
|
684
|
+
operation_id: "deleteAssessment",
|
|
685
|
+
security_source: @sdk_configuration.security_source
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
error = T.let(nil, T.nilable(StandardError))
|
|
689
|
+
http_response = T.let(nil, T.nilable(Faraday::Response))
|
|
690
|
+
|
|
691
|
+
begin
|
|
692
|
+
http_response = T.must(connection).delete(url) do |req|
|
|
693
|
+
req.headers.merge!(headers)
|
|
694
|
+
req.options.timeout = timeout unless timeout.nil?
|
|
695
|
+
Utils.configure_request_security(req, security)
|
|
696
|
+
http_headers&.each do |key, value|
|
|
697
|
+
req.headers[key.to_s] = value
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
@sdk_configuration.hooks.before_request(
|
|
701
|
+
hook_ctx: SDKHooks::BeforeRequestHookContext.new(
|
|
702
|
+
hook_ctx: hook_ctx
|
|
703
|
+
),
|
|
704
|
+
request: req
|
|
705
|
+
)
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
rescue StandardError => e
|
|
709
|
+
error = e
|
|
710
|
+
ensure
|
|
711
|
+
if http_response.nil? || Utils.error_status?(http_response.status)
|
|
712
|
+
http_response = @sdk_configuration.hooks.after_error(
|
|
713
|
+
error: error,
|
|
714
|
+
hook_ctx: SDKHooks::AfterErrorHookContext.new(
|
|
715
|
+
hook_ctx: hook_ctx
|
|
716
|
+
),
|
|
717
|
+
response: http_response
|
|
718
|
+
)
|
|
719
|
+
else
|
|
720
|
+
http_response = @sdk_configuration.hooks.after_success(
|
|
721
|
+
hook_ctx: SDKHooks::AfterSuccessHookContext.new(
|
|
722
|
+
hook_ctx: hook_ctx
|
|
723
|
+
),
|
|
724
|
+
response: http_response
|
|
725
|
+
)
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
if http_response.nil?
|
|
729
|
+
raise error if !error.nil?
|
|
730
|
+
raise "no response"
|
|
731
|
+
end
|
|
732
|
+
end
|
|
733
|
+
|
|
734
|
+
content_type = http_response.headers.fetch("Content-Type", "application/octet-stream")
|
|
735
|
+
if Utils.match_status_code(http_response.status, ["200"])
|
|
736
|
+
if Utils.match_content_type(content_type, "application/json")
|
|
737
|
+
@sdk_configuration.hooks.after_success(
|
|
738
|
+
hook_ctx: SDKHooks::AfterSuccessHookContext.new(
|
|
739
|
+
hook_ctx: hook_ctx
|
|
740
|
+
),
|
|
741
|
+
response: http_response
|
|
742
|
+
)
|
|
743
|
+
response_data = http_response.env.response_body
|
|
744
|
+
obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Shared::AssessmentDeletion)
|
|
745
|
+
result = obj
|
|
746
|
+
response = Models::Operations::DeleteAssessmentResponse.new(
|
|
747
|
+
result: result,
|
|
748
|
+
headers: http_response.headers
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
return response
|
|
752
|
+
else
|
|
753
|
+
raise(
|
|
754
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
755
|
+
status_code: http_response.status,
|
|
756
|
+
body: http_response.env.response_body,
|
|
757
|
+
raw_response: http_response
|
|
758
|
+
),
|
|
759
|
+
"Unknown content type received"
|
|
760
|
+
)
|
|
761
|
+
end
|
|
762
|
+
elsif Utils.match_status_code(http_response.status, ["400"])
|
|
763
|
+
if Utils.match_content_type(content_type, "application/problem+json")
|
|
764
|
+
@sdk_configuration.hooks.after_success(
|
|
765
|
+
hook_ctx: SDKHooks::AfterSuccessHookContext.new(
|
|
766
|
+
hook_ctx: hook_ctx
|
|
767
|
+
),
|
|
768
|
+
response: http_response
|
|
769
|
+
)
|
|
770
|
+
response_data = http_response.env.response_body
|
|
771
|
+
obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::BadRequestError)
|
|
772
|
+
raise obj
|
|
773
|
+
else
|
|
774
|
+
raise(
|
|
775
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
776
|
+
status_code: http_response.status,
|
|
777
|
+
body: http_response.env.response_body,
|
|
778
|
+
raw_response: http_response
|
|
779
|
+
),
|
|
780
|
+
"Unknown content type received"
|
|
781
|
+
)
|
|
782
|
+
end
|
|
783
|
+
elsif Utils.match_status_code(http_response.status, ["401"])
|
|
784
|
+
if Utils.match_content_type(content_type, "application/problem+json")
|
|
785
|
+
@sdk_configuration.hooks.after_success(
|
|
786
|
+
hook_ctx: SDKHooks::AfterSuccessHookContext.new(
|
|
787
|
+
hook_ctx: hook_ctx
|
|
788
|
+
),
|
|
789
|
+
response: http_response
|
|
790
|
+
)
|
|
791
|
+
response_data = http_response.env.response_body
|
|
792
|
+
obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::AuthenticationError)
|
|
793
|
+
raise obj
|
|
794
|
+
else
|
|
795
|
+
raise(
|
|
796
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
797
|
+
status_code: http_response.status,
|
|
798
|
+
body: http_response.env.response_body,
|
|
799
|
+
raw_response: http_response
|
|
800
|
+
),
|
|
801
|
+
"Unknown content type received"
|
|
802
|
+
)
|
|
803
|
+
end
|
|
804
|
+
elsif Utils.match_status_code(http_response.status, ["403"])
|
|
805
|
+
if Utils.match_content_type(content_type, "application/problem+json")
|
|
806
|
+
@sdk_configuration.hooks.after_success(
|
|
807
|
+
hook_ctx: SDKHooks::AfterSuccessHookContext.new(
|
|
808
|
+
hook_ctx: hook_ctx
|
|
809
|
+
),
|
|
810
|
+
response: http_response
|
|
811
|
+
)
|
|
812
|
+
response_data = http_response.env.response_body
|
|
813
|
+
obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::PermissionDeniedError)
|
|
814
|
+
raise obj
|
|
815
|
+
else
|
|
816
|
+
raise(
|
|
817
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
818
|
+
status_code: http_response.status,
|
|
819
|
+
body: http_response.env.response_body,
|
|
820
|
+
raw_response: http_response
|
|
821
|
+
),
|
|
822
|
+
"Unknown content type received"
|
|
823
|
+
)
|
|
824
|
+
end
|
|
825
|
+
elsif Utils.match_status_code(http_response.status, ["404"])
|
|
826
|
+
if Utils.match_content_type(content_type, "application/problem+json")
|
|
827
|
+
@sdk_configuration.hooks.after_success(
|
|
828
|
+
hook_ctx: SDKHooks::AfterSuccessHookContext.new(
|
|
829
|
+
hook_ctx: hook_ctx
|
|
830
|
+
),
|
|
831
|
+
response: http_response
|
|
832
|
+
)
|
|
833
|
+
response_data = http_response.env.response_body
|
|
834
|
+
obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::NotFoundError)
|
|
835
|
+
raise obj
|
|
836
|
+
else
|
|
837
|
+
raise(
|
|
838
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
839
|
+
status_code: http_response.status,
|
|
840
|
+
body: http_response.env.response_body,
|
|
841
|
+
raw_response: http_response
|
|
842
|
+
),
|
|
843
|
+
"Unknown content type received"
|
|
844
|
+
)
|
|
845
|
+
end
|
|
846
|
+
elsif Utils.match_status_code(http_response.status, ["409"])
|
|
847
|
+
if Utils.match_content_type(content_type, "application/problem+json")
|
|
848
|
+
@sdk_configuration.hooks.after_success(
|
|
849
|
+
hook_ctx: SDKHooks::AfterSuccessHookContext.new(
|
|
850
|
+
hook_ctx: hook_ctx
|
|
851
|
+
),
|
|
852
|
+
response: http_response
|
|
853
|
+
)
|
|
854
|
+
response_data = http_response.env.response_body
|
|
855
|
+
obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::ConflictError)
|
|
856
|
+
raise obj
|
|
857
|
+
else
|
|
858
|
+
raise(
|
|
859
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
860
|
+
status_code: http_response.status,
|
|
861
|
+
body: http_response.env.response_body,
|
|
862
|
+
raw_response: http_response
|
|
863
|
+
),
|
|
864
|
+
"Unknown content type received"
|
|
865
|
+
)
|
|
866
|
+
end
|
|
867
|
+
elsif Utils.match_status_code(http_response.status, ["429"])
|
|
868
|
+
if Utils.match_content_type(content_type, "application/problem+json")
|
|
869
|
+
@sdk_configuration.hooks.after_success(
|
|
870
|
+
hook_ctx: SDKHooks::AfterSuccessHookContext.new(
|
|
871
|
+
hook_ctx: hook_ctx
|
|
872
|
+
),
|
|
873
|
+
response: http_response
|
|
874
|
+
)
|
|
875
|
+
response_data = http_response.env.response_body
|
|
876
|
+
obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::RateLimitError)
|
|
877
|
+
raise obj
|
|
878
|
+
else
|
|
879
|
+
raise(
|
|
880
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
881
|
+
status_code: http_response.status,
|
|
882
|
+
body: http_response.env.response_body,
|
|
883
|
+
raw_response: http_response
|
|
884
|
+
),
|
|
885
|
+
"Unknown content type received"
|
|
886
|
+
)
|
|
887
|
+
end
|
|
888
|
+
elsif Utils.match_status_code(http_response.status, ["4XX"])
|
|
889
|
+
raise(
|
|
890
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
891
|
+
status_code: http_response.status,
|
|
892
|
+
body: http_response.env.response_body,
|
|
893
|
+
raw_response: http_response
|
|
894
|
+
),
|
|
895
|
+
"API error occurred"
|
|
896
|
+
)
|
|
897
|
+
elsif Utils.match_status_code(http_response.status, ["5XX"])
|
|
898
|
+
raise(
|
|
899
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
900
|
+
status_code: http_response.status,
|
|
901
|
+
body: http_response.env.response_body,
|
|
902
|
+
raw_response: http_response
|
|
903
|
+
),
|
|
904
|
+
"API error occurred"
|
|
905
|
+
)
|
|
906
|
+
else
|
|
907
|
+
raise(
|
|
908
|
+
::NoResponse::Models::Errors::APIStatusError.new(
|
|
909
|
+
status_code: http_response.status,
|
|
910
|
+
body: http_response.env.response_body,
|
|
911
|
+
raw_response: http_response
|
|
912
|
+
),
|
|
913
|
+
"Unknown status code received"
|
|
914
|
+
)
|
|
915
|
+
|
|
916
|
+
end
|
|
917
|
+
end
|
|
918
|
+
|
|
631
919
|
sig {
|
|
632
920
|
params(
|
|
633
921
|
body: Models::Shared::AssessmentOutcomeRequest,
|
|
@@ -39,17 +39,23 @@ module NoResponse
|
|
|
39
39
|
# with a 5xx so NoResponse retries it. The message holds no response body
|
|
40
40
|
# and no credentials.
|
|
41
41
|
class ProviderActionError < StandardError
|
|
42
|
-
|
|
42
|
+
# code is the provider's error code from the response body, such as
|
|
43
|
+
# Auth0's errorCode "insufficient_scope", when it sent one.
|
|
44
|
+
attr_reader :provider, :status, :code
|
|
43
45
|
|
|
44
|
-
def initialize(provider, status, message)
|
|
46
|
+
def initialize(provider, status, message, code = nil)
|
|
45
47
|
super(message)
|
|
46
48
|
@provider = provider
|
|
47
49
|
@status = status
|
|
50
|
+
@code = code
|
|
48
51
|
end
|
|
49
52
|
end
|
|
50
53
|
|
|
51
|
-
# event is the verified Webhooks::Event. action is the action
|
|
52
|
-
# when the policy, the event or the user id called for nothing.
|
|
54
|
+
# event is the verified Webhooks::Event. action is the action that ran:
|
|
55
|
+
# NONE when the policy, the event or the user id called for nothing. It can
|
|
56
|
+
# be stronger than the policy's action when the provider had to fall back:
|
|
57
|
+
# the auth0 provider reports BAN when it blocked the user because the
|
|
58
|
+
# tenant's plan cannot end sessions. user_id is
|
|
53
59
|
# the provider user id acted on, set only when an action was taken. Answer
|
|
54
60
|
# an endpoint.verification with Webhooks.verification_response(event).
|
|
55
61
|
Result = Struct.new(:event, :action, :user_id, keyword_init: true)
|
|
@@ -102,12 +108,17 @@ module NoResponse
|
|
|
102
108
|
return Result.new(event: event, action: NONE) if resolved.nil? || resolved.to_s.empty?
|
|
103
109
|
|
|
104
110
|
resolved = resolved.to_s
|
|
105
|
-
|
|
111
|
+
# A provider may define act(action, user_id), returning the action that
|
|
112
|
+
# ran; the auth0 provider does, to report a block it had to fall back to.
|
|
113
|
+
ran = action
|
|
114
|
+
if provider.respond_to?(:act)
|
|
115
|
+
ran = provider.act(action, resolved)
|
|
116
|
+
elsif action == BAN
|
|
106
117
|
provider.ban(resolved)
|
|
107
118
|
else
|
|
108
119
|
provider.revoke_sessions(resolved)
|
|
109
120
|
end
|
|
110
|
-
Result.new(event: event, action: action, user_id: resolved)
|
|
121
|
+
Result.new(event: event, action: ACTIONS.include?(ran) ? ran : action, user_id: resolved)
|
|
111
122
|
end
|
|
112
123
|
|
|
113
124
|
# Clerk Backend API. revoke_sessions lists the user's active sessions
|
|
@@ -146,8 +157,18 @@ module NoResponse
|
|
|
146
157
|
# (PATCH /users/{id}), then does the same. Pass domain (such as
|
|
147
158
|
# example.eu.auth0.com; the API is https://{domain}/api/v2) or base_url.
|
|
148
159
|
# token is a Management API access token with update:users,
|
|
149
|
-
# delete:sessions
|
|
150
|
-
#
|
|
160
|
+
# delete:sessions, delete:refresh_tokens, read:device_credentials and
|
|
161
|
+
# delete:device_credentials. A 404 on any call (user already gone)
|
|
162
|
+
# counts as done, so a repeated delivery is safe.
|
|
163
|
+
#
|
|
164
|
+
# Auth0 offers the sessions and refresh-token endpoints on Enterprise
|
|
165
|
+
# plans only; on other plans they answer 403 feature_not_enabled. Then
|
|
166
|
+
# refresh tokens are deleted one by one through /device-credentials
|
|
167
|
+
# (types refresh_token and rotating_refresh_token), which every plan
|
|
168
|
+
# has. A login session cannot be ended, so revoke_sessions blocks the
|
|
169
|
+
# user before deleting the refresh tokens, and act reports BAN. Unblock
|
|
170
|
+
# the user in the dashboard to undo it. Any other refusal, such as 403
|
|
171
|
+
# insufficient_scope, raises.
|
|
151
172
|
def auth0(token:, domain: nil, base_url: nil, http_client: nil)
|
|
152
173
|
raise ArgumentError, 'auth0 needs token' if token.to_s.empty?
|
|
153
174
|
|
|
@@ -191,7 +212,9 @@ module NoResponse
|
|
|
191
212
|
end
|
|
192
213
|
status, text = perform(method, uri, headers, payload)
|
|
193
214
|
return nil if allow_404 && status == 404
|
|
194
|
-
|
|
215
|
+
unless status.between?(200, 299)
|
|
216
|
+
raise ProviderActionError.new(@name, status, "#{@name} #{method} #{path} answered #{status}", error_code(text))
|
|
217
|
+
end
|
|
195
218
|
return nil if text.nil? || text.empty?
|
|
196
219
|
|
|
197
220
|
begin
|
|
@@ -203,6 +226,17 @@ module NoResponse
|
|
|
203
226
|
|
|
204
227
|
private
|
|
205
228
|
|
|
229
|
+
# The error code in a provider's error body: Auth0's errorCode, or a top-level code.
|
|
230
|
+
def error_code(text)
|
|
231
|
+
body = JSON.parse(text.to_s)
|
|
232
|
+
return nil unless body.is_a?(Hash)
|
|
233
|
+
|
|
234
|
+
code = body['errorCode'] || body['code']
|
|
235
|
+
code.is_a?(String) && !code.empty? ? code : nil
|
|
236
|
+
rescue JSON::ParserError
|
|
237
|
+
nil
|
|
238
|
+
end
|
|
239
|
+
|
|
206
240
|
def perform(method, uri, headers, payload)
|
|
207
241
|
return @http_client.call(method, uri, headers, payload) if @http_client
|
|
208
242
|
|
|
@@ -296,6 +330,8 @@ module NoResponse
|
|
|
296
330
|
end
|
|
297
331
|
|
|
298
332
|
class Auth0
|
|
333
|
+
PAGE = 100
|
|
334
|
+
|
|
299
335
|
def initialize(caller_)
|
|
300
336
|
@call = caller_
|
|
301
337
|
end
|
|
@@ -303,15 +339,79 @@ module NoResponse
|
|
|
303
339
|
def name = 'auth0'
|
|
304
340
|
|
|
305
341
|
def revoke_sessions(user_id)
|
|
306
|
-
|
|
307
|
-
@call.call('DELETE', "/users/#{user}/sessions", allow_404: true)
|
|
308
|
-
@call.call('DELETE', "/users/#{user}/refresh-tokens", allow_404: true)
|
|
342
|
+
revoke(user_id)
|
|
309
343
|
nil
|
|
310
344
|
end
|
|
311
345
|
|
|
312
346
|
def ban(user_id)
|
|
313
|
-
|
|
314
|
-
|
|
347
|
+
user = Segment.encode(user_id)
|
|
348
|
+
block(user)
|
|
349
|
+
# The block already ends a session the plan cannot delete.
|
|
350
|
+
delete_sessions(user)
|
|
351
|
+
delete_refresh_tokens(user_id, user)
|
|
352
|
+
nil
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Bans or revokes and returns the action that ran: BAN when revoking had
|
|
356
|
+
# to block the user.
|
|
357
|
+
def act(action, user_id)
|
|
358
|
+
if action == BAN
|
|
359
|
+
ban(user_id)
|
|
360
|
+
return BAN
|
|
361
|
+
end
|
|
362
|
+
revoke(user_id)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
private
|
|
366
|
+
|
|
367
|
+
def revoke(user_id)
|
|
368
|
+
user = Segment.encode(user_id)
|
|
369
|
+
ended = delete_sessions(user)
|
|
370
|
+
# Without the sessions API a login session survives; blocking is the only way to end it.
|
|
371
|
+
block(user) unless ended
|
|
372
|
+
delete_refresh_tokens(user_id, user)
|
|
373
|
+
ended ? REVOKE_SESSIONS : BAN
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Auth0 answers 403 feature_not_enabled when the tenant's plan does not include an endpoint.
|
|
377
|
+
def not_on_plan?(error)
|
|
378
|
+
error.status == 403 && error.code == 'feature_not_enabled'
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def block(user)
|
|
382
|
+
@call.call('PATCH', "/users/#{user}", body: { 'blocked' => true }, allow_404: true)
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Ends every session; false when the plan has no sessions API.
|
|
386
|
+
def delete_sessions(user)
|
|
387
|
+
@call.call('DELETE', "/users/#{user}/sessions", allow_404: true)
|
|
388
|
+
true
|
|
389
|
+
rescue ProviderActionError => e
|
|
390
|
+
raise unless not_on_plan?(e)
|
|
391
|
+
|
|
392
|
+
false
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def delete_refresh_tokens(user_id, user)
|
|
396
|
+
begin
|
|
397
|
+
@call.call('DELETE', "/users/#{user}/refresh-tokens", allow_404: true)
|
|
398
|
+
return
|
|
399
|
+
rescue ProviderActionError => e
|
|
400
|
+
raise unless not_on_plan?(e)
|
|
401
|
+
end
|
|
402
|
+
# Collect every id before deleting any, so the pages do not shift underneath.
|
|
403
|
+
ids = []
|
|
404
|
+
%w[refresh_token rotating_refresh_token].each do |type|
|
|
405
|
+
10.times do |page|
|
|
406
|
+
body = @call.call('GET', '/device-credentials',
|
|
407
|
+
query: [['user_id', user_id], ['type', type], ['page', page.to_s], ['per_page', PAGE.to_s]],
|
|
408
|
+
allow_404: true)
|
|
409
|
+
listed = body.is_a?(Array) ? body.grep(Hash) : []
|
|
410
|
+
ids.concat(listed.map { |c| c['id'] }.select { |id| id.is_a?(String) && !id.empty? })
|
|
411
|
+
break if listed.length < PAGE
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
ids.each { |id| @call.call('DELETE', "/device-credentials/#{ERB::Util.url_encode(id)}", allow_404: true) }
|
|
315
415
|
end
|
|
316
416
|
end
|
|
317
417
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Operations
|
|
7
|
+
|
|
8
|
+
class DeleteAssessmentRequest
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# Path segment, matched case-sensitively. A value that does not match the assessment_id shape answers 404, not 400.
|
|
13
|
+
field(
|
|
14
|
+
:assessment_id,
|
|
15
|
+
::String,
|
|
16
|
+
{'path_param': {'field_name': "assessment_id", 'style': "simple", 'explode': false}}
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
sig { params(assessment_id: ::String).void }
|
|
20
|
+
def initialize(assessment_id:)
|
|
21
|
+
@assessment_id = assessment_id
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
25
|
+
def ==(other)
|
|
26
|
+
return false unless other.is_a?(self.class)
|
|
27
|
+
return false unless @assessment_id == other.assessment_id
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Operations::DeleteAssessmentRequest
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Operations::DeleteAssessmentRequest
|
|
9
|
+
def assessment_id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def assessment_id=(str_)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Operations
|
|
7
|
+
|
|
8
|
+
class DeleteAssessmentResponse
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
field :headers, Crystalline::Hash.new(Symbol, Crystalline::Array.new(::String))
|
|
13
|
+
|
|
14
|
+
field :result, Models::Shared::AssessmentDeletion, {}
|
|
15
|
+
|
|
16
|
+
sig { params(headers: T::Hash[Symbol, T::Array[::String]], result: Models::Shared::AssessmentDeletion).void }
|
|
17
|
+
def initialize(headers:, result:)
|
|
18
|
+
@headers = headers
|
|
19
|
+
@result = result
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
23
|
+
def ==(other)
|
|
24
|
+
return false unless other.is_a?(self.class)
|
|
25
|
+
return false unless @headers == other.headers
|
|
26
|
+
return false unless @result == other.result
|
|
27
|
+
true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Operations::DeleteAssessmentResponse
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Operations::DeleteAssessmentResponse
|
|
9
|
+
def headers
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def headers=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def result
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def result=(str_)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -10,6 +10,8 @@ module NoResponse
|
|
|
10
10
|
autoload :CreateWebhookEndpointResponse, "no_response/models/operations/createwebhookendpoint_response.rb"
|
|
11
11
|
autoload :DeleteAccountRequest, "no_response/models/operations/deleteaccount_request.rb"
|
|
12
12
|
autoload :DeleteAccountResponse, "no_response/models/operations/deleteaccount_response.rb"
|
|
13
|
+
autoload :DeleteAssessmentRequest, "no_response/models/operations/deleteassessment_request.rb"
|
|
14
|
+
autoload :DeleteAssessmentResponse, "no_response/models/operations/deleteassessment_response.rb"
|
|
13
15
|
autoload :DeleteIntegrationRequest, "no_response/models/operations/deleteintegration_request.rb"
|
|
14
16
|
autoload :DeleteIntegrationResponse, "no_response/models/operations/deleteintegration_response.rb"
|
|
15
17
|
autoload :DeleteWebhookEndpointRequest, "no_response/models/operations/deletewebhookendpoint_request.rb"
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Shared
|
|
7
|
+
# Body of the 200 answer to DELETE /v1/assessments/{assessment_id}: one of the calling tenant's assessments was deleted, with its versions, evidence, outcomes and the identity-graph marks its outcomes set. Afterwards GET /v1/assessments/{assessment_id} answers 404 and the assessment leaves the account's history. The account is scored again from what remains: account.current_assessment_id names the assessment GET /v1/accounts/{account_id} now serves its risk from, and is absent when the account has no assessment with a decision left. Deleting an assessment that is already gone answers 404.
|
|
8
|
+
class AssessmentDeletion
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# The assessment that was deleted.
|
|
13
|
+
field :id, ::String, {'format_json': {'letter_case': ::NoResponse::Utils.field_name("id"), required: true}}
|
|
14
|
+
|
|
15
|
+
field(
|
|
16
|
+
:account,
|
|
17
|
+
Models::Shared::AssessmentDeletionAccount,
|
|
18
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("account"), required: true}}
|
|
19
|
+
)
|
|
20
|
+
# When the deletion took effect.
|
|
21
|
+
field(
|
|
22
|
+
:deleted_at,
|
|
23
|
+
::String,
|
|
24
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("deleted_at"), required: true}}
|
|
25
|
+
)
|
|
26
|
+
# Version of the body shape.
|
|
27
|
+
field(
|
|
28
|
+
:schema_version,
|
|
29
|
+
::String,
|
|
30
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("schema_version"), required: true}}
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
field(
|
|
34
|
+
:deleted,
|
|
35
|
+
Crystalline::Boolean.new,
|
|
36
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("deleted"), required: true}}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
sig {
|
|
40
|
+
params(
|
|
41
|
+
id: ::String,
|
|
42
|
+
account: Models::Shared::AssessmentDeletionAccount,
|
|
43
|
+
deleted_at: ::String,
|
|
44
|
+
schema_version: ::String,
|
|
45
|
+
deleted: T::Boolean
|
|
46
|
+
)
|
|
47
|
+
.void
|
|
48
|
+
}
|
|
49
|
+
def initialize(id:, account:, deleted_at:, schema_version: "1", deleted: true)
|
|
50
|
+
@id = id
|
|
51
|
+
@account = account
|
|
52
|
+
@deleted_at = deleted_at
|
|
53
|
+
unless schema_version == "1"
|
|
54
|
+
raise ArgumentError, "Invalid value for schema_version"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
@schema_version = "1"
|
|
58
|
+
unless deleted == true
|
|
59
|
+
raise ArgumentError, "Invalid value for deleted"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
@deleted = true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
66
|
+
def ==(other)
|
|
67
|
+
return false unless other.is_a?(self.class)
|
|
68
|
+
return false unless @id == other.id
|
|
69
|
+
return false unless @account == other.account
|
|
70
|
+
return false unless @deleted_at == other.deleted_at
|
|
71
|
+
return false unless @schema_version == other.schema_version
|
|
72
|
+
return false unless @deleted == other.deleted
|
|
73
|
+
true
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Shared::AssessmentDeletion
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Shared::AssessmentDeletion
|
|
9
|
+
def id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def id=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def account
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def account=(str_)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def deleted_at
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def deleted_at=(str_)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def schema_version
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def schema_version=(str_)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def deleted
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def deleted=(str_)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Shared
|
|
7
|
+
|
|
8
|
+
class AssessmentDeletionAccount
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# The account_id of the deleted assessment.
|
|
13
|
+
field :id, ::String, {'format_json': {'letter_case': ::NoResponse::Utils.field_name("id"), required: true}}
|
|
14
|
+
# The assessment the account's current risk now comes from. Absent when the account has no assessment with a decision left, and GET /v1/accounts/{account_id} then answers 404.
|
|
15
|
+
field(
|
|
16
|
+
:current_assessment_id,
|
|
17
|
+
Crystalline::Nilable.new(::String),
|
|
18
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("current_assessment_id")}}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
sig { params(id: ::String, current_assessment_id: T.nilable(::String)).void }
|
|
22
|
+
def initialize(id:, current_assessment_id: nil)
|
|
23
|
+
@id = id
|
|
24
|
+
@current_assessment_id = current_assessment_id
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
28
|
+
def ==(other)
|
|
29
|
+
return false unless other.is_a?(self.class)
|
|
30
|
+
return false unless @id == other.id
|
|
31
|
+
return false unless @current_assessment_id == other.current_assessment_id
|
|
32
|
+
true
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Shared::AssessmentDeletionAccount
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Shared::AssessmentDeletionAccount
|
|
9
|
+
def id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def id=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def current_assessment_id
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def current_assessment_id=(str_)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -12,6 +12,8 @@ module NoResponse
|
|
|
12
12
|
autoload :AccountRiskReason, "no_response/models/shared/accountriskreason.rb"
|
|
13
13
|
autoload :Assessment, "no_response/models/shared/assessment.rb"
|
|
14
14
|
autoload :AssessmentAuthContext, "no_response/models/shared/assessmentauthcontext.rb"
|
|
15
|
+
autoload :AssessmentDeletion, "no_response/models/shared/assessmentdeletion.rb"
|
|
16
|
+
autoload :AssessmentDeletionAccount, "no_response/models/shared/assessmentdeletionaccount.rb"
|
|
15
17
|
autoload :AssessmentFlow, "no_response/models/shared/assessmentflow.rb"
|
|
16
18
|
autoload :AssessmentList, "no_response/models/shared/assessmentlist.rb"
|
|
17
19
|
autoload :AssessmentOutcome, "no_response/models/shared/assessmentoutcome.rb"
|
|
@@ -95,9 +95,9 @@ module NoResponse
|
|
|
95
95
|
|
|
96
96
|
@language = "ruby"
|
|
97
97
|
@openapi_doc_version = "1"
|
|
98
|
-
@sdk_version = "2.1.
|
|
98
|
+
@sdk_version = "2.1.15"
|
|
99
99
|
@gen_version = "internal"
|
|
100
|
-
@user_agent = "noresponse-sdk/ruby 2.1.
|
|
100
|
+
@user_agent = "noresponse-sdk/ruby 2.1.15 internal 1 noresponse"
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
sig { returns([String, T::Hash[Symbol, String]]) }
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: noresponse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1.
|
|
4
|
+
version: 2.1.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- NoResponse
|
|
@@ -288,6 +288,10 @@ files:
|
|
|
288
288
|
- lib/no_response/models/operations/deleteaccount_request.rbi
|
|
289
289
|
- lib/no_response/models/operations/deleteaccount_response.rb
|
|
290
290
|
- lib/no_response/models/operations/deleteaccount_response.rbi
|
|
291
|
+
- lib/no_response/models/operations/deleteassessment_request.rb
|
|
292
|
+
- lib/no_response/models/operations/deleteassessment_request.rbi
|
|
293
|
+
- lib/no_response/models/operations/deleteassessment_response.rb
|
|
294
|
+
- lib/no_response/models/operations/deleteassessment_response.rbi
|
|
291
295
|
- lib/no_response/models/operations/deleteintegration_request.rb
|
|
292
296
|
- lib/no_response/models/operations/deleteintegration_request.rbi
|
|
293
297
|
- lib/no_response/models/operations/deleteintegration_response.rb
|
|
@@ -361,6 +365,10 @@ files:
|
|
|
361
365
|
- lib/no_response/models/shared/assessment.rbi
|
|
362
366
|
- lib/no_response/models/shared/assessmentauthcontext.rb
|
|
363
367
|
- lib/no_response/models/shared/assessmentauthcontext.rbi
|
|
368
|
+
- lib/no_response/models/shared/assessmentdeletion.rb
|
|
369
|
+
- lib/no_response/models/shared/assessmentdeletion.rbi
|
|
370
|
+
- lib/no_response/models/shared/assessmentdeletionaccount.rb
|
|
371
|
+
- lib/no_response/models/shared/assessmentdeletionaccount.rbi
|
|
364
372
|
- lib/no_response/models/shared/assessmentflow.rb
|
|
365
373
|
- lib/no_response/models/shared/assessmentflow.rbi
|
|
366
374
|
- lib/no_response/models/shared/assessmentlist.rb
|