noresponse 2.1.14 → 3.0.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 +4 -4
- data/lib/no_response/accounts.rb +1 -1
- data/lib/no_response/assessments.rb +290 -2
- data/lib/no_response/late_results.rb +19 -15
- 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/account.rb +1 -1
- data/lib/no_response/models/shared/accountdecisionsbyflow.rb +1 -1
- data/lib/no_response/models/shared/assessment.rb +41 -176
- data/lib/no_response/models/shared/assessment.rbi +10 -82
- 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/assessmentdetail.rb +245 -0
- data/lib/no_response/models/shared/assessmentdetail.rbi +122 -0
- data/lib/no_response/models/shared/{assessmentauthcontext.rb → assessmentdetailauthcontext.rb} +1 -1
- data/lib/no_response/models/shared/{assessmentauthcontext.rbi → assessmentdetailauthcontext.rbi} +2 -2
- data/lib/no_response/models/shared/{assessmenttiming.rb → assessmentdetailtiming.rb} +1 -1
- data/lib/no_response/models/shared/{assessmenttiming.rbi → assessmentdetailtiming.rbi} +2 -2
- data/lib/no_response/models/shared/assessmentlist.rb +3 -3
- data/lib/no_response/models/shared/assessmentrequest.rb +15 -14
- data/lib/no_response/models/shared/assessmentrequest.rbi +4 -4
- data/lib/no_response/models/shared/assessmentrequestpolicycontext.rb +3 -16
- data/lib/no_response/models/shared/assessmentrequestpolicycontext.rbi +0 -6
- data/lib/no_response/models/shared/depth.rb +4 -1
- data/lib/no_response/models/shared/flow.rb +6 -4
- data/lib/no_response/models/shared.rb +5 -3
- data/lib/no_response/sdkconfiguration.rb +2 -2
- data/lib/no_response/webhooks.rb +1 -1
- metadata +15 -7
- data/lib/no_response/models/shared/assessmentflow.rb +0 -17
- data/lib/no_response/models/shared/assessmentflow.rbi +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ba556406e80e6bb7f20aeee106cc215b9872a1fbd1816663d6da76af9c1d568
|
|
4
|
+
data.tar.gz: 3c1214f820469af0cdc955ad85c6526edb30144fdf937f4a41f896f47b0b84cc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0023bb0cc6f1a40b655291291b9f06a478216cf395cde6e734497fbde1b3f304dac4e9fee9f9e9a9f2c779a013cf07b543bec5dbb27a09a90077a275cd763ff0
|
|
7
|
+
data.tar.gz: 79758d27c28ddf6630ac6e7e33db49011e4b19f56c1e272fe85d3d32f67a806f246d16dfa5a459121c1f69463d5a8cab4bdd31b2b3b0c70485caa0196db162dc
|
data/lib/no_response/accounts.rb
CHANGED
|
@@ -49,7 +49,7 @@ module NoResponse
|
|
|
49
49
|
}
|
|
50
50
|
def get(account_id:, retries: nil, timeout_ms: nil, http_headers: nil)
|
|
51
51
|
# get - Read an account's one current risk.
|
|
52
|
-
# An account is the account_id you send with your assessments. Its current risk is the risk of its latest assessment with a decision (status complete or partial), scored as GET /v1/assessments/{assessment_id} scores that assessment, with a decision for each flow. Every assessment updates its account: once an assessment completes, the account carries its risk. Requires the history scope. Read-only and safe to retry. An account with no unexpired assessment that has a decision answers 404 not_found, and a malformed account_id answers 400 invalid_request.
|
|
52
|
+
# An account is the account_id you send with your assessments. Its current risk is the risk of its latest assessment with a decision (status complete or partial), scored as GET /v1/assessments/{assessment_id} scores that assessment, with a decision for each flow; risk.decision is the decision for the flow of that assessment. Every assessment answers with this same account. Every assessment updates its account: once an assessment completes, the account carries its risk. Requires the history scope. Read-only and safe to retry. An account with no unexpired assessment that has a decision answers 404 not_found, and a malformed account_id answers 400 invalid_request.
|
|
53
53
|
request = Models::Operations::GetAccountRequest.new(
|
|
54
54
|
account_id: account_id
|
|
55
55
|
)
|
|
@@ -50,7 +50,7 @@ module NoResponse
|
|
|
50
50
|
}
|
|
51
51
|
def create(body:, idempotency_key: nil, retries: nil, timeout_ms: nil, http_headers: nil)
|
|
52
52
|
# create - Assess identifiers for a signup or gateway decision.
|
|
53
|
-
#
|
|
53
|
+
# Assesses one signup, login or purchase (flow) and answers with the account's one current risk: account.risk.decision is the decision for this flow (allow, step_up, review or block, where block means your block threshold was reached), and detail holds this assessment's own facts. depth sets how long the answer waits for sources: quick waits only for the fast ones (500 ms), full for the whole budget (3000 ms at most); it defaults to full for signup and purchase and quick for login. 200 carries complete or partial, 202 carries pending with Location and Retry-After. While the account's first assessment is pending, account is absent: apply your own fallback for that, 429, 503 or a timeout. NoResponse blocks nothing itself; you decide. Requires the assess scope. Idempotency-Key is optional in the SDK and is bound to the body for 24 hours: the same key with the same body replays the latest assessment with Idempotent-Replayed: true and starts no new work; the same key with a different body answers 409 idempotency_key_reused. response_mode defaults to standard; detailed needs the detailed scope.
|
|
54
54
|
request = Models::Operations::CreateAssessmentRequest.new(
|
|
55
55
|
body: body,
|
|
56
56
|
idempotency_key: idempotency_key
|
|
@@ -348,7 +348,7 @@ module NoResponse
|
|
|
348
348
|
}
|
|
349
349
|
def get(assessment_id:, response_mode: nil, retries: nil, timeout_ms: nil, http_headers: nil)
|
|
350
350
|
# get - Poll the authoritative assessment of one assessment.
|
|
351
|
-
# Returns the highest assessment_version. Requires the assess or history scope. While status is pending, or partial with a source still running, the response carries Retry-After; poll no faster than it says. Another tenant's assessment, an unknown or expired assessment and a malformed assessment_id all answer 404 not_found. response_mode=detailed needs the detailed scope.
|
|
351
|
+
# Returns the highest assessment_version, with the account's current risk. Requires the assess or history scope. While status is pending, or partial with a source still running, the response carries Retry-After; poll no faster than it says. Another tenant's assessment, an unknown or expired assessment and a malformed assessment_id all answer 404 not_found. response_mode=detailed needs the detailed scope.
|
|
352
352
|
request = Models::Operations::GetAssessmentRequest.new(
|
|
353
353
|
assessment_id: assessment_id,
|
|
354
354
|
response_mode: response_mode
|
|
@@ -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,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Late-result handlers. Hand-written beside the generated client.
|
|
5
5
|
#
|
|
6
6
|
# An assessment can be revised after the signup was allowed: a slow source
|
|
7
|
-
# settles and the
|
|
7
|
+
# settles and the account's decision rises. NoResponse sends the new version as a
|
|
8
8
|
# signed assessment.updated webhook. LateResults.handle verifies that delivery
|
|
9
9
|
# with Webhooks.construct_event, picks an action from your policy, and acts
|
|
10
10
|
# through the auth provider's admin API: revoke the user's sessions or ban the
|
|
@@ -30,10 +30,12 @@ module NoResponse
|
|
|
30
30
|
BAN = 'ban'
|
|
31
31
|
ACTIONS = [NONE, REVOKE_SESSIONS, BAN].freeze
|
|
32
32
|
|
|
33
|
-
# Revoke sessions on review; do nothing on allow or step_up.
|
|
34
|
-
|
|
33
|
+
# Revoke sessions on review and block; do nothing on allow or step_up.
|
|
34
|
+
# Banning is opt-in.
|
|
35
|
+
DEFAULT_POLICY = { 'allow' => NONE, 'step_up' => NONE, 'review' => REVOKE_SESSIONS,
|
|
36
|
+
'block' => REVOKE_SESSIONS }.freeze
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
DECISIONS = %w[allow step_up review block].freeze
|
|
37
39
|
|
|
38
40
|
# Raised when the provider's admin API refuses a call. Answer the webhook
|
|
39
41
|
# with a 5xx so NoResponse retries it. The message holds no response body
|
|
@@ -61,23 +63,25 @@ module NoResponse
|
|
|
61
63
|
Result = Struct.new(:event, :action, :user_id, keyword_init: true)
|
|
62
64
|
|
|
63
65
|
class << self
|
|
64
|
-
# The action your policy names for a verified event
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
66
|
+
# The action your policy names for a verified event, from the account's
|
|
67
|
+
# decision (data.account.risk.decision). Only a served assessment whose
|
|
68
|
+
# account has a decision can act; a pending assessment, an expiry and a
|
|
69
|
+
# test event never do. policy maps allow, step_up, review and block (as
|
|
70
|
+
# strings or symbols) to NONE, REVOKE_SESSIONS or BAN; a decision you
|
|
71
|
+
# leave out does nothing. An unknown action raises ArgumentError.
|
|
69
72
|
def action_for(event, policy = DEFAULT_POLICY)
|
|
70
73
|
return NONE if event.type != 'assessment.updated' || event.test? || event.expired?
|
|
71
74
|
|
|
72
75
|
data = event.data
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
return NONE if data.status == Models::Shared::Status::PENDING || data.account.nil?
|
|
77
|
+
|
|
78
|
+
decision = data.account.risk.decision.to_s
|
|
79
|
+
return NONE unless DECISIONS.include?(decision)
|
|
76
80
|
|
|
77
81
|
table = policy.to_h.transform_keys(&:to_s)
|
|
78
|
-
return NONE unless table.key?(
|
|
82
|
+
return NONE unless table.key?(decision)
|
|
79
83
|
|
|
80
|
-
action = table[
|
|
84
|
+
action = table[decision]
|
|
81
85
|
return NONE if action.nil?
|
|
82
86
|
|
|
83
87
|
action = action.to_s
|
|
@@ -103,7 +107,7 @@ module NoResponse
|
|
|
103
107
|
action = action_for(event, policy)
|
|
104
108
|
return Result.new(event: event, action: NONE) if action == NONE || event.type != 'assessment.updated'
|
|
105
109
|
|
|
106
|
-
account_id = event.data.account_id
|
|
110
|
+
account_id = event.data.detail.account_id
|
|
107
111
|
resolved = user_id ? user_id.call(account_id, event) : account_id
|
|
108
112
|
return Result.new(event: event, action: NONE) if resolved.nil? || resolved.to_s.empty?
|
|
109
113
|
|
|
@@ -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"
|
|
@@ -17,7 +17,7 @@ module NoResponse
|
|
|
17
17
|
Models::Shared::AccountRisk,
|
|
18
18
|
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("risk"), required: true}}
|
|
19
19
|
)
|
|
20
|
-
# The decision for each flow. Every flow uses the tenant's signup thresholds today, so all three equal
|
|
20
|
+
# The decision for each flow. Every flow uses the tenant's signup thresholds today, so all three are equal.
|
|
21
21
|
field(
|
|
22
22
|
:decisions_by_flow,
|
|
23
23
|
Models::Shared::AccountDecisionsByFlow,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
module NoResponse
|
|
5
5
|
module Models
|
|
6
6
|
module Shared
|
|
7
|
-
# The decision for each flow. Every flow uses the tenant's signup thresholds today, so all three equal
|
|
7
|
+
# The decision for each flow. Every flow uses the tenant's signup thresholds today, so all three are equal.
|
|
8
8
|
class AccountDecisionsByFlow
|
|
9
9
|
extend T::Sig
|
|
10
10
|
include Crystalline::MetadataFields
|