From 922c94371752892d578a313ca7c5331d58fa4a68 Mon Sep 17 00:00:00 2001 From: Tom Noonan II Date: Mon, 23 Sep 2019 17:46:06 -0400 Subject: [PATCH 1/2] Update Rubocop to 0.74 and resolve ensuring tickets --- .rubocop.yml | 11 +++-- .ruby-version | 1 + lib/oktakit/error.rb | 2 +- spec/client/apps_spec.rb | 32 +++++++------- spec/client/factors_spec.rb | 10 ++--- spec/client/groups_spec.rb | 8 ++-- spec/client/identity_providers_spec.rb | 12 +++--- spec/client/templates_spec.rb | 24 +++++------ spec/client/users_spec.rb | 58 +++++++++++++------------- spec/pagination_spec.rb | 2 +- 10 files changed, 86 insertions(+), 74 deletions(-) create mode 100644 .ruby-version diff --git a/.rubocop.yml b/.rubocop.yml index 226a343..bff6ada 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,7 +2,12 @@ # http://shopify.github.io/ruby-style-guide/ AllCops: - TargetRubyVersion: 2.2 + TargetRubyVersion: 2.6 + +# Allow .ruby-version and spec.required_ruby_version to differ +# to run a newer Ruby version for Rubocop, but don't force users to upgrade +Gemspec/RequiredRubyVersion: + Enabled: false Rails: Enabled: false @@ -19,7 +24,7 @@ Layout/MultilineOperationIndentation: Layout/AlignParameters: EnforcedStyle: with_fixed_indentation -Layout/FirstParameterIndentation: +Layout/IndentFirstArgument: EnforcedStyle: consistent Style/TrailingCommaInArrayLiteral: @@ -34,7 +39,7 @@ Style/NumericLiterals: Layout/CaseIndentation: EnforcedStyle: end -Layout/IndentHash: +Layout/IndentFirstHashElement: EnforcedStyle: consistent Style/WordArray: diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..e70b452 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.6.0 diff --git a/lib/oktakit/error.rb b/lib/oktakit/error.rb index 91f628b..8b981fd 100644 --- a/lib/oktakit/error.rb +++ b/lib/oktakit/error.rb @@ -41,7 +41,7 @@ def initialize(response = nil) # Array of validation errors # @return [Array] Error info def errors - if data && data.is_a?(Hash) + if data&.is_a?(Hash) data[:errors] || [] else [] diff --git a/spec/client/apps_spec.rb b/spec/client/apps_spec.rb index 281476c..534cf23 100644 --- a/spec/client/apps_spec.rb +++ b/spec/client/apps_spec.rb @@ -40,8 +40,8 @@ it 'returns updated application' do VCR.use_cassette 'update_application', record: :new_episodes do resp, = client.update_application(APPS_APP_ID, - id: APPS_APP_ID, - signOnMode: "SAML_2_0") + id: APPS_APP_ID, + signOnMode: "SAML_2_0") expect(resp.id).to be == APPS_APP_ID end end @@ -81,11 +81,11 @@ it 'returns application user' do VCR.use_cassette 'assign_user_to_application_for_sso' do resp, status = client.assign_user_to_application_for_sso(APPS_APP_ID, - id: APPS_USER_ID, - scope: "USER", - credentials: { - userName: "user@example.com" - }) + id: APPS_USER_ID, + scope: "USER", + credentials: { + userName: "user@example.com" + }) expect(status).to be(200) expect(resp.id).to be == '00u6nm9ytbmwHeunx0h7' end @@ -95,11 +95,13 @@ describe '#assign_user_to_application_for_sso_provisioning' do it 'returns application user with user profile mappings applied' do VCR.use_cassette 'assign_user_to_application_for_sso_provisioning', record: :new_episodes do - resp, status = client.assign_user_to_application_for_sso_provisioning(APPS_APP_ID, + resp, status = client.assign_user_to_application_for_sso_provisioning( + APPS_APP_ID, id: APPS_USER_ID, scope: "USER", credentials: { userName: "user@example.com" }, - profile: {}) + profile: {} + ) expect(status).to be(200) expect(resp.id).to be == '00u6nm9ytbmwHeunx0h7' end @@ -128,12 +130,12 @@ it 'returns application user' do VCR.use_cassette 'update_application_credentials_for_assigned_user', record: :new_episodes do resp, = client.update_application_credentials_for_assigned_user(APPS_APP_ID, APPS_USER_ID, - credentials: { - userName: "user@example.com", - password: { - value: "newPassword" - } - }) + credentials: { + userName: "user@example.com", + password: { + value: "newPassword" + } + }) expect(resp.id).to be == '00u6nm9ytbmwHeunx0h7' end end diff --git a/spec/client/factors_spec.rb b/spec/client/factors_spec.rb index 1199819..114bf3d 100644 --- a/spec/client/factors_spec.rb +++ b/spec/client/factors_spec.rb @@ -45,11 +45,11 @@ it 'returns all responses return the enrolled factor with a status of either pending_activation or active.' do VCR.use_cassette 'enroll_factor', record: :new_episodes do resp, = client.enroll_factor(FACTORS_USER_ID, - factorType: "sms", - provider: "OKTA", - profile: { - phoneNumber: "+1-613-456-1234" - }) + factorType: "sms", + provider: "OKTA", + profile: { + phoneNumber: "+1-613-456-1234" + }) expect(resp.id).not_to be_nil end end diff --git a/spec/client/groups_spec.rb b/spec/client/groups_spec.rb index dcba2d4..d8d98bc 100644 --- a/spec/client/groups_spec.rb +++ b/spec/client/groups_spec.rb @@ -40,10 +40,10 @@ it 'returns updated group' do VCR.use_cassette 'update_group' do resp, = client.update_group(GROUPS_GROUP_ID, - profile: { - name: "New Name for the Group", - description: "New Name for the Group" - }) + profile: { + name: "New Name for the Group", + description: "New Name for the Group" + }) expect(resp.profile.name).to be == "New Name for the Group" end end diff --git a/spec/client/identity_providers_spec.rb b/spec/client/identity_providers_spec.rb index 7fd2c05..70fbd66 100644 --- a/spec/client/identity_providers_spec.rb +++ b/spec/client/identity_providers_spec.rb @@ -95,7 +95,8 @@ describe '#update_identity_provider' do it 'returns updated identity provider' do VCR.use_cassette 'update_identity_provider', record: :new_episodes do - _, status = client.update_identity_provider(IDENTITY_PROVIDERS_IDENTITY_ID, + _, status = client.update_identity_provider( + IDENTITY_PROVIDERS_IDENTITY_ID, id: "0oa62bfdjnK55Z5x80h7", type: "SAML2", name: "Example IdP", @@ -158,7 +159,8 @@ matchType: "USERNAME" }, maxClockSkew: 120000 - }) + } + ) expect(status).to be(200) end end @@ -240,9 +242,9 @@ it 'returns identity provider transaction' do VCR.use_cassette 'link_idp_user', record: :new_episodes do resp, = client.link_idp_user(IDENTITY_PROVIDERS_TRANSACTION_ID, IDENTITY_PROVIDERS_USER_ID, - profile: { - userType: "Social" - }) + profile: { + userType: "Social" + }) expect(resp.id).not_to be_nil end end diff --git a/spec/client/templates_spec.rb b/spec/client/templates_spec.rb index 209c391..311043c 100644 --- a/spec/client/templates_spec.rb +++ b/spec/client/templates_spec.rb @@ -44,15 +44,15 @@ it 'returns updated sms template' do VCR.use_cassette 'update_sms_template' do _, status = client.update_sms_template(TEMPLATES_TEMPLATE_ID, - name: "Custom", - type: "SMS_VERIFY_CODE", - template: "Your ${org.name} code is: ${code}", - translations: - { - es: "${org.name}: ${code}.", - fr: "${org.name}: ${code}.", - it: "${org.name}: ${code}." - }) + name: "Custom", + type: "SMS_VERIFY_CODE", + template: "Your ${org.name} code is: ${code}", + translations: + { + es: "${org.name}: ${code}.", + fr: "${org.name}: ${code}.", + it: "${org.name}: ${code}." + }) expect(status).to be(200) end end @@ -62,9 +62,9 @@ it 'returns updated sms template' do VCR.use_cassette 'partial_sms_template_update' do resp, = client.partial_sms_template_update(TEMPLATES_TEMPLATE_ID, - translations: { - de: "${org.name}: ihre bestätigungscode ist ${code}." - }) + translations: { + de: "${org.name}: ihre bestätigungscode ist ${code}." + }) expect(resp.translations.de).to be == '${org.name}: ihre bestätigungscode ist ${code}.' end end diff --git a/spec/client/users_spec.rb b/spec/client/users_spec.rb index fc8dd1a..fd0c4f5 100644 --- a/spec/client/users_spec.rb +++ b/spec/client/users_spec.rb @@ -52,12 +52,12 @@ it 'returns updated user' do VCR.use_cassette 'update_user' do resp, = client.update_user(USERS_USER_ID, - profile: { - firstName: "Bob", - lastName: "User", - email: "example@example.com", - login: "example@example.com" - }) + profile: { + firstName: "Bob", + lastName: "User", + email: "example@example.com", + login: "example@example.com" + }) expect(resp.profile.firstName).to be == 'Bob' end end @@ -67,13 +67,13 @@ it 'returns updated user' do VCR.use_cassette 'update_user_partial' do resp, = client.update_user(USERS_USER_ID, - profile: { - firstName: "Bob", - lastName: "User", - email: "example@example.com", - login: "example@example.com" - }, - partial: true) + profile: { + firstName: "Bob", + lastName: "User", + email: "example@example.com", + login: "example@example.com" + }, + partial: true) expect(resp.profile.firstName).to be == 'Bob' end end @@ -83,12 +83,12 @@ it 'returns updated user' do VCR.use_cassette 'update_profile' do resp, = client.update_profile(USERS_USER_ID, - profile: { - firstName: "Other Bob", - lastName: "User", - email: "example@example.com", - login: "example@example.com" - }) + profile: { + firstName: "Other Bob", + lastName: "User", + email: "example@example.com", + login: "example@example.com" + }) expect(resp.profile.firstName).to be == 'Other Bob' end end @@ -187,9 +187,11 @@ describe '#forgot_password' do it 'returns an empty object by default.' do VCR.use_cassette 'forgot_password' do - resp, = client.forgot_password(USERS_USER_ID, + resp, = client.forgot_password( + USERS_USER_ID, password: { value: "123Password!" }, - recovery_question: { answer: "A woodchuck could chuck as much as he could chuck." }) + recovery_question: { answer: "A woodchuck could chuck as much as he could chuck." } + ) expect(resp.password.to_h).to be == {} end end @@ -199,8 +201,8 @@ it 'returns credentials of the user' do VCR.use_cassette 'change_password' do _, status = client.change_password(USERS_USER_ID, - oldPassword: { value: "uTVM,TPw55" }, - newPassword: { value: "NewPassword1234!" }) + oldPassword: { value: "uTVM,TPw55" }, + newPassword: { value: "NewPassword1234!" }) expect(status).to be(200) end end @@ -210,11 +212,11 @@ it 'returns credentials of the user' do VCR.use_cassette 'change_recovery_question' do resp, = client.change_recovery_question(USERS_USER_ID, - password: { value: "NewPassword1234!" }, - recovery_question: { - question: "Where is Shopify's HQ?", - answer: "Ottawa" - }) + password: { value: "NewPassword1234!" }, + recovery_question: { + question: "Where is Shopify's HQ?", + answer: "Ottawa" + }) expect(resp.recovery_question.question).to be == "Where is Shopify's HQ?" end end diff --git a/spec/pagination_spec.rb b/spec/pagination_spec.rb index 43edd5b..f93f330 100644 --- a/spec/pagination_spec.rb +++ b/spec/pagination_spec.rb @@ -14,7 +14,7 @@ it 'should send query parameters in each page request' do VCR.use_cassette 'pagination_with_query_params' do users, = client.list_users_assigned_to_application(PAGED_APPS_APP_ID, - paginate: true, query: { expand: 'user', limit: '1' }) + paginate: true, query: { expand: 'user', limit: '1' }) users.each do |user| expect(user._embedded).not_to be_nil, "User #{user.id} was expected to have expanded user profile in _embedded" end From 1c84633692e5491ffed897173c0696c54663c992 Mon Sep 17 00:00:00 2001 From: Tom Noonan II Date: Mon, 23 Sep 2019 17:27:23 -0400 Subject: [PATCH 2/2] Add support for System Log API endpoint --- lib/oktakit/client.rb | 2 + lib/oktakit/client/system_log.rb | 20 ++++++++ lib/oktakit/version.rb | 2 +- spec/cassettes/list_logs.yml | 83 ++++++++++++++++++++++++++++++++ spec/client/system_log_spec.rb | 12 +++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 lib/oktakit/client/system_log.rb create mode 100644 spec/cassettes/list_logs.yml create mode 100644 spec/client/system_log_spec.rb diff --git a/lib/oktakit/client.rb b/lib/oktakit/client.rb index a9e6266..dfd8c98 100644 --- a/lib/oktakit/client.rb +++ b/lib/oktakit/client.rb @@ -7,6 +7,7 @@ require 'oktakit/client/groups' require 'oktakit/client/identity_providers' require 'oktakit/client/schemas' +require 'oktakit/client/system_log' require 'oktakit/client/templates' require 'oktakit/client/users' @@ -19,6 +20,7 @@ class Client include Groups include IdentityProviders include Schemas + include SystemLog include Templates include Users diff --git a/lib/oktakit/client/system_log.rb b/lib/oktakit/client/system_log.rb new file mode 100644 index 0000000..3e26d08 --- /dev/null +++ b/lib/oktakit/client/system_log.rb @@ -0,0 +1,20 @@ +module Oktakit + class Client + module SystemLog + # List logs + # + # @param options[:query] [Hash] Optional. Query params for request + # @param options[:headers] [Hash] Optional. Header params for the request. + # @param options[:accept] [String] Optional. The content type to accept. Default application/json + # @param options[:content_type] [String] Optional. The content type for the request. Default application/json + # @param options [Hash] Optional. Body params for request. + # @return [Array] Array of logs + # @see https://developer.okta.com/docs/reference/api/system-log/#list-events + # @example + # Oktakit.list_logs(paginate: true, query: { since: "2019-06-27T00:00:00Z", until: "2019-06-28T00:00:00Z" }) + def list_logs(options = {}) + get('/logs', options) + end + end + end +end diff --git a/lib/oktakit/version.rb b/lib/oktakit/version.rb index 32c7653..72401bd 100644 --- a/lib/oktakit/version.rb +++ b/lib/oktakit/version.rb @@ -1,3 +1,3 @@ module Oktakit - VERSION = '0.2.0'.freeze + VERSION = '0.3.0'.freeze end diff --git a/spec/cassettes/list_logs.yml b/spec/cassettes/list_logs.yml new file mode 100644 index 0000000..0e51e59 --- /dev/null +++ b/spec/cassettes/list_logs.yml @@ -0,0 +1,83 @@ +--- +http_interactions: +- request: + method: get + uri: https://okta-test.okta.com/api/v1/logs + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - Oktakit v0.3.0 + Accept: + - application/json + Content-Type: + - application/json + Authorization: + - SSWS <> + response: + status: + code: 200 + message: + headers: + date: + - Mon, 23 Sep 2019 21:04:35 GMT + content-type: + - application/json;charset=UTF-8 + transfer-encoding: + - chunked + connection: + - close + server: + - nginx + public-key-pins-report-only: + - pin-sha256="jZomPEBSDXoipA9un78hKRIeN/+U4ZteRaiX8YpWfqc="; pin-sha256="axSbM6RQ+19oXxudaOTdwXJbSr6f7AahxbDHFy3p8s8="; + pin-sha256="SE4qe2vdD9tAegPwO79rMnZyhHvqj3i5g1c2HkyGUNE="; pin-sha256="ylP0lMLMvBaiHn0ihLxHjzvlPVQNoyQ+rMiaj0da/Pw="; + max-age=60; report-uri="https://okta.report-uri.io/r/default/hpkp/reportOnly" + vary: + - Accept-Encoding + x-okta-request-id: + - XYkzY3yKVU6ghoLZeSGhrQAAA1c + x-xss-protection: + - 1; mode=block; report=https://oktadev.report-uri.com/r/d/xss/enforce + p3p: + - CP="HONK" + x-rate-limit-limit: + - '600' + x-rate-limit-remaining: + - '599' + x-rate-limit-reset: + - '1569272735' + cache-control: + - no-cache, no-store + pragma: + - no-cache + expires: + - '0' + report-to: + - '{"group":"csp-report","max_age":31536000,"endpoints":[{"url":"https://okta.report-uri.com/r/d/csp/reportOnly"}],"include_subdomains":true}' + content-security-policy-report-only: + - default-src 'self' op1static.oktacdn.com okta-test.okta.com; connect-src + 'self' op1static.oktacdn.com *.mixpanel.com *.mapbox.com app.pendo.io data.pendo.io + pendo-static-5634101834153984.storage.googleapis.com; script-src 'unsafe-inline' + 'unsafe-eval' 'self' op1static.oktacdn.com; style-src 'unsafe-inline' 'self' + op1static.oktacdn.com app.pendo.io cdn.pendo.io pendo-static-5634101834153984.storage.googleapis.com; + frame-src 'self' login.okta.com; img-src 'self' op1static.oktacdn.com okta-test.okta.com + *.mapbox.com app.pendo.io data.pendo.io cdn.pendo.io pendo-static-5634101834153984.storage.googleapis.com; + frame-ancestors 'self'; report-uri https://okta.report-uri.com/r/d/csp/reportOnly; + report-to csp-report + link: + - ; rel="self" + x-content-type-options: + - nosniff + strict-transport-security: + - max-age=315360000 + set-cookie: + - sid=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/, JSESSIONID=1421DC05F96B044916251372C29CD4A0; + Path=/; Secure; HttpOnly + body: + encoding: UTF-8 + string: '[{"actor":{"id":"sprjaqy8d2OwK2qnq0h7","type":"SystemPrincipal","alternateId":"system@okta.com","displayName":"Okta System","detailEntry":null},"client":{"userAgent":null,"zone":null,"device":null,"id":null,"ipAddress":null,"geographicalContext":null},"authenticationContext":{"authenticationProvider":null,"credentialProvider":null,"credentialType":null,"issuer":null,"interface":null,"authenticationStep":0,"externalSessionId":"trs6DA22ImyTiKKlR0RSfwyeA"},"displayMessage":"import started","eventType":"system.import.start","outcome":{"result":"SUCCESS","reason":null},"published":"2019-07-01T03:23:37.478Z","securityContext":{"asNumber":null,"asOrg":null,"isp":null,"domain":null,"isProxy":null},"severity":"INFO","debugContext":{"debugData":{"jobId":"ij1lxp7303kBQlUT40h7","importType":"Incremental","appname":"google","importTrigger":"Schedule"}},"legacyEventType":"app.generic.import.started","transaction":{"type":"JOB","id":"ij1lxp7303kBQlUT40h7","detail":{}},"uuid":"9d74f291-9baf-11e9-95b6-371469f8aeb0","version":"0","request":{"ipChain":[]},"target":[{"id":"0oaktfd2v7z477UR30h7","type":"AppInstance","alternateId":"G Suite","displayName":"G Suite","detailEntry":null}]},{"actor":{"id":"sprjaqy8d2OwK2qnq0h7","type":"SystemPrincipal","alternateId":"system@okta.com","displayName":"Okta System","detailEntry":null},"client":{"userAgent":null,"zone":null,"device":null,"id":null,"ipAddress":null,"geographicalContext":null},"authenticationContext":{"authenticationProvider":null,"credentialProvider":null,"credentialType":null,"issuer":null,"interface":null,"authenticationStep":0,"externalSessionId":"trs6DA22ImyTiKKlR0RSfwyeA"},"displayMessage":"Batch import process complete","eventType":"system.import.complete_batch","outcome":{"result":"SUCCESS","reason":null},"published":"2019-07-01T03:23:39.299Z","securityContext":{"asNumber":null,"asOrg":null,"isp":null,"domain":null,"isProxy":null},"severity":"INFO","debugContext":{"debugData":{"appname":"google","totalTime":"2 seconds"}},"legacyEventType":"app.generic.import.batch.complete","transaction":{"type":"JOB","id":"ij1lxp7303kBQlUT40h7","detail":{}},"uuid":"9e8acf7f-9baf-11e9-95b6-371469f8aeb0","version":"0","request":{"ipChain":[]},"target":[{"id":"0oaktfd2v7z477UR30h7","type":"AppInstance","alternateId":"G Suite","displayName":"G Suite","detailEntry":null}]}]' + http_version: + recorded_at: Mon, 23 Sep 2019 21:04:16 GMT +recorded_with: VCR 2.9.3 diff --git a/spec/client/system_log_spec.rb b/spec/client/system_log_spec.rb new file mode 100644 index 0000000..382fbe4 --- /dev/null +++ b/spec/client/system_log_spec.rb @@ -0,0 +1,12 @@ +require 'spec_helper' + +describe Oktakit::Client::SystemLog do + describe '#list_logs' do + it 'returns array of logs' do + VCR.use_cassette 'list_logs' do + resp, = client.list_logs + expect(resp).to be_a(Array) + end + end + end +end