diff --git a/.circleci/config.yml b/.circleci/config.yml index 3b12bb32759..b64b2514fa9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,16 +17,23 @@ jobs: jdk8: docker: - - image: cimg/openjdk:8.0-node + - image: cimg/openjdk:8.0.345-node environment: - JVM_OPTS: -Xmx3200m + JVM_OPTS: -Xmx3200m steps: *build_steps - + jdk11: docker: - - image: cimg/openjdk:11.0-node + - image: cimg/openjdk:11.0.16-node + environment: + JVM_OPTS: -Xmx3200m + steps: *build_steps + + jdk17: + docker: + - image: cimg/openjdk:17.0.4-node environment: - JVM_OPTS: -Xmx3200m + JVM_OPTS: -Xmx3200m steps: *build_steps workflows: @@ -34,3 +41,4 @@ workflows: jobs: - jdk8 - jdk11 + - jdk17 \ No newline at end of file diff --git a/.gitignore b/.gitignore index dd470ce217d..83167878595 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ travis_phantomjs # api.yaml will be fetched from NPM, the local copy will not be used. src/swagger/api.yaml +/api/src/main/java/com/okta/sdk/client/AppMain.java diff --git a/MIGRATING.md b/MIGRATING.md index 69b4c4705c6..a06dafb630e 100644 --- a/MIGRATING.md +++ b/MIGRATING.md @@ -2,6 +2,46 @@ This SDK uses semantic versioning and follows Okta's [library version policy](https://developer.okta.com/code/library-versions/). In short, we do not make breaking changes unless the major version changes! +## Migrating from 8.x.x to 10.x.x + +In previous versions we use an Open API v2 specification for the management APIs, and an Okta custom client generator to generate the SDK components. +A new version of the Open API specification v3 has been released, and new well-known open source generators are now available to automatically generate code from this specification. + +This revision will embrace the Open Source [openapi-generator](https://github.com/OpenAPITools/openapi-generator) to auto generate the code from Okta's reference specification (v3) of the Management APIs. + +### Okta client vs API clients + +In older version, you would instantiate a global `Client` and access the Okta resources using the Management APIs. +Now, each API area (such as Users, Groups, Applications etc.) would have its own specific client, so you will only instantiate those clients you are interested in: + +_Earlier:_ + +```java +Client client = Clients.builder() + .setOrgUrl("https://{yourOktaDomain}") // e.g. https://dev-123456.okta.com + .setClientCredentials(new TokenClientCredentials("{apiToken}")) + .build(); + +User user = client.getUser("a-user-id"); + +Application app = client.getApplication("appId"); +``` + +_Now:_ + +```java +ApiClient client = Clients.builder() + .setOrgUrl("https://{yourOktaDomain}") // e.g. https://dev-123456.okta.com + .setClientCredentials(new TokenClientCredentials("{apiToken}")) + .build(); + +UserApi userApi = new UserApi(client); +User user = userApi.getUser("userId"); + +ApplicationApi applicationApi = new ApplicationApi(client); +Application app = applicationApi.getApplication("appId", null); +``` + ## Migrating from 7.x.x to 8.0.0 Version 8.0.0 of this SDK introduces few breaking changes from previous versions. diff --git a/README.md b/README.md index 99603261ccc..352451c499e 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,19 @@ This repository contains the Okta management SDK for Java. This SDK can be used * Add security factors to users with the [Factors API](https://developer.okta.com/docs/api/resources/factors) * Manage groups with the [Groups API](https://developer.okta.com/docs/api/resources/groups) * Manage applications with the [Apps API](https://developer.okta.com/docs/api/resources/apps) +* Manage logs with the [Logs API](https://developer.okta.com/docs/api/resources/system_log) +* Manage sessions with the [Sessions API](https://developer.okta.com/docs/api/resources/sessions) +* Manage templates with the [Custom Templates API](https://developer.okta.com/docs/reference/api/templates/) +* Manage identity providers with the [Identity Providers API](https://developer.okta.com/docs/reference/api/idps/) +* Manage authorization servers with the [Authorization Servers API](https://developer.okta.com/docs/reference/api/authorization-servers/) +* Manage event hooks with the [Event Hooks Management API](https://developer.okta.com/docs/reference/api/event-hooks/) +* Manage inline hooks with the [Inline Hooks Management API](https://developer.okta.com/docs/reference/api/inline-hooks/). +* Manage features with the [Features API](https://developer.okta.com/docs/reference/api/features/). +* Manage linked objects with the [Linked Objects API](https://developer.okta.com/docs/reference/api/linked-objects/). +* Manage trusted origins with the [Trusted Origins API](https://developer.okta.com/docs/reference/api/trusted-origins/). +* Manage user types with the [User Types API](https://developer.okta.com/docs/reference/api/user-types/). +* Manage custom domains with the [Domains API](https://developer.okta.com/docs/reference/api/domains/). +* Manage network zones with the [Zones API](https://developer.okta.com/docs/reference/api/zones/). * Much more! We also publish these libraries for Java: @@ -51,6 +64,8 @@ This library uses semantic versioning and follows Okta's [library version policy | 6.x.x | :heavy_check_mark: Stable ([migration guide](https://github.com/okta/okta-sdk-java/blob/master/MIGRATING.md#migrating-from-5xx-to-600)) | | 7.x.x | :heavy_check_mark: Stable ([migration guide](https://github.com/okta/okta-sdk-java/blob/master/MIGRATING.md#migrating-from-6xx-to-700)) | | 8.x.x | :heavy_check_mark: Stable ([migration guide](https://github.com/okta/okta-sdk-java/blob/master/MIGRATING.md#migrating-from-7xx-to-800)) | +| 9.x.x-beta | :heavy_check_mark: Beta release located in [branch](https://github.com/okta/okta-sdk-java/tree/swagger_v3) - Discontinued | +| 10.x.x-beta | :heavy_check_mark: Beta release located in `oasv3` [branch](https://github.com/okta/okta-sdk-java/tree/oasv3) ([migration guide](https://github.com/okta/okta-sdk-java/blob/master/MIGRATING.md#migrating-from-8xx-to-10xx)) | The latest release can always be found on the [releases page][github-releases]. @@ -120,7 +135,7 @@ Construct a client instance by passing it your Okta domain name and API token: [//]: # (method: createClient) ```java -Client client = Clients.builder() +ApiClient client = Clients.builder() .setOrgUrl("https://{yourOktaDomain}") // e.g. https://dev-123456.okta.com .setClientCredentials(new TokenClientCredentials("{apiToken}")) .build(); @@ -128,47 +143,13 @@ Client client = Clients.builder() [//]: # (end: createClient) Hard-coding the Okta domain and API token works for quick tests, but for real projects you should use a more secure way of storing these values (such as environment variables). This library supports a few different configuration sources, covered in the [configuration reference](#configuration-reference) section. - -In some cases, it maybe needed to check if the client is ready and able to execute requests. The _**isReady**_ method can be used for this. It does not produce exceptions if the wrong orgUrl or token have been used, but it returns a boolean indicating the client readiness. - -[//]: # (method: isClientReady) -```java -boolean isClientReadyStatus = client.isReady(client::listApplications); -``` -[//]: # (end: isClientReady) - -## OAuth 2.0 - -Okta allows you to interact with Okta APIs using scoped OAuth 2.0 access tokens. Each access token enables the bearer to perform specific actions on specific Okta endpoints, with that ability controlled by which scopes the access token contains. - -This SDK supports this feature only for service-to-service applications. Check out [our guides](https://developer.okta.com/docs/guides/implement-oauth-for-okta-serviceapp/overview/) to learn more about how to register a new service application using a private and public key pair. - -Check out [our guide](https://developer.okta.com/docs/guides/implement-oauth-for-okta-serviceapp/main/#generate-the-jwk-using-the-admin-console) to learn how to generate a JWK and convert the same to PEM format which would be used as PrivateKey in `Client` creation. - -When using this approach, you won't need an API Token because the SDK will request an access token for you. In order to use OAuth 2.0, construct a client instance by passing the following parameters: - -[//]: # (method: createOAuth2Client) -```java -Client client = Clients.builder() - .setOrgUrl("https://{yourOktaDomain}") // e.g. https://dev-123456.okta.com - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("{clientId}") - .setKid("{kid}") // key id (optional) - .setScopes(new HashSet<>(Arrays.asList("okta.users.read", "okta.apps.read"))) - .setPrivateKey("/path/to/yourPrivateKey.pem") - // (or) .setPrivateKey("full PEM payload") - // (or) .setPrivateKey(Paths.get("/path/to/yourPrivateKey.pem")) - // (or) .setPrivateKey(inputStream) - // (or) .setPrivateKey(privateKey) - .build(); -``` -[//]: # (end: createOAuth2Client) ## Usage guide These examples will help you understand how to use this library. You can also browse the full [API reference documentation][javadocs]. -Once you initialize a `Client`, you can call methods to make requests to the Okta API. +Once you initialize a `ApiClient` instance, you can pass this instance to the constructor of any API area clients (such as `UserApi`, `GroupApi`, `ApplicationApi` etc.). +You can start using these clients to call management APIs relevant to the chosen API area. ### Authenticate a User @@ -178,7 +159,8 @@ This library should be used with the Okta management API. For authentication, we [//]: # (method: getUser) ```java -User user = client.getUser("a-user-id"); +UserApi userApi = new UserApi(client); +User user = userApi.getUser("userId"); ``` [//]: # (end: getUser) @@ -186,10 +168,11 @@ User user = client.getUser("a-user-id"); [//]: # (method: listAllUsers) ```java -UserList users = client.listUsers(); +UserApi userApi = new UserApi(client); +List users = userApi.listUsers(null, null, 5, null, null, null, null); // stream -client.listUsers().stream() +users.stream() .forEach(user -> { // do something }); @@ -202,11 +185,13 @@ For more examples of handling collections see the [paging](#paging) section belo [//]: # (method: userSearch) ```java +UserApi userApi = new UserApi(client); + // search by email -UserList users = client.listUsers("jcoder@example.com", null, null, null, null); +List users = userApi.listUsers(null, null, 5, null, "jcoder@example.com", null, null); // filter parameter -users = client.listUsers(null, "status eq \"ACTIVE\"", null, null, null); +users = userApi.listUsers(null, null, null, "status eq \"ACTIVE\"",null, null, null); ``` [//]: # (end: userSearch) @@ -214,11 +199,12 @@ users = client.listUsers(null, "status eq \"ACTIVE\"", null, null, null); [//]: # (method: createUser) ```java +UserApi userApi = new UserApi(client); User user = UserBuilder.instance() .setEmail("joe.coder@example.com") .setFirstName("Joe") .setLastName("Code") - .buildAndCreate(client); + .buildAndCreate(userApi); ``` [//]: # (end: createUser) @@ -226,12 +212,13 @@ User user = UserBuilder.instance() [//]: # (method: createUserWithGroups) ```java +UserApi userApi = new UserApi(client); User user = UserBuilder.instance() .setEmail("joe.coder@example.com") .setFirstName("Joe") .setLastName("Code") - .setGroups(new HashSet<>(Arrays.asList("group-id-1", "group-id-2"))) - .buildAndCreate(client); + .setGroups(Arrays.asList("groupId-1", "groupId-2")) + .buildAndCreate(userApi); ``` [//]: # (end: createUserWithGroups) @@ -239,28 +226,26 @@ User user = UserBuilder.instance() [//]: # (method: updateUser) ```java -user.getProfile().setFirstName("new-first-name"); -user.update(); +UserApi userApi = new UserApi(client); +UpdateUserRequest updateUserRequest = new UpdateUserRequest(); +UserProfile userProfile = new UserProfile(); +userProfile.setNickName("Batman"); +updateUserRequest.setProfile(userProfile); +userApi.updateUser(user.getId(), updateUserRequest, true); ``` [//]: # (end: updateUser) -### Get and set custom attributes - -Custom attributes must first be defined in the Okta profile editor. Then, you can work with custom attributes on a user: - -[//]: # (method: customAttributes) -```java -user.getProfile().put("customPropertyKey", "a value"); -user.getProfile().get("customPropertyKey"); -``` -[//]: # (end: customAttributes) - ### Remove a User [//]: # (method: deleteUser) ```java -user.deactivate(); -user.delete(); +UserApi userApi = new UserApi(client); + +// deactivate first +userApi.deactivateUser(user.getId(), false); + +// then delete +userApi.deleteUser(user.getId(), false); ``` [//]: # (end: deleteUser) @@ -268,7 +253,8 @@ user.delete(); [//]: # (method: listUsersGroup) ```java -GroupList groups = user.listGroups(); +GroupApi groupApi = new GroupApi(client); +List groups = groupApi.listGroups(null, null, null, 10, null, null); ``` [//]: # (end: listUsersGroup) @@ -276,10 +262,11 @@ GroupList groups = user.listGroups(); [//]: # (method: createGroup) ```java +GroupApi groupApi = new GroupApi(client); Group group = GroupBuilder.instance() .setName("a-group-name") .setDescription("Example Group") - .buildAndCreate(client); + .buildAndCreate(groupApi); ``` [//]: # (end: createGroup) @@ -295,7 +282,8 @@ user.addToGroup("groupId"); [//]: # (method: listUserFactors) ```java -UserFactorList factors = user.listFactors(); +UserFactorApi userFactorApi = new UserFactorApi(client); +List userFactors = userFactorApi.listFactors("userId"); ``` [//]: # (end: listUserFactors) @@ -303,9 +291,10 @@ UserFactorList factors = user.listFactors(); [//]: # (method: enrollUserInFactor) ```java -SmsUserFactor smsFactor = client.instantiate(SmsUserFactor.class); +UserFactorApi userFactorApi = new UserFactorApi(client); +SmsUserFactor smsFactor = new SmsUserFactor(); smsFactor.getProfile().setPhoneNumber("555 867 5309"); -user.enrollFactor(smsFactor); +UserFactor userFactor = userFactorApi.enrollFactor("userId", smsFactor, true, "templateId", 30, true); ``` [//]: # (end: enrollUserInFactor) @@ -313,10 +302,11 @@ user.enrollFactor(smsFactor); [//]: # (method: activateFactor) ```java -UserFactor factor = user.getFactor("factorId"); -ActivateFactorRequest activateFactorRequest = client.instantiate(ActivateFactorRequest.class); +UserFactorApi userFactorApi = new UserFactorApi(client); +UserFactor userFactor = userFactorApi.getFactor("userId", "factorId"); +ActivateFactorRequest activateFactorRequest = new ActivateFactorRequest(); activateFactorRequest.setPassCode("123456"); -factor.activate(activateFactorRequest); +UserFactor activatedUserFactor = userFactorApi.activateFactor("userId", "factorId", activateFactorRequest); ``` [//]: # (end: activateFactor) @@ -324,10 +314,12 @@ factor.activate(activateFactorRequest); [//]: # (method: verifyFactor) ```java -UserFactor factor = user.getFactor("factorId"); -VerifyFactorRequest verifyFactorRequest = client.instantiate(VerifyFactorRequest.class); +UserFactorApi userFactorApi = new UserFactorApi(client); +UserFactor userFactor = userFactorApi.getFactor("userId", "factorId"); +VerifyFactorRequest verifyFactorRequest = new VerifyFactorRequest(); verifyFactorRequest.setPassCode("123456"); -VerifyUserFactorResponse verifyUserFactorResponse = factor.setVerify(verifyFactorRequest).verify(); +VerifyUserFactorResponse verifyUserFactorResponse = + userFactorApi.verifyFactor("userId", "factorId", "templateId", 10, "xForwardedFor", "userAgent", "acceptLanguage", verifyFactorRequest); ``` [//]: # (end: verifyFactor) @@ -335,7 +327,8 @@ VerifyUserFactorResponse verifyUserFactorResponse = factor.setVerify(verifyFacto [//]: # (method: listApplication) ```java -ApplicationList applications = client.listApplications(); +ApplicationApi applicationApi = new ApplicationApi(client); +List applications = applicationApi.listApplications(null, null, 10, null, null, true); ``` [//]: # (end: listApplication) @@ -343,7 +336,8 @@ ApplicationList applications = client.listApplications(); [//]: # (method: getApplication) ```java -Application app = client.getApplication("appId"); +ApplicationApi applicationApi = new ApplicationApi(client); +Application app = applicationApi.getApplication("appId", null); ``` [//]: # (end: getApplication) @@ -351,24 +345,32 @@ Application app = client.getApplication("appId"); [//]: # (method: createSwaApplication) ```java -SwaApplication swaApp = client.instantiate(SwaApplication.class) - .setSettings(client.instantiate(SwaApplicationSettings.class) - .setApp(client.instantiate(SwaApplicationSettingsApplication.class) - .setButtonField("btn-login") - .setPasswordField("txtbox-password") - .setUsernameField("txtbox-username") - .setUrl("https://example.com/login.html"))); +ApplicationApi applicationApi = new ApplicationApi(client); +SwaApplicationSettingsApplication swaApplicationSettingsApplication = new SwaApplicationSettingsApplication(); +swaApplicationSettingsApplication.buttonField("btn-login") + .passwordField("txtbox-password") + .usernameField("txtbox-username") + .url("https://example.com/login.html"); +SwaApplicationSettings swaApplicationSettings = new SwaApplicationSettings(); +swaApplicationSettings.app(swaApplicationSettingsApplication); +BrowserPluginApplication browserPluginApplication = new BrowserPluginApplication(); +browserPluginApplication.name("template_swa"); +browserPluginApplication.label("Sample Plugin App"); +browserPluginApplication.settings(swaApplicationSettings); + +// create +BrowserPluginApplication createdApp = + applicationApi.createApplication(BrowserPluginApplication.class, browserPluginApplication, true, null); ``` [//]: # (end: createSwaApplication) ### List System Logs [//]: # (method: listSysLogs) ```java -// page through all log events -LogEventList logEvents = client.getLogs(); +SystemLogApi systemLogApi = new SystemLogApi(client); -// or use a filter (start date, end date, filter, or query, sort order) all options are nullable -logEvents = client.getLogs(null, null, null, "interestingURI.com", "ASCENDING"); +// use a filter (start date, end date, filter, or query, sort order) all options are nullable +List logEvents = systemLogApi.listLogEvents(null, null, null, "interestingURI.com", 100, "ASCENDING", null); ``` [//]: # (end: listSysLogs) @@ -378,14 +380,33 @@ Not every API endpoint is represented by a method in this library. You can call [//]: # (method: callAnotherEndpoint) ```java -// Create an IdP, see: https://developer.okta.com/docs/api/resources/idps#add-identity-provider -ExtensibleResource resource = client.instantiate(ExtensibleResource.class); -ExtensibleResource protocolNode = client.instantiate(ExtensibleResource.class); -protocolNode.put("type", "OAUTH"); -resource.put("protocol", protocolNode); -ExtensibleResource result = client.http() - .setBody(resource) - .post("/api/v1/idps", ExtensibleResource.class); +ApiClient apiClient = buildApiClient("orgBaseUrl", "apiKey"); + +// Create a BookmarkApplication +BookmarkApplication bookmarkApplication = new BookmarkApplication(); +bookmarkApplication.setName("bookmark"); +bookmarkApplication.setLabel("Sample Bookmark App"); +bookmarkApplication.setSignOnMode(ApplicationSignOnMode.BOOKMARK); +BookmarkApplicationSettings bookmarkApplicationSettings = new BookmarkApplicationSettings(); +BookmarkApplicationSettingsApplication bookmarkApplicationSettingsApplication = + new BookmarkApplicationSettingsApplication(); +bookmarkApplicationSettingsApplication.setUrl("https://example.com/bookmark.htm"); +bookmarkApplicationSettingsApplication.setRequestIntegration(false); +bookmarkApplicationSettings.setApp(bookmarkApplicationSettingsApplication); +bookmarkApplication.setSettings(bookmarkApplicationSettings); +ResponseEntity responseEntity = apiClient.invokeAPI("/api/v1/apps", + HttpMethod.POST, + Collections.emptyMap(), + null, + bookmarkApplication, + new HttpHeaders(), + new LinkedMultiValueMap<>(), + null, + Collections.singletonList(MediaType.APPLICATION_JSON), + MediaType.APPLICATION_JSON, + new String[]{"API Token"}, + new ParameterizedTypeReference() {}); +BookmarkApplication createdApp = responseEntity.getBody(); ``` [//]: # (end: callAnotherEndpoint) @@ -395,23 +416,29 @@ Every instance of the SDK `Client` is thread-safe. You **should** use the same i ## Paging -Paging is handled automatically when iterating over a any collection. +Paging is handled automatically when iterating over a collection. [//]: # (method: paging) ```java -// get the list of users -UserList users = client.listUsers(); +UserApi userApi = new UserApi(client); + +// limit +int pageSize = 2; +PagedList usersPagedListOne = userApi.listUsersWithPaginationInfo(null, null, pageSize, null, null, null, null); + +// e.g. https://example.okta.com/api/v1/users?after=000u3pfv9v4SQXvpBB0g7&limit=2 +String nextPageUrl = usersPagedListOne.getNextPage(); -// get the first user in the collection -log.info("First user in collection: {}", users.iterator().next().getProfile().getEmail()); +// replace 'after' with actual cursor from the nextPageUrl +PagedList usersPagedListTwo = userApi.listUsersWithPaginationInfo("after", null, pageSize, null, null, null, null); -// or loop through all of them (paging is automatic) -for (User tmpUser : users) { +// loop through all of them (paging is automatic) +for (User tmpUser : usersPagedListOne.getItems()) { log.info("User: {}", tmpUser.getProfile().getEmail()); } -// or via a stream -users.stream().forEach(tmpUser -> log.info("User: {}", tmpUser.getProfile().getEmail())); +// or stream +usersPagedListOne.getItems().forEach(tmpUser -> log.info("User: {}", tmpUser.getProfile().getEmail())); ``` [//]: # (end: paging) @@ -472,35 +499,6 @@ okta: rateLimit: maxRetries: 4 ``` - -When you use OAuth 2.0, the full YAML configuration looks like: - -```yaml -okta: - client: - connectionTimeout: 30 # seconds - orgUrl: "https://{yourOktaDomain}" # i.e. https://dev-123456.oktapreview.com - proxy: - port: null - host: null - username: null - password: null - authorizationMode: "PrivateKey" - clientId: "yourClientId" - kid: "yourKeyId" # i.e. "92u3YfA6GgQwL1uSFbgqysQjz61kWtuAhgM2yHbmCuM". This parameter is optional - scopes: "okta.users.read okta.apps.read" - privateKey: | - -----BEGIN PRIVATE KEY----- - b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn - ...b3BlbnNzaC1rZXktdjEAAAAAAAAAAAAABAAABFwAAAAdzc2gtcn-myN3AmcmmPMS... - CO7Hnjlg77HRNFXPAAAAFWxrYW1pcmVkZHlAdm13YXJlLmNvbQECAwQF - -----END PRIVATE KEY----- - # or specify a path to a PEM file - # privateKey: "/path/to/yourPrivateKey.pem" # PEM format. This SDK supports RSA AND EC algorithms - RS256, RS384, RS512, ES256, ES384, ES512. - requestTimeout: 0 # seconds - rateLimit: - maxRetries: 4 -``` ### Environment variables @@ -567,7 +565,6 @@ okta.client.requestTimeout = 0 okta.client.rateLimit.maxRetries = 0 ``` - ## Caching By default, a simple production-grade in-memory CacheManager will be enabled when the Client instance is created. This CacheManager implementation has the following characteristics: @@ -581,24 +578,24 @@ This is because the default implementation is 100% in-memory (in-process) in the As a result, if your application that uses an Okta Client instance is deployed across multiple JVMs, you SHOULD ensure that the Client is configured with a CacheManager implementation that uses coherent and clustered/distributed memory. -See the [`ClientBuilder` Javadoc](https://developer.okta.com/okta-sdk-java/apidocs/com/okta/sdk/client/ClientBuilder) for more details on caching. +See the [`ClientBuilder` Javadoc](https://developer.okta.com/okta-sdk-java/apidocs/com/okta/sdk/client/ClientBuilder) for more details on caching. ### Caching for applications deployed on a single JVM If your application is deployed on a single JVM and you still want to use the default CacheManager implementation, but the default cache configuration does not meet your needs, you can specify a different configuration. For example: - + [//]: # (method: complexCaching) ```java Caches.newCacheManager() - .withDefaultTimeToLive(300, TimeUnit.SECONDS) // default - .withDefaultTimeToIdle(300, TimeUnit.SECONDS) //general default - .withCache(forResource(User.class) //User-specific cache settings - .withTimeToLive(1, TimeUnit.HOURS) - .withTimeToIdle(30, TimeUnit.MINUTES)) - .withCache(forResource(Group.class) //Group-specific cache settings - .withTimeToLive(2, TimeUnit.HOURS)) - //... etc ... - .build(); + .withDefaultTimeToLive(300, TimeUnit.SECONDS) // default + .withDefaultTimeToIdle(300, TimeUnit.SECONDS) //general default + .withCache(forResource(User.class) //User-specific cache settings + .withTimeToLive(1, TimeUnit.HOURS) + .withTimeToIdle(30, TimeUnit.MINUTES)) + .withCache(forResource(Group.class) //Group-specific cache settings + .withTimeToLive(1, TimeUnit.HOURS)) + //... etc ... + .build(); ``` [//]: # (end: complexCaching) @@ -608,7 +605,7 @@ While production applications will usually enable a working CacheManager as desc [//]: # (method: disableCaching) ```java -Client client = Clients.builder() +ApiClient client = Clients.builder() .setCacheManager(Caches.newDisabledCacheManager()) .build(); ``` diff --git a/THIRD-PARTY-NOTICES b/THIRD-PARTY-NOTICES index 93f495dcb2d..e0efdd0ebcd 100644 --- a/THIRD-PARTY-NOTICES +++ b/THIRD-PARTY-NOTICES @@ -13,58 +13,87 @@ See the License for the specific language governing permissions and limitations under the License. This project includes: - Animal Sniffer Annotations under MIT license + A Jackson 2.x helper under The Apache Software License, Version 2.0 Apache Commons Codec under Apache License, Version 2.0 Apache Commons IO under Apache License, Version 2.0 Apache Commons Lang under Apache License, Version 2.0 Apache HttpClient under Apache License, Version 2.0 - Apache HttpClient Mime under Apache License, Version 2.0 Apache HttpCore under Apache License, Version 2.0 Auto Common Libraries under Apache 2.0 + Automaton under BSD AutoService under Apache 2.0 AutoService Processor under Apache 2.0 Bean Validation API under The Apache Software License, Version 2.0 Bouncy Castle ASN.1 Extension and Utility APIs under Bouncy Castle Licence Bouncy Castle PKIX, CMS, EAC, TSP, PKCS, OCSP, CMP, and CRMF APIs under Bouncy Castle Licence Bouncy Castle Provider under Bouncy Castle Licence + btf under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 + Caffeine cache under Apache License, Version 2.0 + Checker Qual under The MIT License commonmark-java core under BSD 2-Clause License - Commons CLI under The Apache Software License, Version 2.0 + error-prone annotations under Apache 2.0 FindBugs-jsr305 under The Apache Software License, Version 2.0 - IntelliJ IDEA Annotations under The Apache Software License, Version 2.0 + Generex under The Apache Software License, Version 2.0 + Guava InternalFutureFailureAccess and InternalFutures under The Apache Software License, Version 2.0 + Guava ListenableFuture only under The Apache Software License, Version 2.0 + Guava: Google Core Libraries for Java under Apache License, Version 2.0 + J2ObjC Annotations under The Apache Software License, Version 2.0 + Jackson datatype: Guava under The Apache Software License, Version 2.0 + Jackson datatype: Joda under The Apache Software License, Version 2.0 + Jackson datatype: JSR310 under The Apache Software License, Version 2.0 + Jackson module: Old JAXB Annotations (javax.xml.bind) under The Apache Software License, Version 2.0 Jackson-annotations under The Apache Software License, Version 2.0 Jackson-core under The Apache Software License, Version 2.0 + jackson-coreutils under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 + jackson-coreutils-equivalence under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 jackson-databind under The Apache Software License, Version 2.0 Jackson-dataformat-YAML under The Apache Software License, Version 2.0 - JavaBeans Activation Framework (JAF) under Common Development and Distribution License (CDDL) v1.0 - JavaMail API jar under CDDL or GPLv2+CE + Jackson-Datatype-ThreeTenBackport under The Apache Software License, Version 2.0 + Jackson-JAXRS: base under The Apache Software License, Version 2.0 + Jackson-JAXRS: JSON under The Apache Software License, Version 2.0 + Jakarta Activation API jar under EDL 1.0 + Jakarta Bean Validation API under Apache License 2.0 + Jakarta XML Binding API under Eclipse Distribution License - v 1.0 + Java Native Access under LGPL, version 2.1 or Apache License v2.0 + JavaMail API (no providers) under CDDL/GPLv2+CE javax.annotation API under CDDL + GPLv2 with classpath exception - JCL 1.2 implemented over SLF4J under Apache License, Version 2.0 JJWT :: API under Apache License, Version 2.0 jmustache under The (New) BSD License - Joda-Time under Apache 2 + Joda-Time under Apache License, Version 2.0 JOpt Simple under The MIT License + json-patch under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 json-schema-core under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 json-schema-validator under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 - Kotlin Stdlib under The Apache License, Version 2.0 - Kotlin Stdlib Common under The Apache License, Version 2.0 + JsonNullable Jackson module under Apache License 2.0 libphonenumber under The Apache Software License, Version 2.0 Mozilla Rhino under Mozilla Public License, Version 2.0 - null under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 - okhttp under The Apache Software License, Version 2.0 - Okio under The Apache Software License, Version 2.0 + msg-simple under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 Okta Commons :: Config Check under The Apache License, Version 2.0 Okta Commons :: HTTP :: API under The Apache License, Version 2.0 - Okta Commons :: HTTP :: HTTP Client under The Apache License, Version 2.0 - Okta Commons :: HTTP :: OkHttp Client under The Apache License, Version 2.0 Okta Commons :: Lang under The Apache License, Version 2.0 + openapi-generator (core library) under Apache License 2.0 + openapi-generator-core under Apache License 2.0 + RgxGen under The Apache Software License, Version 2.0 SLF4J API Module under MIT License + SLF4J Extensions Module under MIT License SnakeYAML under Apache License, Version 2.0 + Spring AOP under Apache License, Version 2.0 + Spring Beans under Apache License, Version 2.0 + Spring Commons Logging Bridge under Apache License, Version 2.0 + Spring Context under Apache License, Version 2.0 + Spring Core under Apache License, Version 2.0 + Spring Expression Language (SpEL) under Apache License, Version 2.0 + Spring Retry under Apache 2.0 + Spring Web under Apache License, Version 2.0 swagger-annotations under Apache License 2.0 - swagger-codegen (core library) under Apache License 2.0 swagger-compat-spec-parser under Apache License 2.0 swagger-core under Apache License 2.0 swagger-models under Apache License 2.0 swagger-parser under Apache License 2.0 + swagger-parser-v2-converter under Apache License 2.0 + swagger-parser-v3 under Apache License 2.0 + ThreeTen backport under BSD 3-clause + uri-template under Lesser General Public License, version 3 or greater or Apache Software License, version 2.0 This project also includes modified code based on the following copyrights: diff --git a/api/pom.xml b/api/pom.xml index ab53ce78704..55946e3d12c 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -21,7 +21,7 @@ com.okta.sdk okta-sdk-root - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT okta-sdk-api @@ -33,6 +33,17 @@ jar + + UTF-8 + 1.6.8 + 5.3.23 + 1.3.3 + 0.2.3 + 1.3.5 + 3.0.2 + 4.13.2 + + com.okta.commons @@ -50,10 +61,100 @@ org.slf4j slf4j-api + + + + io.swagger + swagger-annotations + ${swagger-annotations.version} + + + + + com.google.code.findbugs + jsr305 + ${jsr305.version} + + + + + org.springframework + spring-web + ${spring-web.version} + + + org.springframework + spring-context + ${spring-web.version} + + + + + org.springframework.retry + spring-retry + ${spring-retry.version} + + + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + - javax.annotation - javax.annotation-api - true + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + ${jackson.version} + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable.version} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation.version} + provided + + + + org.openapitools + openapi-generator + 6.2.0 + + + commons-logging + commons-logging + + + commons-cli + commons-cli + + + org.apache.commons + commons-text + + + com.github.jknack + handlebars + + @@ -64,16 +165,25 @@ exec-maven-plugin - org.zalando.maven.plugins - swagger-codegen-maven-plugin + org.openapitools + openapi-generator-maven-plugin + 6.2.0 - swagger-codegen-api - codegen + generate - okta_java + ${project.basedir}/../src/swagger/api.yaml + java + + src/gen/java/main + + true + false + false + src/main/resources/custom_templates + resttemplate @@ -89,12 +199,37 @@ - ${project.build.directory}/generated-sources/swagger-codegen + ${project.build.directory}/generated-sources/openapi + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + attach-javadocs + + jar + + + + + 8 + + + + http.response.details + a + Http Response Details: + + + + @@ -119,4 +254,4 @@ - + \ No newline at end of file diff --git a/api/src/main/java/com/okta/sdk/authc/credentials/ClientCredentials.java b/api/src/main/java/com/okta/sdk/authc/credentials/ClientCredentials.java index ecde3c9f26c..898a6308c4b 100644 --- a/api/src/main/java/com/okta/sdk/authc/credentials/ClientCredentials.java +++ b/api/src/main/java/com/okta/sdk/authc/credentials/ClientCredentials.java @@ -26,9 +26,9 @@ public interface ClientCredentials { * other than the actual account holder. The secret value is mostly used for computing HMAC digests, but can also * be used as a password for password-based key derivation and encryption. * - *

Security Notice

+ *

Security Notice

* - *

Okta SDKs automatically encrypt this value at rest and in SDK cache to prevent plaintext access. The + *

Okta SDKs automatically encrypt this value at rest and in SDK cache to prevent plaintext access. The * plaintext value is only available by calling this method, which returns the plaintext (unencrypted) value. * Please use this method with caution and only when necessary to ensure your API users' secrets remain * secure. diff --git a/api/src/main/java/com/okta/sdk/cache/CacheConfigurationBuilder.java b/api/src/main/java/com/okta/sdk/cache/CacheConfigurationBuilder.java index 245b851f79b..47962a01ee0 100644 --- a/api/src/main/java/com/okta/sdk/cache/CacheConfigurationBuilder.java +++ b/api/src/main/java/com/okta/sdk/cache/CacheConfigurationBuilder.java @@ -24,18 +24,18 @@ * utility class. For example: *

  * Caches.named("cacheRegionNameHere")
- *     .{@link #withTimeToLive(long, java.util.concurrent.TimeUnit) withTimeToLive(1, TimeUnit.DAYS)}
- *     .{@link #withTimeToIdle(long, java.util.concurrent.TimeUnit) withTimeToIdle(2, TimeUnit.HOURS)};
+ *     .{@link #withTimeToLive(long, TimeUnit) withTimeToLive(1, TimeUnit.DAYS)}
+ *     .{@link #withTimeToIdle(long, TimeUnit) withTimeToIdle(2, TimeUnit.HOURS)};
  * 
* or *
  * Caches.forResource(Account.class)
- *     .{@link #withTimeToLive(long, java.util.concurrent.TimeUnit) withTimeToLive(1, TimeUnit.DAYS)}
- *     .{@link #withTimeToIdle(long, java.util.concurrent.TimeUnit) withTimeToIdle(2, TimeUnit.HOURS)};
+ *     .{@link #withTimeToLive(long, TimeUnit) withTimeToLive(1, TimeUnit.DAYS)}
+ *     .{@link #withTimeToIdle(long, TimeUnit) withTimeToIdle(2, TimeUnit.HOURS)};
  * 
* - * @see #withTimeToLive(long, java.util.concurrent.TimeUnit) - * @see #withTimeToIdle(long, java.util.concurrent.TimeUnit) + * @see #withTimeToLive(long, TimeUnit) + * @see #withTimeToIdle(long, TimeUnit) * @see Caches#forResource(Class) * @see Caches#named(String) * @since 0.5.0 @@ -52,7 +52,7 @@ public interface CacheConfigurationBuilder { * If this value is not configured, it is assumed that the Cache's entries could potentially live indefinitely. * Note however that entries can still be expunged due to other conditions (e.g. memory constraints, Time to * Idle setting, etc). - *

Usage

+ * Usage *
      *     ...withTimeToLive(30, TimeUnit.MINUTES)...
      *     ...withTimeToLive(1, TimeUnit.HOURS)...
@@ -74,7 +74,7 @@ public interface CacheConfigurationBuilder {
      * If this value is not configured, it is assumed that the Cache's entries could potentially live indefinitely.
      * Note however that entries can still be expunged due to other conditions (e.g. memory constraints, Time to
      * Live setting, etc).
-     * 

Usage

+ * Usage *
      *     ...withTimeToIdle(30, TimeUnit.MINUTES)...
      *     ...withTimeToIdle(1, TimeUnit.HOURS)...
diff --git a/api/src/main/java/com/okta/sdk/cache/CacheManagerBuilder.java b/api/src/main/java/com/okta/sdk/cache/CacheManagerBuilder.java
index 0eecd876557..88f69864297 100644
--- a/api/src/main/java/com/okta/sdk/cache/CacheManagerBuilder.java
+++ b/api/src/main/java/com/okta/sdk/cache/CacheManagerBuilder.java
@@ -22,7 +22,7 @@
  * Builder for creating simple {@link CacheManager} instances suitable for SINGLE-JVM APPLICATIONS.  If your
  * application is deployed (mirrored or clustered) across multiple JVMs, you might not
  * want to use this builder and use your own clusterable CacheManager implementation instead.  See Clustering below.
- * 

Clustering

+ * Clustering * The default CacheManager instances created by this Builder DO NOT SUPPORT CLUSTERING. *

* If you use this Builder and your application is deployed on multiple JVMs, each of your application instances will @@ -32,8 +32,8 @@ * account as ENABLED, but the other application instance could see it as DISABLED. *

* For some applications, this discrepancy might be an acceptable trade-off, especially if you configure - * {@link #withDefaultTimeToIdle(long, java.util.concurrent.TimeUnit) timeToIdle} and - * {@link #withDefaultTimeToLive(long, java.util.concurrent.TimeUnit) timeToLive} settings low enough. For example, + * {@link #withDefaultTimeToIdle(long, TimeUnit) timeToIdle} and + * {@link #withDefaultTimeToLive(long, TimeUnit) timeToLive} settings low enough. For example, * maybe a TTL of 5 or 10 minutes is an acceptable time to see 'stale' account data. For other applications, this might * not be acceptable. If it is acceptable, configuring the timeToIdle and timeToLive settings will allow you to * fine-tune how much variance you allow. @@ -69,7 +69,7 @@ public interface CacheManagerBuilder { * If this value is not configured, it is assumed that cache entries could potentially live indefinitely. * Note however that entries can still be expunged due to other conditions (e.g. memory constraints, Time to * Idle setting, etc). - *

Usage

+ * Usage *
      *     ...withDefaultTimeToLive(30, TimeUnit.MINUTES)...
      *     ...withDefaultTimeToLive(1, TimeUnit.HOURS)...
@@ -93,7 +93,7 @@ public interface CacheManagerBuilder {
      * If this value is not configured, it is assumed that cache entries could potentially live indefinitely.
      * Note however that entries can still be expunged due to other conditions (e.g. memory constraints, Time to
      * Live setting, etc).
-     * 

Usage

+ * Usage *
      *     ...withDefaultTimeToLive(30, TimeUnit.MINUTES)...
      *     ...withDefaultTimeToLive(1, TimeUnit.HOURS)...
diff --git a/api/src/main/java/com/okta/sdk/cache/Caches.java b/api/src/main/java/com/okta/sdk/cache/Caches.java
index 17ff7799386..81453f2bac9 100644
--- a/api/src/main/java/com/okta/sdk/cache/Caches.java
+++ b/api/src/main/java/com/okta/sdk/cache/Caches.java
@@ -17,7 +17,6 @@
 package com.okta.sdk.cache;
 
 import com.okta.commons.lang.Classes;
-import com.okta.sdk.resource.Resource;
 
 /**
  * Static utility/helper factory methods for
@@ -30,7 +29,7 @@
  * 

See the {@link CacheManagerBuilder} JavaDoc for more information the effects of caching in * single-jvm vs distributed-jvm applications.

* - *

Usage Example

+ * Usage Example * *
  * import static com.okta.sdk.cache.Caches.*;
@@ -40,10 +39,10 @@
  * Caches.{@link #newCacheManager() newCacheManager()}
  *     .withDefaultTimeToLive(1, TimeUnit.DAYS) //general default
  *     .withDefaultTimeToIdle(2, TimeUnit.HOURS) //general default
- *     .withCache({@link com.okta.sdk.cache.Caches#forResource(Class) forResource}(Account.class) //Account-specific cache settings
+ *     .withCache({@link Caches#forResource(Class) forResource}(Account.class) //Account-specific cache settings
  *         .withTimeToLive(1, TimeUnit.HOURS)
  *         .withTimeToIdle(30, TimeUnit.MINUTES))
- *     .withCache({@link com.okta.sdk.cache.Caches#forResource(Class) forResource}(Group.class) //Group-specific cache settings
+ *     .withCache({@link Caches#forResource(Class) forResource}(Group.class) //Group-specific cache settings
  *         .withTimeToLive(2, TimeUnit.HOURS))
  *
  *     // ... etc ...
@@ -105,7 +104,7 @@ public static CacheManager newDisabledCacheManager() {
      * @return a new {@link CacheConfigurationBuilder} to configure a cache region that will store data for instances
      *         of type {@code clazz}.
      */
-    public static  CacheConfigurationBuilder forResource(Class clazz) {
+    public static  CacheConfigurationBuilder forResource(Class clazz) {
         return named(clazz.getName());
     }
 
diff --git a/api/src/main/java/com/okta/sdk/client/ClientBuilder.java b/api/src/main/java/com/okta/sdk/client/ClientBuilder.java
index ebe020765d0..c8fa594e9f8 100644
--- a/api/src/main/java/com/okta/sdk/client/ClientBuilder.java
+++ b/api/src/main/java/com/okta/sdk/client/ClientBuilder.java
@@ -16,10 +16,10 @@
  */
 package com.okta.sdk.client;
 
-import com.okta.commons.http.RequestExecutorFactory;
 import com.okta.commons.http.config.Proxy;
 import com.okta.sdk.authc.credentials.ClientCredentials;
 import com.okta.sdk.cache.CacheManager;
+import org.openapitools.client.ApiClient;
 
 import java.io.InputStream;
 import java.nio.file.Path;
@@ -27,14 +27,12 @@
 import java.util.Set;
 
 /**
- * A Builder design pattern used to
- * construct {@link com.okta.sdk.client.Client} instances.
  *
  * 

The {@code ClientBuilder} is used to construct Client instances with Okta credentials, * Proxy and Cache configuration. Understanding caching is extremely important when creating a Client instance, so * please ensure you read the Caching section below.

* - *

Usage

+ * Usage: * *

The simplest usage is to just call the {@link #build() build()} method, for example:

* @@ -44,8 +42,6 @@ * *

This will:

*
    - *
  • Automatically enable a simple in-memory {@link CacheManager} for enhanced performance (but please read - * the Caching section below for effects/warnings).
  • *
  • Automatically attempt to find your API credentials values in a number of default/conventional locations and then use * the discovered values. Without any other configuration, the following locations will be each be checked, * in order:
  • @@ -64,135 +60,6 @@ * to anyone that can read process listings. As always, secret values should never be exposed to anyone other * than the person that owns the API Key.

    * - *

    While an API Key ID may be configured anywhere (and be visible by anyone), it is recommended to use a private - * read-only file to represent API Key secrets. Never commit secrets to source code - * or version control.

    - * - *

    Explicit API Key Configuration

    - * - *

    The above default API Key searching heuristics may not be suitable to your needs. In that case, you will likely - * need to explicitly configure your API Key. For example:

    - * - *
    - * ClientCredentials clientCredentials = new TokenClientCredentials("apiToken");
    - *
    - * Client client = {@link Clients Clients}.builder().setClientCredentials(clientCredentials).build();
    - * 
    - * - *

    Caching

    - * - *

    By default, a simple production-grade in-memory {@code CacheManager} will be enabled when the Client instance is - * created. This {@code CacheManager} implementation has the following characteristics:

    - * - *
      - *
    • It assumes a default time-to-live and time-to-idle of 1 hour for all cache entries.
    • - *
    • It auto-sizes itself based on your application's memory usage. It will not cause OutOfMemoryExceptions. - * (It does this by retaining only 100 strong references to cached objects. Additional cached objects are - * weakly referenced, ensuring the garbage collector can evict weakly referenced cache entries if it needs - * more memory for your application.). - *
    • - *
    - * - *

    but, please note:

    - * - *

    The default cache manager is not suitable for an application deployed across multiple JVMs.

    - * - *

    This is because the default implementation is 100% in-memory (in-process) in the current JVM. If more than one - * JVM is deployed with the same application codebase - for example, a web application deployed on multiple identical - * hosts for scaling or high availability - each JVM would have it's own in-memory cache. Multiple disconnected caches - * for the same data will cause cache coherency problems and likely cause errors in your application!

    - * - *

    As a result, if your application that uses a Okta Client instance is deployed across multiple JVMs, you - * SHOULD ensure that the Client is configured with a {@code CacheManager} implementation that uses coherent and - * clustered/distributed memory.

    - * - *

    Custom CacheManager

    - * - *

    If you want to specify a custom {@code CacheManager} implementation:

    - * - *
    - * CacheManager cacheManager = new MyCacheManagerImplementation();
    - * Client client = {@link com.okta.sdk.client.Clients Clients}.builder().setCacheManager(cacheManager).build();
    - * 
    - * - *

    Application deployed on a single JVM

    - * - *

    If your application is deployed on a single JVM and you still want to use the default - * {@code CacheManager} implementation, but the default cache configuration does not meet your - * needs, you can specify a different configuration. For example:

    - * - *
    - * import static com.okta.sdk.cache.Caches.*;
    - *
    - * ...
    - *
    - * {@link com.okta.sdk.cache.Caches Caches}.{@link com.okta.sdk.cache.Caches#newCacheManager() newCacheManager()}
    - *     .withDefaultTimeToLive(300, TimeUnit.SECONDS) // default
    - *     .withDefaultTimeToIdle(300, TimeUnit.SECONDS) //general default
    - *     .withCache({@link com.okta.sdk.cache.Caches#forResource(Class) forResource}(User.class) //User-specific cache settings
    - *         .withTimeToLive(1, TimeUnit.HOURS)
    - *         .withTimeToIdle(30, TimeUnit.MINUTES))
    - *     .withCache({@link com.okta.sdk.cache.Caches#forResource(Class) forResource}(Group.class) //Group-specific cache settings
    - *         .withTimeToLive(2, TimeUnit.HOURS))
    - *
    - *     //... etc ...
    - *
    - *     .build(); //build the CacheManager
    - * 
    - * - *

    See the {@link com.okta.sdk.cache.Caches Caches} utility class and the - * {@link com.okta.sdk.cache.CacheManagerBuilder CacheManagerBuilder} docs for more information.

    - * - *

    Application deployed across multiple JVMs

    - * - *

    If your application is deployed across multiple JVMs (for example a web app deployed on multiple web nodes for - * scale and/or high availability), you will likely need to specify a custom - * {@code CacheManager} implementation that is based on network distributed/coherent memory. For example, an - * implementation might delegate to a Hazelcast or - * Redis cluster. For example, if using the out-of-the-box Hazelcast plugin:

    - * - *
    - * import com.okta.sdk.hazelcast.HazelcastCacheManager;
    - * // ... etc ...
    - *
    - * //Get a HazelcastInstance from your app/config.  This can be a HazelcastClient instance too:
    - * HazelcastInstance hazelcastInstance = getHazelcastInstanceOrHazelcastClient();
    - *
    - * CacheManager cacheManager = new HazelcastCacheManager(hazelcastInstance);
    - * Client client = {@link com.okta.sdk.client.Clients Clients}.builder().setCacheManager(cacheManager).build();
    - * 
    - * - *

    NOTE: it should be noted that Memcache DOES NOT guarantee cache - * coherency. It is strongly recommended that you do not use Memcache as your clustered caching solution (memcache - * is fine for caching files, etc, but not data that is expected to be coherent across multiple cluster nodes).

    - * - *

    Disable Caching

    - * - *

    While production applications will usually enable a working CacheManager as described above, you might wish to disable caching - * entirely when testing or debugging to remove 'moving parts' for better clarity into request/response - * behavior. You can do this by configuring a disabled {@code CacheManager} instance. For example:

    - * - *
    - * Client client = {@link com.okta.sdk.client.Clients Clients}.builder().setCacheManager(
    - *     {@code Caches.newDisabledCacheManager()}
    - * ).build();
    - * 
    - * - *

    Single Instance

    - * - *

    Finally, it should be noted that, after building a {@code client} instance, that same instance should be used - * everywhere in your application. Creating multiple client instances in a single application could have - * negative side effects:

    - * - *

    As mentioned above, a client has a {@link #setCacheManager(com.okta.sdk.cache.CacheManager) CacheManager} - * reference. If your application uses multiple client instances, each client's referenced CacheManager would likely - * become out of sync with the others, making your cache - * incoherent. This will likely - * result in exposing stale data to your application and could data errors.

    - * - *

    If you must have multiple {@code Client} instances in your application, you should ensure that each client - * references the same exact {@code CacheManager} instance to guarantee cache coherency.

    - * * @since 0.5.0 */ public interface ClientBuilder { @@ -246,7 +113,7 @@ public interface ClientBuilder { * Sets the {@link CacheManager} that should be used to cache Okta REST resources, reducing round-trips to the * Okta API server and enhancing application performance. * - *

    Single JVM Applications

    + * Single JVM Applications * *

    If your application runs on a single JVM-based applications, the * {@link com.okta.sdk.cache.CacheManagerBuilder CacheManagerBuilder} should be sufficient for your needs. You @@ -258,7 +125,7 @@ public interface ClientBuilder { * * ... * - * Client client = Clients.builder()... + * ApiClient client = Clients.builder()... * .setCacheManager( * {@link com.okta.sdk.cache.Caches#newCacheManager() newCacheManager()} * .withDefaultTimeToLive(1, TimeUnit.DAYS) //general default @@ -276,7 +143,7 @@ public interface ClientBuilder { *

    The above TTL and TTI times are just examples showing API usage - the times themselves are not * recommendations. Choose TTL and TTI times based on your application requirements.

    * - *

    Multi-JVM / Clustered Applications

    + * Multi-JVM / Clustered Applications * *

    The default {@code CacheManager} instances returned by the * {@link com.okta.sdk.cache.CacheManagerBuilder CacheManagerBuilder} might not be sufficient for a @@ -368,7 +235,7 @@ public interface ClientBuilder { * of relying on the default location + override/fallback behavior defined * in the {@link ClientBuilder documentation above}. * - * @param privateKey the {@link java.security.PrivateKey} instance. + * @param privateKey the {@link PrivateKey} instance. * @return the ClientBuilder instance for method chaining. * * @since 3.0.0 @@ -434,18 +301,9 @@ public interface ClientBuilder { ClientBuilder setRetryMaxAttempts(int maxAttempts); /** - * Sets the {@link RequestExecutorFactory}, otherwise it will be loaded as a Service / SPI - * via the {@link RequestExecutorFactory} class. - * - * @param requestExecutorFactory that should be used to create the RequestExecutor - * @return the ClientBuilder instance for method chaining - */ - ClientBuilder setRequestExecutorFactory(RequestExecutorFactory requestExecutorFactory); - - /** - * Constructs a new {@link Client} instance based on the ClientBuilder's current configuration state. + * Constructs a new {@link org.openapitools.client.ApiClient} instance based on the ClientBuilder's current configuration state. * - * @return a new {@link Client} instance based on the ClientBuilder's current configuration state. + * @return a new {@link org.openapitools.client.ApiClient} instance based on the ClientBuilder's current configuration state. */ - Client build(); + ApiClient build(); } diff --git a/api/src/main/java/com/okta/sdk/client/Clients.java b/api/src/main/java/com/okta/sdk/client/Clients.java index 7c44a98242a..9de1068a104 100644 --- a/api/src/main/java/com/okta/sdk/client/Clients.java +++ b/api/src/main/java/com/okta/sdk/client/Clients.java @@ -19,7 +19,7 @@ import com.okta.commons.lang.Classes; /** - * Static utility/helper class for working with {@link Client} resources. For example: + * Static utility/helper class for working with {@link org.openapitools.client.ApiClient} resources. For example: *

      * Clients.builder()
      *     // ... etc ...
    @@ -35,9 +35,9 @@
     public final class Clients {
     
         /**
    -     * Returns a new {@link ClientBuilder} instance, used to construct {@link Client} instances.
    +     * Returns a new {@link ClientBuilder} instance, used to construct {@link org.openapitools.client.ApiClient} instances.
          *
    -     * @return a a new {@link ClientBuilder} instance, used to construct {@link Client} instances.
    +     * @return a a new {@link ClientBuilder} instance, used to construct {@link org.openapitools.client.ApiClient} instances.
          */
         public static ClientBuilder builder() {
             return (ClientBuilder) Classes.newInstance("com.okta.sdk.impl.client.DefaultClientBuilder");
    diff --git a/api/src/main/java/com/okta/sdk/ds/DataStore.java b/api/src/main/java/com/okta/sdk/ds/DataStore.java
    deleted file mode 100644
    index 7c6fb27ba51..00000000000
    --- a/api/src/main/java/com/okta/sdk/ds/DataStore.java
    +++ /dev/null
    @@ -1,125 +0,0 @@
    -/*
    - * Copyright 2014 Stormpath, Inc.
    - * Modifications Copyright 2018 Okta, Inc.
    - *
    - * Licensed under the Apache License, Version 2.0 (the "License");
    - * you may not use this file except in compliance with the License.
    - * You may obtain a copy of the License at
    - *
    - *     http://www.apache.org/licenses/LICENSE-2.0
    - *
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS,
    - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - * See the License for the specific language governing permissions and
    - * limitations under the License.
    - */
    -package com.okta.sdk.ds;
    -
    -import com.okta.sdk.authc.credentials.ClientCredentials;
    -import com.okta.sdk.cache.CacheManager;
    -import com.okta.sdk.resource.Resource;
    -
    -import java.util.function.Supplier;
    -
    -/**
    - * A {@code DataStore} is the liaison between client SDK components and the raw Okta REST API.  It is responsible
    - * for converting SDK objects (Account, Directory, Group instances, etc) into REST HTTP requests, executing those
    - * requests, and converting REST HTTP responses back into SDK objects.
    - *
    - * @since 0.5.0
    - */
    -public interface DataStore {
    -
    -    /**
    -     * Instantiates and returns a new instance of the specified Resource type.  The instance is merely instantiated and
    -     * is not saved/synchronized with the server in any way. 

    This method effectively replaces the {@code new} - * keyword that would have been used otherwise if the concrete implementation was known (Resource implementation - * classes are intentionally not exposed to SDK end-users). - * - * @param clazz the Resource class to instantiate. - * @param the Resource sub-type - * @return a new instance of the specified Resource. - */ - T instantiate(Class clazz); - - /** - * Looks up (retrieves) the resource at the specified {@code href} URL and returns the resource as an instance of - * the specified {@code class}.

    The {@code Class} argument must represent an interface that is a sub-interface - * of {@link Resource}. - * - * @param href the resource URL of the resource to retrieve - * @param clazz the {@link Resource} sub-interface to instantiate - * @param type parameter indicating the returned value is a {@link Resource} instance. - * @return an instance of the specified class based on the data returned from the specified {@code href} URL. - */ - T getResource(String href, Class clazz); - - /** - * Creates a new resource and returns the instance as represented by the server. This could mean default values - * have been set, modification dates changed, etc. - * - * @param parentHref the resource URL of the resource to retrieve - * @param resource the object payload to to send to the server - * @param type parameter indicating the returned value is a {@link Resource} instance. - * @return an updated resource as represented by the server. - * - * @since 1.1.0 - */ - T create(String parentHref, T resource); - - /** - * Saves an exiting resource to the remote server. - *

    - * NOTE: this is typically done by using {@code resource.save()} instead of this method. - * - * @param href the resource URL of the resource to updated - * @param resource the object payload to to send to the server - * @param type parameter indicating the type of {@link Resource} instance. - * - * @since 1.1.0 - */ - void save(String href, T resource); - - /** - * Deleted a resource on the remote server.

    - * NOTE: this is typically done by using {@code resource.delete()} instead of this method. - * - * @param href the resource URL of the resource to deleted - * @param resource the object payload to to send to the server - * @param type parameter indicating the type of {@link Resource} instance. - * - * @since 1.1.0 - */ - void delete(String href, T resource); - - /** - * Returns the ClientCredentials used to authenticate HTTPS requests sent to the Okta API server. - * - * @return the ClientCredentials used to authenticate HTTPS requests sent to the Okta API server. - */ - ClientCredentials getClientCredentials(); - - /** - * Returns the CacheManager used to improve data store performance. - * - * @return the CacheManager used to improve data store performance. - */ - CacheManager getCacheManager(); - - /** - * Returns an http request builder to help make requests to Okta endpoints that are NOT implemented by this SDK. - * - * @return an http request builder to help make requests to Okta endpoints that are NOT implemented by this SDK. - * @since 1.2.0 - */ - RequestBuilder http(); - - /** - * Check if Datastore is configured correctly and able to execute requests. - * - * @param methodReference a reference to the method based on which the ready state will be checked - * @return {@code true} if orgUrl and token are correct and Okta Core is available, otherwise {@code false}. - */ - boolean isReady(Supplier methodReference); -} diff --git a/api/src/main/java/com/okta/sdk/ds/RequestBuilder.java b/api/src/main/java/com/okta/sdk/ds/RequestBuilder.java deleted file mode 100644 index 7425035fe7a..00000000000 --- a/api/src/main/java/com/okta/sdk/ds/RequestBuilder.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018-present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.ds; - -import com.okta.sdk.resource.Resource; -import com.okta.sdk.resource.VoidResource; - -import java.io.InputStream; -import java.util.List; -import java.util.Map; - -/** - * A RequestBuilder allows for making {@link Resource} based request to any Okta endpoint. Not all Okta endpoints are - * implemented by this SDK currently, this interface allow to make requests with: - *

      - *
    • Any Resource as the request {@code body}
    • - *
    • Setting query parameters
    • - *
    • GET, POST, PUT, and DELETE requests
    • - *
    - * - * Example usage for the Set Password:

    - * - * - * // create a resource - * Resource userPasswordRequest = client.instantiate(ExtensibleResource) - * userPasswordRequest.put("credentials", client.instantiate(ExtensibleResource) - * .put("password", client.instantiate(ExtensibleResource) - * .put("value", "aPassword1!".toCharArray()))) - * - * // make a POST request to `/api/v1/users/{userId}` and return a User resource - * User result = client.getDataStore().http() - * .setBody(userPasswordRequest) - * .post("/api/v1/users/"+ userId, User.class) - * - * - * @since 1.2.0 - */ -public interface RequestBuilder { - - /** - * Sets the Resource body for the request. - * - * @param resource the request body - * @return the RequestBuilder to allow for chaining methods. - */ - RequestBuilder setBody(Resource resource); - - /** - * Adds a query parameter to the request builder. - * - * @param key the query parameter field name - * @param value the query parameter field value - * @return the RequestBuilder to allow for chaining methods. - */ - RequestBuilder addQueryParameter(String key, String value); - - /** - * Sets the query parameters to be used for the request. - * - * @param queryParams the query parameters to be used for the request - * @return the RequestBuilder to allow for chaining methods. - */ - RequestBuilder setQueryParameters(Map queryParams); - - /** - * Adds a header parameter to the request builder. - * - * @param key the header parameter field name - * @param value the header parameter field value - * @return the RequestBuilder to allow for chaining methods. - */ - RequestBuilder addHeaderParameter(String key, String value); - - /** - * Adds a header parameter to the request builder. - * - * @param key the header parameter field name - * @param values the header parameter field values - * @return the RequestBuilder to allow for chaining methods. - */ - RequestBuilder addHeaderParameter(String key, List values); - - /** - * Sets the header parameters to be used for the request. - * - * @param headerParams the header parameters to be used for the request - * @return the RequestBuilder to allow for chaining methods. - */ - RequestBuilder setHeaderParameters(Map> headerParams); - - /** - * Executes a {@code GET} request and returns a Resource. - * - * @param href an absolute or partial HREF - * @param type the Resource type to return - * @param the Resource type to return - * @return The response payload unmarshalled into a Resource - */ - T get(String href, Class type); - - /** - * Executes a {@code GET} request and returns a raw response. - * - * @param href an absolute or partial HREF - * @return The response payload as InputStream - */ - InputStream getRaw(String href); - - /** - * Executes a {@code PUT} request and updates the resource used as the {@code body}. - * - * @param href an absolute or partial HREF - */ - void put(String href); - - /** - * Executes a {@code POST} request and returns a Resource. - * - * @param href an absolute or partial HREF - * @param type the Resource type to return - * @param the Resource type to return - * @return The response payload unmarshalled into a Resource - */ - T post(String href, Class type); - - /** - * Executes a {@code POST} request. - * - * @param href an absolute or partial HREF - */ - default void post(String href) { - post(href, VoidResource.class); - } - - /** - * - * Executes a {@code DELETE} request. - * - * @param href an absolute or partial HREF - */ - void delete(String href); -} \ No newline at end of file diff --git a/api/src/main/java/com/okta/sdk/error/ErrorCause.java b/api/src/main/java/com/okta/sdk/error/ErrorCause.java index 9797e4f1d52..6ad82cb564e 100644 --- a/api/src/main/java/com/okta/sdk/error/ErrorCause.java +++ b/api/src/main/java/com/okta/sdk/error/ErrorCause.java @@ -15,10 +15,20 @@ */ package com.okta.sdk.error; +public class ErrorCause { -import com.okta.sdk.resource.Resource; + private final String summary; -public interface ErrorCause extends Resource{ + public ErrorCause(String summary) { + this.summary = summary; + } - String getSummary(); + public String getSummary() { + return this.summary; + } + + @Override + public String toString() { + return "ErrorCause { summary='" + getSummary() + " }"; + } } diff --git a/api/src/main/java/com/okta/sdk/error/ErrorHandler.java b/api/src/main/java/com/okta/sdk/error/ErrorHandler.java new file mode 100644 index 00000000000..ff36e9476b0 --- /dev/null +++ b/api/src/main/java/com/okta/sdk/error/ErrorHandler.java @@ -0,0 +1,124 @@ +/* + * Copyright 2022-Present Okta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.okta.sdk.error; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.JacksonException; + +import org.springframework.http.HttpStatus; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.client.ResponseErrorHandler; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ErrorHandler implements ResponseErrorHandler { + + static final String ERROR_ID_PROPERTY = "errorId"; + static final String SUMMARY_PROPERTY = "errorSummary"; + static final String CAUSES_PROPERTY = "errorCauses"; + static final String HEADERS_PROPERTY = "errorHeaders"; + + private final ObjectMapper mapper = new ObjectMapper(); + + @Override + public boolean hasError(ClientHttpResponse httpResponse) throws IOException { + return httpResponse.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR || + httpResponse.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR; + } + + @Override + public void handleError(ClientHttpResponse httpResponse) throws IOException, ResourceException { + + final int statusCode = httpResponse.getRawStatusCode(); + final String message = new String(FileCopyUtils.copyToByteArray(httpResponse.getBody())); + + if (!isValid(message)) { + throw new ResourceException(new NonJsonError(message)); + } + + final Map errorMap = mapper.readValue(message, Map.class); + + Error error = new Error() { + @Override + public int getStatus() { + return statusCode; + } + + @Override + public String getCode() { + return String.valueOf(statusCode); + } + + @Override + public String getMessage() { + return String.valueOf(errorMap.get(SUMMARY_PROPERTY)); + } + + @Override + public String getId() { + return String.valueOf(errorMap.get(ERROR_ID_PROPERTY)); + } + + @Override + public List getCauses() { + List results = new ArrayList<>(); + Object rawProp = errorMap.get(CAUSES_PROPERTY); + if (rawProp instanceof List) { + ((List>) rawProp).forEach(causeMap -> + results.add(new ErrorCause(String.valueOf(causeMap.get(SUMMARY_PROPERTY))))); + } + return Collections.unmodifiableList(results); + } + + @Override + public Map> getHeaders() { + Map> results = new HashMap<>(); + Object rawProp = errorMap.get(HEADERS_PROPERTY); + if (rawProp instanceof List) { + results.put(HEADERS_PROPERTY, (ArrayList) rawProp); + } + return Collections.unmodifiableMap(results); + } + }; + + if (statusCode == 429) { + // retry 429 + throw new RetryableException(error); + } + throw new ResourceException(error); + } + + /** + * Backend might return a non JSON error message (HTML), so check if error message is a valid JSON. + * + * @param json error message + * @return true if json is valid, false otherwise + */ + boolean isValid(String json) { + try { + mapper.readTree(json); + } catch (JacksonException e) { + return false; + } + return true; + } +} diff --git a/api/src/main/java/com/okta/sdk/error/NonJsonError.java b/api/src/main/java/com/okta/sdk/error/NonJsonError.java new file mode 100644 index 00000000000..875b32b0544 --- /dev/null +++ b/api/src/main/java/com/okta/sdk/error/NonJsonError.java @@ -0,0 +1,58 @@ +/* + * Copyright 2021-Present Okta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.okta.sdk.error; + +import java.util.List; +import java.util.Map; + +public class NonJsonError implements Error { + + private final String message; + + public NonJsonError(String message) { + this.message = message; + } + + @Override + public int getStatus() { + return 0; + } + + @Override + public String getCode() { + return null; + } + + @Override + public String getMessage() { + return message; + } + + @Override + public String getId() { + return null; + } + + @Override + public List getCauses() { + return null; + } + + @Override + public Map> getHeaders() { + return null; + } +} diff --git a/api/src/main/java/com/okta/sdk/resource/ResourceException.java b/api/src/main/java/com/okta/sdk/error/ResourceException.java similarity index 96% rename from api/src/main/java/com/okta/sdk/resource/ResourceException.java rename to api/src/main/java/com/okta/sdk/error/ResourceException.java index b9df3be3ce8..cfdaef27d6e 100644 --- a/api/src/main/java/com/okta/sdk/resource/ResourceException.java +++ b/api/src/main/java/com/okta/sdk/error/ResourceException.java @@ -14,13 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.okta.sdk.resource; +package com.okta.sdk.error; import com.okta.commons.lang.Assert; import com.okta.commons.lang.Collections; import com.okta.commons.lang.Strings; -import com.okta.sdk.error.Error; -import com.okta.sdk.error.ErrorCause; import java.util.List; import java.util.Map; @@ -54,7 +52,7 @@ private static String buildExceptionMessage(Error error) { // if there is only one cause (most common) just include it, otherwise show the cause count int causeCount = Collections.size(error.getCauses()); if (causeCount == 1) { - sb.append(" - ").append(error.getCauses().get(0).getSummary()); + sb.append(" - ").append(error.getCauses()); } else if (causeCount > 1) { sb.append(" - '").append(causeCount).append(" causes'"); } diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/Filter.java b/api/src/main/java/com/okta/sdk/error/RetryableException.java similarity index 80% rename from impl/src/main/java/com/okta/sdk/impl/ds/Filter.java rename to api/src/main/java/com/okta/sdk/error/RetryableException.java index 0e90265de7d..7968b9e2581 100644 --- a/impl/src/main/java/com/okta/sdk/impl/ds/Filter.java +++ b/api/src/main/java/com/okta/sdk/error/RetryableException.java @@ -14,10 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.okta.sdk.impl.ds; +package com.okta.sdk.error; -public interface Filter { - - ResourceDataResult filter(ResourceDataRequest request, FilterChain chain); +public class RetryableException extends ResourceException { + public RetryableException(Error error) { + super(error); + } } diff --git a/api/src/main/java/com/okta/sdk/error/authc/IncorrectCredentialsException.java b/api/src/main/java/com/okta/sdk/error/authc/IncorrectCredentialsException.java deleted file mode 100644 index 0d7b307c13c..00000000000 --- a/api/src/main/java/com/okta/sdk/error/authc/IncorrectCredentialsException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.error.authc; - -import com.okta.sdk.error.Error; -import com.okta.sdk.resource.ResourceException; - -/** - * A sub-class of {@link ResourceException} representing an attempt to login using incorrect credentials. - * - * @since 0.5.0 - */ -public class IncorrectCredentialsException extends ResourceException { - - public IncorrectCredentialsException(Error error) { - super(error); - } - -} diff --git a/api/src/main/java/com/okta/sdk/error/authc/InvalidAuthenticationException.java b/api/src/main/java/com/okta/sdk/error/authc/InvalidAuthenticationException.java deleted file mode 100644 index d57dc00c71b..00000000000 --- a/api/src/main/java/com/okta/sdk/error/authc/InvalidAuthenticationException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.error.authc; - -import com.okta.sdk.error.Error; -import com.okta.sdk.resource.ResourceException; - -/** - * Thrown when the Authentication credentials (or access_token for OAuth requests) cannot be found in the {@code httpRequest}. - * - * @since 0.5.0 - */ -public class InvalidAuthenticationException extends ResourceException { - - public InvalidAuthenticationException(Error error) { - super(error); - } -} diff --git a/api/src/main/java/com/okta/sdk/error/authc/InvalidCredentialsException.java b/api/src/main/java/com/okta/sdk/error/authc/InvalidCredentialsException.java deleted file mode 100644 index 599473d69bc..00000000000 --- a/api/src/main/java/com/okta/sdk/error/authc/InvalidCredentialsException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.error.authc; - -import com.okta.sdk.error.Error; -import com.okta.sdk.resource.ResourceException; - -/** - * A sub-class of {@link ResourceException} representing an attempt to login using an malformed credentials. - * - * @since 0.5.0 - */ -public class InvalidCredentialsException extends ResourceException { - - public InvalidCredentialsException(Error error) { - super(error); - } -} diff --git a/api/src/main/java/com/okta/sdk/error/authc/MissingCredentialsException.java b/api/src/main/java/com/okta/sdk/error/authc/MissingCredentialsException.java deleted file mode 100644 index 34e3a42580b..00000000000 --- a/api/src/main/java/com/okta/sdk/error/authc/MissingCredentialsException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.error.authc; - -import com.okta.sdk.error.Error; -import com.okta.sdk.resource.ResourceException; - -/** - * Thrown when the an Authentication Request lacks a ClientCredentials. - * - * @since 0.5.0 - */ -public class MissingCredentialsException extends ResourceException { - - public MissingCredentialsException(Error error) { - super(error); - } -} diff --git a/api/src/main/java/com/okta/sdk/error/authc/UnsupportedAuthenticationSchemeException.java b/api/src/main/java/com/okta/sdk/error/authc/UnsupportedAuthenticationSchemeException.java deleted file mode 100644 index 18060c7de1e..00000000000 --- a/api/src/main/java/com/okta/sdk/error/authc/UnsupportedAuthenticationSchemeException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.error.authc; - -import com.okta.sdk.error.Error; -import com.okta.sdk.resource.ResourceException; - -/** - * A sub-class of {@link ResourceException} representing an authentication scheme not supported by Okta. - * - * @since 0.5.0 - */ - -public class UnsupportedAuthenticationSchemeException extends ResourceException { - - public UnsupportedAuthenticationSchemeException(Error error) { - super(error); - } - -} \ No newline at end of file diff --git a/api/src/main/java/com/okta/sdk/resource/Auditable.java b/api/src/main/java/com/okta/sdk/resource/Auditable.java deleted file mode 100644 index 3148071c35b..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/Auditable.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -import java.util.Date; - -/** - * Interface to be implemented by {@link Resource Resources} that contain and can be retrieved using the {@code Resource#createdAt}. - * - * @since 0.5.0 - */ -public interface Auditable { - - /** - * Returns the Resource's created date. - * - * @return the Resource's created date. - */ - Date getCreatedAt(); - - /** - * Returns the Resource's last modification date. - * - * @return the Resource's last modification date. - */ - Date getModifiedAt(); -} diff --git a/api/src/main/java/com/okta/sdk/resource/CollectionResource.java b/api/src/main/java/com/okta/sdk/resource/CollectionResource.java deleted file mode 100644 index c386176cf88..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/CollectionResource.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -import java.util.stream.Stream; - -/** - * A {@code CollectionResource} is a first-class {@link Resource} that contains a collection of - * other {@link Resource} instances. - * - * @since 0.5.0 - */ -public interface CollectionResource extends Resource, Iterable { - - /** - * This is just a convenience method to retrieve the single element expected to exist in this collection. This method is - * intended to be used in cases where the returned list is explicitly expected to contain a single element. This operation will throw - * an exception if this list contains zero or more than one element. - * - *

    This method is not backed by any specific property obtained from the backend, as already mentioned, this is a convenience method.

    - * - * @return the single unique resource that is expect to be contained within this list. - * @throws java.lang.IllegalStateException if this list contains either zero or more than one element. - */ - T single(); - - /** - * Returns a sequential {@code Stream} with this collection as its source. - * - * @return a sequential {@code Stream} over the elements in this resource - * @since 1.0 - */ - Stream stream(); - - /** - * Returns a next page URL - * - * @return a URL link to the next resource, or {@code null} if the current resource is the last one. - */ - String getNextPageUrl(); -} diff --git a/api/src/main/java/com/okta/sdk/resource/Deletable.java b/api/src/main/java/com/okta/sdk/resource/Deletable.java deleted file mode 100644 index d7ca1489382..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/Deletable.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -/** - * @since 0.5.0 - */ -public interface Deletable { - - void delete(); -} diff --git a/api/src/main/java/com/okta/sdk/resource/ExtensibleResource.java b/api/src/main/java/com/okta/sdk/resource/ExtensibleResource.java deleted file mode 100644 index a02e0837bce..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/ExtensibleResource.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -import java.util.Map; - -/** - * A {@link Resource} whose's properties are accessible via a map, and convenience methods via {@link PropertyRetriever}. - * - * @since 1.1.0 - */ -public interface ExtensibleResource extends Resource, PropertyRetriever, Map { -} diff --git a/api/src/main/java/com/okta/sdk/resource/FileResource.java b/api/src/main/java/com/okta/sdk/resource/FileResource.java deleted file mode 100644 index ff2585c6309..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/FileResource.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2021-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -public interface FileResource extends Resource { - - String getLocation(); - - String getFormDataName(); -} diff --git a/api/src/main/java/com/okta/sdk/resource/PropertyRetriever.java b/api/src/main/java/com/okta/sdk/resource/PropertyRetriever.java deleted file mode 100644 index 142e2d0ceb8..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/PropertyRetriever.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -import java.util.List; - -public interface PropertyRetriever { - - String getString(String key); - - Double getNumber(String key); - - Boolean getBoolean(String key); - - Integer getInteger(String key); - - List getStringList(String key); - - List getNumberList(String key); - - List getIntegerList(String key); -} \ No newline at end of file diff --git a/api/src/main/java/com/okta/sdk/resource/Resource.java b/api/src/main/java/com/okta/sdk/resource/Resource.java deleted file mode 100644 index eda0931c165..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/Resource.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -/** - * Base representation of a REST resource payload. All objects transferred over the wire by this SDK are Resources. - * @since 0.5.0 - */ -public interface Resource { - - String getResourceHref(); - void setResourceHref(String href); -} diff --git a/api/src/main/java/com/okta/sdk/resource/Saveable.java b/api/src/main/java/com/okta/sdk/resource/Saveable.java deleted file mode 100644 index d29bac0ed9b..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/Saveable.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -/** - * @since 0.5.0 - */ -public interface Saveable { - - R save(); - -} diff --git a/api/src/main/java/com/okta/sdk/resource/VoidResource.java b/api/src/main/java/com/okta/sdk/resource/VoidResource.java deleted file mode 100644 index 236b1ec1b13..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/VoidResource.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource; - -/** - * A generic Resource implementation that can be used when the response type is expected to be empty; - */ -public interface VoidResource extends Resource { -} diff --git a/api/src/main/java/com/okta/sdk/resource/application/ApplicationBuilder.java b/api/src/main/java/com/okta/sdk/resource/application/ApplicationBuilder.java index 75aa07d5c47..d0dce15ee42 100644 --- a/api/src/main/java/com/okta/sdk/resource/application/ApplicationBuilder.java +++ b/api/src/main/java/com/okta/sdk/resource/application/ApplicationBuilder.java @@ -16,9 +16,12 @@ package com.okta.sdk.resource.application; import com.okta.commons.lang.Classes; -import com.okta.sdk.client.Client; +import org.openapitools.client.api.ApplicationApi; +import org.openapitools.client.model.Application; +import org.openapitools.client.model.ApplicationSignOnMode; public interface ApplicationBuilder { + static ApplicationBuilder instance() { return Classes.newInstance("com.okta.sdk.impl.resource.DefaultApplicationBuilder"); } @@ -39,5 +42,5 @@ static ApplicationBuilder instance() { T setWeb(Boolean web); - Application buildAndCreate(Client client); + Application buildAndCreate(ApplicationApi client); } diff --git a/api/src/main/java/com/okta/sdk/resource/application/OIDCApplicationBuilder.java b/api/src/main/java/com/okta/sdk/resource/application/OIDCApplicationBuilder.java index 38b4935e2da..2ed3a69abba 100644 --- a/api/src/main/java/com/okta/sdk/resource/application/OIDCApplicationBuilder.java +++ b/api/src/main/java/com/okta/sdk/resource/application/OIDCApplicationBuilder.java @@ -16,6 +16,12 @@ package com.okta.sdk.resource.application; import com.okta.commons.lang.Classes; +import org.openapitools.client.model.JsonWebKey; +import org.openapitools.client.model.OAuthEndpointAuthenticationMethod; +import org.openapitools.client.model.OAuthGrantType; +import org.openapitools.client.model.OAuthResponseType; +import org.openapitools.client.model.OpenIdConnectApplicationConsentMethod; +import org.openapitools.client.model.OpenIdConnectApplicationType; import java.util.List; @@ -60,4 +66,8 @@ static OIDCApplicationBuilder instance() { OIDCApplicationBuilder setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod tokenEndpointAuthMethod); OIDCApplicationBuilder setJwks(List jsonWebKeyList); + + OIDCApplicationBuilder setImplicitAssignment(Boolean isImplicitAssignment); + + OIDCApplicationBuilder setInlineHookId(String inlineHookId); } diff --git a/api/src/main/java/com/okta/sdk/resource/common/PagedList.java b/api/src/main/java/com/okta/sdk/resource/common/PagedList.java new file mode 100644 index 00000000000..671f05caa78 --- /dev/null +++ b/api/src/main/java/com/okta/sdk/resource/common/PagedList.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022-Present, Okta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.okta.sdk.resource.common; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class PagedList { + + private List items; + private String self; + private String nextPage; + + public List getItems() { + return items; + } + + public String getSelf() { + return self; + } + + public String getNextPage() { + return nextPage; + } + + public void setSelf(String self) { + this.self = self; + } + + public void addItems(List itemsToAdd) { + this.items = (List) flatten(itemsToAdd); + } + + public List items() { + return getItems(); + } + + public void setNextPage(String nextPage) { + this.nextPage = nextPage; + } + + private List flatten(List list) { + return list.stream() + .flatMap(e -> e instanceof List ? flatten((List) e).stream() : Stream.of(e)) + .collect(Collectors.toList()); + } +} diff --git a/api/src/main/java/com/okta/sdk/resource/event/hook/EventHookBuilder.java b/api/src/main/java/com/okta/sdk/resource/event/hook/EventHookBuilder.java deleted file mode 100644 index 74f5fab16c6..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/event/hook/EventHookBuilder.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.event.hook; - -import com.okta.commons.lang.Classes; -import com.okta.sdk.client.Client; - -public interface EventHookBuilder { - EventHookBuilder setName(String name); - - EventHookBuilder setUrl(String url); - - EventHookBuilder setAuthorizationHeaderValue(String authorizationHeaderValue); - - EventHookBuilder addHeader(String name, String value); - - EventHook buildAndCreate(Client client); - - static EventHookBuilder instance() { - return Classes.newInstance("com.okta.sdk.impl.resource.event.hook.DefaultEventHookBuilder"); - } -} diff --git a/api/src/main/java/com/okta/sdk/resource/group/GroupBuilder.java b/api/src/main/java/com/okta/sdk/resource/group/GroupBuilder.java index 2cbfec47779..34416688e5b 100644 --- a/api/src/main/java/com/okta/sdk/resource/group/GroupBuilder.java +++ b/api/src/main/java/com/okta/sdk/resource/group/GroupBuilder.java @@ -16,7 +16,8 @@ package com.okta.sdk.resource.group; import com.okta.commons.lang.Classes; -import com.okta.sdk.client.Client; +import org.openapitools.client.api.GroupApi; +import org.openapitools.client.model.Group; public interface GroupBuilder { @@ -28,6 +29,5 @@ static GroupBuilder instance() { GroupBuilder setDescription(String description); - Group buildAndCreate(Client client); - + Group buildAndCreate(GroupApi client); } diff --git a/api/src/main/java/com/okta/sdk/resource/group/rule/GroupRuleBuilder.java b/api/src/main/java/com/okta/sdk/resource/group/rule/GroupRuleBuilder.java deleted file mode 100644 index 3e6bccbc47d..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/group/rule/GroupRuleBuilder.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.group.rule; - -import com.okta.commons.lang.Classes; -import com.okta.sdk.client.Client; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public interface GroupRuleBuilder { - - static GroupRuleBuilder instance(){ return Classes.newInstance("com.okta.sdk.impl.resource.DefaultGroupRuleBuilder");} - - GroupRuleBuilder setName(String name); - - GroupRuleBuilder setType(String type); - - GroupRuleBuilder setAssignUserToGroups(List assignUserToGroups); - - default GroupRuleBuilder setGroups(String... groupIds) { - return setGroups(Arrays.stream(groupIds).collect(Collectors.toList())); - } - - GroupRuleBuilder setGroups(List groupIds); - - GroupRuleBuilder addGroup(String groupId); - - default GroupRuleBuilder setUsers(String... userIds) { - return setUsers(Arrays.stream(userIds).collect(Collectors.toList())); - } - - GroupRuleBuilder setUsers(List userIds); - - GroupRuleBuilder addUser(String userId); - - GroupRuleBuilder setGroupRuleExpressionType(String groupRuleExpressionType); - - GroupRuleBuilder setGroupRuleExpressionValue(String groupRuleExpressionValue); - - GroupRule buildAndCreate(Client client); - - -} diff --git a/api/src/main/java/com/okta/sdk/resource/identity/provider/IdentityProviderBuilder.java b/api/src/main/java/com/okta/sdk/resource/identity/provider/IdentityProviderBuilder.java deleted file mode 100644 index effc8378ece..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/identity/provider/IdentityProviderBuilder.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.identity.provider; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.policy.PolicySubjectMatchType; - -import java.util.List; - -public interface IdentityProviderBuilder { - - T setName(String name); - - T setClientId(String clientId); - - T setClientSecret(String clientSecret); - - T setScopes(List scopes); - - T setMaxClockSkew(Integer maxClockSkew); - - T setUserName(String userName); - - T setMatchType(PolicySubjectMatchType policySubjectMatchType); - - T setIsProfileMaster(Boolean isProfileMaster); - - T isProfileMaster(Boolean isProfileMaster); - - IdentityProvider buildAndCreate(Client client); -} diff --git a/api/src/main/java/com/okta/sdk/resource/identity/provider/IdentityProviderBuilders.java b/api/src/main/java/com/okta/sdk/resource/identity/provider/IdentityProviderBuilders.java deleted file mode 100644 index 04ef2d00ec7..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/identity/provider/IdentityProviderBuilders.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.identity.provider; - -import com.okta.commons.lang.Classes; - -public class IdentityProviderBuilders { - - public static OIDCIdentityProviderBuilder oidc() { - return Classes.newInstance("com.okta.sdk.impl.resource.identity.provider.OidcIdentityProviderBuilder"); - } - - public static IdentityProviderBuilder google() { - return Classes.newInstance("com.okta.sdk.impl.resource.identity.provider.GoogleIdentityProviderBuilder"); - } - - public static IdentityProviderBuilder facebook() { - return Classes.newInstance("com.okta.sdk.impl.resource.identity.provider.FacebookIdentityProviderBuilder"); - } - - public static IdentityProviderBuilder microsoft() { - return Classes.newInstance("com.okta.sdk.impl.resource.identity.provider.MicrosoftIdentityProviderBuilder"); - } - - public static IdentityProviderBuilder linkedin() { - return Classes.newInstance("com.okta.sdk.impl.resource.identity.provider.LinkedInIdentityProviderBuilder"); - } - - public static IdentityProviderBuilder ofType(String type) { - return Classes.newInstance("com.okta.sdk.impl.resource.identity.provider.StringTypeIdentityProviderBuilder", type); - } -} diff --git a/api/src/main/java/com/okta/sdk/resource/identity/provider/OIDCIdentityProviderBuilder.java b/api/src/main/java/com/okta/sdk/resource/identity/provider/OIDCIdentityProviderBuilder.java deleted file mode 100644 index d17a97a0dd7..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/identity/provider/OIDCIdentityProviderBuilder.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.identity.provider; - -import com.okta.sdk.resource.policy.PolicySubjectMatchType; - -public interface OIDCIdentityProviderBuilder extends IdentityProviderBuilder { - - OIDCIdentityProviderBuilder setIssuerMode(IdentityProvider.IssuerModeEnum issuerMode); - - OIDCIdentityProviderBuilder setRequestSignatureAlgorithm(String requestSignatureAlgorithm); - - OIDCIdentityProviderBuilder setRequestSignatureScope(ProtocolAlgorithmTypeSignature.ScopeEnum requestSignatureScope); - - OIDCIdentityProviderBuilder setResponseSignatureAlgorithm(String responseSignatureAlgorithm); - - OIDCIdentityProviderBuilder setResponseSignatureScope(ProtocolAlgorithmTypeSignature.ScopeEnum responseSignatureScope); - - OIDCIdentityProviderBuilder setAcsEndpointBinding(ProtocolEndpoint.BindingEnum acsEndpointBinding); - - OIDCIdentityProviderBuilder setAcsEndpointType(ProtocolEndpoint.TypeEnum acsEndpointType); - - OIDCIdentityProviderBuilder setAuthorizationEndpointBinding(ProtocolEndpoint.BindingEnum authorizationEndpointBinding); - - OIDCIdentityProviderBuilder setAuthorizationEndpointUrl(String authorizationEndpointUrl); - - OIDCIdentityProviderBuilder setTokenEndpointBinding(ProtocolEndpoint.BindingEnum tokenEndpointBinding); - - OIDCIdentityProviderBuilder setTokenEndpointUrl(String tokenEndpointUrl); - - OIDCIdentityProviderBuilder setUserInfoEndpointBinding(ProtocolEndpoint.BindingEnum userInfoEndpointBinding); - - OIDCIdentityProviderBuilder setUserInfoEndpointUrl(String userInfoEndpointUrl); - - OIDCIdentityProviderBuilder setJwksEndpointBinding(ProtocolEndpoint.BindingEnum jwksEndpointBinding); - - OIDCIdentityProviderBuilder setJwksEndpointUrl(String jwksEndpointUrl); - - OIDCIdentityProviderBuilder setIssuerUrl(String issuerUrl); - - OIDCIdentityProviderBuilder setUserName(String userName); - - OIDCIdentityProviderBuilder setMatchType(PolicySubjectMatchType matchType); -} diff --git a/api/src/main/java/com/okta/sdk/resource/inline/hook/InlineHookBuilder.java b/api/src/main/java/com/okta/sdk/resource/inline/hook/InlineHookBuilder.java deleted file mode 100644 index 1ff51c9045d..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/inline/hook/InlineHookBuilder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.inline.hook; - -import com.okta.commons.lang.Classes; -import com.okta.sdk.client.Client; - -public interface InlineHookBuilder { - - InlineHookBuilder setName(String name); - - InlineHookBuilder setHookType(InlineHookType hookType); - - InlineHookBuilder setChannelType(InlineHookChannel.TypeEnum channelType); - - InlineHookBuilder setUrl(String url); - - InlineHookBuilder setAuthorizationHeaderValue(String authorizationHeaderValue); - - InlineHookBuilder addHeader(String name, String value); - - InlineHook buildAndCreate(Client client); - - static InlineHookBuilder instance() { - return Classes.newInstance("com.okta.sdk.impl.resource.inline.hook.DefaultInlineHookBuilder"); - } -} \ No newline at end of file diff --git a/api/src/main/java/com/okta/sdk/resource/policy/PasswordPolicyBuilder.java b/api/src/main/java/com/okta/sdk/resource/policy/PasswordPolicyBuilder.java index 177f09d3624..786c1f5ca36 100644 --- a/api/src/main/java/com/okta/sdk/resource/policy/PasswordPolicyBuilder.java +++ b/api/src/main/java/com/okta/sdk/resource/policy/PasswordPolicyBuilder.java @@ -16,6 +16,8 @@ package com.okta.sdk.resource.policy; import com.okta.commons.lang.Classes; +import org.openapitools.client.model.PasswordPolicyAuthenticationProviderType; +import org.openapitools.client.model.PasswordPolicyRecoveryFactorSettings; import java.util.Arrays; import java.util.List; @@ -27,7 +29,7 @@ static PasswordPolicyBuilder instance() { return Classes.newInstance("com.okta.sdk.impl.resource.DefaultPasswordPolicyBuilder"); } - PasswordPolicyBuilder setAuthProvider(PasswordPolicyAuthenticationProviderCondition.ProviderEnum provider); + PasswordPolicyBuilder setAuthProvider(PasswordPolicyAuthenticationProviderType provider); default PasswordPolicyBuilder setGroups(String... groupIds) { return setGroups(Arrays.stream(groupIds).collect(Collectors.toList())); @@ -75,11 +77,11 @@ default PasswordPolicyBuilder setUsers(String... userIds) { PasswordPolicyBuilder setShowLockoutFailures(Boolean showLockoutFailures); - PasswordPolicyBuilder setPasswordRecoveryOktaCall(PasswordPolicyRecoveryFactorSettings.StatusEnum pwdRecoveryOktaCall); + PasswordPolicyBuilder setPasswordRecoveryOktaCall(PasswordPolicyRecoveryFactorSettings pwdRecoveryOktaCall); - PasswordPolicyBuilder setPasswordRecoveryOktaSMS(PasswordPolicyRecoveryFactorSettings.StatusEnum pwdRecoveryOktaSMS); + PasswordPolicyBuilder setPasswordRecoveryOktaSMS(PasswordPolicyRecoveryFactorSettings pwdRecoveryOktaSMS); - PasswordPolicyBuilder setPasswordPolicyRecoveryEmailStatus(PasswordPolicyRecoveryFactorSettings.StatusEnum status); + PasswordPolicyBuilder setPasswordPolicyRecoveryEmailStatus(PasswordPolicyRecoveryFactorSettings status); PasswordPolicyBuilder setPasswordRecoveryTokenLifeMinutes(Integer pwdRecoveryTokenLifeMinutes); } diff --git a/api/src/main/java/com/okta/sdk/resource/policy/PolicyBuilder.java b/api/src/main/java/com/okta/sdk/resource/policy/PolicyBuilder.java index 536142319fa..8abb73894a9 100644 --- a/api/src/main/java/com/okta/sdk/resource/policy/PolicyBuilder.java +++ b/api/src/main/java/com/okta/sdk/resource/policy/PolicyBuilder.java @@ -16,8 +16,10 @@ package com.okta.sdk.resource.policy; import com.okta.commons.lang.Classes; -import com.okta.sdk.client.Client; - +import org.openapitools.client.api.PolicyApi; +import org.openapitools.client.model.LifecycleStatus; +import org.openapitools.client.model.Policy; +import org.openapitools.client.model.PolicyType; public interface PolicyBuilder { @@ -33,8 +35,7 @@ static PolicyBuilder instance() { T setPriority(Integer priority); - T setStatus(Policy.StatusEnum status); - - Policy buildAndCreate(Client client); + T setStatus(LifecycleStatus status); + Policy buildAndCreate(PolicyApi client); } diff --git a/api/src/main/java/com/okta/sdk/resource/policy/rule/PasswordPolicyRuleBuilder.java b/api/src/main/java/com/okta/sdk/resource/policy/rule/PasswordPolicyRuleBuilder.java deleted file mode 100644 index 5f5b92825df..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/policy/rule/PasswordPolicyRuleBuilder.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.policy.rule; - -import com.okta.commons.lang.Classes; -import com.okta.sdk.resource.policy.PasswordPolicyRuleAction; -import com.okta.sdk.resource.policy.PolicyNetworkCondition; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public interface PasswordPolicyRuleBuilder extends PolicyRuleBuilder { - - static PasswordPolicyRuleBuilder instance(){ - return Classes.newInstance("com.okta.sdk.impl.resource.DefaultPasswordPolicyRuleBuilder"); - } - - PasswordPolicyRuleBuilder setName(String name); - - PasswordPolicyRuleBuilder setNetworkConnection(PolicyNetworkCondition.ConnectionEnum connection); - - default PasswordPolicyRuleBuilder setUsers(String... userIds) { - return setUsers(Arrays.stream(userIds).collect(Collectors.toList())); - } - - PasswordPolicyRuleBuilder setUsers(List userIds); - - PasswordPolicyRuleBuilder addUser(String userId); - - default PasswordPolicyRuleBuilder setGroups(String... groupIds) { - return setGroups(Arrays.stream(groupIds).collect(Collectors.toList())); - } - - PasswordPolicyRuleBuilder setGroups(List groupIds); - - PasswordPolicyRuleBuilder addGroup(String groupId); - - PasswordPolicyRuleBuilder setSelfServiceUnlockAccess(PasswordPolicyRuleAction.AccessEnum unlockAccess); - - PasswordPolicyRuleBuilder setSelfServicePasswordResetAccess(PasswordPolicyRuleAction.AccessEnum passwordResetAccess); - - PasswordPolicyRuleBuilder setPasswordChangeAccess(PasswordPolicyRuleAction.AccessEnum passwordChangeAccess); - -} diff --git a/api/src/main/java/com/okta/sdk/resource/policy/rule/PolicyRuleBuilder.java b/api/src/main/java/com/okta/sdk/resource/policy/rule/PolicyRuleBuilder.java deleted file mode 100644 index 9be864a906d..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/policy/rule/PolicyRuleBuilder.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.policy.rule; - -import com.okta.commons.lang.Classes; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.policy.Policy; -import com.okta.sdk.resource.policy.PolicyRule; - -public interface PolicyRuleBuilder { - - static PolicyRuleBuilder instance(){ - return Classes.newInstance("com.okta.sdk.impl.resource.DefaultPolicyRuleBuilder"); - } - - T setPriority(Integer priority); - - T setStatus(PolicyRule.StatusEnum status); - - T setType(PolicyRule.TypeEnum type); - - PolicyRule buildAndCreate(Client client, Policy policy); - -} diff --git a/api/src/main/java/com/okta/sdk/resource/policy/rule/SignOnPolicyRuleBuilder.java b/api/src/main/java/com/okta/sdk/resource/policy/rule/SignOnPolicyRuleBuilder.java deleted file mode 100644 index 812eccb0c66..00000000000 --- a/api/src/main/java/com/okta/sdk/resource/policy/rule/SignOnPolicyRuleBuilder.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource.policy.rule; - -import com.okta.commons.lang.Classes; -import com.okta.sdk.resource.policy.OktaSignOnPolicyRuleSignonActions; -import com.okta.sdk.resource.policy.PolicyNetworkCondition; -import com.okta.sdk.resource.policy.PolicyRuleAuthContextCondition; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public interface SignOnPolicyRuleBuilder extends PolicyRuleBuilder { - static SignOnPolicyRuleBuilder instance(){ - return Classes.newInstance("com.okta.sdk.impl.resource.DefaultSignOnPolicyRuleBuilder"); - } - - SignOnPolicyRuleBuilder setName(String name); - - SignOnPolicyRuleBuilder setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum access); - - SignOnPolicyRuleBuilder setFactorLifetime(Integer factorLifetime); - - SignOnPolicyRuleBuilder setFactorPromptMode(OktaSignOnPolicyRuleSignonActions.FactorPromptModeEnum factorPromptMode); - - SignOnPolicyRuleBuilder setRememberDeviceByDefault(Boolean rememberDeviceByDefault); - - SignOnPolicyRuleBuilder setRequireFactor(Boolean requireFactor); - - SignOnPolicyRuleBuilder setMaxSessionIdleMinutes(Integer maxSessionIdleMinutes); - - SignOnPolicyRuleBuilder setMaxSessionLifetimeMinutes(Integer maxSessionLifetimeMinutes); - - SignOnPolicyRuleBuilder setUsePersistentCookie(Boolean usePersistentCookie); - - SignOnPolicyRuleBuilder setAuthType(PolicyRuleAuthContextCondition.AuthTypeEnum authType); - - SignOnPolicyRuleBuilder setNetworkConnection(PolicyNetworkCondition.ConnectionEnum connection); - - default SignOnPolicyRuleBuilder setUsers(String... userIds) { - return setUsers(Arrays.stream(userIds).collect(Collectors.toList())); - } - - SignOnPolicyRuleBuilder setUsers(List userIds); - - SignOnPolicyRuleBuilder addUser(String userId); - - default SignOnPolicyRuleBuilder setGroups(String... groupIds) { - return setGroups(Arrays.stream(groupIds).collect(Collectors.toList())); - } - - SignOnPolicyRuleBuilder setGroups(List groupIds); - - SignOnPolicyRuleBuilder addGroup(String groupId); - - -} diff --git a/api/src/main/java/com/okta/sdk/resource/user/UserBuilder.java b/api/src/main/java/com/okta/sdk/resource/user/UserBuilder.java index 011b0b9e8b5..b899b1103c8 100644 --- a/api/src/main/java/com/okta/sdk/resource/user/UserBuilder.java +++ b/api/src/main/java/com/okta/sdk/resource/user/UserBuilder.java @@ -16,12 +16,14 @@ package com.okta.sdk.resource.user; import com.okta.commons.lang.Classes; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.user.type.UserType; +import org.openapitools.client.api.UserApi; +import org.openapitools.client.model.AuthenticationProvider; +import org.openapitools.client.model.User; +import org.openapitools.client.model.UserNextLogin; +import org.openapitools.client.model.UserType; import java.util.Arrays; -import java.util.Map; -import java.util.Set; +import java.util.List; import java.util.stream.Collectors; public interface UserBuilder { @@ -60,17 +62,11 @@ static UserBuilder instance() { UserBuilder setType(String userTypeId); - UserBuilder setProfileProperties(Map profileProperties); - - UserBuilder putAllProfileProperties(Map profileProperties); - - UserBuilder putProfileProperty(String key, Object value); - default UserBuilder setGroups(String... groupIds) { - return setGroups(Arrays.stream(groupIds).collect(Collectors.toSet())); + return setGroups(Arrays.stream(groupIds).collect(Collectors.toList())); } - UserBuilder setGroups(Set groupIds); + UserBuilder setGroups(List groupIds); UserBuilder addGroup(String groupId); @@ -84,5 +80,5 @@ default UserBuilder setGroups(String... groupIds) { UserBuilder setSha1PasswordHash(String value, String salt, String saltOrder); - User buildAndCreate(Client client); + User buildAndCreate(UserApi client); } diff --git a/api/src/main/resources/custom_templates/ApiClient.mustache b/api/src/main/resources/custom_templates/ApiClient.mustache new file mode 100644 index 00000000000..ef0d3986a3a --- /dev/null +++ b/api/src/main/resources/custom_templates/ApiClient.mustache @@ -0,0 +1,1007 @@ +{{! + Copyright (c) 2022-Present, Okta, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +}} +package {{invokerPackage}}; + +{{#withXml}} + import com.fasterxml.jackson.dataformat.xml.XmlMapper; + import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; +{{/withXml}} +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.okta.commons.lang.Classes; +import com.okta.sdk.cache.Cache; +import com.okta.sdk.cache.CacheManager; +import java.util.LinkedHashMap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.InvalidMediaTypeException; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.RequestEntity.BodyBuilder; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; +{{#withXml}} + import org.springframework.http.converter.HttpMessageConverter; + import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; +{{/withXml}} +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.springframework.retry.support.RetryTemplate; +import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.util.DefaultUriBuilderFactory; +import org.springframework.retry.policy.SimpleRetryPolicy; +{{#openApiNullable}} + import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.TimeZone; + +import java.util.stream.Collectors; + +{{#jsr310}} + import java.time.OffsetDateTime; +{{/jsr310}} + +import com.okta.commons.lang.ApplicationInfo; +import com.okta.sdk.error.ResourceException; +import com.okta.sdk.error.RetryableException; +import org.springframework.retry.backoff.FixedBackOffPolicy; + +import {{invokerPackage}}.auth.Authentication; +{{#hasHttpBasicMethods}} + import {{invokerPackage}}.auth.HttpBasicAuth; +{{/hasHttpBasicMethods}} +{{#hasHttpBearerMethods}} + import {{invokerPackage}}.auth.HttpBearerAuth; +{{/hasHttpBearerMethods}} +{{#hasApiKeyMethods}} + import {{invokerPackage}}.auth.ApiKeyAuth; +{{/hasApiKeyMethods}} +{{#hasOAuthMethods}} + import {{invokerPackage}}.auth.OAuth; +{{/hasOAuthMethods}} + +{{>generatedAnnotation}} +@Component("{{invokerPackage}}.ApiClient") +public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { +public enum CollectionFormat { +CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); + +private final String separator; + +private CollectionFormat(String separator) { +this.separator = separator; +} + +private String collectionToString(Collection collection) { +return StringUtils.collectionToDelimitedString(collection, separator); +} +} + +private boolean debugging = false; + +private HttpHeaders defaultHeaders = new HttpHeaders(); +private MultiValueMap defaultCookies = new LinkedMultiValueMap(); + +private String basePath = "{{basePath}}"; + +private RestTemplate restTemplate; + +private RetryTemplate retryTemplate; + +private Map authentications; + +private DateFormat dateFormat; + +private Cache cache; + +private CacheManager cacheManager; + +public ApiClient() { +init(); +} + +public ApiClient(RestTemplate restTemplate, CacheManager cacheManager) { +this.restTemplate = restTemplate; +this.cacheManager = cacheManager; +init(); +} + +protected void init() { +// Use RFC3339 format for date and datetime. +// See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 +this.dateFormat = new RFC3339DateFormat(); + +// Use UTC as the default time zone. +this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + +// Set default User-Agent. +String userAgentValue = ApplicationInfo.get().entrySet().stream() +.map(entry -> entry.getKey() + "/" + entry.getValue()) +.collect(Collectors.joining(" ")); + +setUserAgent(userAgentValue); + +// Setup authentications (key: authentication name, value: authentication). +authentications = new HashMap();{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} + authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} + authentications.put("{{name}}", new HttpBearerAuth("{{scheme}}"));{{/isBasicBasic}}{{/isBasic}}{{#isApiKey}} + authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}} + authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}} +// Prevent the authentications from being modified. +authentications = Collections.unmodifiableMap(authentications); + +if (restTemplate == null) { +restTemplate = buildRestTemplate(); +} +retryTemplate = buildRetryTemplate(); + +cache = cacheManager.getCache("default"); +} + +/** +* Get the current base path +* +* @return String the base path +*/ +public String getBasePath() { +return basePath; +} + +/** +* Set the base path, which should include the host +* +* @param basePath the base path +* @return ApiClient this client +*/ +public ApiClient setBasePath(String basePath) { +this.basePath = basePath; +return this; +} + +/** +* Get authentications (key: authentication name, value: authentication). +* +* @return Map the currently configured authentication types +*/ +public Map getAuthentications() { +return authentications; +} + +/** +* Get authentication for the given name. +* +* @param authName The authentication name +* @return The authentication, null if not found +*/ +public Authentication getAuthentication(String authName) { +return authentications.get(authName); +} + +{{#hasHttpBearerMethods}} + /** + * Helper method to set token for HTTP bearer authentication. + * + * @param bearerToken the token + */ + public void setBearerToken(String bearerToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBearerAuth) { + ((HttpBearerAuth) auth).setBearerToken(bearerToken); + return; + } + } + throw new RuntimeException("No Bearer authentication configured!"); + } + +{{/hasHttpBearerMethods}} + +{{#hasHttpBasicMethods}} + /** + * Helper method to set username for the first HTTP basic authentication. + * + * @param username Username + */ + public void setUsername(String username) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setUsername(username); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + + /** + * Helper method to set password for the first HTTP basic authentication. + * @param password Password + */ + public void setPassword(String password) { + for (Authentication auth : authentications.values()) { + if (auth instanceof HttpBasicAuth) { + ((HttpBasicAuth) auth).setPassword(password); + return; + } + } + throw new RuntimeException("No HTTP basic authentication configured!"); + } + +{{/hasHttpBasicMethods}} + +{{#hasApiKeyMethods}} + /** + * Helper method to set API key value for the first API key authentication. + * + * @param apiKey the API key + */ + public void setApiKey(String apiKey) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKey(apiKey); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + + /** + * Helper method to set API key prefix for the first API key authentication. + * + * @param apiKeyPrefix API key prefix + */ + public void setApiKeyPrefix(String apiKeyPrefix) { + for (Authentication auth : authentications.values()) { + if (auth instanceof ApiKeyAuth) { + ((ApiKeyAuth) auth).setApiKeyPrefix(apiKeyPrefix); + return; + } + } + throw new RuntimeException("No API key authentication configured!"); + } + +{{/hasApiKeyMethods}} + +{{#hasOAuthMethods}} + /** + * Helper method to set access token for the first OAuth2 authentication. + * + * @param accessToken Access token + */ + public void setAccessToken(String accessToken) { + for (Authentication auth : authentications.values()) { + if (auth instanceof OAuth) { + ((OAuth) auth).setAccessToken(accessToken); + return; + } + } + throw new RuntimeException("No OAuth2 authentication configured!"); + } + +{{/hasOAuthMethods}} + +/** +* Set the User-Agent header's value (by adding to the default header map). +* +* @param userAgent the user agent string +* @return ApiClient this client +*/ +public ApiClient setUserAgent(String userAgent) { +addDefaultHeader("User-Agent", userAgent); +return this; +} + +/** +* Add a default header. +* +* @param name The header's name +* @param value The header's value +* @return ApiClient this client +*/ +public ApiClient addDefaultHeader(String name, String value) { +if (defaultHeaders.containsKey(name)) { +defaultHeaders.remove(name); +} +defaultHeaders.add(name, value); +return this; +} + +/** +* Add a default cookie. +* +* @param name The cookie's name +* @param value The cookie's value +* @return ApiClient this client +*/ +public ApiClient addDefaultCookie(String name, String value) { +if (defaultCookies.containsKey(name)) { +defaultCookies.remove(name); +} +defaultCookies.add(name, value); +return this; +} + +public void setDebugging(boolean debugging) { +List currentInterceptors = this.restTemplate.getInterceptors(); + if (debugging) { + if (currentInterceptors == null) { + currentInterceptors = new ArrayList(); + } + ClientHttpRequestInterceptor interceptor = new ApiClientHttpRequestInterceptor(); + currentInterceptors.add(interceptor); + this.restTemplate.setInterceptors(currentInterceptors); + } else { + if (currentInterceptors != null && !currentInterceptors.isEmpty()) { + Iterator iter = currentInterceptors.iterator(); + while (iter.hasNext()) { + ClientHttpRequestInterceptor interceptor = iter.next(); + if (interceptor instanceof ApiClientHttpRequestInterceptor) { + iter.remove(); + } + } + this.restTemplate.setInterceptors(currentInterceptors); + } + } + this.debugging = debugging; + } + + /** + * Check that whether debugging is enabled for this API client. + * @return boolean true if this client is enabled for debugging, false otherwise + */ + public boolean isDebugging() { + return debugging; + } + + /** + * Get the date format used to parse/format date parameters. + * @return DateFormat format + */ + public DateFormat getDateFormat() { + return dateFormat; + } + + /** + * Set the date format used to parse/format date parameters. + * @param dateFormat Date format + * @return API client + */ + public ApiClient setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + return this; + } + + /** + * Parse the given string into Date object. + * + * @param str the string to parse + * @return the Date parsed from the string + */ + public Date parseDate(String str) { + try { + return dateFormat.parse(str); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + /** + * Format the given Date object into string. + * + * @param date the date to format + * @return the formatted date as string + */ + public String formatDate(Date date) { + return dateFormat.format(date); + } + + /** + * Format the given parameter object into string. + * + * @param param the object to convert + * @return String the parameter represented as a String + */ + public String parameterToString(Object param) { + if (param == null) { + return ""; + } else if (param instanceof Date) { + return formatDate( (Date) param); + } {{#jsr310}}else if (param instanceof OffsetDateTime) { + return formatOffsetDateTime((OffsetDateTime) param); + } {{/jsr310}}else if (param instanceof Collection) { + StringBuilder b = new StringBuilder(); + for (Object o : (Collection) param) { + if (b.length() > 0) { + b.append(","); + } + b.append(String.valueOf(o)); + } + return b.toString(); + } else { + return String.valueOf(param); + } + } + + /** + * Formats the specified collection path parameter to a string value. + * + * @param collectionFormat The collection format of the parameter. + * @param values The values of the parameter. + * @return String representation of the parameter + */ + public String collectionPathParameterToString(CollectionFormat collectionFormat, Collection values) { + // create the value based on the collection format + if (CollectionFormat.MULTI.equals(collectionFormat)) { + // not valid for path params + return parameterToString(values); + } + + // collectionFormat is assumed to be "csv" by default + if (collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + return collectionFormat.collectionToString(values); + } + + /** + * Converts a parameter to a {@link MultiValueMap} for use in REST requests + * + * @param collectionFormat The format to convert to + * @param name The name of the parameter + * @param value The parameter's value + * @return a Map containing the String value(s) of the input parameter + */ + public MultiValueMap parameterToMultiValueMap(CollectionFormat collectionFormat, String name, Object value) { + final MultiValueMap params = new LinkedMultiValueMap(); + + if (name == null || name.isEmpty() || value == null) { + return params; + } + + if (collectionFormat == null) { + collectionFormat = CollectionFormat.CSV; + } + + if (value instanceof Map) { + @SuppressWarnings("unchecked") + final Map valuesMap = (Map) value; + for (final Entry entry : valuesMap.entrySet()) { + params.add(entry.getKey(), parameterToString(entry.getValue())); + } + return params; + } + + Collection valueCollection = null; + if (value instanceof Collection) { + valueCollection = (Collection) value; + } else { + params.add(name, parameterToString(value)); + return params; + } + + if (valueCollection.isEmpty()) { + return params; + } + + if (collectionFormat.equals(CollectionFormat.MULTI)) { + for (Object item : valueCollection) { + params.add(name, parameterToString(item)); + } + return params; + } + + List values = new ArrayList(); + for (Object o : valueCollection) { + values.add(parameterToString(o)); + } + params.add(name, collectionFormat.collectionToString(values)); + + return params; + } + + /** + * Check if the given {@code String} is a JSON MIME. + * + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(String mediaType) { + // "* / *" is default to JSON + if ("*/*".equals(mediaType)) { + return true; + } + + try { + return isJsonMime(MediaType.parseMediaType(mediaType)); + } catch (InvalidMediaTypeException e) { + } + return false; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents JSON, false otherwise + */ + public boolean isJsonMime(MediaType mediaType) { + return mediaType != null && (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || mediaType.getSubtype().matches("^.*\\+json[;]?\\s*$")); + } + + /** + * Check if the given {@code String} is a Problem JSON MIME (RFC-7807). + * + * @param mediaType the input MediaType + * @return boolean true if the MediaType represents Problem JSON, false otherwise + */ + public boolean isProblemJsonMime(String mediaType) { + return "application/problem+json".equalsIgnoreCase(mediaType); + } + + /** + * Select the Accept header's value from the given accepts array: + * if JSON exists in the given array, use it; + * otherwise use all of them (joining into a string) + * + * @param accepts The accepts array to select from + * @return List The list of MediaTypes to use for the Accept header + */ + public List selectHeaderAccept(String[] accepts) { + if (accepts.length == 0) { + return null; + } + for (String accept : accepts) { + MediaType mediaType = MediaType.parseMediaType(accept); + if (isJsonMime(mediaType) && !isProblemJsonMime(accept)) { + return Collections.singletonList(mediaType); + } + } + return MediaType.parseMediaTypes(StringUtils.arrayToCommaDelimitedString(accepts)); + } + + /** + * Select the Content-Type header's value from the given array: + * if JSON exists in the given array, use it; + * otherwise use the first one of the array. + * + * @param contentTypes The Content-Type array to select from + * @return MediaType The Content-Type header to use. If the given array is empty, JSON will be used. + */ + public MediaType selectHeaderContentType(String[] contentTypes) { + if (contentTypes.length == 0) { + return MediaType.APPLICATION_JSON; + } + for (String contentType : contentTypes) { + MediaType mediaType = MediaType.parseMediaType(contentType); + if (isJsonMime(mediaType)) { + return mediaType; + } + } + return MediaType.parseMediaType(contentTypes[0]); + } + + /** + * Select the body to use for the request + * + * @param obj the body object + * @param formParams the form parameters + * @param contentType the content type of the request + * @return Object the selected body + */ + protected Object selectBody(Object obj, MultiValueMap formParams, MediaType contentType) { + boolean isForm = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType) || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType); + return isForm ? formParams : obj; + } + + /** + * Expand path template with variables + * + * @param pathTemplate path template with placeholders + * @param variables variables to replace + * @return path with placeholders replaced by variables + */ + public String expandPath(String pathTemplate, Map variables) { + return restTemplate.getUriTemplateHandler().expand(pathTemplate, variables).toString(); + } + + /** + * Include queryParams in uriParams taking into account the paramName + * + * @param queryParams The query parameters + * @param uriParams The path parameters + * return templatized query string + */ + public String generateQueryUri(MultiValueMap queryParams, Map uriParams) { + StringBuilder queryBuilder = new StringBuilder(); + queryParams.forEach((name, values) -> { + try { + final String encodedName = URLEncoder.encode(name.toString(), "UTF-8"); + if (CollectionUtils.isEmpty(values)) { + if (queryBuilder.length() != 0) { + queryBuilder.append('&'); + } + queryBuilder.append(encodedName); + } else { + int valueItemCounter = 0; + for (Object value : values) { + if (queryBuilder.length() != 0) { + queryBuilder.append('&'); + } + queryBuilder.append(encodedName); + if (value != null) { + String templatizedKey = encodedName + valueItemCounter++; + uriParams.put(templatizedKey, value.toString()); + queryBuilder.append('=').append("{").append(templatizedKey).append("}"); + } + } + } + } catch (UnsupportedEncodingException e) { + + } + }); + return queryBuilder.toString(); + + } + + /** + * Invoke API by sending HTTP request with the given options. + * + * @param the return type to use + * @param path The sub-path of the HTTP URL + * @param method The request method + * @param pathParams The path parameters + * @param queryParams The query parameters + * @param body The request body object + * @param headerParams The header parameters + * @param cookieParams The cookie parameters + * @param formParams The form parameters + * @param accept The request's Accept header + * @param contentType The request's Content-Type header + * @param authNames The authentications to apply + * @param returnType The return type into which to deserialize the response + * @return ResponseEntity<T> The response of the chosen type + */ + public ResponseEntity invokeAPI(String path, HttpMethod method, Map pathParams, MultiValueMap queryParams, Object body, HttpHeaders headerParams, MultiValueMap cookieParams, MultiValueMap formParams, List accept, MediaType contentType, String[] authNames, ParameterizedTypeReference returnType) throws RestClientException { + updateParamsForAuth(authNames, queryParams, headerParams, cookieParams); + + Map uriParams = new HashMap<>(); + uriParams.putAll(pathParams); + + String finalUri = path; + + if (queryParams != null && !queryParams.isEmpty()) { + //Include queryParams in uriParams taking into account the paramName + String queryUri = generateQueryUri(queryParams, uriParams); + //Append to finalUri the templatized query string like "?param1={param1Value}&....... + finalUri += "?" + queryUri; + } + String expandedPath = this.expandPath(finalUri, uriParams); + final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(basePath).path(expandedPath); + + URI uri; + try { + uri = new URI(builder.build().toUriString()); + } catch (URISyntaxException ex) { + throw new RestClientException("Could not build URL: " + builder.toUriString(), ex); + } + + final BodyBuilder requestBuilder = RequestEntity.method(method, uri); + if (accept != null) { + requestBuilder.accept(accept.toArray(new MediaType[accept.size()])); + } + if (contentType != null) { + requestBuilder.contentType(contentType); + } + + addHeadersToRequest(headerParams, requestBuilder); + addHeadersToRequest(defaultHeaders, requestBuilder); + addCookiesToRequest(cookieParams, requestBuilder); + addCookiesToRequest(defaultCookies, requestBuilder); + + RequestEntity requestEntity = requestBuilder.body(selectBody(body, formParams, contentType)); + + String cacheKey = requestEntity.getUrl().toString(); + + if (Objects.nonNull(requestEntity.getUrl().getQuery())) { + cacheKey = requestEntity.getUrl().toString().split("\\?")[0]; + } + + if (method == HttpMethod.DELETE) { + cache.remove(cacheKey); + } + + String[] uriSegments = uri.getPath().split("/"); + + if (uriSegments != null && uriSegments.length >= 5) { + String key = getBasePath() + "/" + uriSegments[1] + "/" + uriSegments[2] + "/" + uriSegments[3] + "/" + uriSegments[4]; + if (cache.get(key) != null) { + cache.remove(key); + } + } + + if (method == HttpMethod.GET && + !returnType.getType().getTypeName().contains("List") && + !(Objects.nonNull(requestEntity.getUrl().getQuery()) && requestEntity.getUrl().getQuery().contains("expand"))) { + + ResponseEntity cacheData = cache.get(cacheKey); + + if (Objects.isNull(cacheData) || !cacheData.hasBody()) { + ResponseEntity responseEntity = retryTemplate.execute(context -> restTemplate.exchange(requestEntity, returnType)); + + if (responseEntity != null && responseEntity.getStatusCode().is2xxSuccessful()) { + + if (method == HttpMethod.GET && Objects.nonNull(responseEntity.getBody())) { + + Map map = objectMapper().convertValue(responseEntity.getBody(), LinkedHashMap.class); + + String href = null; + + if (Objects.nonNull(map)) { + Map links = (Map) map.get("_links"); + if (Objects.nonNull(links)) { + LinkedHashMap self = links.get("self"); + if (Objects.nonNull(self)) { + href = (String) self.get("href"); + } + } + } + + if (Objects.nonNull(href)) { + cache.put(href, responseEntity); + } else { + cache.put(cacheKey, responseEntity); + } + } + + return responseEntity; + } else { + // The error handler built into the RestTemplate should handle 400 and 500 series errors. + throw new RestClientException("API returned " + responseEntity.getStatusCode() + " and it wasn't handled by the RestTemplate error handler"); + } + } else { + // return data from cache + return cache.get(cacheKey); + } + } else { + ResponseEntity responseEntity = retryTemplate.execute(context -> restTemplate.exchange(requestEntity, returnType)); + + if (responseEntity != null && responseEntity.getStatusCode().is2xxSuccessful()) { + if (cache.get(cacheKey) != null) { + cache.put(cacheKey, responseEntity); + } + return responseEntity; + } else { + // The error handler built into the RestTemplate should handle 400 and 500 series errors. + throw new RestClientException("API returned " + responseEntity.getStatusCode() + " and it wasn't handled by the RestTemplate error handler"); + } + } + } + + /** + * Add headers to the request that is being built + * @param headers The headers to add + * @param requestBuilder The current request + */ + protected void addHeadersToRequest(HttpHeaders headers, BodyBuilder requestBuilder) { + for (Entry> entry : headers.entrySet()) { + List values = entry.getValue(); + for (String value : values) { + if (value != null) { + requestBuilder.header(entry.getKey(), value); + } + } + } + } + + /** + * Add cookies to the request that is being built + * + * @param cookies The cookies to add + * @param requestBuilder The current request + */ + protected void addCookiesToRequest(MultiValueMap cookies, BodyBuilder requestBuilder) { + if (!cookies.isEmpty()) { + requestBuilder.header("Cookie", buildCookieHeader(cookies)); + } + } + + /** + * Build cookie header. Keeps a single value per cookie (as per + * RFC6265 section 5.3). + * + * @param cookies map all cookies + * @return header string for cookies. + */ + private String buildCookieHeader(MultiValueMap cookies) { + final StringBuilder cookieValue = new StringBuilder(); + String delimiter = ""; + for (final Map.Entry> entry : cookies.entrySet()) { + final String value = entry.getValue().get(entry.getValue().size() - 1); + cookieValue.append(String.format("%s%s=%s", delimiter, entry.getKey(), value)); + delimiter = "; "; + } + return cookieValue.toString(); + } + + /** + * Build the RestTemplate used to make HTTP requests. + * @return RestTemplate + */ + protected RestTemplate buildRestTemplate() { + {{#withXml}}List> messageConverters = new ArrayList>(); + messageConverters.add(new MappingJackson2HttpMessageConverter()); + XmlMapper xmlMapper = new XmlMapper(); + xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true); + {{#openApiNullable}} + xmlMapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} + messageConverters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper)); + + RestTemplate restTemplate = new RestTemplate(messageConverters); + {{/withXml}}{{^withXml}}RestTemplate restTemplate = new RestTemplate();{{/withXml}} + // This allows us to read the response more than once - Necessary for debugging. + restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(restTemplate.getRequestFactory())); + + // disable default URL encoding + DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(); + uriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); + restTemplate.setUriTemplateHandler(uriBuilderFactory); + return restTemplate; + } + + protected RetryTemplate buildRetryTemplate() { + Map, Boolean> retryableExceptions = new HashMap<>(); + retryableExceptions.put(RetryableException.class, Boolean.TRUE); + + SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(5, retryableExceptions); //TODO - get this from client config + FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy(); + + RetryTemplate retryTemplate = new RetryTemplate(); + retryTemplate.setRetryPolicy(retryPolicy); + retryTemplate.setBackOffPolicy(backOffPolicy); + retryTemplate.setThrowLastExceptionOnExhausted(true); + return retryTemplate; + } + + private ObjectMapper objectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new JsonNullableModule()); + + return objectMapper; + } + + /** + * Update query and header parameters based on authentication settings. + * + * @param authNames The authentications to apply + * @param queryParams The query parameters + * @param headerParams The header parameters + */ + protected void updateParamsForAuth(String[] authNames, MultiValueMap queryParams, HttpHeaders headerParams, MultiValueMap cookieParams) { + for (String authName : authNames) { + Authentication auth = authentications.get(authName); + if (auth == null) { + throw new RestClientException("Authentication undefined: " + authName); + } + auth.applyToParams(queryParams, headerParams, cookieParams); + } + } + + private class ApiClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { + private final Log log = LogFactory.getLog(ApiClientHttpRequestInterceptor.class); + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { + logRequest(request, body); + ClientHttpResponse response = execution.execute(request, body); + logResponse(response); + return response; + } + + private void logRequest(HttpRequest request, byte[] body) throws UnsupportedEncodingException { + log.info("URI: " + request.getURI()); + log.info("HTTP Method: " + request.getMethod()); + log.info("HTTP Headers: " + headersToString(request.getHeaders())); + log.info("Request Body: " + new String(body, StandardCharsets.UTF_8)); + } + + private void logResponse(ClientHttpResponse response) throws IOException { + log.info("HTTP Status Code: " + response.getRawStatusCode()); + log.info("Status Text: " + response.getStatusText()); + log.info("HTTP Headers: " + headersToString(response.getHeaders())); + log.info("Response Body: " + bodyToString(response.getBody())); + } + + private String headersToString(HttpHeaders headers) { + if(headers == null || headers.isEmpty()) { + return ""; + } + StringBuilder builder = new StringBuilder(); + for (Entry> entry : headers.entrySet()) { + builder.append(entry.getKey()).append("=["); + for (String value : entry.getValue()) { + if (entry.getKey().equals("Authorization")) { + builder.append("*****").append(","); + } else { + builder.append(value).append(","); + } + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + builder.append("],"); + } + builder.setLength(builder.length() - 1); // Get rid of trailing comma + return builder.toString(); + } + + private String bodyToString(InputStream body) throws IOException { + StringBuilder builder = new StringBuilder(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(body, StandardCharsets.UTF_8)); + String line = bufferedReader.readLine(); + while (line != null) { + builder.append(line).append(System.lineSeparator()); + line = bufferedReader.readLine(); + } + bufferedReader.close(); + return builder.toString(); + } + } + } \ No newline at end of file diff --git a/api/src/main/resources/custom_templates/api.mustache b/api/src/main/resources/custom_templates/api.mustache new file mode 100644 index 00000000000..825fbee8023 --- /dev/null +++ b/api/src/main/resources/custom_templates/api.mustache @@ -0,0 +1,416 @@ +{{! + Copyright (c) 2022-Present, Okta, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +}} +package {{package}}; + +import {{invokerPackage}}.ApiClient; + +{{#imports}}import {{import}}; +{{/imports}} + +{{^fullJavaUtil}}import java.util.Collections; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.LinkedHashMap; +import java.util.stream.Collectors;{{/fullJavaUtil}} + +import com.okta.sdk.resource.common.PagedList; + +import com.okta.commons.lang.Assert; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; + +import org.openapitools.jackson.nullable.JsonNullableModule; + +{{>generatedAnnotation}} +@Component("{{package}}.{{classname}}") +{{#operations}} + public class {{classname}} { + private ApiClient apiClient; + + public {{classname}}() { + this(new ApiClient()); + } + + @Autowired + public {{classname}}(ApiClient apiClient) { + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return apiClient; + } + + public void setApiClient(ApiClient apiClient) { + this.apiClient = apiClient; + } + + {{#operation}} + /** + * {{summary}} + * {{notes}} + {{#responses}} + *

    {{code}}{{#message}} - {{.}}{{/message}} + {{/responses}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return {{.}} + {{/returnType}} + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{{.}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { + {{#returnType}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody(); + {{/returnType}} + {{^returnType}} + {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/returnType}} + } + + + + {{#bodyParam}} + + /** + * {{summary}} + * {{notes}} + {{#responses}} + *

    {{code}}{{#message}} - {{.}}{{/message}} + {{/responses}} + * @param T (required) - the assignable return type + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + {{#returnType}} + * @return T instance + {{/returnType}} + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}} T{{/returnType}}{{^returnType}}void{{/returnType}} {{operationId}}(Class T, {{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { + {{#returnType}} + return (T) getObjectMapper().convertValue({{operationId}}WithReturnType(T, {{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody(), T); + {{/returnType}} + {{^returnType}} + {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{/returnType}} + } + + {{/bodyParam}} + + + + /** + * {{summary}} + * {{notes}} + {{#responses}} + *

    {{code}}{{#message}} - {{.}}{{/message}} + {{/responses}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return ResponseEntity<{{returnType}}{{^returnType}}Void{{/returnType}}> + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + private ResponseEntity<{{{returnType}}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set '{{paramType}}' + if ({{paramName}} == null) { + throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}}{{#hasPathParams}} + // create path and map variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} + + final MultiValueMap localVarQueryParams = new LinkedMultiValueMap(); + final HttpHeaders localVarHeaderParams = new HttpHeaders(); + final MultiValueMap localVarCookieParams = new LinkedMultiValueMap(); + final MultiValueMap localVarFormParams = new LinkedMultiValueMap();{{#hasQueryParams}} + + {{#queryParams}}localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{^-last}} + {{/-last}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} + + {{#formParams}}if ({{paramName}} != null) + localVarFormParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}addAll{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{^-last}} + {{/-last}}{{/formParams}}{{/hasFormParams}} + + final String[] localVarAccepts = { {{#hasProduces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + {{/hasProduces}} }; + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = { {{#hasConsumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + {{/hasConsumes}} }; + final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> localReturnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.invokeAPI("{{{path}}}", HttpMethod.{{httpMethod}}, {{#hasPathParams}}uriVariables{{/hasPathParams}}{{^hasPathParams}}Collections.emptyMap(){{/hasPathParams}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType); + } + + + + {{#bodyParam}} + {{#returnType}} + + /** + * {{summary}} + * {{notes}} + {{#responses}} + *

    {{code}}{{#message}} - {{.}}{{/message}} + {{/responses}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return ResponseEntity<{{returnType}}{{^returnType}}Void{{/returnType}}> + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + private {{#returnType}} ResponseEntity{{/returnType}}{{^returnType}}ResponseEntity{{/returnType}} {{operationId}}WithReturnType(Class T, {{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}},{{/-last}}{{/allParams}}) throws RestClientException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}}{{#hasPathParams}} + // create path and map variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} + + final MultiValueMap localVarQueryParams = new LinkedMultiValueMap(); + final HttpHeaders localVarHeaderParams = new HttpHeaders(); + final MultiValueMap localVarCookieParams = new LinkedMultiValueMap(); + final MultiValueMap localVarFormParams = new LinkedMultiValueMap();{{#hasQueryParams}} + + {{#queryParams}}localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{^-last}} + {{/-last}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} + + {{#formParams}}if ({{paramName}} != null) + localVarFormParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}addAll{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{^-last}} + {{/-last}}{{/formParams}}{{/hasFormParams}} + + final String[] localVarAccepts = { {{#hasProduces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + {{/hasProduces}} }; + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = { {{#hasConsumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + {{/hasConsumes}} }; + final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference localReturnType = new ParameterizedTypeReference() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localReturnType = new ParameterizedTypeReference() {};{{/returnType}} + return apiClient.invokeAPI("{{{path}}}", HttpMethod.{{httpMethod}}, {{#hasPathParams}}uriVariables{{/hasPathParams}}{{^hasPathParams}}Collections.emptyMap(){{/hasPathParams}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType); + } + {{/returnType}} + {{/bodyParam}} + + + + {{#returnType}} + + /** + * {{summary}} + * {{notes}} + {{#responses}} + *

    {{code}}{{#message}} - {{.}}{{/message}} + {{/responses}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + {{/allParams}} + * @return ResponseEntity<{{returnType}}{{^returnType}}Void{{/returnType}}> + * @throws RestClientException if an error occurs while attempting to invoke the API + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}PagedList{{/returnType}}{{^returnType}}void{{/returnType}} {{operationId}}WithPaginationInfo({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException { + Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; + {{#allParams}}{{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}}{{/allParams}}{{#hasPathParams}} + // create path and map variables + final Map uriVariables = new HashMap();{{#pathParams}} + uriVariables.put("{{baseName}}", {{#collectionFormat}}apiClient.collectionPathParameterToString(ApiClient.CollectionFormat.valueOf("{{{collectionFormat}}}".toUpperCase()), {{{paramName}}}){{/collectionFormat}}{{^collectionFormat}}{{{paramName}}}{{/collectionFormat}});{{/pathParams}}{{/hasPathParams}} + + final MultiValueMap localVarQueryParams = new LinkedMultiValueMap(); + final HttpHeaders localVarHeaderParams = new HttpHeaders(); + final MultiValueMap localVarCookieParams = new LinkedMultiValueMap(); + final MultiValueMap localVarFormParams = new LinkedMultiValueMap();{{#hasQueryParams}} + + {{#queryParams}}localVarQueryParams.putAll(apiClient.parameterToMultiValueMap({{#collectionFormat}}ApiClient.CollectionFormat.valueOf("{{{.}}}".toUpperCase(Locale.ROOT)){{/collectionFormat}}{{^collectionFormat}}null{{/collectionFormat}}, "{{baseName}}", {{paramName}}));{{^-last}} + {{/-last}}{{/queryParams}}{{/hasQueryParams}}{{#hasHeaderParams}} + + {{#headerParams}}if ({{paramName}} != null) + localVarHeaderParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/headerParams}}{{/hasHeaderParams}}{{#hasCookieParams}} + + {{#cookieParams}}if ({{paramName}} != null) + localVarCookieParams.add("{{baseName}}", apiClient.parameterToString({{paramName}}));{{^-last}} + {{/-last}}{{/cookieParams}}{{/hasCookieParams}}{{#hasFormParams}} + + {{#formParams}}if ({{paramName}} != null) + localVarFormParams.{{^collectionFormat}}add{{/collectionFormat}}{{#collectionFormat}}addAll{{/collectionFormat}}("{{baseName}}", {{#isFile}}{{^collectionFormat}}{{#useAbstractionForFiles}}{{paramName}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}new FileSystemResource({{paramName}}){{/useAbstractionForFiles}}{{/collectionFormat}}{{/isFile}}{{#isFile}}{{#collectionFormat}}{{paramName}}.stream(){{^useAbstractionForFiles}}.map(FileSystemResource::new){{/useAbstractionForFiles}}.collect(Collectors.toList()){{/collectionFormat}}{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}});{{^-last}} + {{/-last}}{{/formParams}}{{/hasFormParams}} + + final String[] localVarAccepts = { {{#hasProduces}} + {{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}} + {{/hasProduces}} }; + final List localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = { {{#hasConsumes}} + {{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}} + {{/hasConsumes}} }; + final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { {{#authMethods}}"{{name}}"{{^-last}}, {{/-last}}{{/authMethods}} }; + + {{#returnType}}ParameterizedTypeReference<{{{returnType}}}> localReturnType = new ParameterizedTypeReference<{{{returnType}}}>() {};{{/returnType}}{{^returnType}}ParameterizedTypeReference localReturnType = new ParameterizedTypeReference() {};{{/returnType}} + ResponseEntity<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> responseEntity = apiClient.invokeAPI("{{{path}}}", HttpMethod.{{httpMethod}}, {{#hasPathParams}}uriVariables{{/hasPathParams}}{{^hasPathParams}}Collections.emptyMap(){{/hasPathParams}}, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType); + {{#returnType}} + HttpHeaders headers = responseEntity.getHeaders(); + PagedList pagedList = new PagedList(); + List linkHeaders = headers.get("link"); + String self = null, nextPage = null; + for (String link : linkHeaders) { + if (link.contains("next")) { + nextPage = link.split(";")[0] + .replaceAll("<", "") + .replaceAll(">", ""); + } + if (link.contains("self")) { + self = link.split(";")[0] + .replaceAll("<", "") + .replaceAll(">", ""); + } + } + pagedList.addItems(Arrays.asList(responseEntity.getBody())); + if (Objects.nonNull(nextPage)) { + pagedList.setNextPage(nextPage); + } + if (Objects.nonNull(self)) { + pagedList.setSelf(self); + } + return pagedList; + {{/returnType}} + {{^returnType}} + return; + {{/returnType}} + } + {{/returnType}} + + {{/operation}} + + private ObjectMapper getObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new JsonNullableModule()); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return objectMapper; + } + } +{{/operations}} diff --git a/api/src/main/resources/custom_templates/model.mustache b/api/src/main/resources/custom_templates/model.mustache new file mode 100644 index 00000000000..f426131bac0 --- /dev/null +++ b/api/src/main/resources/custom_templates/model.mustache @@ -0,0 +1,74 @@ +{{! + Copyright (c) 2022-Present, Okta, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +}} +package {{package}}; + +{{#useReflectionEqualsHashCode}} + import org.apache.commons.lang3.builder.EqualsBuilder; + import org.apache.commons.lang3.builder.HashCodeBuilder; +{{/useReflectionEqualsHashCode}} +import java.util.Objects; +import java.util.Arrays; +{{#imports}} + import {{import}}; +{{/imports}} +{{#serializableModel}} + import java.io.Serializable; +{{/serializableModel}} +{{#jackson}} + import com.fasterxml.jackson.annotation.JsonPropertyOrder; + import com.fasterxml.jackson.annotation.JsonTypeName; + {{#withXml}} + import com.fasterxml.jackson.dataformat.xml.annotation.*; + {{/withXml}} + {{#vendorExtensions.x-has-readonly-properties}} + import com.fasterxml.jackson.annotation.JsonCreator; + {{/vendorExtensions.x-has-readonly-properties}} +{{/jackson}} +{{#withXml}} + import javax.xml.bind.annotation.*; +{{/withXml}} +{{#jsonb}} + import java.lang.reflect.Type; + import javax.json.bind.annotation.JsonbTypeDeserializer; + import javax.json.bind.annotation.JsonbTypeSerializer; + import javax.json.bind.serializer.DeserializationContext; + import javax.json.bind.serializer.JsonbDeserializer; + import javax.json.bind.serializer.JsonbSerializer; + import javax.json.bind.serializer.SerializationContext; + import javax.json.stream.JsonGenerator; + import javax.json.stream.JsonParser; + import javax.json.bind.annotation.JsonbProperty; + {{#vendorExtensions.x-has-readonly-properties}} + import javax.json.bind.annotation.JsonbCreator; + {{/vendorExtensions.x-has-readonly-properties}} +{{/jsonb}} +{{#parcelableModel}} + import android.os.Parcelable; + import android.os.Parcel; +{{/parcelableModel}} +{{#useBeanValidation}} + import javax.validation.constraints.*; + import javax.validation.Valid; +{{/useBeanValidation}} +{{#performBeanValidation}} + import org.hibernate.validator.constraints.*; +{{/performBeanValidation}} + +{{#models}} + {{#model}} + {{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{#vendorExtensions.x-is-one-of-interface}}{{>oneof_interface}}{{/vendorExtensions.x-is-one-of-interface}}{{^vendorExtensions.x-is-one-of-interface}}{{>pojo}}{{/vendorExtensions.x-is-one-of-interface}}{{/isEnum}} + {{/model}} +{{/models}} \ No newline at end of file diff --git a/api/src/main/resources/custom_templates/pojo.mustache b/api/src/main/resources/custom_templates/pojo.mustache new file mode 100644 index 00000000000..43fca289ebb --- /dev/null +++ b/api/src/main/resources/custom_templates/pojo.mustache @@ -0,0 +1,410 @@ +{{! + Copyright (c) 2022-Present, Okta, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +}} +/** +* {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} +*/{{#isDeprecated}} + @Deprecated{{/isDeprecated}}{{#description}} + @ApiModel(description = "{{{.}}}"){{/description}} +{{#jackson}} + @JsonPropertyOrder({ + {{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} + {{/vars}} + }) + {{#isClassnameSanitized}} + @JsonTypeName("{{name}}") + {{/isClassnameSanitized}} +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}} +{{#vendorExtensions.x-class-extra-annotation}} + {{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +{{#additionalPropertiesType}} +public class {{classname}} {{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{/additionalPropertiesType}} +{{^additionalPropertiesType}} +public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{/additionalPropertiesType}} + +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} +{{#additionalPropertiesType}} + public Map additionalProperties = new java.util.LinkedHashMap<>(); + + public Map getAdditionalProperties() { + return additionalProperties; + } + + public void setAdditionalProperties(Map additionalProperties) { + this.additionalProperties = additionalProperties; + } +{{/additionalPropertiesType}} + +{{#vars}} + {{#isEnum}} + {{^isContainer}} + {{>modelInnerEnum}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} + {{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private {{{datatypeWithEnum}}} {{name}}{{#required}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/required}}{{^required}} = null{{/required}}; + {{/isContainer}} + {{^isContainer}} + {{#isDiscriminator}}protected{{/isDiscriminator}}{{^isDiscriminator}}private{{/isDiscriminator}} {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + +{{/vars}} +public {{classname}}() { {{#parent}}{{#parcelableModel}} + super();{{/parcelableModel}}{{/parent}}{{#gson}}{{#discriminator}} + //this.{{{discriminatorName}}} = this.getClass().getSimpleName();{{/discriminator}}{{/gson}} +}{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}} + + /* + {{#jsonb}}@JsonbCreator{{/jsonb}}{{#jackson}}@JsonCreator{{/jackson}} + public {{classname}}( + {{#readOnlyVars}} + {{#jsonb}}@JsonbProperty("{{baseName}}"){{/jsonb}}{{#jackson}}@JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}){{/jackson}} {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + this(); + {{#readOnlyVars}} + this.{{name}} = {{name}}; + {{/readOnlyVars}} + }*/ +{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}} +{{#vars}} + + {{^isReadOnly}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});{{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}}this.{{name}} = {{name}};{{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + {{^required}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}; + } + {{/required}} + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{.}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{.}} + {{/minimum}} + {{#maximum}} + * maximum: {{.}} + {{/maximum}} + * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} + **/ + {{#deprecated}} + @Deprecated + {{/deprecated}} + {{#required}} + {{#isNullable}} + @javax.annotation.Nullable + {{/isNullable}} + {{^isNullable}} + @javax.annotation.Nonnull + {{/isNullable}} + {{/required}} + {{^required}} + @javax.annotation.Nullable + {{/required}} + {{#jsonb}} + @JsonbProperty("{{baseName}}") + {{/jsonb}} + {{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") + {{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} + {{/vendorExtensions.x-extra-annotation}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} + {{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} + {{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + +{{/vars}} + +@Override +public boolean equals(Object o) { +{{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o, false, null, true); +{{/useReflectionEqualsHashCode}} +{{^useReflectionEqualsHashCode}} + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} +{{/useReflectionEqualsHashCode}} +}{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public int hashCode() { +{{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); +{{/useReflectionEqualsHashCode}} +{{^useReflectionEqualsHashCode}} + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}); +{{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); +{{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); +{{/parent}} +{{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); +{{/vars}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private{{#jsonb}} static{{/jsonb}} String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { + {{#model}} + {{#isArray}} + out.writeList(this); + {{/isArray}} + {{^isArray}} + {{#parent}} + super.writeToParcel(out, flags); + {{/parent}} + {{#vars}} + out.writeValue({{name}}); + {{/vars}} + {{/isArray}} + {{/model}} + } + + {{classname}}(Parcel in) { + {{#isArray}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); + {{/isArray}} + {{^isArray}} + {{#parent}} + super(in); + {{/parent}} + {{#vars}} + {{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); + {{/isPrimitiveType}} + {{/vars}} + {{/isArray}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { + {{#model}} + {{#isArray}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; + {{/isArray}} + {{^isArray}} + return new {{classname}}(in); + {{/isArray}} + {{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} + } \ No newline at end of file diff --git a/api/src/test/groovy/com/okta/sdk/resource/ApiSpecTest.groovy b/api/src/test/groovy/com/okta/sdk/resource/ApiSpecTest.groovy deleted file mode 100644 index fdc80d2ce16..00000000000 --- a/api/src/test/groovy/com/okta/sdk/resource/ApiSpecTest.groovy +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.resource - -import groovy.json.JsonSlurper -import org.testng.annotations.Test - -import java.util.Map.Entry - -/** - * Simple tests to validate the api.yaml spec. We want to check for methods that likely SHOULD belong to a - * model and NOT the Client directly. - */ -class ApiSpecTest { - - /** - * This doesn't do any actual validation at the moment, it is just a helper method to output the missing - * x-okta-operations json. - */ - @Test(enabled = false) - void checkForModelOperations() { - - def opPathMap = new LinkedHashMap() - def json = new JsonSlurper().parse(new File("../src/swagger/api.yaml")) - for(def pathE : json.paths) { - - for(def opE : pathE.value) { - def op = opE.value - opPathMap.put(op.operationId, new Pair(pathE.key, opE.key)) -// println(op.operationId +" : "+ pathE.key) - } - } - - def opModelMap = new LinkedHashMap() - for (def defE : json.definitions) { - String modelName = defE.key - def links = defE.value['x-okta-operations'] - if (links) { - for (def link : links) { - opModelMap.put(link.operationId, modelName) -// println(link.operationId +" : "+ modelName) - } - } - - } - - // now we have our lookup maps, now it is time to compare them - - for (Iterator iter = opPathMap.iterator(); iter.hasNext(); ) { - Map.Entry entry = iter.next() - if (opModelMap.keySet().contains(entry.key)) { - iter.remove() - } - } - - printMethodsThatShouldBeLinked(opPathMap, "User", "/api/v1/users/{userId}", "userId", "id") - printMethodsThatShouldBeLinked(opPathMap, "PublicAppInstance", "/api/v1/apps/{appId}", "appId", "id") - printMethodsThatShouldBeLinked(opPathMap, "UserGroup", "/api/v1/groups/{groupId}", "groupId", "id") - printMethodsThatShouldBeLinked(opPathMap, "MediationPolicy", "/api/v1/policies/{policyId}", "policyId", "id") - printMethodsThatShouldBeLinked(opPathMap, "IdpTransaction", "/api/v1/idps/tx/{transactionId}", "transactionId", "id") - - printMethodsThatShouldBeLinked(opPathMap, "CVDAppUserProfile", "/api/v1/apps/user/types/{typeId}", "typeId", "id") - printMethodsThatShouldBeLinked(opPathMap, "IdpTrust", "/api/v1/idps/{idpId}", "idpId", "id") - - printMethodsThatShouldBeLinked(opPathMap, "GroupMembershipMediationRule", "/api/v1/groups/rules/{ruleId}", "ruleId", "id") - printMethodsThatShouldBeLinked(opPathMap, "OrgCustomSmsMediationTemplate", "/api/v1/templates/sms/{templateId}", "templateId", "id") - - - - } - - void printMethodsThatShouldBeLinked(Map opPathMap, String model, String startsWithPath, String pathDest, String pathSrc) { - - Map toBeLinked = new LinkedHashMap() - for (Entry entry : opPathMap) { -// println(entry.value +" : "+ entry.key) - - if (entry.value.name.startsWith(startsWithPath)) { - if (!((entry.value.name.equals(startsWithPath)) && "get".equals(entry.value.value))) { - toBeLinked.put(entry.key, entry.value.name) - } - } - } - - if (!toBeLinked.isEmpty()) { - println(model) - - println('\t"x-okta-operations": [') - StringBuilder sb = new StringBuilder() - for (Entry entry : toBeLinked) { - - sb.append(""" - { - "alias": "${entry.key}", - "operationId": "${entry.key}", - "arguments": [ - { - "dest": "${pathDest}", - "src": "${pathSrc}" - } - ] - },""") - } - - sb.deleteCharAt(sb.length()-1) - sb.append('\n\t],') - println(sb.toString()) - } - - } - - static class Pair { - def name - def value - - Pair(def name, def value) { - this.name = name - this.value = value - } - } - -} diff --git a/api/src/test/groovy/com/okta/sdk/resource/ResourceExceptionTest.groovy b/api/src/test/groovy/com/okta/sdk/resource/ResourceExceptionTest.groovy index 60706fec21c..5da7fd635de 100644 --- a/api/src/test/groovy/com/okta/sdk/resource/ResourceExceptionTest.groovy +++ b/api/src/test/groovy/com/okta/sdk/resource/ResourceExceptionTest.groovy @@ -17,6 +17,7 @@ package com.okta.sdk.resource import com.okta.sdk.error.ErrorCause +import com.okta.sdk.error.ResourceException import org.testng.annotations.Test import static org.testng.Assert.assertEquals @@ -67,6 +68,4 @@ class ResourceExceptionTest { assertEquals ex.message, 'HTTP 400, Okta I2000 (foo)' assertEquals ex.id, null } - - } diff --git a/coverage/pom.xml b/coverage/pom.xml index feb64fe5815..f67078f5731 100644 --- a/coverage/pom.xml +++ b/coverage/pom.xml @@ -21,7 +21,7 @@ com.okta.sdk okta-sdk-root - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT okta-sdk-coverage @@ -37,14 +37,6 @@ com.okta.sdk okta-sdk-impl - - com.okta.sdk - okta-sdk-httpclient - - - com.okta.sdk - okta-sdk-okhttp - com.okta.sdk okta-sdk-examples-quickstart @@ -75,4 +67,4 @@ - + \ No newline at end of file diff --git a/examples/pom.xml b/examples/pom.xml index 249654e88b4..beed5c740ad 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -21,15 +21,14 @@ com.okta.sdk okta-sdk-root - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT okta-sdk-examples - com.okta.sdk Okta Java SDK :: Examples pom quickstart - + \ No newline at end of file diff --git a/examples/quickstart/pom.xml b/examples/quickstart/pom.xml index 313aac5f63f..5e5919ef1bb 100644 --- a/examples/quickstart/pom.xml +++ b/examples/quickstart/pom.xml @@ -20,7 +20,7 @@ com.okta.sdk okta-sdk-examples - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT ../pom.xml @@ -38,11 +38,11 @@ okta-sdk-impl runtime - - com.okta.sdk - okta-sdk-httpclient - runtime - + + + + + ch.qos.logback logback-classic @@ -81,4 +81,4 @@ - + \ No newline at end of file diff --git a/examples/quickstart/src/main/java/quickstart/Quickstart.java b/examples/quickstart/src/main/java/quickstart/Quickstart.java index bee903a3d4a..917529565c2 100644 --- a/examples/quickstart/src/main/java/quickstart/Quickstart.java +++ b/examples/quickstart/src/main/java/quickstart/Quickstart.java @@ -15,18 +15,21 @@ */ package quickstart; -import com.okta.sdk.client.Client; -import com.okta.sdk.client.ClientBuilder; +import org.openapitools.client.ApiClient; import com.okta.sdk.client.Clients; +import com.okta.sdk.client.ClientBuilder; import com.okta.sdk.resource.group.GroupBuilder; -import com.okta.sdk.resource.ResourceException; import com.okta.sdk.resource.user.UserBuilder; -import com.okta.sdk.resource.group.Group; -import com.okta.sdk.resource.user.User; -import com.okta.sdk.resource.user.UserList; -import com.okta.sdk.resource.user.UserStatus; +import org.openapitools.client.api.UserApi; +import org.openapitools.client.api.GroupApi; + +import org.openapitools.client.model.Group; +import org.openapitools.client.model.User; +import org.openapitools.client.model.UserStatus; +import java.util.List; +import java.util.Objects; import java.util.UUID; /** @@ -39,15 +42,18 @@ public class Quickstart { public static void main(String[] args) { - final String email = "joe.coder+" + UUID.randomUUID().toString() + "@example.com"; + final String email = "joe.coder+" + UUID.randomUUID() + "@example.com"; final String groupName = "java-sdk-quickstart-" + UUID.randomUUID().toString(); final char[] password = {'P','a','s','s','w','o','r','d','1'}; ClientBuilder builder; - Client client; + ApiClient client; Group group = null; User user = null; + UserApi userApi = null; + GroupApi groupApi = null; + try { // Instantiate a builder for your Client. If needed, settings like Proxy and Caching can be defined here. builder = Clients.builder(); @@ -56,11 +62,14 @@ public static void main(String[] args) { // in pre-defined locations: i.e. ~/.okta/okta.yaml client = builder.build(); + userApi = new UserApi(client); + groupApi = new GroupApi(client); + // Create a group group = GroupBuilder.instance() .setName(groupName) .setDescription("Quickstart created Group") - .buildAndCreate(client); + .buildAndCreate(groupApi); println("Group: '" + group.getId() + "' was last updated on: " + group.getLastUpdated()); @@ -72,43 +81,30 @@ public static void main(String[] args) { .setPassword(password) .setSecurityQuestion("Favorite security question?") .setSecurityQuestionAnswer("None of them!") - .putProfileProperty("division", "Seven") // key/value pairs predefined in the user profile schema + //.putProfileProperty("division", "Seven") // key/value pairs predefined in the user profile schema //TODO: fix me .setActive(true) - .buildAndCreate(client); - - // add user to the newly created group - user.addToGroup(group.getId()); + .addGroup(group.getId()) // add user to the newly created group + .buildAndCreate(userApi); String userId = user.getId(); println("User created with ID: " + userId); // You can look up user by ID - println("User lookup by ID: "+ client.getUser(userId).getProfile().getLogin()); + println("User lookup by ID: "+ userApi.getUser(userId).getProfile().getLogin()); // or by Email - println("User lookup by Email: "+ client.getUser(email).getProfile().getLogin()); - + println("User lookup by Email: "+ userApi.getUser(email).getProfile().getLogin()); // get the list of users - UserList users = client.listUsers(); + List users = userApi.listUsers(null, null, null, "status eq \"ACTIVE\"", null, null, null); // get the first user in the collection - println("First user in collection: " + users.iterator().next().getProfile().getEmail()); - - // or loop through all of them (paging is automatic) -// int ii = 0; -// for (User tmpUser : users) { -// println("["+ ii++ +"] User: " + tmpUser.getProfile().getEmail()); -// } - + println("First user in collection: " + users.stream().findFirst().get().getProfile().getEmail()); } - catch (ResourceException e) { + catch (Exception e) { - // we can get the user friendly message from the Exception + // we can get the user-friendly message from the Exception println(e.getMessage()); - - // and you can get the details too - e.getCauses().forEach( cause -> println("\t" + cause.getSummary())); throw e; } finally { @@ -116,15 +112,15 @@ public static void main(String[] args) { // deactivate (if de-provisioned) and delete user if (user != null) { - if (user.getStatus() != UserStatus.DEPROVISIONED) { - user.deactivate(); + if (!Objects.equals(user.getStatus(), UserStatus.DEPROVISIONED)) { + userApi.deactivateUser(user.getId(), false); } - user.delete(); + userApi.deleteUser(user.getId(), false); } // delete group if (group != null) { - group.delete(); + groupApi.deleteGroup(group.getId()); } } } diff --git a/examples/quickstart/src/main/java/quickstart/ReadmeSnippets.java b/examples/quickstart/src/main/java/quickstart/ReadmeSnippets.java index 16eac6c1777..a9ef0c28e7a 100644 --- a/examples/quickstart/src/main/java/quickstart/ReadmeSnippets.java +++ b/examples/quickstart/src/main/java/quickstart/ReadmeSnippets.java @@ -17,36 +17,50 @@ import com.okta.sdk.authc.credentials.TokenClientCredentials; import com.okta.sdk.cache.Caches; -import com.okta.sdk.client.AuthorizationMode; -import com.okta.sdk.client.Client; import com.okta.sdk.client.Clients; -import com.okta.sdk.resource.ExtensibleResource; -import com.okta.sdk.resource.application.Application; -import com.okta.sdk.resource.application.ApplicationList; -import com.okta.sdk.resource.application.SwaApplication; -import com.okta.sdk.resource.application.SwaApplicationSettings; -import com.okta.sdk.resource.application.SwaApplicationSettingsApplication; -import com.okta.sdk.resource.group.Group; +import com.okta.sdk.resource.common.PagedList; import com.okta.sdk.resource.group.GroupBuilder; -import com.okta.sdk.resource.group.GroupList; -import com.okta.sdk.resource.log.LogEventList; -import com.okta.sdk.resource.user.User; import com.okta.sdk.resource.user.UserBuilder; -import com.okta.sdk.resource.user.UserList; -import com.okta.sdk.resource.user.factor.ActivateFactorRequest; -import com.okta.sdk.resource.user.factor.UserFactor; -import com.okta.sdk.resource.user.factor.UserFactorList; -import com.okta.sdk.resource.user.factor.SmsUserFactor; -import com.okta.sdk.resource.user.factor.VerifyFactorRequest; -import com.okta.sdk.resource.user.factor.VerifyUserFactorResponse; +import org.openapitools.client.ApiClient; +import org.openapitools.client.api.ApplicationApi; +import org.openapitools.client.api.GroupApi; +import org.openapitools.client.api.SystemLogApi; +import org.openapitools.client.api.UserApi; +import org.openapitools.client.api.UserFactorApi; +import org.openapitools.client.model.ActivateFactorRequest; +import org.openapitools.client.model.Application; +import org.openapitools.client.model.ApplicationSignOnMode; +import org.openapitools.client.model.BookmarkApplication; +import org.openapitools.client.model.BookmarkApplicationSettings; +import org.openapitools.client.model.BookmarkApplicationSettingsApplication; +import org.openapitools.client.model.BrowserPluginApplication; +import org.openapitools.client.model.Group; +import org.openapitools.client.model.LogEvent; +import org.openapitools.client.model.SmsUserFactor; +import org.openapitools.client.model.SwaApplicationSettings; +import org.openapitools.client.model.SwaApplicationSettingsApplication; +import org.openapitools.client.model.UpdateUserRequest; +import org.openapitools.client.model.User; +import org.openapitools.client.model.UserFactor; +import org.openapitools.client.model.UserProfile; +import org.openapitools.client.model.VerifyFactorRequest; +import org.openapitools.client.model.VerifyUserFactorResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; import java.util.Arrays; -import java.util.HashSet; +import java.util.Collections; +import java.util.List; import java.util.concurrent.TimeUnit; import static com.okta.sdk.cache.Caches.forResource; + /** * Example snippets used for this projects README.md. *

    @@ -57,198 +71,258 @@ public class ReadmeSnippets { private static final Logger log = LoggerFactory.getLogger(ReadmeSnippets.class); - private final Client client = Clients.builder().build(); + private final ApiClient client = Clients.builder().build(); private final User user = null; private void createClient() { - Client client = Clients.builder() + ApiClient client = Clients.builder() .setOrgUrl("https://{yourOktaDomain}") // e.g. https://dev-123456.okta.com .setClientCredentials(new TokenClientCredentials("{apiToken}")) .build(); } - private void isClientReady() { - boolean isClientReadyStatus = client.isReady(client::listApplications); - } - - private void createOAuth2Client() { - Client client = Clients.builder() - .setOrgUrl("https://{yourOktaDomain}") // e.g. https://dev-123456.okta.com - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("{clientId}") - .setKid("{kid}") // key id (optional) - .setScopes(new HashSet<>(Arrays.asList("okta.users.read", "okta.apps.read"))) - .setPrivateKey("/path/to/yourPrivateKey.pem") - // (or) .setPrivateKey("full PEM payload") - // (or) .setPrivateKey(Paths.get("/path/to/yourPrivateKey.pem")) - // (or) .setPrivateKey(inputStream) - // (or) .setPrivateKey(privateKey) - .build(); - } - private void getUser() { - User user = client.getUser("a-user-id"); + UserApi userApi = new UserApi(client); + + User user = userApi.getUser("userId"); } private void listAllUsers() { - UserList users = client.listUsers(); + UserApi userApi = new UserApi(client); + List users = userApi.listUsers(null, null, 5, null, null, null, null); // stream - client.listUsers().stream() + users.stream() .forEach(user -> { // do something }); } private void userSearch() { + UserApi userApi = new UserApi(client); // search by email - UserList users = client.listUsers("jcoder@example.com", null, null, null, null); + List users = userApi.listUsers(null, null, 5, null, "jcoder@example.com", null, null); // filter parameter - users = client.listUsers(null, "status eq \"ACTIVE\"", null, null, null); + users = userApi.listUsers(null, null, null, "status eq \"ACTIVE\"",null, null, null); } private void createUser() { + UserApi userApi = new UserApi(client); + User user = UserBuilder.instance() .setEmail("joe.coder@example.com") .setFirstName("Joe") .setLastName("Code") - .buildAndCreate(client); + .buildAndCreate(userApi); } private void createUserWithGroups() { + UserApi userApi = new UserApi(client); + User user = UserBuilder.instance() .setEmail("joe.coder@example.com") .setFirstName("Joe") .setLastName("Code") - .setGroups(new HashSet<>(Arrays.asList("group-id-1", "group-id-2"))) - .buildAndCreate(client); + .setGroups(Arrays.asList("groupId-1", "groupId-2")) + .buildAndCreate(userApi); } private void updateUser() { - user.getProfile().setFirstName("new-first-name"); - user.update(); - } + UserApi userApi = new UserApi(client); + + UpdateUserRequest updateUserRequest = new UpdateUserRequest(); + UserProfile userProfile = new UserProfile(); + userProfile.setNickName("Batman"); + updateUserRequest.setProfile(userProfile); - private void customAttributes() { - user.getProfile().put("customPropertyKey", "a value"); - user.getProfile().get("customPropertyKey"); + userApi.updateUser(user.getId(), updateUserRequest, true); } private void deleteUser() { - user.deactivate(); - user.delete(); + UserApi userApi = new UserApi(client); + + // deactivate first + userApi.deactivateUser(user.getId(), false); + // then delete + userApi.deleteUser(user.getId(), false); } private void listUsersGroup() { - GroupList groups = user.listGroups(); + GroupApi groupApi = new GroupApi(client); + List groups = groupApi.listGroups(null, null, null, 10, null, null); } private void createGroup() { + GroupApi groupApi = new GroupApi(client); + Group group = GroupBuilder.instance() .setName("a-group-name") .setDescription("Example Group") - .buildAndCreate(client); - } - - private void addUserToGroup() { - user.addToGroup("groupId"); + .buildAndCreate(groupApi); } private void listUserFactors() { - UserFactorList factors = user.listFactors(); + UserFactorApi userFactorApi = new UserFactorApi(client); + + List userFactors = userFactorApi.listFactors("userId"); } private void enrollUserInFactor() { - SmsUserFactor smsFactor = client.instantiate(SmsUserFactor.class); + UserFactorApi userFactorApi = new UserFactorApi(client); + + SmsUserFactor smsFactor = new SmsUserFactor(); smsFactor.getProfile().setPhoneNumber("555 867 5309"); - user.enrollFactor(smsFactor); + + UserFactor userFactor = userFactorApi.enrollFactor("userId", smsFactor, true, "templateId", 30, true); } private void activateFactor() { - UserFactor factor = user.getFactor("factorId"); - ActivateFactorRequest activateFactorRequest = client.instantiate(ActivateFactorRequest.class); + UserFactorApi userFactorApi = new UserFactorApi(client); + + UserFactor userFactor = userFactorApi.getFactor("userId", "factorId"); + ActivateFactorRequest activateFactorRequest = new ActivateFactorRequest(); activateFactorRequest.setPassCode("123456"); - factor.activate(activateFactorRequest); + + UserFactor activatedUserFactor = userFactorApi.activateFactor("userId", "factorId", activateFactorRequest); } private void verifyFactor() { - UserFactor factor = user.getFactor("factorId"); - VerifyFactorRequest verifyFactorRequest = client.instantiate(VerifyFactorRequest.class); + UserFactorApi userFactorApi = new UserFactorApi(client); + + UserFactor userFactor = userFactorApi.getFactor("userId", "factorId"); + VerifyFactorRequest verifyFactorRequest = new VerifyFactorRequest(); verifyFactorRequest.setPassCode("123456"); - VerifyUserFactorResponse verifyUserFactorResponse = factor.setVerify(verifyFactorRequest).verify(); + + VerifyUserFactorResponse verifyUserFactorResponse = + userFactorApi.verifyFactor("userId", "factorId", "templateId", 10, "xForwardedFor", "userAgent", "acceptLanguage", verifyFactorRequest); } private void listApplication() { - ApplicationList applications = client.listApplications(); + ApplicationApi applicationApi = new ApplicationApi(client); + + List applications = applicationApi.listApplications(null, null, 10, null, null, true); } private void getApplication() { - Application app = client.getApplication("appId"); + ApplicationApi applicationApi = new ApplicationApi(client); + + Application app = applicationApi.getApplication("appId", null); } private void createSwaApplication() { - SwaApplication swaApp = client.instantiate(SwaApplication.class) - .setSettings(client.instantiate(SwaApplicationSettings.class) - .setApp(client.instantiate(SwaApplicationSettingsApplication.class) - .setButtonField("btn-login") - .setPasswordField("txtbox-password") - .setUsernameField("txtbox-username") - .setUrl("https://example.com/login.html"))); + ApplicationApi applicationApi = new ApplicationApi(client); + + SwaApplicationSettingsApplication swaApplicationSettingsApplication = new SwaApplicationSettingsApplication(); + swaApplicationSettingsApplication.buttonField("btn-login") + .passwordField("txtbox-password") + .usernameField("txtbox-username") + .url("https://example.com/login.html"); + SwaApplicationSettings swaApplicationSettings = new SwaApplicationSettings(); + swaApplicationSettings.app(swaApplicationSettingsApplication); + BrowserPluginApplication browserPluginApplication = new BrowserPluginApplication(); + browserPluginApplication.name("template_swa"); + browserPluginApplication.label("Sample Plugin App"); + browserPluginApplication.settings(swaApplicationSettings); + + // create + BrowserPluginApplication createdApp = + applicationApi.createApplication(BrowserPluginApplication.class, browserPluginApplication, true, null); } private void listSysLogs() { - // page through all log events - LogEventList logEvents = client.getLogs(); + SystemLogApi systemLogApi = new SystemLogApi(client); - // or use a filter (start date, end date, filter, or query, sort order) all options are nullable - logEvents = client.getLogs(null, null, null, "interestingURI.com", "ASCENDING"); + // use a filter (start date, end date, filter, or query, sort order) all options are nullable + List logEvents = systemLogApi.listLogEvents(null, null, null, "interestingURI.com", 100, "ASCENDING", null); } private void callAnotherEndpoint() { - // Create an IdP, see: https://developer.okta.com/docs/api/resources/idps#add-identity-provider - ExtensibleResource resource = client.instantiate(ExtensibleResource.class); - ExtensibleResource protocolNode = client.instantiate(ExtensibleResource.class); - protocolNode.put("type", "OAUTH"); - resource.put("protocol", protocolNode); - ExtensibleResource result = client.http() - .setBody(resource) - .post("/api/v1/idps", ExtensibleResource.class); + ApiClient apiClient = buildApiClient("orgBaseUrl", "apiKey"); + + // Create a BookmarkApplication + BookmarkApplication bookmarkApplication = new BookmarkApplication(); + bookmarkApplication.setName("bookmark"); + bookmarkApplication.setLabel("Sample Bookmark App"); + bookmarkApplication.setSignOnMode(ApplicationSignOnMode.BOOKMARK); + BookmarkApplicationSettings bookmarkApplicationSettings = new BookmarkApplicationSettings(); + BookmarkApplicationSettingsApplication bookmarkApplicationSettingsApplication = + new BookmarkApplicationSettingsApplication(); + bookmarkApplicationSettingsApplication.setUrl("https://example.com/bookmark.htm"); + bookmarkApplicationSettingsApplication.setRequestIntegration(false); + bookmarkApplicationSettings.setApp(bookmarkApplicationSettingsApplication); + bookmarkApplication.setSettings(bookmarkApplicationSettings); + + ResponseEntity responseEntity = apiClient.invokeAPI("/api/v1/apps", + HttpMethod.POST, + Collections.emptyMap(), + null, + bookmarkApplication, + new HttpHeaders(), + new LinkedMultiValueMap<>(), + null, + Collections.singletonList(MediaType.APPLICATION_JSON), + MediaType.APPLICATION_JSON, + new String[]{"API Token"}, + new ParameterizedTypeReference() {}); + + BookmarkApplication createdApp = responseEntity.getBody(); } private void paging() { - // get the list of users - UserList users = client.listUsers(); - // get the first user in the collection - log.info("First user in collection: {}", users.iterator().next().getProfile().getEmail()); + UserApi userApi = new UserApi(client); + + // limit + int pageSize = 2; + + PagedList usersPagedListOne = userApi.listUsersWithPaginationInfo(null, null, pageSize, null, null, null, null); + + // e.g. https://example.okta.com/api/v1/users?after=000u3pfv9v4SQXvpBB0g7&limit=2 + String nextPageUrl = usersPagedListOne.getNextPage(); - // or loop through all of them (paging is automatic) - for (User tmpUser : users) { + // replace 'after' with actual cursor from the nextPageUrl + PagedList usersPagedListTwo = userApi.listUsersWithPaginationInfo("after", null, pageSize, null, null, null, null); + + // loop through all of them (paging is automatic) + for (User tmpUser : usersPagedListOne.getItems()) { log.info("User: {}", tmpUser.getProfile().getEmail()); } - // or via a stream - users.stream().forEach(tmpUser -> log.info("User: {}", tmpUser.getProfile().getEmail())); + // or stream + usersPagedListOne.getItems().forEach(tmpUser -> log.info("User: {}", tmpUser.getProfile().getEmail())); } private void complexCaching() { - Caches.newCacheManager() - .withDefaultTimeToLive(300, TimeUnit.SECONDS) // default - .withDefaultTimeToIdle(300, TimeUnit.SECONDS) //general default - .withCache(forResource(User.class) //User-specific cache settings - .withTimeToLive(1, TimeUnit.HOURS) - .withTimeToIdle(30, TimeUnit.MINUTES)) - .withCache(forResource(Group.class) //Group-specific cache settings - .withTimeToLive(2, TimeUnit.HOURS)) - //... etc ... - .build(); //build the CacheManager + Caches.newCacheManager() + .withDefaultTimeToLive(300, TimeUnit.SECONDS) // default + .withDefaultTimeToIdle(300, TimeUnit.SECONDS) //general default + .withCache(forResource(User.class) //User-specific cache settings + .withTimeToLive(1, TimeUnit.HOURS) + .withTimeToIdle(30, TimeUnit.MINUTES)) + .withCache(forResource(Group.class) //Group-specific cache settings + .withTimeToLive(1, TimeUnit.HOURS)) + //... etc ... + .build(); //build the CacheManager } private void disableCaching() { - Client client = Clients.builder() + ApiClient client = Clients.builder() .setCacheManager(Caches.newDisabledCacheManager()) .build(); } + + private static ApiClient buildApiClient(String orgBaseUrl, String apiKey) { + + ApiClient apiClient = new ApiClient(); + // set your custom rest template and retry template, + // not setting it would use the default templates + //apiClient.setRestTemplate(); + //apiClient.setRetryTemplate(retryTemplate(this.clientConfig)); + apiClient.setBasePath(orgBaseUrl); + apiClient.setApiKey(apiKey); + apiClient.setApiKeyPrefix("SSWS"); + return apiClient; + } } diff --git a/httpclients/httpclient/pom.xml b/httpclients/httpclient/pom.xml deleted file mode 100644 index 960aa51f27e..00000000000 --- a/httpclients/httpclient/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - 4.0.0 - - - com.okta.sdk - okta-sdk-root - 8.2.3-SNAPSHOT - ../.. - - - okta-sdk-httpclient - Okta Java SDK :: Extensions :: HTTP Client - - Moved to com.okta.commons:okta-http-httpclient - - - - - com.okta.commons - okta-http-httpclient - - - - diff --git a/httpclients/okhttp/pom.xml b/httpclients/okhttp/pom.xml deleted file mode 100644 index 7e293f22852..00000000000 --- a/httpclients/okhttp/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - 4.0.0 - - - com.okta.sdk - okta-sdk-root - 8.2.3-SNAPSHOT - ../.. - - - okta-sdk-okhttp - Okta Java SDK :: Extensions :: OkHttp Client - - Moved to com.okta.commons:okta-http-okhttp - - - - - com.okta.commons - okta-http-okhttp - ${okta.commons.version} - - - diff --git a/impl/pom.xml b/impl/pom.xml index 1af38feb330..9780fd59c1e 100644 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -21,13 +21,13 @@ com.okta.sdk okta-sdk-root - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT okta-sdk-impl Okta Java SDK :: Impl - The Okta Java SDK core implemenation .jar is used at runtime to support API invocations. This + The Okta Java SDK core implementation .jar is used at runtime to support API invocations. This implementation jar should be a runtime dependency only and should NOT be depended on at compile time by your code. The implementations within this jar can change at any time without warning - use it with runtime scope only. @@ -40,16 +40,12 @@ okta-sdk-api - com.okta.commons - okta-config-check + org.slf4j + slf4j-api com.okta.commons - okta-http-api - - - org.slf4j - slf4j-api + okta-config-check com.fasterxml.jackson.core @@ -61,7 +57,7 @@ org.bouncycastle - bcprov-jdk15on + bcprov-jdk15on org.bouncycastle @@ -151,21 +147,21 @@ - - org.zalando.maven.plugins - swagger-codegen-maven-plugin - - - swagger-codegen-impl - - codegen - - - okta_java_impl - - - - + + + + + + + + + + + + + + + org.codehaus.mojo build-helper-maven-plugin @@ -177,7 +173,7 @@ - ${project.build.directory}/generated-sources/swagger-codegen + ${project.build.directory}/generated-sources/openapi @@ -186,4 +182,4 @@ - + \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCache.java b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCache.java index d70c0d60531..a319494da8b 100644 --- a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCache.java +++ b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCache.java @@ -16,20 +16,20 @@ */ package com.okta.sdk.impl.cache; +import com.okta.commons.lang.Assert; import com.okta.sdk.cache.Cache; import com.okta.sdk.impl.util.SoftHashMap; -import com.okta.commons.lang.Assert; -import java.time.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; /** * A {@code DefaultCache} is a {@link Cache Cache} implementation that uses a backing {@link Map} instance to store * and retrieve cached data. - *

    Thread Safety

    + * Thread Safety * This implementation is thread-safe only if the backing map is thread-safe. * * @since 0.5.0 @@ -71,16 +71,16 @@ public class DefaultCache implements Cache { * This constructor uses a {@link SoftHashMap} instance as the cache's backing map, which is thread-safe and * auto-sizes itself based on the application's memory constraints. *

    - * Finally, the {@link #setTimeToIdle(java.time.Duration) timeToIdle} and - * {@link #setTimeToLive(java.time.Duration) timeToLive} settings are both {@code null}, + * Finally, the {@link #setTimeToIdle(Duration) timeToIdle} and + * {@link #setTimeToLive(Duration) timeToLive} settings are both {@code null}, * indicating that cache entries will live indefinitely (except due to memory constraints as managed by the * {@code SoftHashMap}). * * @param name the name to assign to this instance, expected to be unique among all other caches in the parent * {@code CacheManager}. * @see SoftHashMap - * @see #setTimeToIdle(java.time.Duration) - * @see #setTimeToLive(java.time.Duration) + * @see #setTimeToIdle(Duration) + * @see #setTimeToLive(Duration) */ public DefaultCache(String name) { this(name, new SoftHashMap>()); @@ -91,8 +91,8 @@ public DefaultCache(String name) { * {@code backingMap}. It is expected that the {@code backingMap} implementation be thread-safe and preferrably * auto-sizing based on memory constraints (see {@link SoftHashMap} for such an implementation). *

    - * The {@link #setTimeToIdle(java.time.Duration) timeToIdle} and - * {@link #setTimeToLive(java.time.Duration) timeToLive} settings are both {@code null}, + * The {@link #setTimeToIdle(Duration) timeToIdle} and + * {@link #setTimeToLive(Duration) timeToLive} settings are both {@code null}, * indicating that cache entries will live indefinitely (except due to memory constraints as managed by the * {@code backingMap} instance). * @@ -100,8 +100,8 @@ public DefaultCache(String name) { * {@code CacheManager}. * @param backingMap the (ideally thread-safe) map instance to store the Cache entries. * @see SoftHashMap - * @see #setTimeToIdle(java.time.Duration) - * @see #setTimeToLive(java.time.Duration) + * @see #setTimeToIdle(Duration) + * @see #setTimeToLive(Duration) */ public DefaultCache(String name, Map> backingMap) { this(name, backingMap, null, null); @@ -122,8 +122,8 @@ public DefaultCache(String name, Map> backingMap) { * @throws IllegalArgumentException if either {@code timeToLive} or {@code timeToIdle} are non-null and * represent a non-positive (zero or negative) value. This is only enforced for * non-null values - {@code null} values are allowed for either argument. - * @see #setTimeToIdle(java.time.Duration) - * @see #setTimeToLive(java.time.Duration) + * @see #setTimeToIdle(Duration) + * @see #setTimeToLive(Duration) */ public DefaultCache(String name, Map> backingMap, Duration timeToLive, Duration timeToIdle) { Assert.notNull(name, "Cache name cannot be null."); diff --git a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheConfiguration.java b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheConfiguration.java index d1d8d65fcf8..4301d5433ff 100644 --- a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheConfiguration.java +++ b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheConfiguration.java @@ -17,8 +17,8 @@ package com.okta.sdk.impl.cache; import com.okta.commons.lang.Assert; -import java.time.Duration; +import java.time.Duration; import java.util.concurrent.TimeUnit; /** diff --git a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheConfigurationBuilder.java b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheConfigurationBuilder.java index 689d56dc113..b6a5353569b 100644 --- a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheConfigurationBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheConfigurationBuilder.java @@ -18,8 +18,8 @@ import com.okta.commons.lang.Assert; import com.okta.sdk.cache.CacheConfigurationBuilder; -import java.time.Duration; +import java.time.Duration; import java.util.concurrent.TimeUnit; /** diff --git a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheManager.java b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheManager.java index 572285f0e25..fb6eff33996 100644 --- a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheManager.java +++ b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheManager.java @@ -20,10 +20,10 @@ import com.okta.sdk.cache.Cache; import com.okta.sdk.cache.CacheManager; import com.okta.sdk.impl.util.SoftHashMap; -import java.time.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Duration; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -34,7 +34,7 @@ * an in-memory {@link ConcurrentMap ConcurrentMap}. By default, this implementation creates thread-safe * {@link DefaultCache} instances via the {@link #createCache(String) createCache(name)} method, but this can be overridden * by subclasses that wish to provide different Cache implementations. - *

    Clustering

    + *

    Clustering

    * This implementation DOES NOT SUPPORT CLUSTERING. *

    * If your application is deployed on multiple hosts, it is @@ -49,29 +49,29 @@ * no longer be available. If a cache entry is not accessed at all after this amount of time, it will be * removed from the cache as soon as possible. *

    - * This implementation's {@link #setDefaultTimeToIdle(java.time.Duration) defaultTimeToIdle} + * This implementation's {@link #setDefaultTimeToIdle(Duration) defaultTimeToIdle} * is {@code null}, which means that cache entries can potentially remain idle indefinitely. Note however that a * cache entry can still be expunged due to other conditions (e.g. memory constraints, Time to Live setting, etc). *

    - * The {@link #setDefaultTimeToIdle(java.time.Duration) defaultTimeToIdle} setting is only + * The {@link #setDefaultTimeToIdle(Duration) defaultTimeToIdle} setting is only * applied to newly created {@code Cache} instances. It does not affect already existing {@code Cache}s. *

    Time to Live

    * Time to Live is the amount of time a cache entry may exist after first being created before it will expire and no * longer be available. If a cache entry ever becomes older than this amount of time (regardless of how often * it is accessed), it will be removed from the cache as soon as possible. *

    - * This implementation's {@link #setDefaultTimeToLive(java.time.Duration) defaultTimeToLive} + * This implementation's {@link #setDefaultTimeToLive(Duration) defaultTimeToLive} * is {@code null}, which means that cache entries could potentially live indefinitely. Note however that a * cache entry can still be expunged due to other conditions (e.g. memory constraints, Time to Idle setting, etc). *

    - * The {@link #setDefaultTimeToLive(java.time.Duration) defaultTimeToLive} setting is only + * The {@link #setDefaultTimeToLive(Duration) defaultTimeToLive} setting is only * applied to newly created {@code Cache} instances. It does not affect already existing {@code Cache}s. *

    Thread Safety

    * This implementation and the cache instances it creates are thread-safe and usable in concurrent environments. * - * @see #setDefaultTimeToIdle(java.time.Duration) + * @see #setDefaultTimeToIdle(Duration) * @see #setDefaultTimeToIdleSeconds(long) - * @see #setDefaultTimeToLive(java.time.Duration) + * @see #setDefaultTimeToLive(Duration) * @see #setDefaultTimeToLiveSeconds(long) * @since 0.5.0 */ @@ -127,10 +127,10 @@ public void setDefaultTimeToLive(Duration defaultTimeToLive) { } /** - * Convenience method that sets the {@link #setDefaultTimeToLive(java.time.Duration) defaultTimeToLive} + * Convenience method that sets the {@link #setDefaultTimeToLive(Duration) defaultTimeToLive} * value using a {@code TimeUnit} of {@link TimeUnit#SECONDS}. * - * @param seconds the {@link #setDefaultTimeToLive(java.time.Duration) defaultTimeToLive} value in seconds. + * @param seconds the {@link #setDefaultTimeToLive(Duration) defaultTimeToLive} value in seconds. */ public void setDefaultTimeToLiveSeconds(long seconds) { setDefaultTimeToLive(Duration.ofSeconds(seconds)); @@ -162,10 +162,10 @@ public void setDefaultTimeToIdle(Duration defaultTimeToIdle) { } /** - * Convenience method that sets the {@link #setDefaultTimeToIdle(java.time.Duration) defaultTimeToIdle} + * Convenience method that sets the {@link #setDefaultTimeToIdle(Duration) defaultTimeToIdle} * value using a {@code TimeUnit} of {@link TimeUnit#SECONDS}. * - * @param seconds the {@link #setDefaultTimeToIdle(java.time.Duration) defaultTimeToIdle} value in seconds. + * @param seconds the {@link #setDefaultTimeToIdle(Duration) defaultTimeToIdle} value in seconds. */ public void setDefaultTimeToIdleSeconds(long seconds) { setDefaultTimeToIdle(Duration.ofSeconds(seconds)); diff --git a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheManagerBuilder.java b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheManagerBuilder.java index 5a5a0053134..92dd0e38383 100644 --- a/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheManagerBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/cache/DefaultCacheManagerBuilder.java @@ -21,8 +21,8 @@ import com.okta.sdk.cache.CacheConfigurationBuilder; import com.okta.sdk.cache.CacheManager; import com.okta.sdk.cache.CacheManagerBuilder; -import java.time.Duration; +import java.time.Duration; import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.TimeUnit; diff --git a/impl/src/main/java/com/okta/sdk/impl/client/BaseClient.java b/impl/src/main/java/com/okta/sdk/impl/client/BaseClient.java deleted file mode 100644 index 94b9fbc2944..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/client/BaseClient.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License.BaseClientTest - */ -package com.okta.sdk.impl.client; - -import com.okta.commons.http.RequestExecutor; -import com.okta.commons.http.RequestExecutorFactory; -import com.okta.commons.http.config.BaseUrlResolver; -import com.okta.commons.lang.Assert; -import com.okta.commons.lang.Classes; -import com.okta.sdk.authc.credentials.ClientCredentials; -import com.okta.sdk.cache.CacheManager; -import com.okta.sdk.ds.DataStore; -import com.okta.sdk.ds.RequestBuilder; -import com.okta.sdk.impl.api.ClientCredentialsResolver; -import com.okta.sdk.impl.config.ClientConfiguration; -import com.okta.sdk.impl.ds.DefaultDataStore; -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.resource.Resource; - -import java.util.function.Supplier; - -/** - * The base client class. - * @since 1.1.0 - */ -public abstract class BaseClient implements DataStore { - - private final InternalDataStore dataStore; - - public BaseClient(ClientConfiguration clientConfiguration, CacheManager cacheManager) { - this(clientConfiguration, cacheManager, null); - } - - public BaseClient(ClientConfiguration clientConfiguration, CacheManager cacheManager, RequestExecutor requestExecutor) { - Assert.notNull(clientConfiguration, "clientConfiguration argument cannot be null."); - this.dataStore = createDataStore(requestExecutor != null ? requestExecutor : createRequestExecutor(clientConfiguration), - clientConfiguration.getBaseUrlResolver(), - clientConfiguration.getClientCredentialsResolver(), - cacheManager); - } - - protected InternalDataStore createDataStore(RequestExecutor requestExecutor, BaseUrlResolver baseUrlResolver, ClientCredentialsResolver clientCredentialsResolver, CacheManager cacheManager) { - return new DefaultDataStore(requestExecutor, baseUrlResolver, clientCredentialsResolver, cacheManager); - } - - @Override - public ClientCredentials getClientCredentials() { - return this.dataStore.getClientCredentials(); - } - - @Override - public CacheManager getCacheManager() { - return this.dataStore.getCacheManager(); - } - - public InternalDataStore getDataStore() { - return this.dataStore; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - protected RequestExecutor createRequestExecutor(ClientConfiguration clientConfiguration) { - - String msg = "Unable to find a '" + RequestExecutorFactory.class.getName() + "' " + - "implementation on the classpath. Please ensure you have added the " + - "okta-sdk-httpclient.jar file to your runtime classpath."; // TODO fix jar name - return Classes.loadFromService(RequestExecutorFactory.class, msg).create(clientConfiguration); - } - - // ======================================================================== - // DataStore methods (delegate to underlying DataStore instance) - // ======================================================================== - - /** - * Delegates to the internal {@code dataStore} instance. This is a convenience mechanism to eliminate the constant - * need to call {@code client.getDataStore()} every time one needs to instantiate Resource. - * - * @param clazz the Resource class to instantiate. - * @param the Resource sub-type - * @return a new instance of the specified Resource. - */ - @Override - public T instantiate(Class clazz) { - return this.dataStore.instantiate(clazz); - } - - /** - * Delegates to the internal {@code dataStore} instance. This is a convenience mechanism to eliminate the constant - * need to call {@code client.getDataStore()} every time one needs to look up a Resource. - * - * @param href the resource URL of the resource to retrieve - * @param clazz the {@link Resource} sub-interface to instantiate - * @param type parameter indicating the returned value is a {@link Resource} instance. - * @return an instance of the specified class based on the data returned from the specified {@code href} URL. - */ - @Override - public T getResource(String href, Class clazz) { - return this.dataStore.getResource(href, clazz); - } - - @Override - public T create(String parentHref, T resource) { - return this.dataStore.create(parentHref, resource); - } - - @Override - public void save(String href, T resource) { - this.dataStore.save(href, resource); - } - - @Override - public void delete(String href, T resource) { - this.dataStore.delete(href, resource); - } - - @Override - public RequestBuilder http() { - return this.dataStore.http(); - } - - @Override - public boolean isReady(Supplier methodReference) { - return this.dataStore.isReady(methodReference); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/client/DefaultClientBuilder.java b/impl/src/main/java/com/okta/sdk/impl/client/DefaultClientBuilder.java index f313478c649..4a7b0456203 100644 --- a/impl/src/main/java/com/okta/sdk/impl/client/DefaultClientBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/client/DefaultClientBuilder.java @@ -16,9 +16,13 @@ */ package com.okta.sdk.impl.client; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.okta.commons.configcheck.ConfigurationValidator; -import com.okta.commons.http.RequestExecutorFactory; -import com.okta.commons.http.config.BaseUrlResolver; +import com.okta.commons.http.config.Proxy; import com.okta.commons.lang.Assert; import com.okta.commons.lang.Classes; import com.okta.commons.lang.Strings; @@ -29,10 +33,8 @@ import com.okta.sdk.cache.Caches; import com.okta.sdk.client.AuthenticationScheme; import com.okta.sdk.client.AuthorizationMode; -import com.okta.sdk.client.Client; import com.okta.sdk.client.ClientBuilder; -import com.okta.commons.http.config.Proxy; -import com.okta.sdk.impl.api.ClientCredentialsResolver; +import com.okta.sdk.error.ErrorHandler; import com.okta.sdk.impl.api.DefaultClientCredentialsResolver; import com.okta.sdk.impl.config.ClientConfiguration; import com.okta.sdk.impl.config.EnvironmentVariablesPropertiesSource; @@ -41,7 +43,8 @@ import com.okta.sdk.impl.config.ResourcePropertiesSource; import com.okta.sdk.impl.config.SystemPropertiesSource; import com.okta.sdk.impl.config.YAMLPropertiesSource; -import com.okta.sdk.impl.http.authc.RequestAuthenticatorFactory; +import com.okta.sdk.impl.serializer.UserProfileSerializer; +import com.okta.sdk.impl.deserializer.UserProfileDeserializer; import com.okta.sdk.impl.io.ClasspathResource; import com.okta.sdk.impl.io.DefaultResourceFactory; import com.okta.sdk.impl.io.Resource; @@ -51,12 +54,33 @@ import com.okta.sdk.impl.oauth2.OAuth2ClientCredentials; import com.okta.sdk.impl.util.ConfigUtil; import com.okta.sdk.impl.util.DefaultBaseUrlResolver; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.ProxyAuthenticationStrategy; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.openapitools.client.ApiClient; +import org.openapitools.client.model.UserProfile; +import org.openapitools.jackson.nullable.JsonNullableModule; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import java.io.*; +import org.springframework.http.MediaType; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -65,9 +89,16 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.security.PrivateKey; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; /** *

    The default {@link ClientBuilder} implementation. This looks for configuration files @@ -98,14 +129,11 @@ public class DefaultClientBuilder implements ClientBuilder { private static final String OKTA_YAML = "okta.yaml"; private static final String OKTA_PROPERTIES = "okta.properties"; - private static final String OKTA_REQUEST_EXECUTOR_PREFIX = "okta.client.requestExecutor."; - private CacheManager cacheManager; private ClientCredentials clientCredentials; private boolean allowNonHttpsForTesting = false; private ClientConfiguration clientConfig = new ClientConfiguration(); - private RequestExecutorFactory requestExecutorFactory; private AccessTokenRetrieverService accessTokenRetrieverService; @@ -153,7 +181,7 @@ else if (SYSPROPS_TOKEN.equalsIgnoreCase(location)) { } if (Strings.hasText(props.get(DEFAULT_CLIENT_CACHE_ENABLED_PROPERTY_NAME))) { - clientConfig.setCacheManagerEnabled(Boolean.valueOf(props.get(DEFAULT_CLIENT_CACHE_ENABLED_PROPERTY_NAME))); + clientConfig.setCacheManagerEnabled(Boolean.parseBoolean(props.get(DEFAULT_CLIENT_CACHE_ENABLED_PROPERTY_NAME))); } if (Strings.hasText(props.get(DEFAULT_CLIENT_CACHE_TTL_PROPERTY_NAME))) { @@ -185,7 +213,7 @@ else if (SYSPROPS_TOKEN.equalsIgnoreCase(location)) { } if (Strings.hasText(props.get(DEFAULT_CLIENT_TESTING_DISABLE_HTTPS_CHECK_PROPERTY_NAME))) { - allowNonHttpsForTesting = Boolean.valueOf(props.get(DEFAULT_CLIENT_TESTING_DISABLE_HTTPS_CHECK_PROPERTY_NAME)); + allowNonHttpsForTesting = Boolean.parseBoolean(props.get(DEFAULT_CLIENT_TESTING_DISABLE_HTTPS_CHECK_PROPERTY_NAME)); } if (Strings.hasText(props.get(DEFAULT_CLIENT_ORG_URL_PROPERTY_NAME))) { @@ -248,27 +276,6 @@ else if (SYSPROPS_TOKEN.equalsIgnoreCase(location)) { if (Strings.hasText(props.get(DEFAULT_CLIENT_RETRY_MAX_ATTEMPTS_PROPERTY_NAME))) { clientConfig.setRetryMaxAttempts(Integer.parseInt(props.get(DEFAULT_CLIENT_RETRY_MAX_ATTEMPTS_PROPERTY_NAME))); } - - clientConfig.setRequestExecutorParams( - props - .entrySet().stream() - .filter(x -> x.getKey().toLowerCase().startsWith(OKTA_REQUEST_EXECUTOR_PREFIX.toLowerCase())) - .collect( - Collectors.toMap( - k -> { - //get property key, cut 'okta.client.requestExecutor.' and make it camelCase - String camelCaseString = Arrays.stream(k.getKey() - .substring(OKTA_REQUEST_EXECUTOR_PREFIX.length()) - .split("\\.")) - .map(word -> word.substring(0, 1).toUpperCase() + word.substring(1)) - .collect(Collectors.joining("")); - return camelCaseString.substring(0, 1).toLowerCase() + camelCaseString.substring(1); - }, - v -> v.getValue(), - (oldValue, newValue) -> newValue - ) - ) - ); } @Override @@ -303,24 +310,6 @@ public ClientBuilder setClientCredentials(ClientCredentials clientCredentials) { return this; } - public ClientBuilder setRequestAuthenticatorFactory(RequestAuthenticatorFactory factory) { - Assert.notNull(factory, "factory argument cannot be null"); - this.clientConfig.setRequestAuthenticatorFactory(factory); - return this; - } - - public ClientBuilder setClientCredentialsResolver(ClientCredentialsResolver clientCredentialsResolver) { - Assert.notNull(clientCredentialsResolver, "clientCredentialsResolver must not be null."); - this.clientConfig.setClientCredentialsResolver(clientCredentialsResolver); - return this; - } - - public ClientBuilder setBaseUrlResolver(BaseUrlResolver baseUrlResolver) { - Assert.notNull(baseUrlResolver, "baseUrlResolver must not be null"); - this.clientConfig.setBaseUrlResolver(baseUrlResolver); - return this; - } - @Override public ClientBuilder setRetryMaxElapsed(int maxElapsed) { this.clientConfig.setRetryMaxElapsed(maxElapsed); @@ -334,13 +323,8 @@ public ClientBuilder setRetryMaxAttempts(int maxAttempts) { } @Override - public ClientBuilder setRequestExecutorFactory(RequestExecutorFactory requestExecutorFactory) { - this.requestExecutorFactory = requestExecutorFactory; - return this; - } + public ApiClient build() { - @Override - public Client build() { if (!this.clientConfig.isCacheManagerEnabled()) { log.debug("CacheManager disabled. Defaulting to DisabledCacheManager"); this.cacheManager = Caches.newDisabledCacheManager(); @@ -348,8 +332,8 @@ public Client build() { log.debug("No CacheManager configured. Defaulting to in-memory CacheManager with default TTL and TTI of five minutes."); CacheManagerBuilder cacheManagerBuilder = Caches.newCacheManager() - .withDefaultTimeToIdle(this.clientConfig.getCacheManagerTti(), TimeUnit.SECONDS) - .withDefaultTimeToLive(this.clientConfig.getCacheManagerTtl(), TimeUnit.SECONDS); + .withDefaultTimeToIdle(this.clientConfig.getCacheManagerTti(), TimeUnit.SECONDS) + .withDefaultTimeToLive(this.clientConfig.getCacheManagerTtl(), TimeUnit.SECONDS); if (this.clientConfig.getCacheManagerCaches().size() > 0) { for (CacheConfigurationBuilder builder : this.clientConfig.getCacheManagerCaches().values()) { cacheManagerBuilder.withCache(builder); @@ -360,22 +344,28 @@ public Client build() { } if (this.clientConfig.getBaseUrlResolver() == null) { - ConfigurationValidator.assertOrgUrl(this.clientConfig.getBaseUrl(), allowNonHttpsForTesting); + ConfigurationValidator.validateOrgUrl(this.clientConfig.getBaseUrl(), allowNonHttpsForTesting); this.clientConfig.setBaseUrlResolver(new DefaultBaseUrlResolver(this.clientConfig.getBaseUrl())); } + ApiClient apiClient = new ApiClient(restTemplate(this.clientConfig), this.cacheManager); + if (!isOAuth2Flow()) { if (this.clientConfig.getClientCredentialsResolver() == null && this.clientCredentials != null) { this.clientConfig.setClientCredentialsResolver(new DefaultClientCredentialsResolver(this.clientCredentials)); } else if (this.clientConfig.getClientCredentialsResolver() == null) { this.clientConfig.setClientCredentialsResolver(new DefaultClientCredentialsResolver(this.clientConfig)); } + + apiClient.setBasePath(this.clientConfig.getBaseUrl()); + apiClient.setApiKeyPrefix("SSWS"); + apiClient.setApiKey((String) this.clientConfig.getClientCredentialsResolver().getClientCredentials().getCredentials()); } else { this.clientConfig.setAuthenticationScheme(AuthenticationScheme.OAUTH2_PRIVATE_KEY); validateOAuth2ClientConfig(this.clientConfig); - accessTokenRetrieverService = new AccessTokenRetrieverServiceImpl(clientConfig); + accessTokenRetrieverService = new AccessTokenRetrieverServiceImpl(clientConfig, apiClient); OAuth2ClientCredentials oAuth2ClientCredentials = new OAuth2ClientCredentials(accessTokenRetrieverService); @@ -383,9 +373,7 @@ public Client build() { this.clientConfig.setClientCredentialsResolver(new DefaultClientCredentialsResolver(oAuth2ClientCredentials)); } - return requestExecutorFactory == null - ? new DefaultClient(clientConfig, cacheManager) - : new DefaultClient(clientConfig, cacheManager, requestExecutorFactory.create(clientConfig)); + return apiClient; } /** @@ -411,6 +399,65 @@ private void validateOAuth2ClientConfig(ClientConfiguration clientConfiguration) } } + private RestTemplate restTemplate(ClientConfiguration clientConfig) { + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new JsonNullableModule()); + + SimpleModule module = new SimpleModule(); + module.addSerializer(UserProfile.class, new UserProfileSerializer()); + module.addDeserializer(UserProfile.class, new UserProfileDeserializer()); + objectMapper.registerModule(module); + + MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = + new MappingJackson2HttpMessageConverter(objectMapper); + + mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList( + MediaType.APPLICATION_JSON, + MediaType.parseMediaType("application/x-pem-file"), + MediaType.parseMediaType("application/x-x509-ca-cert"), + MediaType.parseMediaType("application/pkix-cert"))); + + List> messageConverters = new ArrayList<>(); + messageConverters.add(mappingJackson2HttpMessageConverter); + + RestTemplate restTemplate = new RestTemplate(messageConverters); + restTemplate.setErrorHandler(new ErrorHandler()); + restTemplate.setRequestFactory(requestFactory(clientConfig)); + + return restTemplate; + } + + private HttpComponentsClientHttpRequestFactory requestFactory(ClientConfiguration clientConfig) { + + final HttpClientBuilder clientBuilder = HttpClientBuilder.create(); + + if (clientConfig.getProxy() != null) { + clientBuilder.useSystemProperties(); + clientBuilder.setProxy(new HttpHost(clientConfig.getProxyHost(), clientConfig.getProxyPort())); + final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + AuthScope authScope = new AuthScope(clientConfig.getProxyHost(), clientConfig.getProxyPort()); + UsernamePasswordCredentials usernamePasswordCredentials = + new UsernamePasswordCredentials(clientConfig.getProxyUsername(), clientConfig.getProxyPassword()); + credentialsProvider.setCredentials(authScope, usernamePasswordCredentials); + clientBuilder.setDefaultCredentialsProvider(credentialsProvider); + clientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy()); + } + + final CloseableHttpClient httpClient = clientBuilder.build(); + + final HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); + clientHttpRequestFactory.setHttpClient(httpClient); + clientHttpRequestFactory.setConnectionRequestTimeout(clientConfig.getConnectionTimeout() * 1000); + clientHttpRequestFactory.setConnectTimeout(clientConfig.getConnectionTimeout() * 1000); + clientHttpRequestFactory.setReadTimeout(clientConfig.getConnectionTimeout() * 1000); + + return clientHttpRequestFactory; + } + @Override public ClientBuilder setOrgUrl(String baseUrl) { ConfigurationValidator.assertOrgUrl(baseUrl, allowNonHttpsForTesting); diff --git a/impl/src/main/java/com/okta/sdk/impl/config/ClientConfiguration.java b/impl/src/main/java/com/okta/sdk/impl/config/ClientConfiguration.java index afd3df36e98..3a3fb663ef2 100644 --- a/impl/src/main/java/com/okta/sdk/impl/config/ClientConfiguration.java +++ b/impl/src/main/java/com/okta/sdk/impl/config/ClientConfiguration.java @@ -16,7 +16,6 @@ */ package com.okta.sdk.impl.config; -import com.okta.commons.http.authc.RequestAuthenticator; import com.okta.commons.http.config.BaseUrlResolver; import com.okta.commons.http.config.HttpClientConfiguration; import com.okta.commons.lang.Strings; @@ -24,8 +23,6 @@ import com.okta.sdk.client.AuthenticationScheme; import com.okta.sdk.client.AuthorizationMode; import com.okta.sdk.impl.api.ClientCredentialsResolver; -import com.okta.sdk.impl.http.authc.DefaultRequestAuthenticatorFactory; -import com.okta.sdk.impl.http.authc.RequestAuthenticatorFactory; import java.util.HashSet; import java.util.LinkedHashMap; @@ -49,7 +46,6 @@ public class ClientConfiguration extends HttpClientConfiguration { private long cacheManagerTtl; private long cacheManagerTti; private Map cacheManagerCaches = new LinkedHashMap<>(); - private RequestAuthenticatorFactory requestAuthenticatorFactory = new DefaultRequestAuthenticatorFactory(); private AuthenticationScheme authenticationScheme; private BaseUrlResolver baseUrlResolver; private AuthorizationMode authorizationMode; @@ -82,14 +78,6 @@ public void setAuthenticationScheme(AuthenticationScheme authenticationScheme) { this.authenticationScheme = authenticationScheme; } - public RequestAuthenticatorFactory getRequestAuthenticatorFactory() { - return requestAuthenticatorFactory; - } - - public void setRequestAuthenticatorFactory(RequestAuthenticatorFactory requestAuthenticatorFactory) { - this.requestAuthenticatorFactory = requestAuthenticatorFactory; - } - public BaseUrlResolver getBaseUrlResolver() { return baseUrlResolver; } @@ -186,17 +174,6 @@ public void setCacheManagerTtl(long cacheManagerTtl) { this.cacheManagerTtl = cacheManagerTtl; } - @Override - public RequestAuthenticator getRequestAuthenticator() { - RequestAuthenticator requestAuthenticator = super.getRequestAuthenticator(); - - if (requestAuthenticator == null) { - requestAuthenticator = requestAuthenticatorFactory.create(authenticationScheme, this.getClientCredentialsResolver().getClientCredentials()); - } - - return requestAuthenticator; - } - @Override public String getBaseUrl() { String baseUrl = super.getBaseUrl(); @@ -225,5 +202,4 @@ public String toString() { ", proxy=" + getProxy() + " }"; } - -} +} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/deserializer/UserProfileDeserializer.java b/impl/src/main/java/com/okta/sdk/impl/deserializer/UserProfileDeserializer.java new file mode 100644 index 00000000000..b83fe9c2b6c --- /dev/null +++ b/impl/src/main/java/com/okta/sdk/impl/deserializer/UserProfileDeserializer.java @@ -0,0 +1,189 @@ +/* + * Copyright 2022-Present Okta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.okta.sdk.impl.deserializer; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.openapitools.client.model.UserProfile; + +import java.io.IOException; +import java.util.Map; + +public class UserProfileDeserializer extends StdDeserializer { + + private static final long serialVersionUID = -6166716736969489408L; + + private final ObjectMapper mapper = new ObjectMapper(); + + public UserProfileDeserializer() { + this(null); + } + + public UserProfileDeserializer(Class vc) { + super(vc); + } + + @Override + public UserProfile deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + + JsonNode node = jp.getCodec().readTree(jp); + + Map profileMap = mapper.convertValue(node, new TypeReference>(){}); + + UserProfile userProfile = new UserProfile(); + + for (Map.Entry entry : profileMap.entrySet()) { + + String key = entry.getKey(); + String value = String.valueOf(entry.getValue()); + + switch (key) { + case UserProfile.JSON_PROPERTY_CITY: + userProfile.setCity(value); + break; + + case UserProfile.JSON_PROPERTY_COST_CENTER: + userProfile.setCostCenter(value); + break; + + case UserProfile.JSON_PROPERTY_COUNTRY_CODE: + userProfile.setCountryCode(value); + break; + + case UserProfile.JSON_PROPERTY_DEPARTMENT: + userProfile.setDepartment(value); + break; + + case UserProfile.JSON_PROPERTY_DISPLAY_NAME: + userProfile.setDisplayName(value); + break; + + case UserProfile.JSON_PROPERTY_DIVISION: + userProfile.setDivision(value); + break; + + case UserProfile.JSON_PROPERTY_EMAIL: + userProfile.setEmail(value); + break; + + case UserProfile.JSON_PROPERTY_EMPLOYEE_NUMBER: + userProfile.setEmployeeNumber(value); + break; + + case UserProfile.JSON_PROPERTY_FIRST_NAME: + userProfile.setFirstName(value); + break; + + case UserProfile.JSON_PROPERTY_HONORIFIC_PREFIX: + userProfile.setHonorificPrefix(value); + break; + + case UserProfile.JSON_PROPERTY_HONORIFIC_SUFFIX: + userProfile.setHonorificSuffix(value); + break; + + case UserProfile.JSON_PROPERTY_LAST_NAME: + userProfile.setLastName(value); + break; + + case UserProfile.JSON_PROPERTY_LOCALE: + userProfile.setLocale(value); + break; + + case UserProfile.JSON_PROPERTY_LOGIN: + userProfile.setLogin(value); + break; + + case UserProfile.JSON_PROPERTY_MANAGER: + userProfile.setManager(value); + break; + + case UserProfile.JSON_PROPERTY_MANAGER_ID: + userProfile.setManagerId(value); + break; + + case UserProfile.JSON_PROPERTY_MIDDLE_NAME: + userProfile.setMiddleName(value); + break; + + case UserProfile.JSON_PROPERTY_MOBILE_PHONE: + userProfile.setMobilePhone(value); + break; + + case UserProfile.JSON_PROPERTY_NICK_NAME: + userProfile.setNickName(value); + break; + + case UserProfile.JSON_PROPERTY_ORGANIZATION: + userProfile.setOrganization(value); + break; + + case UserProfile.JSON_PROPERTY_POSTAL_ADDRESS: + userProfile.setPostalAddress(value); + break; + + case UserProfile.JSON_PROPERTY_PREFERRED_LANGUAGE: + userProfile.setPreferredLanguage(value); + break; + + case UserProfile.JSON_PROPERTY_PRIMARY_PHONE: + userProfile.setPrimaryPhone(value); + break; + + case UserProfile.JSON_PROPERTY_PROFILE_URL: + userProfile.setProfileUrl(value); + break; + + case UserProfile.JSON_PROPERTY_SECOND_EMAIL: + userProfile.setSecondEmail(value); + break; + + case UserProfile.JSON_PROPERTY_STATE: + userProfile.setState(value); + break; + + case UserProfile.JSON_PROPERTY_STREET_ADDRESS: + userProfile.setStreetAddress(value); + break; + + case UserProfile.JSON_PROPERTY_TIMEZONE: + userProfile.setTimezone(value); + break; + + case UserProfile.JSON_PROPERTY_TITLE: + userProfile.setTitle(value); + break; + + case UserProfile.JSON_PROPERTY_USER_TYPE: + userProfile.setUserType(value); + break; + + case UserProfile.JSON_PROPERTY_ZIP_CODE: + userProfile.setZipCode(value); + break; + + default: + userProfile.getAdditionalProperties().put(key, value); + } + } + + return userProfile; + } +} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapCreator.java b/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapCreator.java deleted file mode 100644 index e27ec4034ca..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapCreator.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import java.util.Map; - -/** - *

    - * This interface defines the method used to create a cache map. - *

    - * @since 0.5.0 - * @see DefaultCacheMapCreator - */ -public interface CacheMapCreator { - - /** - * Creates a cache map. - * - * @return the created cache map. - * - * @see DefaultCacheMapCreator#create() - */ - Map create(); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapCreatorFactory.java b/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapCreatorFactory.java deleted file mode 100644 index 372bfcaf5eb..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapCreatorFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.QueryString; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -/** - *

    - * This interface defines the method to create a {@link CacheMapCreator} based on the provided arguments. - *

    - * @since 0.5.0 - */ -public interface CacheMapCreatorFactory { - - /** - *

    - * Creates a {@link CacheMapCreator} based on the provided arguments. - *

    - * @param clazz the class used to determined the type of {@link CacheMapCreator} to create. - * @param data the data map used to create the {@link CacheMapCreator}. - * @param queryString the query string used to create the {@link CacheMapCreator}. - * - * @return a new {@link CacheMapCreator} instance. - */ - CacheMapCreator create(Class clazz, Map data, QueryString queryString); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapInitializer.java b/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapInitializer.java deleted file mode 100644 index d76d594ac08..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/CacheMapInitializer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.QueryString; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -/** - *

    - * Interface used to define the method to initialize a cache map. Used in the {@link DefaultDataStore}. - *

    - * @since 0.5.0 - */ -public interface CacheMapInitializer { - - /** - * Used to initialize a cache map based on the provided class, data and query string. - * - * @param clazz the resource class that will be used to identify the type of resource. - * @param data the data to be cached that should be analyzed to initialize the map. - * @param queryString the query string to be analyzed to initialize the map. - * @return the initialized map. - */ - Map initialize(Class clazz, Map data, QueryString queryString); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/CacheRegionNameResolver.java b/impl/src/main/java/com/okta/sdk/impl/ds/CacheRegionNameResolver.java deleted file mode 100644 index 119108f8068..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/CacheRegionNameResolver.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.sdk.resource.Resource; - -/** - * @since 0.5.0 - */ -public interface CacheRegionNameResolver { - - String getCacheRegionName(Class clazz); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheKey.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheKey.java deleted file mode 100644 index d415bcf3d80..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheKey.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.QueryString; -import com.okta.commons.lang.Assert; -import com.okta.commons.lang.Collections; -import com.okta.commons.lang.Strings; - -/** - * @since 0.5.0 - */ -public class DefaultCacheKey { - - private final String url; - - public DefaultCacheKey(String href, QueryString queryString) { - Assert.notNull(href, "href argument cannot be null."); - - String tmpUrl = href; - QueryString qs = queryString; - - int questionMarkIndex = href.lastIndexOf('?'); - if (questionMarkIndex >= 0) { - tmpUrl = href.substring(0, questionMarkIndex); - String after = href.substring(questionMarkIndex + 1); - - if (Strings.hasLength(after)) { - qs = new QueryString(queryString); //create a copy so we don't manipulate the argument - //the query values from the href portion are explicit and therefore take precedence over - //any query string values passed in as a separate argument: - QueryString queryStringFromHref = QueryString.create(after); - qs.putAll(queryStringFromHref); - } - } - - if (!Collections.isEmpty(qs)) { - tmpUrl += "?" + qs.toString(); - } - - this.url = tmpUrl; - } - - @Override - public String toString() { - return url; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (o instanceof DefaultCacheKey) { - DefaultCacheKey other = (DefaultCacheKey) o; - return url.equals(other.url); - } - return false; - } - - @Override - public int hashCode() { - return url.hashCode(); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapCreator.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapCreator.java deleted file mode 100644 index 998bb10b52e..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapCreator.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.lang.Assert; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * @since 0.5.0 - */ -public class DefaultCacheMapCreator implements CacheMapCreator { - - private final Map data; - - public DefaultCacheMapCreator(Map data) { - Assert.notEmpty(data, "Data cannot be null or empty."); - this.data = data; - } - - /** - * Creates an empty cache map with the initial size being the size of the - * data map provided in the constructor. - * - * @return an empty cache map with the initial size being the size of the - * provided data. - */ - @Override - public Map create() { - return new LinkedHashMap<>(data.size()); - } - - public Map getData() { - return data; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapCreatorFactory.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapCreatorFactory.java deleted file mode 100644 index debe3f8cca3..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapCreatorFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.QueryString; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -/** - * @since 0.5.0 - * @see CacheMapCreator - */ -public class DefaultCacheMapCreatorFactory implements CacheMapCreatorFactory { - - /** - *

    - * Creates a {@link CacheMapCreator} based on the provided arguments. - *

    - * @param clazz the class used to determined the type of {@link CacheMapCreator} to create. - * @param data the data map used to create the {@link CacheMapCreator}. - * @param queryString the query string used to create the {@link CacheMapCreator}. - * - * @return a new {@link CacheMapCreator} instance. - */ - @Override - public CacheMapCreator create(Class clazz, Map data, QueryString queryString) { - - return new DefaultCacheMapCreator(data); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapInitializer.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapInitializer.java deleted file mode 100644 index e367a838c65..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheMapInitializer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.QueryString; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -/** - * @since 0.5.0 - * @see CacheMapCreatorFactory - */ -public class DefaultCacheMapInitializer implements CacheMapInitializer { - - private final CacheMapCreatorFactory cacheMapCreatorFactory; - - public DefaultCacheMapInitializer() { - cacheMapCreatorFactory = new DefaultCacheMapCreatorFactory(); - } - - /** - *

    - * Used to initialize a cache map based on the provided class, data and query string. - *

    - *

    - * It uses the {@link CacheMapCreatorFactory} to initialize a map. - *

    - * - * @param clazz the resource class that will be used to identify the type of resource. - * @param data the data to be cached that should be analyzed to initialize the map. - * @param queryString the query string to be analyzed to initialize the map. - * @return the initialized map. - * - * @see CacheMapCreatorFactory#create(Class, Map, QueryString) - */ - @Override - public Map initialize(Class clazz, Map data, QueryString queryString) { - CacheMapCreator creator = cacheMapCreatorFactory.create(clazz, data, queryString); - return creator.create(); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheRegionNameResolver.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheRegionNameResolver.java deleted file mode 100644 index af7b7490076..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultCacheRegionNameResolver.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.lang.Assert; -import com.okta.sdk.resource.Resource; - -/** - * @since 0.5.0 - */ -public class DefaultCacheRegionNameResolver implements CacheRegionNameResolver { - - @Override - public String getCacheRegionName(Class clazz) { - Assert.notNull(clazz, "Class argument cannot be null."); - Class iface = DefaultResourceFactory.getInterfaceClass(clazz); - return iface.getName(); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultDataStore.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultDataStore.java deleted file mode 100644 index 222ffec04a1..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultDataStore.java +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.DefaultRequest; -import com.okta.commons.http.HttpException; -import com.okta.commons.http.HttpHeaders; -import com.okta.commons.http.HttpMethod; -import com.okta.commons.http.MediaType; -import com.okta.commons.http.QueryString; -import com.okta.commons.http.Request; -import com.okta.commons.http.RequestExecutor; -import com.okta.commons.http.Response; -import com.okta.commons.http.config.BaseUrlResolver; -import com.okta.commons.lang.ApplicationInfo; -import com.okta.sdk.authc.credentials.ClientCredentials; -import com.okta.sdk.cache.CacheManager; -import com.okta.sdk.ds.DataStore; -import com.okta.sdk.ds.RequestBuilder; -import com.okta.sdk.impl.api.ClientCredentialsResolver; -import com.okta.sdk.impl.cache.DisabledCacheManager; -import com.okta.sdk.impl.ds.cache.CacheResolver; -import com.okta.sdk.impl.ds.cache.DefaultCacheResolver; -import com.okta.sdk.impl.ds.cache.DefaultResourceCacheStrategy; -import com.okta.sdk.impl.ds.cache.ReadCacheFilter; -import com.okta.sdk.impl.ds.cache.ResourceCacheStrategy; -import com.okta.sdk.impl.ds.cache.WriteCacheFilter; -import com.okta.sdk.impl.error.DefaultError; -import com.okta.sdk.impl.http.CanonicalUri; -import com.okta.sdk.impl.http.HttpHeadersHolder; -import com.okta.sdk.impl.http.support.DefaultCanonicalUri; -import com.okta.sdk.impl.resource.AbstractInstanceResource; -import com.okta.sdk.impl.resource.AbstractResource; -import com.okta.sdk.impl.resource.HalResourceHrefResolver; -import com.okta.sdk.impl.resource.ReferenceFactory; -import com.okta.sdk.impl.util.DefaultBaseUrlResolver; -import com.okta.commons.lang.Assert; -import com.okta.commons.lang.Collections; -import com.okta.commons.lang.Strings; -import com.okta.sdk.resource.CollectionResource; -import com.okta.sdk.resource.FileResource; -import com.okta.sdk.resource.Resource; -import com.okta.sdk.resource.ResourceException; -import com.okta.sdk.resource.VoidResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -import static com.okta.commons.http.HttpHeaders.OKTA_USER_AGENT; -import static com.okta.commons.http.HttpHeaders.USER_AGENT; -import static com.okta.commons.http.HttpHeaders.OKTA_AGENT; - -/** - * @since 0.5.0 - */ -public class DefaultDataStore implements InternalDataStore { - - private static final Logger log = LoggerFactory.getLogger(DefaultDataStore.class); - private static final Logger requestLog = LoggerFactory.getLogger(DataStore.class.getName() + "-request"); - - private static final String HREF_REQD_MSG = "'save' may only be called on objects that have already been " + - "persisted and have an existing 'href' attribute."; - - private final RequestExecutor requestExecutor; - private final ResourceFactory resourceFactory; - private final MapMarshaller mapMarshaller; - private final CacheManager cacheManager; - private final ResourceConverter resourceConverter; - private final List filters; - private final ClientCredentialsResolver clientCredentialsResolver; - private final BaseUrlResolver baseUrlResolver; - - private static final String USER_AGENT_STRING = ApplicationInfo.get().entrySet().stream() - .map(e -> e.getKey() + "/" + e.getValue()) - .collect(Collectors.joining(" ")); - - public DefaultDataStore(RequestExecutor requestExecutor, String baseUrl, ClientCredentialsResolver clientCredentialsResolver) { - this(requestExecutor, new DefaultBaseUrlResolver(baseUrl), clientCredentialsResolver, new DisabledCacheManager()); - } - - public DefaultDataStore(RequestExecutor requestExecutor, BaseUrlResolver baseUrlResolver, ClientCredentialsResolver clientCredentialsResolver, CacheManager cacheManager) { - Assert.notNull(baseUrlResolver, "baseUrlResolver cannot be null"); - Assert.notNull(requestExecutor, "RequestExecutor cannot be null."); - Assert.notNull(clientCredentialsResolver, "clientCredentialsResolver cannot be null."); - Assert.notNull(cacheManager, "CacheManager cannot be null. Use the DisabledCacheManager if you wish to turn off caching."); - this.requestExecutor = requestExecutor; - this.baseUrlResolver = baseUrlResolver; - this.cacheManager = cacheManager; - this.resourceFactory = new DefaultResourceFactory(this); - this.mapMarshaller = new JacksonMapMarshaller(); - CacheResolver cacheResolver = new DefaultCacheResolver(this.cacheManager, new DefaultCacheRegionNameResolver()); - this.clientCredentialsResolver = clientCredentialsResolver; - - ReferenceFactory referenceFactory = new ReferenceFactory(); - this.resourceConverter = new DefaultResourceConverter(referenceFactory); - - this.filters = new ArrayList<>(); - - if (isCachingEnabled()) { - ResourceCacheStrategy cacheStrategy = new DefaultResourceCacheStrategy(new HalResourceHrefResolver(), cacheResolver); - this.filters.add(new ReadCacheFilter(cacheStrategy)); - this.filters.add(new WriteCacheFilter(cacheStrategy)); - } - } - - @Override - public ClientCredentials getClientCredentials() { - return this.clientCredentialsResolver.getClientCredentials(); - } - - @Override - public CacheManager getCacheManager() { - return this.cacheManager; - } - - /* ===================================================================== - Resource Instantiation - ===================================================================== */ - - @Override - public T instantiate(Class clazz) { - return this.resourceFactory.instantiate(clazz); - } - - @Override - public T instantiate(Class clazz, Map properties) { - return this.resourceFactory.instantiate(clazz, properties); - } - - private T instantiate(Class clazz, Map properties, QueryString qs) { - if (CollectionResource.class.isAssignableFrom(clazz)) { - //only collections can support a query string constructor argument: - return this.resourceFactory.instantiate(clazz, properties, qs); - } - //otherwise it must be an instance resource, so use the two-arg constructor: - return this.resourceFactory.instantiate(clazz, properties); - } - - /* ===================================================================== - Resource Retrieval - ===================================================================== */ - - @SuppressWarnings("unchecked") - @Override - public T getResource(String href, Class clazz) { - return getResource(href, clazz, null); - } - - @Override - public T getResource(String href, Class clazz, Map queryParameters) { - return getResource(href, clazz, queryParameters, null); - } - - @Override - public T getResource(String href, Class clazz, Map queryParameters, Map> headerParameters) { - ResourceDataResult result = getResourceData(href, clazz, queryParameters, headers(headerParameters)); - T resource = instantiate(clazz, result.getData(), result.getUri().getQuery()); - - resource.setResourceHref(href); - - return resource; - } - - @Override - public InputStream getRawResponse(String href, Map queryParameters, Map> headerParameters) { - - Assert.hasText(href, "href argument cannot be null or empty."); - - CanonicalUri uri = canonicalize(href, queryParameters); - Request getRequest = new DefaultRequest(HttpMethod.GET, uri.getAbsolutePath(), uri.getQuery(), headers(headerParameters)); - Response getResponse = execute(getRequest); - - return getRawBody(getResponse) - .orElseThrow(() -> new IllegalStateException("Unable to obtain resource data from the API server.")); - } - - @SuppressWarnings("unchecked") - private ResourceDataResult getResourceData(String href, Class clazz, Map queryParameters, HttpHeaders httpHeaders) { - - Assert.hasText(href, "href argument cannot be null or empty."); - Assert.notNull(clazz, "Resource class argument cannot be null."); - - FilterChain chain = new DefaultFilterChain(this.filters, req -> { - - CanonicalUri uri = req.getUri(); - - Request getRequest = new DefaultRequest(HttpMethod.GET, uri.getAbsolutePath(), uri.getQuery(), req.getHttpHeaders()); - Response getResponse = execute(getRequest); - Map body = getBody(getResponse); - - if (Collections.isEmpty(body)) { - throw new IllegalStateException("Unable to obtain resource data from the API server or from cache."); - } - - return new DefaultResourceDataResult(req.getAction(), uri, req.getResourceClass(), (Map)body); - }); - - CanonicalUri uri = canonicalize(href, queryParameters); - ResourceDataRequest req = new DefaultResourceDataRequest(ResourceAction.READ, uri, clazz, new HashMap<>(), httpHeaders); - return chain.filter(req); - } - - private ResourceAction getPostAction(ResourceDataRequest request, Response response) { - int httpStatus = response.getHttpStatus(); - if (httpStatus == 201) { - return ResourceAction.CREATE; - } - // TODO: verify this is an issue with Okta - //Fix for https://github.com/stormpath/stormpath-sdk-java/issues/403 - if (httpStatus == 200) { - return ResourceAction.READ; - } - - return request.getAction(); - } - - /* ===================================================================== - Resource Persistence - ===================================================================== */ - - @SuppressWarnings("unchecked") - @Override - public T create(String parentHref, T resource, T parentResource) { - return (T)create(parentHref, resource, parentResource, resource.getClass()); - } - - @Override - public R create(String parentHref, T resource, T parentResource, Class returnType) { - return create(parentHref, resource, parentResource, returnType, null); - } - - @Override - public R create(String parentHref, T resource, T parentResource, Class returnType, Map queryParameters) { - return create(parentHref, resource, parentResource, returnType, queryParameters, null); - } - - @Override - public R create(String parentHref, T resource, T parentResource, Class returnType, Map queryParameters, Map> headerParameters) { - return save(parentHref, resource, parentResource, headers(headerParameters), returnType, new QueryString(queryParameters), true); - } - - @Override - public R save(String parentHref, T resource, Class returnType, boolean create) { - return save(parentHref, resource, null, headers(null), returnType, new QueryString(), create); - } - - @Override - public void save(T resource) { - save(resource.getResourceHref(), resource); - } - - @Override - public void save(String href, T resource, T parentResource) { - save(href, resource, parentResource, null); - } - - @Override - public void save(String href, T resource, T parentResource, Map queryParameters) { - save(href, resource, parentResource, queryParameters, null); - } - - @Override - public void save(String href, T resource, T parentResource, Map queryParameters, Map> headerParameters) { - Assert.hasText(href, HREF_REQD_MSG); - save(href, resource, parentResource, headers(headerParameters), getResourceClass(resource), new QueryString(queryParameters), false); - } - - @SuppressWarnings("unchecked") - private R save(String href, - final T resource, - final T parentResource, - HttpHeaders requestHeaders, - final Class returnType, - final QueryString qs, - final boolean create) { - Assert.hasText(href, "href argument cannot be null or empty."); - Assert.notNull(resource, "resource argument cannot be null."); - Assert.notNull(returnType, "returnType class cannot be null."); - Assert.isInstanceOf(AbstractResource.class, resource); - Assert.isTrue(!CollectionResource.class.isAssignableFrom(resource.getClass()), "Collections cannot be persisted."); - - final CanonicalUri uri = canonicalize(href, qs); - final AbstractResource abstractResource = (AbstractResource) resource; - // Most Okta endpoints do not support partial update, we can revisit in the future. - final Map props = resourceConverter.convert(abstractResource, false); - - FilterChain chain = new DefaultFilterChain(this.filters, req -> { - - CanonicalUri uri1 = req.getUri(); - String href1 = uri1.getAbsolutePath(); - QueryString qs1 = uri1.getQuery(); - - HttpHeaders httpHeaders = req.getHttpHeaders(); - - // create == POST - HttpMethod method = HttpMethod.POST; - if (!create) { - method = HttpMethod.PUT; - } - - InputStream body; - long length = 0; - if (resource instanceof VoidResource) { - body = new ByteArrayInputStream(new byte[0]); - } else if(resource instanceof FileResource) { - body = new ByteArrayInputStream(new byte[0]); - httpHeaders.add("x-fileLocation", ((FileResource)resource).getLocation()); - httpHeaders.add("x-fileFormDataName", ((FileResource)resource).getFormDataName()); - } else { - ByteArrayOutputStream bodyOut = new ByteArrayOutputStream(); - mapMarshaller.marshal(bodyOut, req.getData()); - body = new ByteArrayInputStream(bodyOut.toByteArray()); - length = bodyOut.size(); - } - - Request request = new DefaultRequest(method, href1, qs1, httpHeaders, body, length); - - Response response = execute(request); - Map responseBody = getBody(response); - - if (Collections.isEmpty(responseBody)) { - // Fix for https://github.com/stormpath/stormpath-sdk-java/issues/218 - // Okta response with 200 for deactivate requests (i.e. /api/v1/apps//lifecycle/deactivate) - if (response.getHttpStatus() == 202 - || response.getHttpStatus() == 200 - || response.getHttpStatus() == 201 - || response.getHttpStatus() == 204) { - //202 means that the request has been accepted for processing, but the processing has not been completed. Therefore we do not have a response setBody. - responseBody = java.util.Collections.emptyMap(); - } else { - throw new IllegalStateException("Unable to obtain resource data from the API server."); - } - } - - ResourceAction responseAction = getPostAction(req, response); - - return new DefaultResourceDataResult(responseAction, uri1, returnType, responseBody); - }); - - ResourceAction action = create ? ResourceAction.CREATE : ResourceAction.UPDATE; - - ResourceDataRequest request = new DefaultResourceDataRequest( - action, - uri, - canonicalizeParent(parentResource), - returnType, - getResourceClass(parentResource), - props, - requestHeaders); - - DefaultResourceDataResult result = (DefaultResourceDataResult) chain.filter(request); - - Map data = result.getData(); - - //ensure the caller's argument is updated with what is returned from the server if the types are the same: - if (returnType.isAssignableFrom(abstractResource.getClass())) { - abstractResource.setInternalProperties(data); - } - - return resourceFactory.instantiate(returnType, data); - } - - /* ===================================================================== - Resource Deletion - ===================================================================== */ - - @Override - public void delete(String href) { - delete(href, (Map) null); - } - - @Override - public void delete(String href, Map queryParameters) { - delete(href, queryParameters, null); - } - - @Override - public void delete(String href, Map queryParameters, Map> headerParameters) { - doDelete(href, VoidResource.class, new QueryString(queryParameters), headers(headerParameters)); - } - - @Override - public void delete(String href, T resource, Map queryParameters, Map> headerParameters) { - doDelete(href != null ? href : resource.getResourceHref(), getResourceClass(resource), new QueryString(queryParameters), headers(headerParameters)); - } - - @Override - public void delete(T resource) { - doDelete(resource.getResourceHref(), resource); - } - - @Override - public void delete(String href, T resource) { - doDelete(href, resource); - } - - private void doDelete(String resourceHref, Class resourceClass, QueryString qs, HttpHeaders httpHeaders) { - - Assert.hasText(resourceHref, "This resource does not have an href value, therefore it cannot be deleted."); - - // if this URL is a partial, then we MUST add the baseUrl - final CanonicalUri uri = canonicalize(resourceHref, qs); - - FilterChain chain = new DefaultFilterChain(this.filters, request -> { - Request deleteRequest = new DefaultRequest(HttpMethod.DELETE, uri.getAbsolutePath(), uri.getQuery(), httpHeaders); - execute(deleteRequest); - //delete requests have HTTP 204 (no content), so just create an empty setBody for the result: - return new DefaultResourceDataResult(request.getAction(), request.getUri(), request.getResourceClass(), new HashMap<>()); - }); - - final CanonicalUri resourceUri = canonicalize(resourceHref, null); - ResourceDataRequest request = new DefaultResourceDataRequest(ResourceAction.DELETE, resourceUri, resourceClass, new HashMap<>()); - chain.filter(request); - } - - private void doDelete(String href, T resource) { - - Assert.notNull(resource, "resource argument cannot be null."); - Assert.isInstanceOf(AbstractResource.class, resource, "Resource argument must be an AbstractResource."); - - doDelete(href != null ? href : resource.getResourceHref(), getResourceClass(resource), null, null); - } - - /* ===================================================================== - Resource Caching - ===================================================================== */ - - protected boolean isCachingEnabled() { - return this.cacheManager != null && !(this.cacheManager instanceof DisabledCacheManager); - } - - /** - * @return the Base URL (i.e. https://api.stormpaht.com/v1) at which the current SDK instance is connected to. - - */ - @Override - public String getBaseUrl() { - return this.baseUrlResolver.getBaseUrl(); - } - - private Response execute(Request request) throws ResourceException { - - applyDefaultRequestHeaders(request); - - Response response = this.requestExecutor.executeRequest(request); - log.trace("Executed HTTP request."); - - if (requestLog.isTraceEnabled()) { - requestLog.trace("Executing request: method: '{}', url: {}", request.getMethod(), request.getResourceUrl()); - } - - if (response.isError()) { - Map body = getBody(response); - - String requestId = response.getHeaders().getOktaRequestId(); - - if (Strings.hasText(requestId)) { - body.put(DefaultError.ERROR_ID.getName(), requestId); - } - - throw new ResourceException(new DefaultError(body) - .setHeaders(response.getHeaders().getXHeaders()) - .setStatus(response.getHttpStatus())); - } - - return response; - } - - private Map getBody(Response response) { - - Assert.notNull(response, "response argument cannot be null."); - - if (response.hasBody() && (MediaType.APPLICATION_JSON.equals(response.getHeaders().getContentType()) - || Strings.endsWithIgnoreCase(String.valueOf(response.getHeaders().getContentType()), "+json"))) { - return mapMarshaller.unmarshal(response.getBody(), response.getHeaders().getLinkMap()); - } - - return java.util.Collections.emptyMap(); - } - - private Optional getRawBody(Response response) { - Assert.notNull(response, "response argument cannot be null."); - return Optional.ofNullable(response.getBody()); - } - - protected void applyDefaultRequestHeaders(Request request) { - if (!request.getHeaders().containsKey("Accept")) { - request.getHeaders().setAccept(java.util.Collections.singletonList(MediaType.APPLICATION_JSON)); - } - - // Get runtime headers from http client - Map> headerMap = HttpHeadersHolder.get(); - String oktaAgentHeaderName = OKTA_AGENT.toLowerCase(Locale.ENGLISH); - if (headerMap != null && headerMap.get(oktaAgentHeaderName) != null) { - List oktaAgents = headerMap.get(oktaAgentHeaderName); - if (oktaAgents != null && !oktaAgents.isEmpty()) { - String oktaAgent = Strings.arrayToDelimitedString(oktaAgents.toArray(), " "); - applyUserAgent(oktaAgent + " " + USER_AGENT_STRING, request); - } - } else { - applyUserAgent(USER_AGENT_STRING, request); - } - - if (request.getHeaders().getContentType() == null && request.getBody() != null) { - // We only add the default content type (application/json) if a content type is not already in the request - request.getHeaders().setContentType(MediaType.APPLICATION_JSON); - } - - // all other headers - if (headerMap != null) { - headerMap.entrySet().stream() - // filter use agent, there is logic to add that above - .filter(entry -> !OKTA_AGENT.equals(entry.getKey())) - .filter(entry -> !USER_AGENT.equals(entry.getKey())) - .forEach(entry -> request.getHeaders().put(entry.getKey(), entry.getValue())); - } - } - - private void applyUserAgent(String userAgentString, Request request) { - - if (request.getHeaders().containsKey(USER_AGENT)) { - request.getHeaders().set(OKTA_USER_AGENT, userAgentString); - } else { - request.getHeaders().set(USER_AGENT, userAgentString); - } - } - - private CanonicalUri canonicalize(String href, Map queryParams) { - href = ensureFullyQualified(href); - return DefaultCanonicalUri.create(href, queryParams); - } - - private CanonicalUri canonicalizeParent(Resource parentResource) { - if (parentResource != null && parentResource.getResourceHref() != null) { - String href = ensureFullyQualified(parentResource.getResourceHref()); - return DefaultCanonicalUri.create(href, null); - } - return null; - } - - private String ensureFullyQualified(String href) { - String value = href; - if (!isFullyQualified(href)) { - value = qualify(href); - } - return value; - } - - private boolean isFullyQualified(String href) { - - if (href == null || href.length() < 5) { - return false; - } - return href.regionMatches(true, 0, "http", 0, 4); - } - - private String qualify(String href) { - StringBuilder sb = new StringBuilder(this.baseUrlResolver.getBaseUrl()); - if (!href.startsWith("/")) { - sb.append("/"); - } - // encode a reference special character - sb.append(href.replace("#", "%23")); - return sb.toString(); - } - - private Class getResourceClass(Resource resource) { - if (AbstractInstanceResource.class.isInstance(resource)) { - return ((AbstractInstanceResource)resource).getResourceClass(); - } - return resource != null ? resource.getClass() : null; - } - - private HttpHeaders headers(Map> headerParameters) { - if (!Collections.isEmpty(headerParameters)) { - HttpHeaders headers = new HttpHeaders(); - headers.putAll(headerParameters); - return headers; - } - return null; - } - - @Override - public RequestBuilder http() { - return new DefaultRequestBuilder(this); - } - - @Override - public boolean isReady(Supplier methodReference) { - try { - return methodReference.get() != null; - } catch (ResourceException | HttpException exception) { - log.error("DataStore is not ready", exception); - return false; - } - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultDiscriminatorRegistry.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultDiscriminatorRegistry.java deleted file mode 100644 index d75646f3ab8..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultDiscriminatorRegistry.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.lang.Classes; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Default implementation of @{link DiscriminatorRegistry} that looks up implementations based on - * the configuration from {@link DiscriminatorConfig}. - * - * @since 0.8.0 - */ -public class DefaultDiscriminatorRegistry implements DiscriminatorRegistry { - - private final Map supportedClassMap = new HashMap<>(); - - public DefaultDiscriminatorRegistry() { - - DiscriminatorConfig.loadConfig().getConfig().forEach((key, value) -> { - Class clazz = Classes.forName(key); - - Map values = value.getValues().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> Classes.forName(e.getValue()))); - supportedClassMap.put(clazz, new AttributeDiscriminationStrategy(value.getFieldName(), values)); - }); - } - - public boolean supportedClass(Class clazz) { - return supportedClassMap.containsKey(clazz); - } - - public

    Class

    resolve(Class

    clazz, Map data) { - - if (supportedClass(clazz)) { - Class

    result = supportedClassMap.get(clazz).resolve(clazz, data); - - // recursive lookup if clazz != result - if (clazz != result) { - return resolve(result, data); - } else { - return result; - } - } - return clazz; - } - - private static class AttributeDiscriminationStrategy { - - private final String key; - private final Map values; - - private AttributeDiscriminationStrategy(String key, Map values) { - this.key = key; - this.values = values; - } - - @SuppressWarnings({"PMD.UnusedPrivateMethod"}) - private

    Class

    resolve(Class

    clazz, Map data) { - - if (data.containsKey(key)) { - Object value = data.get(key); - Class

    result = values.get(value); - if (result != null) { - return result; - } - } - return clazz; - } - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultFilterChain.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultFilterChain.java deleted file mode 100644 index af81786c994..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultFilterChain.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.lang.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -public class DefaultFilterChain implements FilterChain { - - private static final Logger log = LoggerFactory.getLogger(DefaultFilterChain.class); - - private final List filters; - private int index = 0; - private final FilterChain completionHandler; - - public DefaultFilterChain(List filters, FilterChain completionHandler) { - this.filters = filters; - Assert.notNull(completionHandler, "completionHandler cannot be null."); - this.completionHandler = completionHandler; - } - - @Override - public ResourceDataResult filter(ResourceDataRequest request) { - if (this.filters == null || this.filters.size() == this.index) { - //we've reached the end of the wrapped chain, so invoke the original one: - if (log.isTraceEnabled()) { - log.trace("Invoking completion handler."); - } - - return this.completionHandler.filter(request); - } else { - if (log.isTraceEnabled()) { - log.trace("Invoking wrapped filter at index [" + this.index + "]"); - } - return this.filters.get(this.index++).filter(request, this); - } - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultRequestBuilder.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultRequestBuilder.java deleted file mode 100644 index c5ecb3311f5..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultRequestBuilder.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2018-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.HttpHeaders; -import com.okta.sdk.ds.RequestBuilder; -import com.okta.sdk.resource.Resource; -import com.okta.sdk.resource.VoidResource; - -import java.io.InputStream; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * The default implementation of {@link RequestBuilder}. - * - * @since 1.2.0 - */ -class DefaultRequestBuilder implements RequestBuilder { - - private final InternalDataStore dataStore; - - private Resource body; - private Map queryParams = new HashMap<>(); - private HttpHeaders headers = new HttpHeaders(); - - DefaultRequestBuilder(InternalDataStore dataStore) { - this.dataStore = dataStore; - this.body = dataStore.instantiate(VoidResource.class); - } - - @Override - public RequestBuilder setBody(Resource resource) { - this.body = resource; - return this; - } - - @Override - public RequestBuilder addQueryParameter(String key, String value) { - queryParams.put(key, value); - return this; - } - - @Override - public RequestBuilder setQueryParameters(Map queryParams) { - this.queryParams.clear(); - if (!com.okta.commons.lang.Collections.isEmpty(queryParams)) { - this.queryParams.putAll(queryParams); - } - return this; - } - - @Override - public RequestBuilder addHeaderParameter(String key, String value) { - this.headers.add(key, value); - return this; - } - - @Override - public RequestBuilder addHeaderParameter(String key, List values) { - this.headers.put(key, values); - return this; - } - - @Override - public RequestBuilder setHeaderParameters(Map> headerParams) { - this.headers.clear(); - if (!com.okta.commons.lang.Collections.isEmpty(headerParams)) { - this.headers.putAll(headerParams); - } - return this; - } - - @Override - public T get(String href, Class type) { - return dataStore.getResource(href, type, queryParams, headers); - } - - @Override - public InputStream getRaw(String href) { - return dataStore.getRawResponse(href, queryParams, headers); - } - - @Override - public void put(String href) { - dataStore.save(href, body, null, queryParams, headers); - } - - @Override - public T post(String href, Class type) { - return dataStore.create(href, body, null, type, queryParams, headers); - } - - @Override - public void delete(String href) { - dataStore.delete(href, queryParams, headers); - } - - // exposed for testing - Resource getBody() { - return body; - } - - Map getQueryParameters() { - return Collections.unmodifiableMap(queryParams); - } - - Map> getHeaderParameters() { - return Collections.unmodifiableMap(headers); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceConverter.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceConverter.java deleted file mode 100644 index 0896fd47c44..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceConverter.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.sdk.impl.resource.AbstractResource; -import com.okta.sdk.impl.resource.ReferenceFactory; -import com.okta.commons.lang.Assert; - -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -/** - * @since 0.5.0 - */ -public class DefaultResourceConverter implements ResourceConverter { - - private final ReferenceFactory referenceFactory; - - public DefaultResourceConverter(ReferenceFactory referenceFactory) { - Assert.notNull(referenceFactory, "referenceFactory cannot be null."); - this.referenceFactory = referenceFactory; - } - - @Override - public Map convert(AbstractResource resource, boolean dirtOnly) { - Assert.notNull(resource, "resource cannot be null."); - - return toMap(resource, dirtOnly); - } - - private LinkedHashMap toMap(final AbstractResource resource, boolean partialUpdate) { - - Set propNames = new HashSet<>(resource.getUpdatedPropertyNames()); - - if (!partialUpdate) { - propNames.addAll(resource.getPropertyNames()); - } - - LinkedHashMap props = new LinkedHashMap<>(propNames.size()); - - for (String propName : propNames) { - Object value = resource.getProperty(propName); - value = toMapValue(propName, value, partialUpdate); - props.put(propName, value); - } - - return props; - } - - private Object toMapValue(final String propName, Object value, boolean dirtyOnly) { - - if (value instanceof AbstractResource) { - return toMap((AbstractResource)value, dirtyOnly); - } - - if (value instanceof Map) { - //Since defaultModel is a map, the DataStore thinks it is a Resource. This causes the code to crash later one as Resources - //do need to have an href property - return this.referenceFactory.createUnmaterializedReference(propName, (Map) value); - } - - return value; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceDataRequest.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceDataRequest.java deleted file mode 100644 index 803e528f303..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceDataRequest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.HttpHeaders; -import com.okta.sdk.impl.http.CanonicalUri; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -public class DefaultResourceDataRequest extends DefaultResourceMessage implements ResourceDataRequest { - - private final CanonicalUri parentUri; - private final Class parentResourceClass; - - public DefaultResourceDataRequest(ResourceAction action, CanonicalUri uri, Class resourceClass, Map data) { - this(action, uri, resourceClass, data, null); - } - - public DefaultResourceDataRequest(ResourceAction action, CanonicalUri uri, Class resourceClass, Map data, HttpHeaders customHeaders) { - this(action, uri, null, resourceClass, null, data, customHeaders); - } - - public DefaultResourceDataRequest(ResourceAction action, CanonicalUri uri, CanonicalUri parentUri, Class resourceClass, Class parentResourceClass, Map data, HttpHeaders customHeaders) { - super(action, uri, resourceClass, data, customHeaders); - this.parentUri = parentUri; - this.parentResourceClass = parentResourceClass; - } - - @Override - public CanonicalUri getParentUri() { - return parentUri; - } - - @Override - public Class getParentResourceClass() { - return parentResourceClass; - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceDataResult.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceDataResult.java deleted file mode 100644 index a762b536399..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceDataResult.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.sdk.impl.http.CanonicalUri; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -//todo - remove this - DefaultResourceMessage currently contains everything necessary -public class DefaultResourceDataResult extends DefaultResourceMessage implements ResourceDataResult { - - public DefaultResourceDataResult(ResourceAction action, CanonicalUri uri, Class resourceClass, Map data) { - super(action, uri, resourceClass, data); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceFactory.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceFactory.java deleted file mode 100644 index 4b7481afa94..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceFactory.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.lang.Classes; -import com.okta.sdk.resource.Resource; - -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.ServiceLoader; -import java.util.Set; -import java.util.stream.Collectors; - -import static java.util.stream.StreamSupport.stream; - -/** - * @since 0.5.0 - */ -public class DefaultResourceFactory implements ResourceFactory { - - private final InternalDataStore dataStore; - - private static final Set SUPPORTED_PACKAGES = getSupportedPackages(); - private static final String IMPL_PACKAGE_NAME_FRAGMENT = "impl"; - private static final String IMPL_PACKAGE_NAME = IMPL_PACKAGE_NAME_FRAGMENT + "."; - private static final String IMPL_CLASS_PREFIX = "Default"; - - private final DiscriminatorRegistry registry = new DefaultDiscriminatorRegistry(); - - public DefaultResourceFactory(InternalDataStore dataStore) { - this.dataStore = dataStore; - } - - @Override - public T instantiate(Class clazz, Object... constructorArgs) { - - if (clazz == null) { - throw new NullPointerException("Resource class cannot be null."); - } - - Class classToResolve = clazz; - - Object[] ctorArgs = createConstructorArgs(constructorArgs); - - if (ctorArgs.length >= 2 && ctorArgs[1] instanceof Map) { - - Map data = (Map) ctorArgs[1]; - if (registry.supportedClass(clazz)) { - classToResolve = registry.resolve(clazz, data); - } - } - - Class implClass = getImplementationClass(classToResolve); - - Constructor ctor; - - if (ctorArgs.length == 1) { - ctor = Classes.getConstructor(implClass, InternalDataStore.class); - } else if (ctorArgs.length == 2) { - ctor = Classes.getConstructor(implClass, InternalDataStore.class, Map.class); - } else { - //collection resource - we want to retain the query parameters (3rd ctor argument): - ctor = Classes.getConstructor(implClass, InternalDataStore.class, Map.class, Map.class); - } - - return Classes.instantiate(ctor, ctorArgs); - } - - private static Class getImplementationClass(Class clazz) { - if (clazz.isInterface()) { - return convertToImplClass(clazz); - } - return clazz; - } - - public static Class getInterfaceClass(Class clazz) { - if (clazz.isInterface()) { - return clazz; - } - return convertToInterfaceClass(clazz); - } - - static Class convertToInterfaceClass(Class clazz) { - String fqcn = clazz.getName(); - - String basePackage = SUPPORTED_PACKAGES.stream() - .filter(fqcn::startsWith) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Could not determine interface for class: '" + fqcn +"'")); - - String afterBase = fqcn.substring(basePackage.length()); - - //e.g. if impl is com.okta.sdk.impl.account.DefaultAccount, 'afterBase' is impl.account.DefaultAccount - - //split interface simple name and the remainder of the package structure: - - if (afterBase.startsWith(IMPL_PACKAGE_NAME)) { - afterBase = afterBase.substring(IMPL_PACKAGE_NAME.length()); - } - - //now afterBase is account.DefaultAccount - - //now append the intermediate package name to the base package: - int index = afterBase.lastIndexOf('.'); - String beforeSimpleName = afterBase.substring(0, index); - - String simpleName = clazz.getSimpleName(); - - //strip off any 'Default' prefix: - index = simpleName.indexOf(IMPL_CLASS_PREFIX); - simpleName = simpleName.substring(index + IMPL_CLASS_PREFIX.length()); - - String ifaceFqcn = basePackage + beforeSimpleName + "." + simpleName; - - return Classes.forName(ifaceFqcn); - } - - @SuppressWarnings("unchecked") - static Class convertToImplClass(Class clazz) { - String implFqcn = constructImplFqcn(clazz); - return Classes.forName(implFqcn); - } - - static String constructImplFqcn(Class clazz) { - String fqcn = clazz.getName(); - - String basePackage = SUPPORTED_PACKAGES.stream() - .filter(fqcn::startsWith) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Could not determine impl for class: '" + fqcn +"'")); - - String afterBase = fqcn.substring(basePackage.length()); - //e.g. if interface is com.okta.sdk.account.Account, 'afterBase' is account.Account - - //split interface simple name and the remainder of the package structure: - - //if this is an impl-module-specific class, strip off the existing 'impl.' package: - if (afterBase.startsWith(IMPL_PACKAGE_NAME)) { - afterBase = afterBase.substring(IMPL_PACKAGE_NAME.length()); - } - - int index = afterBase.lastIndexOf('.'); - - String implFqcn; - - if (index == -1) { - implFqcn = basePackage + IMPL_PACKAGE_NAME_FRAGMENT + "." + IMPL_CLASS_PREFIX + clazz.getSimpleName(); - } else { - String beforeConcreteClassName = afterBase.substring(0, index); - implFqcn = basePackage + IMPL_PACKAGE_NAME_FRAGMENT + "." + - beforeConcreteClassName + "." + IMPL_CLASS_PREFIX + clazz.getSimpleName(); - } - - return implFqcn; - } - - private Object[] createConstructorArgs(Object[] existing) { - int argsLength = existing != null ? existing.length : 0; - argsLength += 1; //account for the 'DataStore' instance that is required for every implementation. - - List args = new ArrayList<>(argsLength); - args.add(this.dataStore); //always first arg - if (existing != null) { - Collections.addAll(args, existing); - } - - return args.toArray(); - } - - private static Set getSupportedPackages() { - Set result = new HashSet<>(); - stream(ServiceLoader.load(ResourceFactoryConfig.class).spliterator(), false) - .map(config -> config.getSupportedPackages().stream() - .map(it -> it + ".") - .collect(Collectors.toSet())) - .forEach(result::addAll); - return result; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceFactoryConfig.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceFactoryConfig.java deleted file mode 100644 index 59dfeded200..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceFactoryConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2018-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import java.util.Collections; -import java.util.Set; -import com.google.auto.service.AutoService; - -/** - * @since 1.1.0 - */ -@AutoService(ResourceFactoryConfig.class) -public class DefaultResourceFactoryConfig implements ResourceFactoryConfig { - - @Override - public Set getSupportedPackages() { - return Collections.singleton("com.okta.sdk"); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceMessage.java b/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceMessage.java deleted file mode 100644 index 8b05c58c999..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DefaultResourceMessage.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.HttpHeaders; -import com.okta.sdk.impl.http.CanonicalUri; -import com.okta.commons.lang.Assert; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -public class DefaultResourceMessage implements ResourceMessage { - - private final ResourceAction action; - private final CanonicalUri uri; - private final Class resourceClass; - private final Map data; - private HttpHeaders httpHeaders; - - public DefaultResourceMessage(ResourceAction action, CanonicalUri uri, Class resourceClass, Map data) { - Assert.notNull(action, "resource action cannot be null."); - Assert.notNull(uri, "uri cannot be null."); - Assert.notNull(resourceClass, "resourceClass cannot be null."); - Assert.notNull(data, "data map cannot be null - specify an empty map instead of null."); - this.action = action; - this.uri = uri; - this.resourceClass = resourceClass; - this.data = data; - } - - public DefaultResourceMessage(ResourceAction action, CanonicalUri uri, Class resourceClass, Map data, HttpHeaders customHeaders) { - this(action, uri, resourceClass, data); - this.httpHeaders = customHeaders; - } - - @Override - public CanonicalUri getUri() { - return this.uri; - } - - @Override - public Class getResourceClass() { - return this.resourceClass; - } - - @Override - public Map getData() { - return this.data; - } - - @Override - public ResourceAction getAction() { - return action; - } - - public HttpHeaders getHttpHeaders() { - return httpHeaders != null ? httpHeaders : new HttpHeaders(); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DiscriminatorConfig.java b/impl/src/main/java/com/okta/sdk/impl/ds/DiscriminatorConfig.java deleted file mode 100644 index f7e7aa52be4..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DiscriminatorConfig.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -import java.io.IOException; -import java.net.URL; -import java.util.Collections; -import java.util.Map; - -/** - * Simple configuration bean which allows the {@link DiscriminatorRegistry} configuration to be loaded from a file. - * - * @since 0.8.0 - */ -public class DiscriminatorConfig { - - private static final Logger logger = LoggerFactory.getLogger(DiscriminatorConfig.class); - - private Map config = Collections.emptyMap(); - - public Map getConfig() { - return config; - } - - public void setConfig(Map config) { - this.config = config; - } - - public static class ClassConfig { - - private String fieldName; - - private Map values; - - public String getFieldName() { - return fieldName; - } - - public void setFieldName(String fieldName) { - this.fieldName = fieldName; - } - - public Map getValues() { - return values; - } - - public void setValues(Map values) { - this.values = values; - } - } - - /** - * Loads DiscriminatorConfig from the classpath file: {code}/com/okta/sdk/resource/discrimination.json{code}. - * If this file cannot be found an empty DiscriminatorConfig is returned. - * - * @return a DiscriminatorConfig based on the discrimination.json found on the classpath. - */ - static DiscriminatorConfig loadConfig() { - String configFile = "/com/okta/sdk/resource/discrimination.json"; - URL configJson = DefaultDiscriminatorRegistry.class.getResource(configFile); - - if (configJson != null) { - try { - return new ObjectMapper().readValue(configJson, DiscriminatorConfig.class); - } catch (IOException e) { - logger.warn("Failed to load config file: {}", configFile, e); - } - } - else { - logger.warn("Could not find config file on the classpath: {}", configFile); - } - return new DiscriminatorConfig(); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/DiscriminatorRegistry.java b/impl/src/main/java/com/okta/sdk/impl/ds/DiscriminatorRegistry.java deleted file mode 100644 index a242174cd8b..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/DiscriminatorRegistry.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import java.util.Map; - -/** - * A DiscriminatorRegistry allows for the resolution of a specific type, based on the data of the object. - * For example, the Factors API return a collection of {@link com.okta.sdk.resource.user.factor.UserFactor UserFactor} objects, - * The actual type is dependent on a property of the data map 'factorType'. - * - * @since 0.8.0 - */ -public interface DiscriminatorRegistry { - - boolean supportedClass(Class clazz); - -

    Class

    resolve(Class

    clazz, Map data); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/FilterChain.java b/impl/src/main/java/com/okta/sdk/impl/ds/FilterChain.java deleted file mode 100644 index 3e693bfa0ce..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/FilterChain.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -public interface FilterChain { - - ResourceDataResult filter(ResourceDataRequest request); - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/InternalDataStore.java b/impl/src/main/java/com/okta/sdk/impl/ds/InternalDataStore.java deleted file mode 100644 index d393e352aad..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/InternalDataStore.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.sdk.ds.DataStore; -import com.okta.sdk.resource.Resource; - -import java.io.InputStream; -import java.util.List; -import java.util.Map; - -/** - * Internal DataStore used for implementation purposes only. Not intended to be called by SDK end users! - *

    - * WARNING: This API CAN CHANGE AT ANY TIME, WITHOUT NOTICE. DO NOT DEPEND ON IT. - * - * @since 0.5.0 - */ -public interface InternalDataStore extends DataStore { - - T instantiate(Class clazz, Map properties); - - T create(String parentHref, T resource, T parentResource); - - R create(String parentHref, T resource, T parentResource, Class returnType); - - /** - * @since 1.2.0 - */ - R create(String parentHref, T resource, T parentResource, Class returnType, Map queryParameters); - - /** - * @since 1.5.0 - */ - R create(String parentHref, T resource, T parentResource, Class returnType, Map queryParameters, Map> headerParameters); - - void save(T resource); - - void save(String href, T resource, T parentResource); - - /** - * @since 1.2.0 - */ - void save(String href, T resource, T parentResource, Map queryParameters); - - /** - * @since 1.5.0 - */ - void save(String href, T resource, T parentResource, Map queryParameters, Map> headerParameters); - - void delete(T resource); - - void delete(String href, T resource); - - void delete(String href); - - /** - * @since 1.2.0 - */ - void delete(String href, Map queryParameters); - - /** - * @since 1.5.0 - */ - void delete(String href, Map queryParameters, Map> headerParameters); - - /** - * @since 1.6.0 - */ - void delete(String href, T resource, Map queryParameters, Map> headerParameters); - - T getResource(String href, Class clazz, Map queryParameters); - - /** - * @since 1.5.0 - */ - T getResource(String href, Class clazz, Map queryParameters, Map> headerParameters); - - String getBaseUrl(); - - default T create(String parentHref, T resource) { - return create(parentHref, resource, (T) null); - } - - default R create(String parentHref, T resource, Class returnType) { - return create(parentHref, resource, null, returnType); - } - - default void save(String href, T resource) { - save(href, resource, null); - } - - InputStream getRawResponse(String href, Map queryParameters, Map> headerParameters); - - R save(String parentHref, T resource, Class returnType, boolean create); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/JacksonMapMarshaller.java b/impl/src/main/java/com/okta/sdk/impl/ds/JacksonMapMarshaller.java deleted file mode 100644 index 7953f9861ec..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/JacksonMapMarshaller.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import com.okta.sdk.impl.resource.AbstractResource; -import com.okta.sdk.impl.resource.ReferenceFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * @since 0.5.0 - */ -public class JacksonMapMarshaller implements MapMarshaller { - - private ObjectMapper objectMapper; - - public JacksonMapMarshaller() { - this.objectMapper = new ObjectMapper(); - this.objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); - - SimpleModule simpleModule = new SimpleModule(); - simpleModule.addSerializer(new AbstractResourceSerializer(AbstractResource.class)); - this.objectMapper.registerModule(simpleModule); - } - - public ObjectMapper getObjectMapper() { - return this.objectMapper; - } - - public void setObjectMapper(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } - - public boolean isPrettyPrint() { - return this.objectMapper.getSerializationConfig().isEnabled(SerializationFeature.INDENT_OUTPUT); - } - - public void setPrettyPrint(boolean prettyPrint) { - this.objectMapper.configure(SerializationFeature.INDENT_OUTPUT, prettyPrint); - } - - @Override - public void marshal(OutputStream out, Map map) { - if (map == null) { - throw new MarshalingException("Cannot convert null to JSON."); - } - - try { - this.objectMapper.writeValue(out, map); - } catch (IOException e) { - throw new MarshalingException("Unable to convert Map to JSON.", e); - } - } - - @SuppressWarnings("unchecked") - @Override - public Map unmarshal(InputStream marshalled, Map linkMap) { - try { - Object resolvedObj = this.objectMapper.readValue(marshalled, Object.class); - if (resolvedObj instanceof Map) { - return (Map) resolvedObj; - } else if (resolvedObj instanceof List) { - List list = (List) resolvedObj; - Map ret = new LinkedHashMap<>(); - ret.put("items", list); - ret.put("nextPage", linkMap.get("next")); - ret.put("href", "local"); - return ret; - } - throw new MarshalingException("Unable to convert InputStream String to Map. " + - "Resolved Object is neither a Map or a List: " + resolvedObj.getClass()); - } catch (IOException e) { - throw new MarshalingException("Unable to convert InputStream String to Map.", e); - } - } - - static class AbstractResourceSerializer extends StdSerializer { - - private static final long serialVersionUID = 42L; - private final transient ResourceConverter resourceConverter = new DefaultResourceConverter(new ReferenceFactory()); - - AbstractResourceSerializer(Class t) { - super(t); - } - - @Override - public void serialize(AbstractResource resource, - JsonGenerator jgen, - SerializerProvider sp) throws IOException { - jgen.writeObject(resourceConverter.convert(resource, false)); - } - - // method not used, but here to prevent java serialization PMD warnings - private void writeObject(ObjectOutputStream stream) throws IOException { - stream.defaultWriteObject(); - } - - // method not used, but here to prevent java serialization PMD warnings - private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { - stream.defaultReadObject(); - } - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/MapMarshaller.java b/impl/src/main/java/com/okta/sdk/impl/ds/MapMarshaller.java deleted file mode 100644 index 938cf2d302b..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/MapMarshaller.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; - -/** - * @since 0.5.0 - */ -public interface MapMarshaller { - - void marshal(OutputStream outputStream, Map map); - - Map unmarshal(InputStream inputStream, Map linkMap); - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/MarshalingException.java b/impl/src/main/java/com/okta/sdk/impl/ds/MarshalingException.java deleted file mode 100644 index 9fee2e713d5..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/MarshalingException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.HttpException; - -/** - * @since 0.5.0 - */ -public class MarshalingException extends HttpException { - - public MarshalingException(String s) { - super(s); - } - - public MarshalingException(Throwable cause) { - super(cause); - } - - public MarshalingException(String s, Throwable cause) { - super(s, cause); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceAction.java b/impl/src/main/java/com/okta/sdk/impl/ds/ResourceAction.java deleted file mode 100644 index 88e07a9b484..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceAction.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -public enum ResourceAction { - - CREATE, READ, UPDATE, DELETE -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceConverter.java b/impl/src/main/java/com/okta/sdk/impl/ds/ResourceConverter.java deleted file mode 100644 index 704fc2fb80d..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceConverter.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.sdk.impl.resource.AbstractResource; - -import java.util.Map; - -public interface ResourceConverter { - - Map convert(AbstractResource resource, boolean dirtOnly); - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceDataRequest.java b/impl/src/main/java/com/okta/sdk/impl/ds/ResourceDataRequest.java deleted file mode 100644 index c625f9844e7..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceDataRequest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.HttpHeaders; -import com.okta.sdk.impl.http.CanonicalUri; -import com.okta.sdk.resource.Resource; - -/** - * This class represents a request to obtain a resource and its related data. - */ -public interface ResourceDataRequest extends ResourceMessage { - - ResourceAction getAction(); - - /** - * Returns the {@code HttpHeaders HttpHeaders} instance associated with a {@link ResourceDataRequest ResourceDataRequest} - * @return the {@link HttpHeaders HttpHeaders} instance representing the Http Headers added to a data request. - * - */ - HttpHeaders getHttpHeaders(); - - CanonicalUri getParentUri(); - - Class getParentResourceClass(); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceDataResult.java b/impl/src/main/java/com/okta/sdk/impl/ds/ResourceDataResult.java deleted file mode 100644 index 43278de6458..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceDataResult.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -public interface ResourceDataResult extends ResourceMessage { - - ResourceAction getAction(); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceFactory.java b/impl/src/main/java/com/okta/sdk/impl/ds/ResourceFactory.java deleted file mode 100644 index dc2f24f201d..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.sdk.resource.Resource; - -/** - * @since 0.5.0 - */ -public interface ResourceFactory { - - T instantiate(Class clazz, Object... constructorArgs); - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceFactoryConfig.java b/impl/src/main/java/com/okta/sdk/impl/ds/ResourceFactoryConfig.java deleted file mode 100644 index 81d5dc12026..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceFactoryConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import java.util.Set; - -/** - * @since 1.1.0 - */ -public interface ResourceFactoryConfig { - - Set getSupportedPackages(); -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceMessage.java b/impl/src/main/java/com/okta/sdk/impl/ds/ResourceMessage.java deleted file mode 100644 index ffc37a76308..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/ResourceMessage.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds; - -import com.okta.commons.http.HttpHeaders; -import com.okta.sdk.impl.http.CanonicalUri; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -public interface ResourceMessage { - - ResourceAction getAction(); - - CanonicalUri getUri(); - - Map getData(); - - Class getResourceClass(); - - HttpHeaders getHttpHeaders(); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/cache/CacheResolver.java b/impl/src/main/java/com/okta/sdk/impl/ds/cache/CacheResolver.java deleted file mode 100644 index 397758ab9fa..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/cache/CacheResolver.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds.cache; - -import com.okta.sdk.cache.Cache; - -import java.util.Map; - -public interface CacheResolver { - - Cache> getCache(Class clazz); - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/cache/DefaultCacheResolver.java b/impl/src/main/java/com/okta/sdk/impl/ds/cache/DefaultCacheResolver.java deleted file mode 100644 index d9d246b6db1..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/cache/DefaultCacheResolver.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds.cache; - -import com.okta.commons.lang.Assert; -import com.okta.sdk.cache.Cache; -import com.okta.sdk.cache.CacheManager; -import com.okta.sdk.impl.ds.CacheRegionNameResolver; - -import java.util.Map; - -public class DefaultCacheResolver implements CacheResolver { - - private final CacheManager cacheManager; - private final CacheRegionNameResolver cacheRegionNameResolver; - - public DefaultCacheResolver(CacheManager cacheManager, CacheRegionNameResolver cacheRegionNameResolver) { - Assert.notNull(cacheManager, "cacheManager cannot be null."); - Assert.notNull(cacheRegionNameResolver, "cacheRegionNameResolver cannot be null."); - this.cacheManager = cacheManager; - this.cacheRegionNameResolver = cacheRegionNameResolver; - } - - public Cache> getCache(Class clazz) { - Assert.notNull(clazz, "Class argument cannot be null."); - String cacheRegionName = this.cacheRegionNameResolver.getCacheRegionName(clazz); - return this.cacheManager.getCache(cacheRegionName); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/cache/DefaultResourceCacheStrategy.java b/impl/src/main/java/com/okta/sdk/impl/ds/cache/DefaultResourceCacheStrategy.java deleted file mode 100644 index 76c3da653bf..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/cache/DefaultResourceCacheStrategy.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds.cache; - -import com.okta.sdk.cache.Cache; -import com.okta.sdk.impl.ds.CacheMapInitializer; -import com.okta.sdk.impl.ds.DefaultCacheMapInitializer; -import com.okta.sdk.impl.ds.DefaultResourceDataResult; -import com.okta.sdk.impl.ds.ResourceAction; -import com.okta.sdk.impl.ds.ResourceDataRequest; -import com.okta.sdk.impl.ds.ResourceDataResult; -import com.okta.sdk.impl.http.CanonicalUri; -import com.okta.sdk.impl.resource.ResourceHrefResolver; -import com.okta.commons.lang.Assert; -import com.okta.commons.lang.Collections; -import com.okta.sdk.resource.CollectionResource; -import com.okta.sdk.resource.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -/** - * This default implementation of {@link ResourceCacheStrategy} manages reading and writing to/from a {@link Cache}. This - * implementation also invalidates an object's cache when {@code DELETE} and other mutating operations are called. - *

    - * Key Points: - *

      - *
    • Collection Resources are NOT cached
    • - *
    • Any individual Resource with a {@code _link.self.href} is cached
    • - *
    • The {@link ResourceHrefResolver} will be consulted if a Resource does NOT have a @{code _link.self.href} property
    • - *
    • A call to the {@code cache} method with a {@code DELETE} action will also remove that object from the cache
    • - *
    • Any @{code CREATE} or {@code UPDATE} call to the {@code cache} method, that has a _parent_ set in the {@link ResourceDataRequest} will also remove the parent from the cache
    • - *
    - * - * @since 1.0 - */ -public class DefaultResourceCacheStrategy implements ResourceCacheStrategy { - - private final Logger logger = LoggerFactory.getLogger(DefaultResourceCacheStrategy.class); - - private final ResourceHrefResolver hrefResolver; - private final CacheResolver cacheResolver; - private final CacheMapInitializer cacheMapInitializer = new DefaultCacheMapInitializer(); - - public DefaultResourceCacheStrategy(ResourceHrefResolver hrefResolver, CacheResolver cacheResolver) { - this.hrefResolver = hrefResolver; - this.cacheResolver = cacheResolver; - } - - @Override - public void cache(ResourceDataRequest request, ResourceDataResult result) { - - if (request.getAction() == ResourceAction.DELETE) { - String key = getCacheKey(request); - uncache(key, request.getResourceClass()); - } else if (isCacheable(result)) { - cache(result.getResourceClass(), result.getData(), result.getUri()); - } else { - if (request.getParentUri() != null) { - logger.debug("Removing parent cache '{}'", request.getUri().getAbsolutePath()); - String key = getCacheKey(request.getParentUri().getAbsolutePath()); - uncache(key, request.getParentResourceClass()); - } else { - logger.debug("Cannot cache action: '{}', href: '{}', class: '{}'", result.getAction(), result.getUri().getAbsolutePath(), result.getResourceClass()); - } - } - } - - @Override - public ResourceDataResult readFromCache(ResourceDataRequest request) { - - if (!isCacheRetrievalEnabled(request)) { - return null; - } - - final CanonicalUri uri = request.getUri(); - final Class clazz = request.getResourceClass(); - - Map data = null; - - // Prevent an expanded request to obtain a non-expanded resource from the cache - String cacheKey = getCacheKey(request); - if (! (request.getUri().hasQuery() && request.getUri().getQuery().containsKey("expand") ^ (cacheKey != null && cacheKey.contains("expand=")))) { - data = getCachedValue(cacheKey, clazz); - } - - // return if no data - if (Collections.isEmpty(data)) { - return null; - } - - return new DefaultResourceDataResult(request.getAction(), uri, clazz, coerce(data)); - } - - @SuppressWarnings("unchecked") - private void cache(Class clazz, Map data, CanonicalUri uri) { - - Assert.notEmpty(data, "Resource data cannot be null or empty."); - String href = hrefResolver.resolveHref(data, clazz); - - if (isDirectlyCacheable(clazz, data)) { - Assert.notNull(href, "Resource data must contain an 'href' attribute."); - Assert.isTrue(data.size() > 0, "Resource data must be materialized to be cached " + - "(need more at least one attribute)."); - } - - // create a map to reflect the resource's canonical representation - this is what will be cached: - Map cacheValue = cacheMapInitializer.initialize(clazz, data, uri.getQuery()); - - data.entrySet().forEach(entry -> - cacheValue.put(entry.getKey(), entry.getValue()) - ); - - if (isDirectlyCacheable(clazz, cacheValue)) { - Cache cache = getCache(clazz); - String cacheKey = getCacheKey(href); - Object previousCacheValue = cache.put(cacheKey, cacheValue); - logger.debug("Caching object for key '{}', class: '{}', updated {}", cacheKey, clazz, previousCacheValue != null); - } - } - - @SuppressWarnings("unchecked") - private void uncache(String cacheKey, Class resourceType) { - Assert.hasText(cacheKey, "cacheKey cannot be null or empty."); - Assert.notNull(resourceType, "resourceType cannot be null."); - Cache> cache = getCache(resourceType); - cache.remove(cacheKey); - logger.debug("Removing cache for key '{}', class: '{}'", cacheKey, resourceType); - } - - private boolean isCacheable(ResourceDataResult result) { - if (Collections.isEmpty(result.getData())) { - return false; - } - - Class clazz = result.getResourceClass(); - - // @since 0.5.0 - boolean materialized = isMaterialized(result.getData(), clazz); - - if (!materialized) { - logger.debug("Class: {}, is not cacheable.", clazz.getSimpleName()); - } - - return materialized; - } - - /** - * Quick fix for Issue #17. - * - */ - private boolean isDirectlyCacheable(Class clazz, Map data) { - return isMaterialized(data, clazz) && - // do NOT cache collections - !CollectionResource.class.isAssignableFrom(clazz); - } - - private boolean isCacheRetrievalEnabled(ResourceDataRequest request) { - return - // create, update and delete all should bypass cache reads: - request.getAction() == ResourceAction.READ && - - // Collection caching is disabled - !CollectionResource.class.isAssignableFrom(request.getResourceClass()); - } - - /** - * Returns {@code true} if the specified data map represents a materialized resource data set, {@code false} - * otherwise. - * - * @param props the data properties to test - * @return {@code true} if the specified data map represents a materialized resource data set, {@code false} - * otherwise. - */ - private boolean isMaterialized(Map props, Class clazz) { - - // this check to see if the data map has an self href in it (which is used for the caching key) - return hrefResolver.resolveHref(props, clazz) != null; - } - - private Cache> getCache(Class clazz) { - return this.cacheResolver.getCache(clazz); - } - - private Map getCachedValue(String href, Class clazz) { - Assert.hasText(href, "href argument cannot be null or empty."); - Assert.notNull(clazz, "Class argument cannot be null."); - Cache> cache = getCache(clazz); - - Map value = cache.get(href); - if (value != null) { - logger.debug("Cache hit for key '{}', class: '{}'", href, clazz); - } - return value; - } - - private String getCacheKey(ResourceDataRequest request) { - return getCacheKey(request.getUri().getAbsolutePath()); - } - - private String getCacheKey(String href) { - return href; - } - - @SuppressWarnings("unchecked") - private static Map coerce(Map data) { - return (Map) data; - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/cache/ReadCacheFilter.java b/impl/src/main/java/com/okta/sdk/impl/ds/cache/ReadCacheFilter.java deleted file mode 100644 index 087b09cf139..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/cache/ReadCacheFilter.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds.cache; - -import com.okta.sdk.impl.ds.Filter; -import com.okta.sdk.impl.ds.FilterChain; -import com.okta.sdk.impl.ds.ResourceDataRequest; -import com.okta.sdk.impl.ds.ResourceDataResult; - - -public class ReadCacheFilter implements Filter { - - private final ResourceCacheStrategy cacheStrategy; - - public ReadCacheFilter(ResourceCacheStrategy cacheStrategy) { - this.cacheStrategy = cacheStrategy; - } - - @Override - public ResourceDataResult filter(ResourceDataRequest request, FilterChain chain) { - - ResourceDataResult result = cacheStrategy.readFromCache(request); - if (result != null) { - return result; - } - - //cache miss - let the chain continue: - return chain.filter(request); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/cache/ResourceCacheStrategy.java b/impl/src/main/java/com/okta/sdk/impl/ds/cache/ResourceCacheStrategy.java deleted file mode 100644 index 8bab7058318..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/cache/ResourceCacheStrategy.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds.cache; - -import com.okta.sdk.impl.ds.ResourceDataRequest; -import com.okta.sdk.impl.ds.ResourceDataResult; - -/** - * Defines the strategy used for reading/adding/updating/removing objects from the cache based on a - * {@link ResourceDataRequest} and {@link ResourceDataResult}. - * - * @since 1.0 - */ -public interface ResourceCacheStrategy { - - /** - * Cache the {@code result} data that was returned based on the {@code request}. - * @param request the data request - * @param result the result to be cached - */ - void cache(ResourceDataRequest request, ResourceDataResult result); - - /** - * Attempts to retrieve data from the cache based on the {@code request}. If the object is NOT found in the cache, - * {@code null} is returned. - * @param request the source request used to query the cache. - * @return A result containing data from cache, or null - */ - ResourceDataResult readFromCache(ResourceDataRequest request); -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/ds/cache/WriteCacheFilter.java b/impl/src/main/java/com/okta/sdk/impl/ds/cache/WriteCacheFilter.java deleted file mode 100644 index c2e295120b9..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/ds/cache/WriteCacheFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds.cache; - -import com.okta.sdk.impl.ds.Filter; -import com.okta.sdk.impl.ds.FilterChain; -import com.okta.sdk.impl.ds.ResourceDataRequest; -import com.okta.sdk.impl.ds.ResourceDataResult; - -public class WriteCacheFilter implements Filter { - - private final ResourceCacheStrategy cacheStrategy; - - public WriteCacheFilter(ResourceCacheStrategy cacheStrategy) { - this.cacheStrategy = cacheStrategy; - } - - @Override - public ResourceDataResult filter(ResourceDataRequest request, FilterChain chain) { - ResourceDataResult result = chain.filter(request); - cacheStrategy.cache(request, result); - return result; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/error/DefaultError.java b/impl/src/main/java/com/okta/sdk/impl/error/DefaultError.java deleted file mode 100644 index 4ad3c9bd22b..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/error/DefaultError.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.error; - -import com.okta.sdk.error.Error; -import com.okta.sdk.error.ErrorCause; -import com.okta.sdk.impl.resource.AbstractResource; -import com.okta.sdk.impl.resource.IntegerProperty; -import com.okta.sdk.impl.resource.ListProperty; -import com.okta.sdk.impl.resource.MapProperty; -import com.okta.sdk.impl.resource.Property; -import com.okta.sdk.impl.resource.StringProperty; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * @since 0.5.0 - */ -public class DefaultError extends AbstractResource implements Error { - - static final long serialVersionUID = 42L; - - static final IntegerProperty STATUS = new IntegerProperty("status"); - static final StringProperty CODE = new StringProperty("errorCode"); - static final StringProperty MESSAGE = new StringProperty("errorSummary"); - static final ListProperty CAUSES = new ListProperty("errorCauses"); - static final MapProperty HEADERS = new MapProperty("errorHeaders"); - public static final StringProperty ERROR_ID = new StringProperty("errorId"); - - private static final Map PROPERTY_DESCRIPTORS = createPropertyDescriptorMap( - STATUS, CODE, MESSAGE, CAUSES, ERROR_ID, HEADERS - ); - - public DefaultError(Map body) { - super(null, body); - } - - // Needed for this class to be serializable - public DefaultError() { - super(null, null); - } - - @Override - public Map getPropertyDescriptors() { - return PROPERTY_DESCRIPTORS; - } - - @Override - public int getStatus() { - return getInt(STATUS); - } - - public DefaultError setStatus(int status) { - setProperty(STATUS, status); - return this; - } - - @Override - public String getCode() { - return getString(CODE); - } - - public DefaultError setCode(String code) { - setProperty(CODE, code); - return this; - } - - @Override - public String getMessage() { - return getString(MESSAGE); - } - - public DefaultError setMessage(String message) { - setProperty(MESSAGE, message); - return this; - } - - @Override - public String getId() { - return getString(ERROR_ID); - } - - public DefaultError setId(String requestId) { - setProperty(ERROR_ID, requestId); - return this; - } - - @Override - public List getCauses() { - List results = new ArrayList<>(); - Object rawProp = getProperty(CAUSES.getName()); - if (rawProp instanceof List) { - ((List>) rawProp).forEach(causeMap -> - results.add(new DefaultErrorCause(getDataStore(), causeMap))); - } - return Collections.unmodifiableList(results); - } - - public DefaultError setCauses(Map causes) { - setProperty(CAUSES, causes); - return this; - } - - @Override - public Map> getHeaders() { - return getMap(HEADERS); - } - - public DefaultError setHeaders(Map> headers) { - setProperty(HEADERS, headers); - return this; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/error/DefaultErrorCause.java b/impl/src/main/java/com/okta/sdk/impl/error/DefaultErrorCause.java deleted file mode 100644 index ad188c3c6ed..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/error/DefaultErrorCause.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.error; - -import com.okta.sdk.error.ErrorCause; -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.impl.resource.AbstractResource; -import com.okta.sdk.impl.resource.Property; -import com.okta.sdk.impl.resource.StringProperty; - -import java.util.Map; - -public class DefaultErrorCause extends AbstractResource implements ErrorCause { - - private static final StringProperty SUMMARY = new StringProperty("errorSummary"); - - private static final Map PROPERTY_DESCRIPTORS = createPropertyDescriptorMap( - SUMMARY - ); - - protected DefaultErrorCause(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - @Override - public Map getPropertyDescriptors() { - return PROPERTY_DESCRIPTORS; - } - - @Override - public String getSummary() { - return getString(SUMMARY); - } - - @Override - public String getResourceHref() { - return null; - } - - @Override - public void setResourceHref(String href) { - - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/http/CanonicalUri.java b/impl/src/main/java/com/okta/sdk/impl/http/CanonicalUri.java deleted file mode 100644 index c0319da25f6..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/http/CanonicalUri.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http; - -import com.okta.commons.http.QueryString; - -/** - * A canonical representation of a Uniform Resource Identifier (URI) - * suitable for the SDK's needs. - * - * @since 0.5.0 - */ -public interface CanonicalUri { - - /** - * Returns a fully-qualified URI without {@code query} or {@code fragment} components. - * - * @return a fully-qualified URI without {@code query} or {@code fragment} components. - */ - String getAbsolutePath(); - - /** - * Returns {@code true} if the URI has a {@code query} component, {@code false} otherwise. - * - * @return {@code true} if the URI has a {@code query} component, {@code false} otherwise. - */ - boolean hasQuery(); - - /** - * Returns the URI's canonical {@code query} representation or {@code null} if there is no query component. - * - * @return the URI's canonical {@code query} representation or {@code null} if there is no query component. - */ - QueryString getQuery(); - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/http/HttpHeadersHolder.java b/impl/src/main/java/com/okta/sdk/impl/http/HttpHeadersHolder.java deleted file mode 100644 index 17f7d7f55de..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/http/HttpHeadersHolder.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http; - -import java.util.List; -import java.util.Map; - -/** - * This class is used to hold key/value pairs in a ThreadLocal. - */ -public abstract class HttpHeadersHolder { - private static final ThreadLocal>> current = new ThreadLocal<>(); - - public static void set(Map> headers) { - current.set(headers); - } - - public static Map> get() { - return current.get(); - } - - public static void clear() { - current.remove(); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/http/authc/DefaultRequestAuthenticatorFactory.java b/impl/src/main/java/com/okta/sdk/impl/http/authc/DefaultRequestAuthenticatorFactory.java deleted file mode 100644 index 4fcba3aaa70..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/http/authc/DefaultRequestAuthenticatorFactory.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http.authc; - -import com.okta.commons.http.authc.DisabledAuthenticator; -import com.okta.commons.http.authc.RequestAuthenticationException; -import com.okta.commons.http.authc.RequestAuthenticator; -import com.okta.sdk.authc.credentials.ClientCredentials; -import com.okta.sdk.client.AuthenticationScheme; -import com.okta.commons.lang.Classes; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Constructor; - -/** - * This default factory is responsible of creating a {@link RequestAuthenticator} out of a given {@link AuthenticationScheme} - *

    - * This implementation returns a {@link SswsAuthenticator} when the authentication scheme is undefined. - * - * @since 0.5.0 - */ -public class DefaultRequestAuthenticatorFactory implements RequestAuthenticatorFactory { - - private final Logger log = LoggerFactory.getLogger(DefaultRequestAuthenticatorFactory.class); - - /** - * Creates a {@link RequestAuthenticator} out of the given {@link AuthenticationScheme}. - * - * @param scheme the authentication scheme enum defining the request authenticator to be created - * @return the corresponding `RequestAuthenticator` for the given `AuthenticationScheme`. Returns `SswsAuthenticator` if - * the authentication scheme is undefined. - */ - @SuppressWarnings("unchecked") - public RequestAuthenticator create(AuthenticationScheme scheme, ClientCredentials clientCredentials) { - - if (scheme == null) { - //By default, this factory creates a digest authentication when a scheme is not defined - return new SswsAuthenticator(clientCredentials); - } - - try { - Class requestAuthenticatorClass = Classes.forName(scheme.getRequestAuthenticatorClassName()); - - // check if disabled and skip reflection - if (DisabledAuthenticator.class.equals(requestAuthenticatorClass)) { - return new DisabledAuthenticator(); - } - - Constructor ctor = Classes.getConstructor(requestAuthenticatorClass, ClientCredentials.class); - return Classes.instantiate(ctor, clientCredentials); - } catch (RuntimeException ex) { - String errormessage = "There was an error instantiating " + scheme.getRequestAuthenticatorClassName(); - log.error(errormessage, ex); - throw new RequestAuthenticationException(errormessage); - } - } - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/http/authc/OAuth2RequestAuthenticator.java b/impl/src/main/java/com/okta/sdk/impl/http/authc/OAuth2RequestAuthenticator.java deleted file mode 100644 index d802b4234a1..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/http/authc/OAuth2RequestAuthenticator.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http.authc; - -import com.okta.commons.http.Request; -import com.okta.commons.http.authc.RequestAuthenticationException; -import com.okta.commons.http.authc.RequestAuthenticator; -import com.okta.commons.lang.Assert; -import com.okta.sdk.authc.credentials.ClientCredentials; -import com.okta.sdk.impl.oauth2.OAuth2AccessToken; -import com.okta.sdk.impl.oauth2.OAuth2ClientCredentials; -import com.okta.sdk.impl.oauth2.OAuth2TokenRetrieverException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.security.InvalidKeyException; - -/** - * This implementation used by OAuth2 flow adds Bearer header with access token as the - * value in all outgoing requests. This has logic to fetch a new token and store it in - * {@link OAuth2ClientCredentials} object if the existing one has expired. - * - * @since 1.6.0 - */ -public class OAuth2RequestAuthenticator implements RequestAuthenticator { - private static final Logger log = LoggerFactory.getLogger(OAuth2RequestAuthenticator.class); - - private final ClientCredentials clientCredentials; - - public OAuth2RequestAuthenticator(ClientCredentials clientCredentials) { - Assert.notNull(clientCredentials, "clientCredentials may not be null"); - this.clientCredentials = clientCredentials; - } - - @Override - public void authenticate(Request request) throws RequestAuthenticationException { - OAuth2AccessToken oAuth2AccessToken = clientCredentials.getCredentials(); - - if (oAuth2AccessToken.hasExpired()) { - log.debug("OAuth2 access token expiry detected. Will fetch a new token from Authorization server"); - - synchronized (this) { - if (oAuth2AccessToken.hasExpired()) { - try { - OAuth2ClientCredentials oAuth2ClientCredentials = (OAuth2ClientCredentials) clientCredentials; - // fetch new token - oAuth2AccessToken = oAuth2ClientCredentials.getAccessTokenRetrieverService().getOAuth2AccessToken(); - // store the new token - oAuth2ClientCredentials.setCredentials(oAuth2AccessToken); - } catch (IOException | InvalidKeyException e) { - throw new OAuth2TokenRetrieverException("Failed to renew expired OAuth2 access token", e); - } - } - } - } - - // add Bearer header with token value - request.getHeaders().set(AUTHORIZATION_HEADER, "Bearer " + oAuth2AccessToken.getAccessToken()); - } - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/http/authc/RequestAuthenticatorFactory.java b/impl/src/main/java/com/okta/sdk/impl/http/authc/RequestAuthenticatorFactory.java deleted file mode 100644 index 06954e7f490..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/http/authc/RequestAuthenticatorFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http.authc; - -import com.okta.commons.http.authc.RequestAuthenticator; -import com.okta.sdk.authc.credentials.ClientCredentials; -import com.okta.sdk.client.AuthenticationScheme; - -/** - * Factory interface to create {@link RequestAuthenticator}s out of {@link AuthenticationScheme}s. - * - * @since 0.5.0 - */ -public interface RequestAuthenticatorFactory { - - RequestAuthenticator create(AuthenticationScheme scheme, ClientCredentials clientCredentials); - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/http/authc/SswsAuthenticator.java b/impl/src/main/java/com/okta/sdk/impl/http/authc/SswsAuthenticator.java deleted file mode 100644 index 5b3b1974e75..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/http/authc/SswsAuthenticator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http.authc; - -import com.okta.commons.http.Request; -import com.okta.commons.http.authc.RequestAuthenticationException; -import com.okta.commons.http.authc.RequestAuthenticator; -import com.okta.commons.lang.Assert; -import com.okta.sdk.authc.credentials.ClientCredentials; - - -public class SswsAuthenticator implements RequestAuthenticator { - - public static final String AUTHENTICATION_SCHEME = "SSWS"; - - private final ClientCredentials clientCredentials; - - public SswsAuthenticator(ClientCredentials clientCredentials) { - Assert.notNull(clientCredentials, "clientCredentials must be not be null."); - this.clientCredentials = clientCredentials; - } - - @Override - public void authenticate(Request request) throws RequestAuthenticationException { - request.getHeaders().set(AUTHORIZATION_HEADER, AUTHENTICATION_SCHEME + " " + clientCredentials.getCredentials()); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/http/support/DefaultCanonicalUri.java b/impl/src/main/java/com/okta/sdk/impl/http/support/DefaultCanonicalUri.java deleted file mode 100644 index 00f2aaccd16..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/http/support/DefaultCanonicalUri.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http.support; - -import com.okta.sdk.impl.http.CanonicalUri; -import com.okta.commons.http.QueryString; -import com.okta.commons.lang.Assert; -import com.okta.commons.lang.Collections; -import com.okta.commons.lang.Strings; - -import java.util.Map; - -public class DefaultCanonicalUri implements CanonicalUri { - - private final String absolutePath; - private final QueryString query; - - public DefaultCanonicalUri(String absolutePath, QueryString query) { - Assert.hasText(absolutePath, "absolutePath argument cannot be null or empty."); - this.absolutePath = absolutePath; - this.query = query; - } - - @Override - public String getAbsolutePath() { - return absolutePath; - } - - @Override - public boolean hasQuery() { - return query != null; - } - - @Override - public QueryString getQuery() { - return query; - } - - public static CanonicalUri create(String href, Map queryParams) { - - Assert.hasText(href, "href argument cannot be null or empty."); - - QueryString query = null; - - if (!Collections.isEmpty(queryParams)) { - - query = new QueryString(queryParams); //create a copy so we don't manipulate the argument - - int questionMarkIndex = href.lastIndexOf('?'); - - if (questionMarkIndex >= 0) { - - String queryString = href.substring(questionMarkIndex + 1); - href = href.substring(0, questionMarkIndex); - - if (Strings.hasLength(queryString)) { - - //the query values from the href portion are explicit and therefore take precedence over - //any values in the queryParams argument: - QueryString queryStringFromHref = QueryString.create(queryString); - - if (queryStringFromHref != null) { - query.putAll(queryStringFromHref); - } - } - } - - } - - return new DefaultCanonicalUri(href, query); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/oauth2/AccessTokenRetrieverServiceImpl.java b/impl/src/main/java/com/okta/sdk/impl/oauth2/AccessTokenRetrieverServiceImpl.java index 0ce35a48a89..80d384d6b67 100644 --- a/impl/src/main/java/com/okta/sdk/impl/oauth2/AccessTokenRetrieverServiceImpl.java +++ b/impl/src/main/java/com/okta/sdk/impl/oauth2/AccessTokenRetrieverServiceImpl.java @@ -15,26 +15,32 @@ */ package com.okta.sdk.impl.oauth2; -import com.okta.commons.http.MediaType; import com.okta.commons.http.authc.DisabledAuthenticator; import com.okta.commons.lang.Assert; import com.okta.commons.lang.Strings; import com.okta.sdk.client.AuthenticationScheme; import com.okta.sdk.client.AuthorizationMode; +import com.okta.sdk.error.Error; +import com.okta.sdk.error.ResourceException; import com.okta.sdk.impl.api.DefaultClientCredentialsResolver; import com.okta.sdk.impl.config.ClientConfiguration; -import com.okta.sdk.impl.error.DefaultError; import com.okta.sdk.impl.util.ConfigUtil; -import com.okta.sdk.resource.ExtensibleResource; -import com.okta.sdk.resource.ResourceException; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.openapitools.client.ApiClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; import java.io.IOException; import java.io.Reader; @@ -47,6 +53,7 @@ import java.security.PrivateKey; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.Collections; import java.util.Date; import java.util.Optional; import java.util.UUID; @@ -64,19 +71,12 @@ public class AccessTokenRetrieverServiceImpl implements AccessTokenRetrieverServ private static final String TOKEN_URI = "/oauth2/v1/token"; private final ClientConfiguration tokenClientConfiguration; - private final OAuth2TokenClient tokenClient; + private final ApiClient apiClient; - public AccessTokenRetrieverServiceImpl(ClientConfiguration apiClientConfiguration) { + public AccessTokenRetrieverServiceImpl(ClientConfiguration apiClientConfiguration, ApiClient apiClient) { Assert.notNull(apiClientConfiguration, "apiClientConfiguration must not be null."); - ClientConfiguration tokenClientConfig = constructTokenClientConfig(apiClientConfiguration); - this.tokenClient = new OAuth2TokenClient(tokenClientConfig); - this.tokenClientConfiguration = tokenClientConfig; - } - - public AccessTokenRetrieverServiceImpl(ClientConfiguration apiClientConfiguration, OAuth2TokenClient tokenClient) { - Assert.notNull(apiClientConfiguration, "apiClientConfiguration must not be null."); - Assert.notNull(tokenClient, "tokenClient must not be null."); - this.tokenClient = tokenClient; + Assert.notNull(apiClient, "apiClient must not be null."); + this.apiClient = apiClient; this.tokenClientConfiguration = constructTokenClientConfig(apiClientConfiguration); } @@ -92,32 +92,38 @@ public OAuth2AccessToken getOAuth2AccessToken() throws IOException, InvalidKeyEx String scope = String.join(" ", tokenClientConfiguration.getScopes()); try { - ExtensibleResource accessTokenResponse = tokenClient.http() - .addHeaderParameter("Accept", MediaType.APPLICATION_JSON_VALUE) - .addHeaderParameter("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE) - .addQueryParameter("grant_type", "client_credentials") - .addQueryParameter("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") - .addQueryParameter("client_assertion", signedJwt) - .addQueryParameter("scope", scope) - .post(TOKEN_URI, ExtensibleResource.class); - - OAuth2AccessToken oAuth2AccessToken = new OAuth2AccessToken(); - oAuth2AccessToken.setTokenType(accessTokenResponse.getString(OAuth2AccessToken.TOKEN_TYPE_KEY)); - oAuth2AccessToken.setExpiresIn(accessTokenResponse.getInteger(OAuth2AccessToken.EXPIRES_IN_KEY)); - oAuth2AccessToken.setAccessToken(accessTokenResponse.getString(OAuth2AccessToken.ACCESS_TOKEN_KEY)); - oAuth2AccessToken.setScope(accessTokenResponse.getString(OAuth2AccessToken.SCOPE_KEY)); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + MultiValueMap queryParams = new LinkedMultiValueMap<>(); + queryParams.add("grant_type", "client_credentials"); + queryParams.add("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); + queryParams.add("client_assertion", signedJwt); + queryParams.add("scope", scope); + + ResponseEntity responseEntity = apiClient.invokeAPI(TOKEN_URI, + HttpMethod.POST, + Collections.emptyMap(), + queryParams, + null, + httpHeaders, + new LinkedMultiValueMap<>(), + null, + Collections.singletonList(MediaType.APPLICATION_JSON), + MediaType.APPLICATION_JSON, + new String[] { "OAuth_2.0" }, + new ParameterizedTypeReference() {}); + + OAuth2AccessToken oAuth2AccessToken = responseEntity.getBody(); log.debug("Got OAuth2 access token for client id {} from {}", tokenClientConfiguration.getClientId(), tokenClientConfiguration.getBaseUrl() + TOKEN_URI); return oAuth2AccessToken; } catch (ResourceException e) { - //TODO: clean up the ugly casting and refactor code around it. - DefaultError defaultError = (DefaultError) e.getError(); - String errorMessage = defaultError.getString(OAuth2AccessToken.ERROR_KEY); - String errorDescription = defaultError.getString(OAuth2AccessToken.ERROR_DESCRIPTION); - defaultError.setMessage(errorMessage + " - " + errorDescription); - throw new OAuth2HttpException(defaultError, e, e.getStatus() == 401); + Error defaultError = e.getError(); + throw new OAuth2HttpException(defaultError.getMessage(), e, e.getStatus() == 401); } catch (Exception e) { throw new OAuth2TokenRetrieverException("Exception while trying to get " + "OAuth2 access token for client id " + tokenClientConfiguration.getClientId(), e); @@ -131,8 +137,8 @@ public OAuth2AccessToken getOAuth2AccessToken() throws IOException, InvalidKeyEx * We use 50 minutes in order to have a 10 minutes leeway in case of clock skew. * * @return signed JWT string - * @throws InvalidKeyException - * @throws IOException + * @throws InvalidKeyException if the supplied key is invalid + * @throws IOException if the key could not be read */ String createSignedJWT() throws InvalidKeyException, IOException { String clientId = tokenClientConfiguration.getClientId(); @@ -160,8 +166,8 @@ String createSignedJWT() throws InvalidKeyException, IOException { * * @param pemReader a {@link Reader} that has access to a full PEM resource * @return {@link PrivateKey} - * @throws IOException - * @throws InvalidKeyException + * @throws IOException if the private key could not be read + * @throws InvalidKeyException if the supplied key is invalid */ PrivateKey parsePrivateKey(Reader pemReader) throws IOException, InvalidKeyException { @@ -188,9 +194,9 @@ private Reader getPemReader() throws IOException { /** * Get Private key from input PEM file. * - * @param reader - * @return {@link PrivateKey} - * @throws IOException + * @param reader the reader instance + * @return {@link PrivateKey} private key instance + * @throws IOException if the parser could not read the reader object */ PrivateKey getPrivateKeyFromPEM(Reader reader) throws IOException { PrivateKey privateKey; @@ -233,11 +239,12 @@ ClientConfiguration constructTokenClientConfig(ClientConfiguration apiClientConf ClientConfiguration tokenClientConfiguration = new ClientConfiguration(); tokenClientConfiguration.setClientCredentialsResolver( - new DefaultClientCredentialsResolver(() -> Optional.empty())); + new DefaultClientCredentialsResolver(Optional::empty)); tokenClientConfiguration.setRequestAuthenticator(new DisabledAuthenticator()); - tokenClientConfiguration.setCacheManagerEnabled(false); + // TODO: set this to false explicitly when caching is implemented in OASv3 SDK + //tokenClientConfiguration.setCacheManagerEnabled(false); if (apiClientConfiguration.getBaseUrlResolver() != null) tokenClientConfiguration.setBaseUrlResolver(apiClientConfiguration.getBaseUrlResolver()); diff --git a/impl/src/main/java/com/okta/sdk/impl/oauth2/OAuth2HttpException.java b/impl/src/main/java/com/okta/sdk/impl/oauth2/OAuth2HttpException.java index abfcc1166d6..f24358ec59e 100644 --- a/impl/src/main/java/com/okta/sdk/impl/oauth2/OAuth2HttpException.java +++ b/impl/src/main/java/com/okta/sdk/impl/oauth2/OAuth2HttpException.java @@ -16,14 +16,13 @@ package com.okta.sdk.impl.oauth2; import com.okta.commons.http.HttpException; -import com.okta.sdk.impl.error.DefaultError; /** * @since 1.6.0 */ public class OAuth2HttpException extends HttpException { - public OAuth2HttpException(DefaultError e, Throwable cause, boolean retryable) { - super(e.getMessage(), cause, retryable); + public OAuth2HttpException(String errMsg, Throwable cause, boolean retryable) { + super(errMsg, cause, retryable); } } diff --git a/impl/src/main/java/com/okta/sdk/impl/oauth2/OAuth2TokenClient.java b/impl/src/main/java/com/okta/sdk/impl/oauth2/OAuth2TokenClient.java deleted file mode 100644 index eb78e44894c..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/oauth2/OAuth2TokenClient.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.oauth2; - -import com.okta.sdk.cache.Caches; -import com.okta.sdk.impl.client.BaseClient; -import com.okta.sdk.impl.config.ClientConfiguration; - -/** - * @since 1.6.0 - */ -public class OAuth2TokenClient extends BaseClient { - - public OAuth2TokenClient(ClientConfiguration tokenClientConfig) { - super(tokenClientConfig, Caches.newDisabledCacheManager()); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/AbstractCollectionResource.java b/impl/src/main/java/com/okta/sdk/impl/resource/AbstractCollectionResource.java deleted file mode 100644 index 5c756b668b4..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/AbstractCollectionResource.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.resource.CollectionResource; -import com.okta.sdk.resource.Resource; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * @since 0.5.0 - */ -public abstract class AbstractCollectionResource extends AbstractResource implements CollectionResource { - - private static final StringProperty NEXT_PAGE = new StringProperty("nextPage"); - private static final String ITEMS_PROPERTY_NAME = "items"; - - private final Map queryParams; - private String nextPageHref = null; - - private final AtomicBoolean firstPageQueryRequired = new AtomicBoolean(); - - protected AbstractCollectionResource(InternalDataStore dataStore) { - super(dataStore); - this.queryParams = Collections.emptyMap(); - } - - protected AbstractCollectionResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - this.queryParams = Collections.emptyMap(); - this.nextPageHref = getString(NEXT_PAGE); - } - - protected AbstractCollectionResource(InternalDataStore dataStore, Map properties, Map queryParams) { - super(dataStore, properties); - this.nextPageHref = getString(NEXT_PAGE); - if (queryParams != null) { - this.queryParams = queryParams; - } else { - this.queryParams = Collections.emptyMap(); - } - } - - @Override - public String getNextPageUrl() { - return nextPageHref; - } - - private boolean hasNextPage() { - return getNextPageUrl() != null; - } - - @Override - public T single() { - Iterator iterator = iterator(false); - if (!iterator.hasNext()) { - throw new IllegalStateException("This list is empty while it was expected to contain one (and only one) element."); - } - T itemToReturn = iterator.next(); - if (iterator.hasNext()) { - throw new IllegalStateException("Only a single resource was expected, but this list contains more than one item."); - } - return itemToReturn; - } - - @Override - public boolean isEmpty() { - return getCurrentPage().getItems().isEmpty(); - } - - protected abstract Class getItemType(); - - @SuppressWarnings("unchecked") - public Page getCurrentPage() { - - Collection items = Collections.emptyList(); - - Object value = getProperty(ITEMS_PROPERTY_NAME); - - if (value != null) { - Collection c = null; - if (value instanceof Map[]) { - Map[] vals = (Map[]) value; - if (vals.length > 0) { - c = Arrays.asList((Map[]) vals); - } - } else if (value instanceof Collection) { - Collection vals = (Collection) value; - if (vals.size() > 0) { - c = vals; - } - } - if (c != null && !c.isEmpty()) { - //do a look ahead to see if resource conversion has already taken place: - if (!getItemType().isInstance(c.iterator().next())) { - //need to convert the list of links to a list of unmaterialized Resources - items = toResourceList(c, getItemType()); - //replace the existing list of links with the newly constructed list of Resources. Don't dirty - //the instance - we're just swapping out a property that already exists for the materialized version. - setProperty(ITEMS_PROPERTY_NAME, items, false); - } else { - //the collection has already been converted to Resources - use it directly: - items = c; - } - } - } - - return new DefaultPage<>(items); - } - - private Iterator iterator(boolean firstPageQueryRequired) { - return new PaginatedIterator<>(this, firstPageQueryRequired); - } - - @Override - public Iterator iterator() { - //firstPageQueryRequired ensures that newly obtained collection resources don't need to query unnecessarily - return iterator(firstPageQueryRequired.getAndSet(true)); - } - - @Override - public Stream stream() { - return StreamSupport.stream(spliterator(), false); - } - - @Override - public Spliterator spliterator() { - return Spliterators.spliteratorUnknownSize(iterator(), Spliterator.ORDERED); - } - - private Collection toResourceList(Collection vals, Class itemType) { - - List list = new ArrayList<>(vals.size()); - - for (Object o : vals) { - Map properties = (Map) o; - T resource = toResource(itemType, properties); - list.add(resource); - } - - return list; - } - - protected T toResource(Class resourceClass, Map properties) { - return getDataStore().instantiate(resourceClass, properties); - } - - private class PaginatedIterator implements Iterator { - - private AbstractCollectionResource resource; - - private Page currentPage; - private Iterator currentPageIterator; - - private PaginatedIterator(AbstractCollectionResource resource, boolean firstPageQueryRequired) { - - if (firstPageQueryRequired) { - //We get a new resource in order to have different iterator instances: issue 62 (https://github.com/stormpath/stormpath-sdk-java/issues/62) - this.resource = getDataStore().getResource(resource.getResourceHref(), resource.getClass(), resource.queryParams); - this.currentPage = this.resource.getCurrentPage(); - } else { - this.resource = resource; - this.currentPage = resource.getCurrentPage(); - } - - this.currentPageIterator = this.currentPage.getItems().iterator(); - } - - @SuppressWarnings("unchecked") - @Override - public boolean hasNext() { - - boolean hasNext = currentPageIterator.hasNext(); - - //If we have already exhausted the whole collection size there is no need to contact the backend again - if (!hasNext && hasNextPage()) { - - //if we're done with the current page, and we've exhausted the page limit (i.e. we've read a - //full page), we will have to execute another request to check to see if another page exists. - //We can't 'trust' the current page iterator to know if more results exist on the server since it - //only represents a single page. - - AbstractCollectionResource nextResource = queryParams.isEmpty() - ? getDataStore().getResource(getNextPageUrl(), resource.getClass()) - : getDataStore().getResource(getNextPageUrl(), resource.getClass(), queryParams); - Page nextPage = nextResource.getCurrentPage(); - Iterator nextIterator = nextPage.getItems().iterator(); - - if (nextIterator.hasNext()) { - hasNext = true; - //update to reflect the new page: - this.resource = nextResource; - this.currentPage = nextPage; - this.currentPageIterator = nextIterator; - nextPageHref = nextResource.getString(NEXT_PAGE); - } - } - - return hasNext; - } - - @Override - public T next() { - return currentPageIterator.next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Remove is not supported."); - } - } - - private static class DefaultPage implements Page { - - private final Collection items; - - DefaultPage(Collection items) { - this.items = Collections.unmodifiableCollection(items); - } - - @Override - public Collection getItems() { - return this.items; - } - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/AbstractInstanceResource.java b/impl/src/main/java/com/okta/sdk/impl/resource/AbstractInstanceResource.java deleted file mode 100644 index 61cf79b86cf..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/AbstractInstanceResource.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.resource.Resource; -import com.okta.sdk.resource.Saveable; - -import java.util.Map; - -/** - * @since 0.5.0 - */ -public abstract class AbstractInstanceResource extends AbstractResource implements Saveable { - - protected AbstractInstanceResource(InternalDataStore dataStore) { - super(dataStore); - } - - protected AbstractInstanceResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - @Override - public R save() { - getDataStore().save(this); - return (R) this; - } - - /** - * Basic delete support method that simply calls, {@code dataStore.delete(this)}. This can be exposed from child - * classes when needed. - */ - protected void delete() { - writeLock.lock(); - try { - getDataStore().delete(this); - } finally { - writeLock.unlock(); - } - } - - /** - * Returns the class this resource represents. This is used when you need to figure out what the main type of - * Resource this object is. For example, DefaultFoo, ImplFoo, and SuperFoo may all represent the Resource of - * {@code Foo}, in this case this method may return Foo.class. - * (Defaults to {@code getClass()}.) - * - * @return The type of resource this class represents. - * @since 1.0 - */ - public Class getResourceClass() { - return getClass(); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/AbstractPropertyRetriever.java b/impl/src/main/java/com/okta/sdk/impl/resource/AbstractPropertyRetriever.java deleted file mode 100644 index d2a58848800..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/AbstractPropertyRetriever.java +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.fasterxml.jackson.databind.util.ISO8601DateFormat; -import com.okta.commons.lang.Assert; -import com.okta.sdk.resource.PropertyRetriever; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.DateFormat; -import java.text.ParseException; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.stream.Collectors; - -/** - * Refactored methods from {@link AbstractResource} to make them common to subclasses. - * - * @since 0.5.0 - */ -public abstract class AbstractPropertyRetriever implements PropertyRetriever { - - private static final Logger log = LoggerFactory.getLogger(AbstractPropertyRetriever.class); - - private final DateFormat dateFormatter = new ISO8601DateFormat(); - private final EnumConverter enumConverter = new EnumConverter(); - - protected final Lock readLock; - - protected final Lock writeLock; - - - protected AbstractPropertyRetriever() { - ReadWriteLock rwl = new ReentrantReadWriteLock(); - this.readLock = rwl.readLock(); - this.writeLock = rwl.writeLock(); - } - - public abstract Object getProperty(String name); - - @Override - public String getString(String key) { - return getStringProperty(key); - } - - @Override - public Integer getInteger(String key) { - return getIntProperty(key); - } - - @Override - public Double getNumber(String key) { - return getDoubleProperty(key); - } - - @Override - public Boolean getBoolean(String key) { - return getNullableBooleanProperty(key); - } - - @Override - public List getStringList(String key) { - return getListProperty(key); - } - - @Override - public List getIntegerList(String key) { - return getListProperty(key); - } - - @Override - public List getNumberList(String key) { - return getListProperty(key); - } - - protected String getString(StringProperty property) { - return getStringProperty(property.getName()); - } - - protected String getStringProperty(String key) { - Object value = getProperty(key); - if (value == null) { - return null; - } - return String.valueOf(value); - } - - protected int getInt(IntegerProperty property) { - Integer value = getIntProperty(property.getName()); - return (value == null) ? -1 : value; - } - - protected Integer getIntProperty(IntegerProperty property) { - return getIntProperty(property.getName()); - } - - protected Integer getIntProperty(String key) { - Object value = getProperty(key); - if (value != null) { - if (value instanceof String) { - return parseInt((String) value); - } else if (value instanceof Number) { - return ((Number) value).intValue(); - } - } - return null; - } - - protected Double getDoubleProperty(DoubleProperty property) { - return getDoubleProperty(property.getName()); - } - - protected Double getDoubleProperty(String key) { - Object value = getProperty(key); - if (value != null) { - if (value instanceof String) { - return parseDouble((String) value); - } else if (value instanceof Number) { - return ((Number) value).doubleValue(); - } - } - return null; - } - - protected boolean getBoolean(BooleanProperty property) { - return getBooleanProperty(property.getName()); - } - - /** - * Returns an actual boolean value instead of a possible null Boolean value since desired usage - * is to have either a true or false. - * @param key the identifier - * @return a boolean representation of the value (null == false) - */ - protected Boolean getBooleanProperty(String key) { - return Boolean.TRUE.equals(getNullableBooleanProperty(key)); - } - - protected Boolean getNullableBoolean(BooleanProperty property) { - return getNullableBooleanProperty(property.getName()); - } - - protected Boolean getNullableBooleanProperty(String key) { - Object value = getProperty(key); - if (value != null) { - if (value instanceof Boolean) { - return (Boolean) value; - } else if (value instanceof String) { - return Boolean.valueOf((String) value); - } - } - return null; - } - - private int parseInt(String value) { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - if (log.isErrorEnabled()) { - String msg = "Unable to parse string '{}' into an integer value. Defaulting to -1"; - log.error(msg, e); - } - } - return -1; - } - - private double parseDouble(String value) { - try { - return Double.parseDouble(value); - } catch (NumberFormatException e) { - if (log.isErrorEnabled()) { - String msg = "Unable to parse string '{}' into an double value. Defaulting to -1"; - log.error(msg, e); - } - } - return -1; - } - - protected Date getDateProperty(DateProperty key) { - Object value = getProperty(key.getName()); - if (value == null) { - return null; - } - - if(value instanceof Date) { - return (Date)value; - } - - try { - return dateFormatter.parse(String.valueOf(value)); - } catch (ParseException e) { - if (log.isErrorEnabled()) { - String msg = "Unabled to parse string '{}' into an date value. Defaulting to null."; - log.error(msg, e); - } - } - return null; - } - - /** - * Returns the {@link List} property identified by {@code key} - * @param key the identifier - * @return a List - * - */ - protected List getListProperty(String key) { - return (List) getProperty(key); - } - - /** - * Returns the {@link List} property identified by {@code key} - * @param property identifier - * @return property identified by {@code property} - */ - protected List getListProperty(ListProperty property){ - return getListProperty(property.getName()); - } - - /** - * Returns the {@link List} property identified by {@code key} - * @param property identifier - * @return property identified by {@code property} - */ - protected List getEnumListProperty(EnumListProperty property){ - List rawList = (List) getProperty(property.getName()); - - return (rawList == null) ? null : (List) rawList.stream() - .map(item -> enumConverter.fromValue(property.getType(), item)) - .collect(Collectors.toList()); - } - - protected Map getMap(MapProperty mapProperty) { - return getMapProperty(mapProperty.getName()); - } - - protected Map getNonEmptyMap(MapProperty mapProperty) { - Map result = getMap(mapProperty); - return result != null ? result : Collections.emptyMap(); - } - - protected Map getMapProperty(String key) { - Object value = getProperty(key); - if (value != null) { - if (value instanceof Map) { - return (Map) value; - } - String msg = "'" + key + "' property value type does not match the specified type. Specified type: Map. " + - "Existing type: " + value.getClass().getName(); - msg += isPrintableProperty(key) ? ". Value: " + value : "."; - throw new IllegalArgumentException(msg); - } - return null; - } - - protected > E getEnumProperty(EnumProperty enumProperty) { - return getEnumProperty(enumProperty.getName(), enumProperty.getType()); - } - - protected > E getEnumProperty(String key, Class type) { - Assert.notNull(type, "type cannot be null."); - - Object value = getProperty(key); - - if (value != null) { - if (value instanceof String) { - E convertedValue; - try { - convertedValue = enumConverter.fromValue(type, value.toString()); - } catch (IllegalArgumentException e) { - convertedValue = enumConverter.fromValue(type, "SDK_UNKNOWN"); - String msg = "Undeclared enum value {}.{}. Defaulting to SDK_UNKNOWN. " + - "Call get(\"{}\", String.class) to receive raw value."; - log.warn(msg, type.getSimpleName(), value, key); - } - return convertedValue; - } - if (type.isAssignableFrom(value.getClass())) { - //noinspection unchecked - return (E) value; - } - } - return null; - } - - protected char[] getCharArray(CharacterArrayProperty property) { - - Object value = getProperty(property.getName()); - if (value instanceof char[]) { - return (char[]) value; - } else if (value != null) { - return value.toString().toCharArray(); - } - return null; - } - - /** - * Returns {@code true} if the internal property is safe to print in toString(), {@code false} otherwise. - * - * @param name The name of the property to check for safe printing - * @return {@code true} if the internal property is safe to print in toString(), {@code false} otherwise. - */ - protected boolean isPrintableProperty(String name) { - return true; - } - - protected void setProperty(Property property, Object value) { - if(property.getType().isEnum() && value.toString().equals("SDK_UNKNOWN")) { - throw new IllegalArgumentException( - "The " + property.getType() + ".SDK_UNKNOWN value can not be used in setter." + - " Try to use put(\"" + property.getName() + "\", )"); - } else if(property.getType().isEnum() - && value instanceof List - && ((List) value).stream().anyMatch(x -> x.toString().equals("SDK_UNKNOWN"))) { - throw new IllegalArgumentException( - "The " + property.getType() + ".SDK_UNKNOWN value can not be used in setter." + - " Try to use put(\"" + property.getName() + "\", )"); - } - setProperty(property.getName(), value, true); - } - - public void setProperty(String name, Object value) { - setProperty(name, value, true); - } - - protected abstract Object setProperty(String name, Object value, final boolean dirty); - - protected abstract Map getInternalProperties(); - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/AbstractResource.java b/impl/src/main/java/com/okta/sdk/impl/resource/AbstractResource.java deleted file mode 100644 index 701e141083f..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/AbstractResource.java +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.commons.lang.Assert; -import com.okta.commons.lang.Collections; -import com.okta.commons.lang.Strings; -import com.okta.sdk.resource.CollectionResource; -import com.okta.sdk.resource.Resource; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @since 0.5.0 - */ -public abstract class AbstractResource extends AbstractPropertyRetriever implements Resource { - - private final Map dirtyProperties; //Protected by read/write lock - private final Set deletedPropertyNames; //Protected by read/write lock - private final InternalDataStore dataStore; - protected Map properties; //Protected by read/write lock - private String href = null; - private volatile boolean dirty; - private volatile boolean materialized; - private final ResourceHrefResolver hrefResolver; - - protected AbstractResource(InternalDataStore dataStore) { - this(dataStore, null); - } - - protected AbstractResource(InternalDataStore dataStore, Map properties) { - this.dataStore = dataStore; - this.dirtyProperties = new LinkedHashMap<>(); - this.deletedPropertyNames = new HashSet<>(); - this.properties = new LinkedHashMap<>(); - this.hrefResolver = new OktaResourceHrefResolver(); - setInternalProperties(properties); - } - - protected static Map createPropertyDescriptorMap(Property... props) { - return createPropertyDescriptorMap(new LinkedHashMap<>(), props); - } - - protected static Map createPropertyDescriptorMap(Map existingProperties, Property... props) { - for (Property prop : props) { - existingProperties.put(prop.getName(), prop); - } - return existingProperties; - } - - public abstract Map getPropertyDescriptors(); - - public void setInternalProperties(Map properties) { - writeLock.lock(); - try { - this.dirtyProperties.clear(); - this.dirty = false; - if (properties != null && !properties.isEmpty()) { - if (this.properties != properties) { - this.properties.clear(); - this.properties.putAll(properties); - } else { - this.properties = properties; - } - setResourceHref(hrefResolver.resolveHref(properties, getClass())); - // Don't consider this resource materialized if it is only a reference. A reference is any object that - // has only one 'href' property. - - // TODO: validate this flow -// boolean hrefOnly = this.properties.size() == 1 && this.properties.containsKey(HREF_PROP_NAME); -// this.materialized = !hrefOnly; - this.materialized = this.properties.size() > 0; - } else { - this.materialized = false; - } - } finally { - writeLock.unlock(); - } - } - - public String getResourceHref() { - return this.href; - } - - public void setResourceHref(String href) { - this.href = href; - } - - protected final InternalDataStore getDataStore() { - return this.dataStore; - } - - private boolean isMaterialized() { - return this.materialized; - } - - /** - * Returns {@code true} if the resource's properties have been modified in anyway since the resource instance was - * created. - * - * @return {@code true} {@code true} if the resource's properties have been modified in anyway since the resource - * instance was created - */ - public final boolean isDirty() { - return this.dirty; - } - - /** - * Returns {@code true} if the resource doesn't yet have an assigned 'href' property, {@code false} otherwise. - * - * @return {@code true} if the resource doesn't yet have an assigned 'href' property, {@code false} otherwise. - */ - private boolean isNew() { - String href = getResourceHref(); - return !Strings.hasText(href); - } - - public void materialize() { - if (this.materialized) { - return; - } - AbstractResource resource = dataStore.getResource(getResourceHref(), getClass()); - writeLock.lock(); - try { - if (this.properties != resource.properties) { - this.properties.clear(); - this.properties.putAll(resource.properties); - } - - //retain dirty properties: - this.properties.putAll(this.dirtyProperties); - - this.materialized = true; - } finally { - writeLock.unlock(); - } - } - - public Set getPropertyNames() { - readLock.lock(); - try { - Set keys = this.properties.keySet(); - return new LinkedHashSet<>(keys); - } finally { - readLock.unlock(); - } - } - - public Set getUpdatedPropertyNames() { - readLock.lock(); - try { - Set keys = this.dirtyProperties.keySet(); - return new LinkedHashSet<>(keys); - } finally { - readLock.unlock(); - } - } - - protected Set getDeletedPropertyNames() { - readLock.lock(); - try { - return new LinkedHashSet<>(this.deletedPropertyNames); - } finally { - readLock.unlock(); - } - } - - public Object getProperty(String name) { - //not the href/id, must be a property that requires materialization: - if (!isNew() && !isMaterialized()) { - - //only materialize if the property hasn't been set previously (no need to execute a server - // request since we have the most recent value already): - boolean present; - readLock.lock(); - try { - present = this.dirtyProperties.containsKey(name); - } finally { - readLock.unlock(); - } - - if (!present) { - //exhausted present properties - we require a server call: - materialize(); - } - } - - return readProperty(name); - } - - /** - * Returns {@code true} if this resource has a property with the specified name, {@code false} otherwise. - * - * @param name the name of the property to check for existence - * @return {@code true} if this resource has a property with the specified name, {@code false} otherwise. - */ - public boolean hasProperty(String name) { - readLock.lock(); - try { - return !this.deletedPropertyNames.contains(name) && - (this.dirtyProperties.containsKey(name) || this.properties.containsKey(name)); - } finally { - readLock.unlock(); - } - } - - private Object readProperty(String name) { - readLock.lock(); - try { - if (this.deletedPropertyNames.contains(name)) { - return null; - } - Object value = this.dirtyProperties.get(name); - if (value == null) { - value = this.properties.get(name); - } - return value; - } finally { - readLock.unlock(); - } - } - - /** - */ - protected Object setProperty(String name, Object value, final boolean dirty) { - return setProperty(name, value, dirty, true); - } - - /** - * Use this method and the set the isNullable flag to true, to set the value to - * null for the Property. Certain properties can have a value=null in the REST API - * and therefore, this method will allow to explicitly do that. - * All other overloaded implementations of setProperty method will assume isNullable=false - * and therefore setting the value to null by calling those methods, will take no effect and - * retain the old/previous value for the property. - * @param property the key of the value to set - * @param value the actual value to be set - * @param dirty mark the object as dirty if true - * @param isNullable true if the value can be set to {@code null} - */ - protected void setProperty(Property property, Object value, final boolean dirty, final boolean isNullable) { - setProperty(property.getName(), value, dirty, isNullable); - } - - private Object setProperty(String name, Object value, final boolean dirty, final boolean isNullable) { - writeLock.lock(); - Object previous; - try { - previous = this.dirtyProperties.put(name, value); - if (previous == null) { - previous = this.properties.get(name); - } - this.dirty = dirty; - - /* - * The instance variable "deletedPropertyNames" is overloaded here. - * For "CustomData" value=null means that the property/field has been deleted from custom data, - * hence it is added to "deletedPropertyNames". See DefaultCustomData.java - * In this case, where value=null and the field is nullable, adding it to "deletedPropertyNames" forces - * and makes sure that the property is saved with value=null (but not deleted). - * e.g. matchingProperty in AccountLinkingPolicy - */ - if (isNullable && value == null) { //fix for https://github.com/stormpath/stormpath-sdk-java/issues/966 - this.deletedPropertyNames.add(name); - } else { - if (this.deletedPropertyNames.contains(name)) { - this.deletedPropertyNames.remove(name); - } - } - } finally { - writeLock.unlock(); - } - return previous; - } - - @SuppressWarnings("unchecked") - protected T getResourceProperty(ResourceReference property) { - String key = property.getName(); - Class clazz = property.getType(); - - Object value = getProperty(key); - if (value == null) { - - if (property.isCreateOnAccess()) { - // create the new resource as an empty object so the developer does not need to deal with - // calling .instantiate directly - T resource = dataStore.instantiate(clazz); - setProperty(key, resource, false); - return resource; - } - return null; - } - - if (clazz.isInstance(value)) { - return (T) value; - } - - if (value instanceof Map) { - T resource = dataStore.instantiate(clazz, (Map) value); - - //replace the existing link object (map with an href) with the newly constructed Resource instance. - //Don't dirty the instance - we're just swapping out a property that already exists for the materialized version. - //let's not materialize internal collection resources, so they are always retrieved from the backend: https://github.com/stormpath/stormpath-sdk-java/issues/160 - if (!CollectionResource.class.isAssignableFrom(clazz)) { - setProperty(key, resource, false); - } - return resource; - } - - String msg = "'" + key + "' property value type does not match the specified type. Specified type: " + - clazz.getName() + ". Existing type: " + value.getClass().getName(); - msg += isPrintableProperty(key) ? ". Value: " + value : "."; - throw new IllegalArgumentException(msg); - } - - /** - * Returns the {@link List} property identified by {@code key} - * @param property identifier - * @return property identified by {@code property} - */ - protected List getResourceListProperty(ResourceListProperty property){ - List rawList = (List) getProperty(property.getName()); - - return (rawList == null) ? null : (List) rawList.stream() - .map(item -> { - if (property.getType().isInstance(item)) { - return item; - } else { - return dataStore.instantiate(property.getType(), (Map) item); - } - }) - .collect(Collectors.toList()); - } - - public String toString() { - readLock.lock(); - try { - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : this.properties.entrySet()) { - if (sb.length() > 0) { - sb.append(", "); - } - String key = entry.getKey(); - //prevent printing of any sensitive values: - if (isPrintableProperty(key)) { - sb.append(key).append(": ").append(String.valueOf(entry.getValue())); - } - } - return sb.toString(); - } finally { - readLock.unlock(); - } - } - - /** - * Returns {@code true} if the internal property is safe to print in toString(), {@code false} otherwise. - * - * @param name The name of the property to check for safe printing - * @return {@code true} if the internal property is safe to print in toString(), {@code false} otherwise. - */ - protected boolean isPrintableProperty(String name) { - return true; - } - - @Override - public int hashCode() { - readLock.lock(); - try { - return this.properties.isEmpty() ? 0 : this.properties.hashCode(); - } finally { - readLock.unlock(); - } - } - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } - if (this == o) { - return true; - } - if (!o.getClass().equals(getClass())) { - return false; - } - AbstractResource other = (AbstractResource) o; - readLock.lock(); - try { - other.readLock.lock(); - try { - return this.properties.equals(other.properties); - } finally { - other.readLock.unlock(); - } - } finally { - readLock.unlock(); - } - } - - @Override - protected Map getInternalProperties() { - return properties; - } - - - /* -------------------------------------------------------------------------------------- - Map methods: child classes can implement Map to expose these methods - -------------------------------------------------------------------------------------- */ - - public int size() { - readLock.lock(); - try { - Set keySet = new LinkedHashSet<>(); - keySet.addAll(this.properties.keySet()); - keySet.addAll(this.dirtyProperties.keySet()); - keySet.removeAll(this.deletedPropertyNames); - return keySet.size(); - } finally { - readLock.unlock(); - } - } - - public boolean isEmpty() { - return this.size() <= 0; - } - - @SuppressWarnings("SuspiciousMethodCalls") - public boolean containsKey(Object key) { - return this.keySet().contains(key); - } - - public boolean containsValue(Object value) { - for(Map.Entry entry: this.entrySet()) { - if(entry.getValue().equals(value)) { - return true; - } - } - return false; - } - - public Object get(Object key) { - Assert.isInstanceOf(String.class, key); - return getProperty(key.toString()); - } - - public Object put(String key, Object value) { - return setProperty(key, value, true); - } - - public Object remove(Object key) { - Assert.isInstanceOf(String.class, key); - writeLock.lock(); - try { - //noinspection SuspiciousMethodCalls - Object object = this.dirtyProperties.remove(key); - this.deletedPropertyNames.add(key.toString()); - this.dirty = true; - return object; - } finally { - writeLock.unlock(); - } - } - - public void putAll(Map m) { - if (Collections.isEmpty(m)) { - return; - } - Set> entrySet = m.entrySet(); - writeLock.lock(); - try { - for (Map.Entry entry : entrySet) { - setProperty(entry.getKey(), entry.getValue()); - } - } finally { - writeLock.unlock(); - } - } - - public void clear() { - - writeLock.lock(); - try { - Set propertiesToFilter = new HashSet<>(getPropertyDescriptors().keySet()); - for (String propertyName : this.keySet()) { - if (propertiesToFilter.contains(propertyName)) { - continue; - } - this.dirtyProperties.remove(propertyName); - this.deletedPropertyNames.add(propertyName); - dirty = true; - } - } finally { - writeLock.unlock(); - } - } - - public Set keySet() { - if(!isMaterialized()) { - writeLock.lock(); - try { - materialize(); - } finally { - writeLock.unlock(); - } - } - readLock.lock(); - try { - Set keySet = new LinkedHashSet(); - keySet.addAll(this.properties.keySet()); - keySet.addAll(this.dirtyProperties.keySet()); - keySet.removeAll(this.deletedPropertyNames); - return java.util.Collections.unmodifiableSet(keySet); - } finally { - readLock.unlock(); - } - } - - public Collection values() { - Set keySet = this.keySet(); - Collection values = new ArrayList<>(keySet.size()); - for (String key : keySet) { - values.add(this.get(key)); - } - return java.util.Collections.unmodifiableCollection(values); - } - - public Set> entrySet() { - Set keySet = this.keySet(); - readLock.lock(); - try { - Set> entrySet = new LinkedHashSet>(keySet.size()); - for(String key : keySet) { - entrySet.add(new AbstractMap.SimpleEntry(key, this.get(key))); - } - return java.util.Collections.unmodifiableSet(entrySet); - } finally { - readLock.unlock(); - } - } - - /** - * Parses path parameters from URL based on a template string. - *

    - * Example: - * For the template string: {@code /users/{userId}/favorite/{iceCream}}, and the href of this resource: - * {@code /users/42/favorite/vanilla}}, the resulting map would be: {@code [userId: 42, iceCream: vanilla]}. - * - * @param templateUrl template of the URL to parse - * @return a map of path parameters - * @since 0.8.0 - */ - protected Map getParamsFromHref(String templateUrl) { - Assert.hasText(href, "Resource 'href' must be set before attempting to call an operation."); - Assert.hasText(templateUrl, "Template URL must not be empty."); - Map resultMap = new HashMap<>(); - - try { - String hrefPath = new URI(href).getPath(); - - Iterator templatePartsIter = Arrays.asList(templateUrl.split("/")).iterator(); - Iterator hrefPartsIter = Arrays.asList(hrefPath.split("/")).iterator(); - - while (templatePartsIter.hasNext() && hrefPartsIter.hasNext()) { - String templatePart = templatePartsIter.next(); - String hrefPart = hrefPartsIter.next(); - - // if the template string starts with '{' we have named path param - if (templatePart.startsWith("{") && templatePart.endsWith("}")) { - String paramName = templatePart.substring(1,templatePart.length()-1); - resultMap.put(paramName, hrefPart); - } else if (!Objects.equals(templatePart, hrefPart)) { - // otherwise break, the template and the href no longer match - break; - } - // otherwise the parts match, just continue - } - } catch (URISyntaxException e) { - throw new URIParseException("Invalid URI for resource: " + href, e); - } - return resultMap; - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/ArrayProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/ArrayProperty.java deleted file mode 100644 index f6218a091c0..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/ArrayProperty.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.resource.Resource; - -/** - * @since 0.5.0 - */ -public class ArrayProperty extends Property { - - public ArrayProperty(String name, Class type) { - super(name, type); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/BooleanProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/BooleanProperty.java deleted file mode 100644 index 24b044954ce..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/BooleanProperty.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -/** - * @since 0.5.0 - */ -public class BooleanProperty extends Property { - - public BooleanProperty(String name) { - super(name, Boolean.class); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/CharacterArrayProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/CharacterArrayProperty.java deleted file mode 100644 index 38481e4be30..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/CharacterArrayProperty.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -/** - * @since 1.0 - */ -public class CharacterArrayProperty extends Property { - - public CharacterArrayProperty(String name) { - super(name, char[].class); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DateProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/DateProperty.java deleted file mode 100644 index 8af7fdc81c9..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DateProperty.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import java.util.Date; - -/** - * @since 0.5.0 - */ -public class DateProperty extends Property { - - public DateProperty(String name) { - super(name, Date.class); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultApplicationBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultApplicationBuilder.java index 645d7c2e101..a8ddebf8ab5 100644 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultApplicationBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultApplicationBuilder.java @@ -16,8 +16,13 @@ package com.okta.sdk.impl.resource; import com.okta.commons.lang.Strings; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.application.*; +import com.okta.sdk.resource.application.ApplicationBuilder; +import org.openapitools.client.api.ApplicationApi; +import org.openapitools.client.model.Application; +import org.openapitools.client.model.ApplicationAccessibility; +import org.openapitools.client.model.ApplicationSignOnMode; +import org.openapitools.client.model.ApplicationVisibility; +import org.openapitools.client.model.ApplicationVisibilityHide; import java.util.Objects; @@ -32,7 +37,6 @@ public class DefaultApplicationBuilder implements protected Boolean iOS; protected Boolean web; - @Override public T setName(String name) { this.name = name; @@ -65,10 +69,6 @@ public T setSelfService(Boolean selfService) { @Override public T setSignOnMode(ApplicationSignOnMode signOnMode) { - if(signOnMode == ApplicationSignOnMode.SDK_UNKNOWN) { - throw new IllegalArgumentException( - "The " + signOnMode.getClass().getName() + ".SDK_UNKNOWN can not be used in setter"); - } this.signOnMode = signOnMode; return self(); } @@ -89,22 +89,18 @@ public T setWeb(Boolean web) { protected T self() { return (T) this;} @Override - public Application buildAndCreate(Client client) { return client.createApplication(build(client)); } - - private Application build(Client client){ + public Application buildAndCreate(ApplicationApi client) { return client.createApplication(build(), false, null); } - Application application = client.instantiate(Application.class); + private Application build(){ - if (Strings.hasText(name)) - ((AbstractResource)application).setProperty("name", name, true); + Application application = new Application(); if (Strings.hasText(label)) application.setLabel(label); if (Objects.nonNull(signOnMode)) application.setSignOnMode(signOnMode); // Accessibility - application.setAccessibility(client.instantiate(ApplicationAccessibility.class)); - ApplicationAccessibility applicationAccessibility = application.getAccessibility(); + ApplicationAccessibility applicationAccessibility = new ApplicationAccessibility(); if (Strings.hasText(loginRedirectUrl)) applicationAccessibility.setLoginRedirectUrl(loginRedirectUrl); @@ -115,18 +111,22 @@ private Application build(Client client){ if (Objects.nonNull(selfService)) applicationAccessibility.setSelfService(selfService); + application.setAccessibility(applicationAccessibility); + // Visibility - application.setVisibility(client.instantiate(ApplicationVisibility.class)); - ApplicationVisibility applicationVisibility = application.getVisibility(); - ApplicationVisibilityHide applicationVisibilityHide = client.instantiate(ApplicationVisibilityHide.class); + ApplicationVisibility applicationVisibility = new ApplicationVisibility(); + + ApplicationVisibilityHide applicationVisibilityHide = new ApplicationVisibilityHide(); + + if (Objects.nonNull(iOS)) + applicationVisibilityHide.setiOS(iOS); + + if (Objects.nonNull(web)) + applicationVisibilityHide.setWeb(web); - if(Objects.nonNull(iOS)) - applicationVisibility.setHide(applicationVisibilityHide - .setIOS(iOS)); + applicationVisibility.setHide(applicationVisibilityHide); - if(Objects.nonNull(web)) - applicationVisibility.setHide(applicationVisibilityHide - .setWeb(web)); + application.setVisibility(applicationVisibility); return application; } diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultExtensibleResource.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultExtensibleResource.java deleted file mode 100644 index 6d300fcd125..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultExtensibleResource.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2018-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.resource.ExtensibleResource; - -import java.util.Collections; -import java.util.Map; - -/** - * Default implementation of {@link ExtensibleResource}. - * - * @since 1.2.0 - */ -public class DefaultExtensibleResource extends AbstractResource implements ExtensibleResource { - - public DefaultExtensibleResource(InternalDataStore dataStore) { - super(dataStore); - } - - public DefaultExtensibleResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - @Override - public Map getPropertyDescriptors() { - return Collections.emptyMap(); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultFileResource.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultFileResource.java deleted file mode 100644 index 9df6f69d337..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultFileResource.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2021-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.resource.FileResource; - -import java.nio.file.Path; -import java.util.Collections; -import java.util.Map; - -public class DefaultFileResource extends AbstractResource implements FileResource { - - private final Path path; - private final String formDataName; - - public DefaultFileResource(InternalDataStore dataStore, Path filePath, String formDataName) { - super(dataStore); - this.path = filePath; - this.formDataName = formDataName; - } - - @Override - public String getLocation() { - return path.toAbsolutePath().toString(); - } - - @Override - public String getFormDataName() { - return formDataName; - } - - @Override - public Map getPropertyDescriptors() { - return Collections.emptyMap(); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultGroupBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultGroupBuilder.java index f2ed2907cd5..35d6dc2b727 100644 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultGroupBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultGroupBuilder.java @@ -15,11 +15,11 @@ */ package com.okta.sdk.impl.resource; -import com.okta.sdk.client.Client; import com.okta.commons.lang.Strings; import com.okta.sdk.resource.group.GroupBuilder; -import com.okta.sdk.resource.group.Group; -import com.okta.sdk.resource.group.GroupProfile; +import org.openapitools.client.api.GroupApi; +import org.openapitools.client.model.Group; +import org.openapitools.client.model.GroupProfile; public class DefaultGroupBuilder implements GroupBuilder { @@ -39,13 +39,14 @@ public GroupBuilder setDescription(String description) { } @Override - public Group buildAndCreate(Client client) { + public Group buildAndCreate(GroupApi client) { - Group group = client.instantiate(Group.class); - group.setProfile(client.instantiate(GroupProfile.class)); - group.getProfile().setName(name); - if (Strings.hasText(description)) group.getProfile().setDescription(description); + Group group = new Group(); + GroupProfile groupProfile = new GroupProfile(); + groupProfile.setName(name); + if (Strings.hasText(description)) groupProfile.setDescription(description); + group.setProfile(groupProfile); return client.createGroup(group); } -} +} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultGroupRuleBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultGroupRuleBuilder.java deleted file mode 100644 index afdbca58270..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultGroupRuleBuilder.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.commons.lang.Collections; -import com.okta.commons.lang.Strings; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.group.rule.*; - -import java.util.ArrayList; -import java.util.List; - -public class DefaultGroupRuleBuilder implements GroupRuleBuilder { - - private String name; - private String type; - private List assignUserToGroups = new ArrayList<>(); - private List groupIds = new ArrayList<>(); - private List userIds = new ArrayList<>(); - private String groupRuleExpressionType; - private String groupRuleExpressionValue; - - @Override - public GroupRuleBuilder setName(String name) { - this.name = name; - return this; - } - - @Override - public GroupRuleBuilder setType(String type) { - this.type = type; - return this; - } - - @Override - public GroupRuleBuilder setAssignUserToGroups(List assignUserToGroups) { - this.assignUserToGroups = assignUserToGroups; - return this; - } - - @Override - public GroupRuleBuilder setGroups(List groupIds) { - this.groupIds = groupIds; - return this; - } - - @Override - public GroupRuleBuilder addGroup(String groupId) { - this.groupIds.add(groupId); - return this; - } - - @Override - public GroupRuleBuilder setUsers(List userIds) { - this.userIds = userIds; - return this; - } - - @Override - public GroupRuleBuilder addUser(String userId) { - this.userIds.add(userId); - return this; - } - - @Override - public GroupRuleBuilder setGroupRuleExpressionType(String groupRuleExpressionType) { - this.groupRuleExpressionType = groupRuleExpressionType; - return this; - } - - @Override - public GroupRuleBuilder setGroupRuleExpressionValue(String groupRuleExpressionValue) { - this.groupRuleExpressionValue = groupRuleExpressionValue; - return this; - } - - @Override - public GroupRule buildAndCreate(Client client) { - return client.createGroupRule(build(client)); - } - - private GroupRule build(Client client){ - GroupRule groupRule = client.instantiate(GroupRule.class); - - if (Strings.hasText(name)) groupRule.setName(name); - - if (Strings.hasText(type)) groupRule.setType(type); - - // Actions - groupRule.setActions(client.instantiate(GroupRuleAction.class)); - GroupRuleAction groupRuleActions = groupRule.getActions(); - - if (!Collections.isEmpty(assignUserToGroups)) - groupRuleActions.setAssignUserToGroups(client.instantiate(GroupRuleGroupAssignment.class) - .setGroupIds(assignUserToGroups)); - - // Conditions - groupRule.setConditions(client.instantiate(GroupRuleConditions.class)); - GroupRuleConditions groupRuleConditions = groupRule.getConditions(); - GroupRulePeopleCondition groupRulePeopleCondition = client.instantiate(GroupRulePeopleCondition.class); - - if (!Collections.isEmpty(groupIds)) - groupRuleConditions.setPeople(groupRulePeopleCondition - .setGroups(client.instantiate(GroupRuleGroupCondition.class) - .setInclude(groupIds))); - - if (!Collections.isEmpty(userIds)) - groupRuleConditions.setPeople(groupRulePeopleCondition - .setUsers(client.instantiate(GroupRuleUserCondition.class) - .setInclude(userIds))); - - GroupRuleExpression groupRuleExpression = client.instantiate(GroupRuleExpression.class); - - if (Strings.hasText(groupRuleExpressionType)) - groupRuleConditions.setExpression(groupRuleExpression.setType(groupRuleExpressionType)); - - if (Strings.hasText(groupRuleExpressionValue)) - groupRuleConditions.setExpression(groupRuleExpression.setValue(groupRuleExpressionValue)); - - return groupRule; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultOIDCApplicationBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultOIDCApplicationBuilder.java index f00d4188ac6..3c6e57c9a70 100644 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultOIDCApplicationBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultOIDCApplicationBuilder.java @@ -16,8 +16,24 @@ package com.okta.sdk.impl.resource; import com.okta.commons.lang.Strings; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.application.*; +import com.okta.sdk.resource.application.OIDCApplicationBuilder; +import org.openapitools.client.api.ApplicationApi; +import org.openapitools.client.model.ApplicationAccessibility; +import org.openapitools.client.model.ApplicationCredentialsOAuthClient; +import org.openapitools.client.model.ApplicationSignOnMode; +import org.openapitools.client.model.ApplicationVisibility; +import org.openapitools.client.model.ApplicationVisibilityHide; +import org.openapitools.client.model.JsonWebKey; +import org.openapitools.client.model.OAuthApplicationCredentials; +import org.openapitools.client.model.OAuthEndpointAuthenticationMethod; +import org.openapitools.client.model.OAuthGrantType; +import org.openapitools.client.model.OAuthResponseType; +import org.openapitools.client.model.OpenIdConnectApplication; +import org.openapitools.client.model.OpenIdConnectApplicationConsentMethod; +import org.openapitools.client.model.OpenIdConnectApplicationSettings; +import org.openapitools.client.model.OpenIdConnectApplicationSettingsClient; +import org.openapitools.client.model.OpenIdConnectApplicationSettingsClientKeys; +import org.openapitools.client.model.OpenIdConnectApplicationType; import java.util.ArrayList; import java.util.List; @@ -40,7 +56,8 @@ public class DefaultOIDCApplicationBuilder extends DefaultApplicationBuilder jsonWebKeyList = new ArrayList<>(); - + private Boolean isImplicitAssignment; + private String inlineHookId; @Override public OIDCApplicationBuilder setApplicationType(OpenIdConnectApplicationType applicationType) { @@ -151,18 +168,29 @@ public OIDCApplicationBuilder setJwks(List jsonWebKeyList) { } @Override - public OpenIdConnectApplication buildAndCreate(Client client){ return (OpenIdConnectApplication) client.createApplication(build(client)); } + public OIDCApplicationBuilder setImplicitAssignment(Boolean isImplicitAssignment) { + this.isImplicitAssignment = isImplicitAssignment; + return this; + } - private Application build(Client client){ - OpenIdConnectApplication application = client.instantiate(OpenIdConnectApplication.class); + @Override + public OIDCApplicationBuilder setInlineHookId(String inlineHookId) { + this.inlineHookId = inlineHookId; + return this; + } + + @Override + public OpenIdConnectApplication buildAndCreate(ApplicationApi client){ return client.createApplication(OpenIdConnectApplication.class, build(), false, null); } + + private OpenIdConnectApplication build(){ + OpenIdConnectApplication application = new OpenIdConnectApplication(); if (Strings.hasText(label)) application.setLabel(label); - if (Objects.nonNull(signOnMode)) application.setSignOnMode(signOnMode); + application.setSignOnMode(ApplicationSignOnMode.OPENID_CONNECT); // Accessibility - application.setAccessibility(client.instantiate(ApplicationAccessibility.class)); - ApplicationAccessibility applicationAccessibility = application.getAccessibility(); + ApplicationAccessibility applicationAccessibility = new ApplicationAccessibility(); if (Strings.hasText(loginRedirectUrl)) applicationAccessibility.setLoginRedirectUrl(loginRedirectUrl); @@ -173,88 +201,101 @@ private Application build(Client client){ if (Objects.nonNull(selfService)) applicationAccessibility.setSelfService(selfService); + application.setAccessibility(applicationAccessibility); + // Visibility - application.setVisibility(client.instantiate(ApplicationVisibility.class)); - ApplicationVisibility applicationVisibility = application.getVisibility(); - ApplicationVisibilityHide applicationVisibilityHide = client.instantiate(ApplicationVisibilityHide.class); + ApplicationVisibility applicationVisibility = new ApplicationVisibility(); + + ApplicationVisibilityHide applicationVisibilityHide = new ApplicationVisibilityHide(); - if(Objects.nonNull(iOS)) - applicationVisibility.setHide(applicationVisibilityHide - .setIOS(iOS)); + if (Objects.nonNull(iOS)) + applicationVisibilityHide.setiOS(iOS); - if(Objects.nonNull(web)) - applicationVisibility.setHide(applicationVisibilityHide - .setWeb(web)); + if (Objects.nonNull(web)) + applicationVisibilityHide.setWeb(web); + + applicationVisibility.setHide(applicationVisibilityHide); + + application.setVisibility(applicationVisibility); // Settings - application.setSettings(client.instantiate(OpenIdConnectApplicationSettings.class)); - OpenIdConnectApplicationSettings openIdConnectApplicationSettings = application.getSettings(); - OpenIdConnectApplicationSettingsClient openIdConnectApplicationSettingsClient= client.instantiate(OpenIdConnectApplicationSettingsClient.class); + OpenIdConnectApplicationSettings openIdConnectApplicationSettings = new OpenIdConnectApplicationSettings(); + + OpenIdConnectApplicationSettingsClient openIdConnectApplicationSettingsClient = new OpenIdConnectApplicationSettingsClient(); if (Strings.hasText(clientUri)) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setClientUri(clientUri)); + openIdConnectApplicationSettingsClient.setClientUri(clientUri); if (Strings.hasText(logoUri)) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setLogoUri(logoUri)); + openIdConnectApplicationSettingsClient.setLogoUri(logoUri); if (Strings.hasText(policyUri)) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setPolicyUri(policyUri)); + openIdConnectApplicationSettingsClient.setPolicyUri(policyUri); if (Strings.hasText(tosUri)) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setTosUri(tosUri)); + openIdConnectApplicationSettingsClient.setTosUri(tosUri); if (Objects.nonNull(postLogoutRedirectUris) && !postLogoutRedirectUris.isEmpty()) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setPostLogoutRedirectUris(postLogoutRedirectUris)); + openIdConnectApplicationSettingsClient.setPostLogoutRedirectUris(postLogoutRedirectUris); if (Objects.nonNull(redirectUris)) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setRedirectUris(redirectUris)); + openIdConnectApplicationSettingsClient.setRedirectUris(redirectUris); if (Objects.nonNull(responseTypes) && responseTypes.size()>0) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setResponseTypes(responseTypes)); + openIdConnectApplicationSettingsClient.setResponseTypes(responseTypes); else throw new IllegalArgumentException("Response Type cannot be null, value should be of type OAuthResponseType"); - if (Objects.nonNull(grantTypes) && grantTypes.size()>0) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setGrantTypes(grantTypes)); + if (Objects.nonNull(grantTypes) && grantTypes.size() > 0) + openIdConnectApplicationSettingsClient.setGrantTypes(grantTypes); else throw new IllegalArgumentException("Grant Type cannot be null, value should be of type OAuthGrantType"); if (Objects.nonNull(consentMethod)) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setConsentMethod(consentMethod)); + openIdConnectApplicationSettingsClient.setConsentMethod(consentMethod); if (Objects.nonNull(applicationType)) - openIdConnectApplicationSettings.setOAuthClient(openIdConnectApplicationSettingsClient.setApplicationType(applicationType)); + openIdConnectApplicationSettingsClient.setApplicationType(applicationType); else throw new IllegalArgumentException("Application Type cannot be null, value should be of type OpenIdConnectApplicationType"); - if(jsonWebKeyList.size() > 0) { - openIdConnectApplicationSettings - .getOAuthClient() - .setJwks( - client.instantiate(OpenIdConnectApplicationSettingsClientKeys.class) - .setKeys(this.jsonWebKeyList) - ); - } + if (Objects.nonNull(isImplicitAssignment)) + openIdConnectApplicationSettings.setImplicitAssignment(isImplicitAssignment); + + if (Objects.nonNull(inlineHookId)) + openIdConnectApplicationSettings.setInlineHookId(inlineHookId); // Credentials - application.setCredentials(client.instantiate(OAuthApplicationCredentials.class)); - OAuthApplicationCredentials oAuthApplicationCredentials = application.getCredentials(); - ApplicationCredentialsOAuthClient applicationCredentialsOAuthClient = client.instantiate(ApplicationCredentialsOAuthClient.class); + OAuthApplicationCredentials oAuthApplicationCredentials = new OAuthApplicationCredentials(); + ApplicationCredentialsOAuthClient applicationCredentialsOAuthClient = new ApplicationCredentialsOAuthClient(); if (Strings.hasText(clientId)) - oAuthApplicationCredentials.setOAuthClient(applicationCredentialsOAuthClient.setClientId(clientId)); + applicationCredentialsOAuthClient.setClientId(clientId); if (Strings.hasText(clientSecret)) - oAuthApplicationCredentials.setOAuthClient(applicationCredentialsOAuthClient.setClientSecret(clientSecret)); + applicationCredentialsOAuthClient.setClientSecret(clientSecret); if (Objects.nonNull(autoKeyRotation)) - oAuthApplicationCredentials.setOAuthClient(applicationCredentialsOAuthClient.setAutoKeyRotation(autoKeyRotation)); + applicationCredentialsOAuthClient.setAutoKeyRotation(autoKeyRotation); if (Objects.nonNull(tokenEndpointAuthMethod)) - oAuthApplicationCredentials.setOAuthClient(applicationCredentialsOAuthClient.setTokenEndpointAuthMethod(tokenEndpointAuthMethod)); + applicationCredentialsOAuthClient.setTokenEndpointAuthMethod(tokenEndpointAuthMethod); else throw new IllegalArgumentException("Token Endpoint Auth Method cannot be null, value should be of type OAuthEndpointAuthenticationMethod"); + oAuthApplicationCredentials.setOauthClient(applicationCredentialsOAuthClient); + + application.setCredentials(oAuthApplicationCredentials); + + openIdConnectApplicationSettings.setOauthClient(openIdConnectApplicationSettingsClient); + + if (jsonWebKeyList.size() > 0) { + OpenIdConnectApplicationSettingsClientKeys openIdConnectApplicationSettingsClientKeys = new OpenIdConnectApplicationSettingsClientKeys(); + openIdConnectApplicationSettingsClientKeys.setKeys(this.jsonWebKeyList); + openIdConnectApplicationSettings.getOauthClient().setJwks(openIdConnectApplicationSettingsClientKeys); + } + + application.setSettings(openIdConnectApplicationSettings); return application; } } diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultOktaSignOnPolicyBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultOktaSignOnPolicyBuilder.java index a1af6fcc03a..c06ab6a572e 100644 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultOktaSignOnPolicyBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultOktaSignOnPolicyBuilder.java @@ -17,8 +17,14 @@ import com.okta.commons.lang.Collections; import com.okta.commons.lang.Strings; -import com.okta.sdk.client.Client; import com.okta.sdk.resource.policy.*; +import org.openapitools.client.api.PolicyApi; +import org.openapitools.client.model.GroupCondition; +import org.openapitools.client.model.OktaSignOnPolicy; +import org.openapitools.client.model.OktaSignOnPolicyConditions; +import org.openapitools.client.model.PolicyPeopleCondition; +import org.openapitools.client.model.PolicyType; +import org.openapitools.client.model.UserCondition; import java.util.ArrayList; import java.util.List; @@ -54,12 +60,12 @@ public OktaSignOnPolicyBuilder addUser(String userId) { } @Override - public OktaSignOnPolicy buildAndCreate(Client client) { - return (OktaSignOnPolicy) client.createPolicy(build(client), isActive); + public OktaSignOnPolicy buildAndCreate(PolicyApi client) { + return client.createPolicy(OktaSignOnPolicy.class, build(), isActive); } - private OktaSignOnPolicy build(Client client){ - OktaSignOnPolicy policy = client.instantiate(OktaSignOnPolicy.class); + private OktaSignOnPolicy build() { + OktaSignOnPolicy policy = new OktaSignOnPolicy(); if (Strings.hasText(name)) policy.setName(name); if (Strings.hasText(description)) policy.setDescription(description); @@ -74,17 +80,25 @@ private OktaSignOnPolicy build(Client client){ if (Objects.nonNull(status)) policy.setStatus(status); - policy.setConditions(client.instantiate(OktaSignOnPolicyConditions.class)); + policy.setConditions( new OktaSignOnPolicyConditions()); OktaSignOnPolicyConditions oktaSignOnPolicyConditions = policy.getConditions(); - if (!Collections.isEmpty(groupIds)) - oktaSignOnPolicyConditions.setPeople(client.instantiate(PolicyPeopleCondition.class) - .setGroups(client.instantiate(GroupCondition.class).setInclude(groupIds))); - - if (!Collections.isEmpty(userIds)) - oktaSignOnPolicyConditions.setPeople(client.instantiate(PolicyPeopleCondition.class) - .setUsers(client.instantiate(UserCondition.class).setInclude(userIds))); + if (!Collections.isEmpty(groupIds)) { + GroupCondition groupCondition = new GroupCondition(); + groupCondition.setInclude(groupIds); + PolicyPeopleCondition policyPeopleCondition = new PolicyPeopleCondition(); + policyPeopleCondition.setGroups(groupCondition); + oktaSignOnPolicyConditions.setPeople(policyPeopleCondition); + } + + if (!Collections.isEmpty(userIds)) { + UserCondition userCondition = new UserCondition(); + userCondition.setInclude(userIds); + PolicyPeopleCondition policyPeopleCondition = new PolicyPeopleCondition(); + policyPeopleCondition.setUsers(userCondition); + oktaSignOnPolicyConditions.setPeople(policyPeopleCondition); + } return policy; } -} +} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPasswordPolicyBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPasswordPolicyBuilder.java index e6972ba4005..bfda0fb73a9 100644 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPasswordPolicyBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPasswordPolicyBuilder.java @@ -17,8 +17,31 @@ import com.okta.commons.lang.Collections; import com.okta.commons.lang.Strings; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.policy.*; +import com.okta.sdk.resource.policy.PasswordPolicyBuilder; +import org.openapitools.client.api.PolicyApi; +import org.openapitools.client.model.GroupCondition; +import org.openapitools.client.model.PasswordDictionary; +import org.openapitools.client.model.PasswordDictionaryCommon; +import org.openapitools.client.model.PasswordPolicy; +import org.openapitools.client.model.PasswordPolicyAuthenticationProviderCondition; +import org.openapitools.client.model.PasswordPolicyAuthenticationProviderType; +import org.openapitools.client.model.PasswordPolicyConditions; +import org.openapitools.client.model.PasswordPolicyDelegationSettings; +import org.openapitools.client.model.PasswordPolicyDelegationSettingsOptions; +import org.openapitools.client.model.PasswordPolicyPasswordSettings; +import org.openapitools.client.model.PasswordPolicyPasswordSettingsAge; +import org.openapitools.client.model.PasswordPolicyPasswordSettingsComplexity; +import org.openapitools.client.model.PasswordPolicyPasswordSettingsLockout; +import org.openapitools.client.model.PasswordPolicyRecoveryEmail; +import org.openapitools.client.model.PasswordPolicyRecoveryEmailProperties; +import org.openapitools.client.model.PasswordPolicyRecoveryEmailRecoveryToken; +import org.openapitools.client.model.PasswordPolicyRecoveryFactorSettings; +import org.openapitools.client.model.PasswordPolicyRecoveryFactors; +import org.openapitools.client.model.PasswordPolicyRecoverySettings; +import org.openapitools.client.model.PasswordPolicySettings; +import org.openapitools.client.model.PolicyPeopleCondition; +import org.openapitools.client.model.PolicyType; +import org.openapitools.client.model.UserCondition; import java.util.ArrayList; import java.util.List; @@ -26,7 +49,7 @@ public class DefaultPasswordPolicyBuilder extends DefaultPolicyBuilder implements PasswordPolicyBuilder { - private PasswordPolicyAuthenticationProviderCondition.ProviderEnum provider; + private PasswordPolicyAuthenticationProviderType provider; private List groupIds = new ArrayList<>(); private List userIds = new ArrayList<>(); private Boolean excludePasswordDictionary; @@ -44,9 +67,9 @@ public class DefaultPasswordPolicyBuilder extends DefaultPolicyBuilder implements PasswordPolicyRuleBuilder { - - private String name; - private PolicyNetworkCondition.ConnectionEnum connection; - private List userIds = new ArrayList<>(); - private List groupIds = new ArrayList<>(); - private PasswordPolicyRuleAction.AccessEnum unlockAccess; - private PasswordPolicyRuleAction.AccessEnum passwordResetAccess; - private PasswordPolicyRuleAction.AccessEnum passwordChangeAccess; - - - - @Override - public PasswordPolicyRuleBuilder setName(String name) { - this.name = name; - return this; - } - - @Override - public PasswordPolicyRuleBuilder setNetworkConnection(PolicyNetworkCondition.ConnectionEnum connection) { - this.connection = connection; - return this; - } - - @Override - public PasswordPolicyRuleBuilder setUsers(List userIds) { - this.userIds = userIds; - return this; - } - - @Override - public PasswordPolicyRuleBuilder addUser(String userId) { - this.userIds.add(userId); - return this; - } - - @Override - public PasswordPolicyRuleBuilder setGroups(List groupIds) { - this.groupIds = groupIds; - return this; - } - - @Override - public PasswordPolicyRuleBuilder addGroup(String groupId) { - this.groupIds.add(groupId); - return this; - } - - @Override - public PasswordPolicyRuleBuilder setSelfServiceUnlockAccess(PasswordPolicyRuleAction.AccessEnum unlockAccess) { - this.unlockAccess = unlockAccess; - return this; - } - - @Override - public PasswordPolicyRuleBuilder setSelfServicePasswordResetAccess(PasswordPolicyRuleAction.AccessEnum passwordResetAccess) { - this.passwordResetAccess = passwordResetAccess; - return this; - } - - @Override - public PasswordPolicyRuleBuilder setPasswordChangeAccess(PasswordPolicyRuleAction.AccessEnum passwordChangeAccess) { - this.passwordChangeAccess = passwordChangeAccess; - return this; - } - - @Override - public PasswordPolicyRule buildAndCreate(Client client, Policy policy){ - return (PasswordPolicyRule) policy.createRule(build(client)); - } - - private PasswordPolicyRule build(Client client){ - PasswordPolicyRule policyRule = client.instantiate(PasswordPolicyRule.class); - - if (Objects.nonNull(priority)) policyRule.setPriority(priority); - - if (Objects.nonNull(status)) policyRule.setStatus(status); - - if (Strings.hasText(name)) policyRule.setName(name); - - if (Objects.nonNull(type)) - if(type.equals(PolicyRule.TypeEnum.PASSWORD)) - policyRule.setType(type); - else - throw new IllegalArgumentException("Type should be specified as PASSWORD while using PasswordPolicyRuleBuilder."); - - - // Actions - policyRule.setActions(client.instantiate(PasswordPolicyRuleActions.class)); - PasswordPolicyRuleActions passwordPolicyRuleActions = policyRule.getActions(); - - if (Objects.nonNull(passwordChangeAccess)) - passwordPolicyRuleActions.setPasswordChange(client.instantiate(PasswordPolicyRuleAction.class).setAccess(passwordChangeAccess)); - if (Objects.nonNull(passwordResetAccess)) - passwordPolicyRuleActions.setSelfServicePasswordReset(client.instantiate(PasswordPolicyRuleAction.class).setAccess(passwordResetAccess)); - if (Objects.nonNull(unlockAccess)) - passwordPolicyRuleActions.setSelfServiceUnlock(client.instantiate(PasswordPolicyRuleAction.class).setAccess(unlockAccess)); - - // Conditions - policyRule.setConditions(client.instantiate(PasswordPolicyRuleConditions.class)); - PasswordPolicyRuleConditions passwordPolicyRuleConditions = policyRule.getConditions(); - PolicyNetworkCondition policyNetworkCondition = client.instantiate(PolicyNetworkCondition.class); - PolicyPeopleCondition policyPeopleCondition = client.instantiate(PolicyPeopleCondition.class); - - if (Objects.nonNull(connection)) - passwordPolicyRuleConditions.setNetwork(policyNetworkCondition.setConnection(connection)); - - if (!Collections.isEmpty(userIds)) - passwordPolicyRuleConditions.setPeople(policyPeopleCondition - .setUsers(client.instantiate(UserCondition.class).setInclude(userIds))); - if (!Collections.isEmpty(groupIds)) - passwordPolicyRuleConditions.setPeople(policyPeopleCondition - .setGroups(client.instantiate(GroupCondition.class).setInclude(groupIds))); - - return policyRule; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPolicyBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPolicyBuilder.java index cd7230ebaa9..b0f9665765d 100644 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPolicyBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPolicyBuilder.java @@ -16,25 +16,25 @@ package com.okta.sdk.impl.resource; import com.okta.commons.lang.Strings; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.policy.Policy; import com.okta.sdk.resource.policy.PolicyBuilder; -import com.okta.sdk.resource.policy.PolicyType; +import org.openapitools.client.api.PolicyApi; +import org.openapitools.client.model.LifecycleStatus; +import org.openapitools.client.model.Policy; +import org.openapitools.client.model.PolicyType; import java.util.Objects; - public class DefaultPolicyBuilder implements PolicyBuilder { protected String name; protected String description; protected PolicyType policyType; protected Integer priority; - protected Policy.StatusEnum status; + protected LifecycleStatus status; protected Boolean isActive = true; DefaultPolicyBuilder(){ - this.status = Policy.StatusEnum.ACTIVE; + this.status = LifecycleStatus.ACTIVE; } @Override @@ -62,12 +62,9 @@ public T setPriority(Integer priority) { } @Override - public T setStatus(Policy.StatusEnum status) { + public T setStatus(LifecycleStatus status) { this.status = status; - if (Policy.StatusEnum.ACTIVE.equals(status)) - this.isActive = true; - else - this.isActive = false; + this.isActive = LifecycleStatus.ACTIVE.equals(status); return self(); } @@ -77,12 +74,12 @@ protected T self() { } @Override - public Policy buildAndCreate(Client client) { - return client.createPolicy(build(client), isActive); + public Policy buildAndCreate(PolicyApi client) { + return client.createPolicy(build(), isActive); } - private Policy build(Client client) { - Policy policy = client.instantiate(Policy.class); + private Policy build() { + Policy policy = new Policy(); if (Strings.hasText(name)) policy.setName(name); if (Strings.hasText(description)) policy.setDescription(description); @@ -100,4 +97,4 @@ private Policy build(Client client) { return policy; } -} +} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPolicyRuleBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPolicyRuleBuilder.java deleted file mode 100644 index 437a4322d3e..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultPolicyRuleBuilder.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.policy.Policy; -import com.okta.sdk.resource.policy.PolicyRule; -import com.okta.sdk.resource.policy.rule.PolicyRuleBuilder; - -import java.util.Objects; - -public class DefaultPolicyRuleBuilder implements PolicyRuleBuilder { - - protected Integer priority; - protected PolicyRule.TypeEnum type; - protected PolicyRule.StatusEnum status; - - DefaultPolicyRuleBuilder(){ this.type = PolicyRule.TypeEnum.SIGN_ON; } - - @Override - public T setPriority(Integer priority) { - this.priority = priority; - return self(); - } - - @Override - public T setStatus(PolicyRule.StatusEnum status) { - this.status = status; - return self(); - } - - @Override - public T setType(PolicyRule.TypeEnum type) { - this.type = type; - return self(); - } - - @Override - public PolicyRule buildAndCreate(Client client, Policy policy) { - return (PolicyRule) policy.createRule(build(client)); - } - - @SuppressWarnings("unchecked") - protected T self() { - return (T) this; - } - - private PolicyRule build(Client client){ - PolicyRule policyRule = client.instantiate(PolicyRule.class); - - if (Objects.nonNull(priority)) policyRule.setPriority(priority); - - if (Objects.nonNull(status)) policyRule.setStatus(status); - - if (Objects.nonNull(type)) policyRule.setType(type); - - return policyRule; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultSignOnPolicyRuleBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultSignOnPolicyRuleBuilder.java deleted file mode 100644 index c2e99420f98..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultSignOnPolicyRuleBuilder.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.commons.lang.Collections; -import com.okta.commons.lang.Strings; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.policy.*; -import com.okta.sdk.resource.policy.rule.SignOnPolicyRuleBuilder; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class DefaultSignOnPolicyRuleBuilder extends DefaultPolicyRuleBuilder implements SignOnPolicyRuleBuilder { - - private String name; - private List groupIds = new ArrayList<>(); - private List userIds = new ArrayList<>(); - private OktaSignOnPolicyRuleSignonActions.AccessEnum access; - private Integer factorLifetime; - private OktaSignOnPolicyRuleSignonActions.FactorPromptModeEnum factorPromptMode; - private Boolean rememberDeviceByDefault; - private Boolean requireFactor; - private Integer maxSessionIdleMinutes; - private Integer maxSessionLifetimeMinutes; - private Boolean usePersistentCookie; - private PolicyRuleAuthContextCondition.AuthTypeEnum authType; - private PolicyNetworkCondition.ConnectionEnum connection; - - @Override - public SignOnPolicyRuleBuilder setName(String name) { - this.name = name; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum access) { - this.access = access; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setFactorLifetime(Integer factorLifetime) { - this.factorLifetime = factorLifetime; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setFactorPromptMode(OktaSignOnPolicyRuleSignonActions.FactorPromptModeEnum factorPromptMode) { - this.factorPromptMode = factorPromptMode; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setRememberDeviceByDefault(Boolean rememberDeviceByDefault) { - this.rememberDeviceByDefault = rememberDeviceByDefault; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setRequireFactor(Boolean requireFactor) { - this.requireFactor = requireFactor; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setMaxSessionIdleMinutes(Integer maxSessionIdleMinutes) { - this.maxSessionIdleMinutes = maxSessionIdleMinutes; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setMaxSessionLifetimeMinutes(Integer maxSessionLifetimeMinutes) { - this.maxSessionLifetimeMinutes = maxSessionLifetimeMinutes; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setUsePersistentCookie(Boolean usePersistentCookie) { - this.usePersistentCookie = usePersistentCookie; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setAuthType(PolicyRuleAuthContextCondition.AuthTypeEnum authType) { - this.authType = authType; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setNetworkConnection(PolicyNetworkCondition.ConnectionEnum connection) { - this.connection = connection; - return this; - } - - @Override - public SignOnPolicyRuleBuilder setUsers(List userIds) { - this.userIds = userIds; - return this; - } - - @Override - public SignOnPolicyRuleBuilder addUser(String userId) { - this.userIds.add(userId); - return this; - } - - @Override - public SignOnPolicyRuleBuilder setGroups(List groupIds) { - this.groupIds = groupIds; - return this; - } - - @Override - public SignOnPolicyRuleBuilder addGroup(String groupId) { - this.groupIds.add(groupId); - return this; - } - - @Override - public OktaSignOnPolicyRule buildAndCreate(Client client, Policy policy) { - return (OktaSignOnPolicyRule) policy.createRule(build(client)); - } - - private OktaSignOnPolicyRule build(Client client){ - OktaSignOnPolicyRule policyRule = client.instantiate(OktaSignOnPolicyRule.class); - - if (Strings.hasText(name)) policyRule.setName(name); - - if (Objects.nonNull(priority)) policyRule.setPriority(priority); - - if (Objects.nonNull(status)) policyRule.setStatus(status); - - if (Objects.nonNull(type)) - if(type.equals(PolicyRule.TypeEnum.SIGN_ON)) - policyRule.setType(type); - else - throw new IllegalArgumentException("Type should be SIGN_ON while using SignOnPolicyRuleBuilder."); - - - // Actions - policyRule.setActions(client.instantiate(OktaSignOnPolicyRuleActions.class)); - OktaSignOnPolicyRuleActions oktaSignOnPolicyRuleActions = policyRule.getActions(); - OktaSignOnPolicyRuleSignonActions oktaSignOnPolicyRuleSignonActions = client.instantiate(OktaSignOnPolicyRuleSignonActions.class); - - if (Objects.nonNull(access)) - oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions.setAccess(access)); - if (Objects.nonNull(factorLifetime)) - oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions.setFactorLifetime(factorLifetime)); - if (Objects.nonNull(factorPromptMode)) - oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions.setFactorPromptMode(factorPromptMode)); - if (Objects.nonNull(requireFactor)) - oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions.setRequireFactor(requireFactor)); - if (Objects.nonNull(rememberDeviceByDefault)) - oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions.setRememberDeviceByDefault(rememberDeviceByDefault)); - - OktaSignOnPolicyRuleSignonSessionActions oktaSignOnPolicyRuleSignonSessionActions = client.instantiate(OktaSignOnPolicyRuleSignonSessionActions.class); - - if (Objects.nonNull(maxSessionIdleMinutes)) - oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions.setSession(oktaSignOnPolicyRuleSignonSessionActions - .setMaxSessionIdleMinutes(maxSessionIdleMinutes))); - if (Objects.nonNull(maxSessionLifetimeMinutes)) - oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions.setSession(oktaSignOnPolicyRuleSignonSessionActions - .setMaxSessionLifetimeMinutes(maxSessionLifetimeMinutes))); - if (Objects.nonNull(usePersistentCookie)) - oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions.setSession(oktaSignOnPolicyRuleSignonSessionActions - .setUsePersistentCookie(usePersistentCookie))); - - // Conditions - policyRule.setConditions(client.instantiate(OktaSignOnPolicyRuleConditions.class)); - OktaSignOnPolicyRuleConditions oktaSignOnPolicyRuleConditions = policyRule.getConditions(); - - if (Objects.nonNull(authType)) - oktaSignOnPolicyRuleConditions.setAuthContext(client.instantiate(PolicyRuleAuthContextCondition.class) - .setAuthType(authType)); - - PolicyNetworkCondition policyNetworkCondition = client.instantiate(PolicyNetworkCondition.class); - PolicyPeopleCondition policyPeopleCondition = client.instantiate(PolicyPeopleCondition.class); - - if (Objects.nonNull(connection)) - oktaSignOnPolicyRuleConditions.setNetwork(policyNetworkCondition.setConnection(connection)); - - if (!Collections.isEmpty(userIds)) - oktaSignOnPolicyRuleConditions.setPeople(policyPeopleCondition - .setUsers(client.instantiate(UserCondition.class).setInclude(userIds))); - if (!Collections.isEmpty(groupIds)) - oktaSignOnPolicyRuleConditions.setPeople(policyPeopleCondition - .setGroups(client.instantiate(GroupCondition.class).setInclude(groupIds))); - - return policyRule; - } -} - diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultUserBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultUserBuilder.java index e9642d07c4d..ba648fa2057 100644 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultUserBuilder.java +++ b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultUserBuilder.java @@ -15,27 +15,28 @@ */ package com.okta.sdk.impl.resource; -import com.okta.sdk.client.Client; import com.okta.commons.lang.Collections; import com.okta.commons.lang.Strings; -import com.okta.sdk.resource.user.AuthenticationProvider; -import com.okta.sdk.resource.user.PasswordCredentialHook; -import com.okta.sdk.resource.user.RecoveryQuestionCredential; import com.okta.sdk.resource.user.UserBuilder; -import com.okta.sdk.resource.user.PasswordCredential; -import com.okta.sdk.resource.user.User; -import com.okta.sdk.resource.user.UserCredentials; -import com.okta.sdk.resource.user.UserNextLogin; -import com.okta.sdk.resource.user.UserProfile; -import com.okta.sdk.resource.user.type.UserType; -import com.okta.sdk.resource.user.CreateUserRequest; - +import org.openapitools.client.api.UserApi; +import org.openapitools.client.model.AuthenticationProvider; +import org.openapitools.client.model.CreateUserRequest; +import org.openapitools.client.model.PasswordCredential; +import org.openapitools.client.model.PasswordCredentialHash; +import org.openapitools.client.model.PasswordCredentialHashAlgorithm; +import org.openapitools.client.model.PasswordCredentialHook; +import org.openapitools.client.model.RecoveryQuestionCredential; +import org.openapitools.client.model.User; +import org.openapitools.client.model.UserCredentials; +import org.openapitools.client.model.UserNextLogin; +import org.openapitools.client.model.UserProfile; +import org.openapitools.client.model.UserType; + +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; -import java.util.Set; public class DefaultUserBuilder implements UserBuilder { @@ -53,12 +54,10 @@ public class DefaultUserBuilder implements UserBuilder { private UserType userType; private String userTypeId; private UserNextLogin nextLogin; - private Set groupIds = new HashSet<>(); + private List groupIds = new ArrayList<>(); private Map passwordHashProperties; private String passwordHookImportType; - private Map customProfileAttributes = new LinkedHashMap<>(); - public UserBuilder setPassword(char[] password) { this.password = Arrays.copyOf(password, password.length); return this; @@ -135,24 +134,7 @@ public UserBuilder setType(String userTypeId) { return this; } - public UserBuilder setProfileProperties(Map profileProperties) { - - this.customProfileAttributes.clear(); - return putAllProfileProperties(profileProperties); - } - - public UserBuilder putAllProfileProperties(Map profileProperties) { - - this.customProfileAttributes.putAll(profileProperties); - return this; - } - - public UserBuilder putProfileProperty(String key, Object value) { - this.customProfileAttributes.put(key, value); - return this; - } - - public UserBuilder setGroups(Set groupIds) { + public UserBuilder setGroups(List groupIds) { this.groupIds = groupIds; return this; } @@ -168,10 +150,10 @@ public UserBuilder setNextLogin(UserNextLogin nextLogin) { return this; } - private CreateUserRequest build(Client client) { + private CreateUserRequest build() { - CreateUserRequest createUserRequest = client.instantiate(CreateUserRequest.class); - createUserRequest.setProfile(client.instantiate(UserProfile.class)); + CreateUserRequest createUserRequest = new CreateUserRequest(); + createUserRequest.setProfile(new UserProfile()); UserProfile userProfile = createUserRequest.getProfile(); if (Strings.hasText(firstName)) userProfile.setFirstName(firstName); if (Strings.hasText(lastName)) userProfile.setLastName(lastName); @@ -187,33 +169,29 @@ private CreateUserRequest build(Client client) { } if (Strings.hasText(userTypeId)) { - createUserRequest.setType(client.instantiate(UserType.class).setId(userTypeId)); + UserType userType = new UserType(); + userType.setId(userTypeId); + createUserRequest.setType(userType); } else if (userType != null) { createUserRequest.setType(userType); } if (!Collections.isEmpty(groupIds)) { - if (createUserRequest instanceof AbstractResource) { - ((AbstractResource) createUserRequest).setProperty("groupIds", groupIds, true); - } else { - throw new IllegalArgumentException("'User' is not an instance of 'AbstractResource', so 'groupIds' cannot be set. This would only happen if the implementation of 'User' has been customized."); - } + createUserRequest.setGroupIds(groupIds); } - userProfile.putAll(customProfileAttributes); - // security question if (Strings.hasText(securityQuestion)) { - RecoveryQuestionCredential question = client.instantiate(RecoveryQuestionCredential.class); + RecoveryQuestionCredential question = new RecoveryQuestionCredential(); question.setQuestion(securityQuestion); question.setAnswer(securityQuestionAnswer); - createCredentialsIfNeeded(createUserRequest, client).setRecoveryQuestion(question); + createCredentialsIfNeeded(createUserRequest).setRecoveryQuestion(question); } // authentication provider if (provider != null) { - createCredentialsIfNeeded(createUserRequest, client).setProvider(provider); + createCredentialsIfNeeded(createUserRequest).setProvider(provider); } // user password @@ -223,32 +201,39 @@ else if (userType != null) { throw new IllegalArgumentException("Cannot specify both password and password hash, use one or the other."); } - PasswordCredential passwordCredential = client.instantiate(PasswordCredential.class); - createCredentialsIfNeeded(createUserRequest, client).setPassword(passwordCredential.setValue(password)); + PasswordCredential passwordCredential = new PasswordCredential(); + passwordCredential.setValue(new String(password)); + createCredentialsIfNeeded(createUserRequest).setPassword(passwordCredential); } // direct password import if (passwordHashProperties != null) { - PasswordCredential passwordCredential = client.instantiate(PasswordCredential.class); - passwordCredential.put("hash", passwordHashProperties); - createCredentialsIfNeeded(createUserRequest, client).setPassword(passwordCredential); + PasswordCredential passwordCredential = new PasswordCredential(); + PasswordCredentialHash passwordCredentialHash = new PasswordCredentialHash(); + passwordCredentialHash.setAlgorithm(PasswordCredentialHashAlgorithm.valueOf(((String) passwordHashProperties.get("algorithm")).replaceAll("-", "_"))); + passwordCredentialHash.setWorkFactor((Integer) passwordHashProperties.get("workFactor")); + passwordCredentialHash.setSalt((String) passwordHashProperties.get("salt")); + passwordCredentialHash.setValue((String) passwordHashProperties.get("value")); + passwordCredentialHash.setSaltOrder((String) passwordHashProperties.get("saltOrder")); + passwordCredential.setHash(passwordCredentialHash); + createCredentialsIfNeeded(createUserRequest).setPassword(passwordCredential); } // password hook import if (passwordHookImportType != null) { - PasswordCredential passwordCredential = client.instantiate(PasswordCredential.class); - PasswordCredentialHook passwordCredentialHook = client.instantiate(PasswordCredentialHook.class); + PasswordCredential passwordCredential = new PasswordCredential(); + PasswordCredentialHook passwordCredentialHook = new PasswordCredentialHook(); passwordCredentialHook.setType(passwordHookImportType); passwordCredential.setHook(passwordCredentialHook); - createCredentialsIfNeeded(createUserRequest, client).setPassword(passwordCredential); + createCredentialsIfNeeded(createUserRequest).setPassword(passwordCredential); } return createUserRequest; } - private UserCredentials createCredentialsIfNeeded(CreateUserRequest createUserRequest, Client client) { + private UserCredentials createCredentialsIfNeeded(CreateUserRequest createUserRequest) { if (createUserRequest.getCredentials() == null) { - UserCredentials credentials = client.instantiate(UserCredentials.class); + UserCredentials credentials = new UserCredentials(); createUserRequest.setCredentials(credentials); } return createUserRequest.getCredentials(); @@ -285,7 +270,7 @@ private UserBuilder setShaPasswordHash(String shaAlgorithm, String value, String } @Override - public User buildAndCreate(Client client) { - return client.createUser(build(client), active, provider != null, nextLogin); + public User buildAndCreate(UserApi client) { + return client.createUser(build(), active, provider != null, nextLogin); } } \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultVoidResource.java b/impl/src/main/java/com/okta/sdk/impl/resource/DefaultVoidResource.java deleted file mode 100644 index 547ffd15649..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DefaultVoidResource.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.resource.VoidResource; - -import java.util.Collections; -import java.util.Map; - -/** - * Default implementation of {@link VoidResource}. - */ -public class DefaultVoidResource extends AbstractResource implements VoidResource { - - public DefaultVoidResource(InternalDataStore dataStore) { - super(dataStore); - } - - public DefaultVoidResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - @Override - public Map getPropertyDescriptors() { - return Collections.emptyMap(); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/DoubleProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/DoubleProperty.java deleted file mode 100644 index 2bbff38b179..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/DoubleProperty.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -/** - * @since 1.0 - */ -public class DoubleProperty extends NonStringProperty { - - public DoubleProperty(String name) { - super(name, Double.class); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/EnumConverter.java b/impl/src/main/java/com/okta/sdk/impl/resource/EnumConverter.java deleted file mode 100644 index e1d80f98515..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/EnumConverter.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.commons.lang.Assert; - -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -/** - * Converts Strings to enum's based on the {code}.toString(){code} or {code}name{code} of the enum. Reverse lookup maps - * from value-to-enum will be cached forever. - * - * @since 0.8.1 - */ -final class EnumConverter { - - private final Map, Map> cachedEnums = new ConcurrentHashMap<>(); - - /** - * Lookup enum by {code}toString(){code} or {code}name{code}. If the enum cannot be found based on the - * {code}toString(){code} value then {code}Enum.valueOf{code} is used. - * - * @param The enum type whose constant is to be returned - * @param enumType the {@code Class} object of the enum type from which to return a constant - * @param value the toString() or name value of the enum to return - * @return the enum constant of the specified enum type with the specified value - */ - > E fromValue(Class enumType, String value) { - - Assert.notNull(value, "[Assertion failed] - 'value' is required; it must not be null"); - - // Get the reverse enum map - Map reverseMap = getReverseLookupMap(enumType); - - // lookup the value - E result = reverseMap.get(value); - - // if null, then revert to Enum.valueOf - if (result == null) { - result = Enum.valueOf(enumType, value); - } - return result; - } - - private Map getReverseLookupMap(Class type) { - - Map result = (Map) cachedEnums.get(type); - if (result == null) { - result = Arrays.stream(type.getEnumConstants()) - .collect(Collectors.toMap(Enum::toString, e -> e)); - cachedEnums.put((Class) type, (Map) result); - } - return result; - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/EnumListProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/EnumListProperty.java deleted file mode 100644 index ea2b1a10019..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/EnumListProperty.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.commons.lang.Assert; - -/** - * @since 1.0 - */ -public class EnumListProperty extends Property { - - public EnumListProperty(String name, Class type) { - super(name, type); - Assert.isTrue(Enum.class.isAssignableFrom(type), "List type must be an Enum."); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/EnumProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/EnumProperty.java deleted file mode 100644 index e7a8c98c83d..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/EnumProperty.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -/** - * @since 0.5.0 - */ -public class EnumProperty extends NonStringProperty { - - public EnumProperty(Class clazz) { - super("status", clazz); - } - - public EnumProperty(String propertyName, Class clazz) { - super(propertyName, clazz); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/HalResourceHrefResolver.java b/impl/src/main/java/com/okta/sdk/impl/resource/HalResourceHrefResolver.java deleted file mode 100644 index 01403c14424..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/HalResourceHrefResolver.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.commons.lang.Collections; -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -/** - * The default HREF resolver return a HAL self link if available ({@code _links.self.href}). - * - * @since 1.0 - */ -public class HalResourceHrefResolver implements ResourceHrefResolver { - - @Override - public String resolveHref(Map properties, Class clazz) { - Map links = getMapValue(properties, "_links"); - Map self = getMapValue(links, "self"); - if (!Collections.isEmpty(self)) { - return (String) self.get("href"); - } - return null; - } - - private Map getMapValue(Map properties, String key) { - if (!Collections.isEmpty(properties)) { - return (Map) properties.get(key); - } - return null; - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/IntegerProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/IntegerProperty.java deleted file mode 100644 index e2fd2fd1983..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/IntegerProperty.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -/** - * @since 0.5.0 - */ -public class IntegerProperty extends NonStringProperty { - - public IntegerProperty(String name) { - super(name, Integer.class); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/ListProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/ListProperty.java deleted file mode 100644 index 0839b14af3c..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/ListProperty.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -* Copyright 2015 Okta, Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package com.okta.sdk.impl.resource; - -import java.util.List; - -/** - * @since 0.5.0 - */ -public class ListProperty extends Property { - - public ListProperty(String name) { - super(name, List.class); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/MapProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/MapProperty.java deleted file mode 100644 index 46226a804a6..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/MapProperty.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import java.util.Map; - -/** - * This is a {@link java.util.Map} backed subclass of a {@link Property}. - * - * @since 0.5.0 - */ -public class MapProperty extends Property { - - public MapProperty(String name) { - super(name, Map.class); - } - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/NonStringProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/NonStringProperty.java deleted file mode 100644 index 724a7d6fc92..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/NonStringProperty.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -/** - * @since 0.5.0 - */ -public abstract class NonStringProperty extends Property { - - protected NonStringProperty(String name, Class type) { - super(name, type); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/OktaResourceHrefResolver.java b/impl/src/main/java/com/okta/sdk/impl/resource/OktaResourceHrefResolver.java deleted file mode 100644 index 41c9bd0046f..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/OktaResourceHrefResolver.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.commons.lang.Collections; -import com.okta.sdk.resource.Resource; -import com.okta.sdk.resource.application.AppUser; -import com.okta.sdk.resource.application.Application; -import com.okta.sdk.resource.group.Group; -import com.okta.sdk.resource.group.rule.GroupRule; -import com.okta.sdk.resource.user.Role; - -import java.util.Map; - -/** - * The default HREF resolver return a HAL self link if available ({@code _links.self.href}). If the {@code self} link is - * missing, it will be statically built for known objects (or null will be returned). - *

    - * Known Objects: - *

      - *
    • AppUser
    • - *
    • Application
    • - *
    • Group
    • - *
    • GroupRule
    • - *
    - * - * @since 1.0 - */ -public class OktaResourceHrefResolver implements ResourceHrefResolver { - - private final ResourceHrefResolver halResourceHrefResolver = new HalResourceHrefResolver(); - - @Override - public String resolveHref(Map properties, Class clazz) { - String href = halResourceHrefResolver.resolveHref(properties, clazz); - - return href != null - ? href - : fixSelfHref(properties, clazz); - } - - private String fixSelfHref(Map properties, Class clazz) { - - // the AppUsers object does NOT contain a self link, in this case we need build it based on the 'app' link - Map links = getMapValue(properties, "_links"); - if (links != null) { - if (AppUser.class.isAssignableFrom(clazz)) { - Map self = getMapValue(links, "app"); - if (!Collections.isEmpty(self)) { - return self.get("href") + "/users/" + properties.get("id"); - } - } - if (Application.class.isAssignableFrom(clazz)) { - Map self = getMapValue(links, "users"); - if (!Collections.isEmpty(self)) { - String href = self.get("href").toString(); - return href.substring(0, href.lastIndexOf("/users")); - } - } - if (Role.class.isAssignableFrom(clazz)) { - Map assignee = getMapValue(links, "assignee"); - if (!Collections.isEmpty(assignee)) { - String href = assignee.get("href").toString(); - return href + "/roles/" + properties.get("id"); - } - } - } - - if (Group.class.isAssignableFrom(clazz)) { - return "/api/v1/groups/" + properties.get("id"); - } - - if (GroupRule.class.isAssignableFrom(clazz)) { - return "/api/v1/groups/rules/" + properties.get("id"); - } - - return null; - } - - private Map getMapValue(Map properties, String key) { - if (!Collections.isEmpty(properties)) { - return (Map) properties.get(key); - } - return null; - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/Page.java b/impl/src/main/java/com/okta/sdk/impl/resource/Page.java deleted file mode 100644 index 695e520bfdf..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/Page.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import java.util.Collection; - -/** - * @since 0.5.0 - */ -public interface Page { - - Collection getItems(); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/Property.java b/impl/src/main/java/com/okta/sdk/impl/resource/Property.java deleted file mode 100644 index f8480e8923f..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/Property.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.commons.lang.Assert; - -/** - * @since 0.5.0 - */ -public abstract class Property { - - private final String name; - private final Class type; - - protected Property(String name, Class type) { - Assert.notNull(name, "name is required."); - Assert.notNull(type, "type is required."); - this.name = name; - this.type = type; - } - - public String getName() { - return this.name; - } - - public Class getType() { - return type; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/ReferenceFactory.java b/impl/src/main/java/com/okta/sdk/impl/resource/ReferenceFactory.java deleted file mode 100644 index 6f89fa61576..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/ReferenceFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import java.util.HashMap; -import java.util.Map; - -/** - * @since 0.5.0 - */ -public class ReferenceFactory { - - public ReferenceFactory(){} - - public Map createUnmaterializedReference(String resourceName, Map map) { - return new HashMap<>(map); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/ResourceHrefResolver.java b/impl/src/main/java/com/okta/sdk/impl/resource/ResourceHrefResolver.java deleted file mode 100644 index fbc67c4152e..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/ResourceHrefResolver.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.resource.Resource; - -import java.util.Map; - -/** - * Resolves an HREF for a given {@link Resource} class and data. This class allows for a plugable way to resolve a - * Resource's HREF. Okta uses HAL style links, but other implementations could be used to resolve or augment the HREF. - * - * @since 1.0 - */ -public interface ResourceHrefResolver { - - String resolveHref(Map properties, Class clazz); -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/ResourceListProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/ResourceListProperty.java deleted file mode 100644 index b3ba6bca567..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/ResourceListProperty.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.resource.Resource; - -/** - * @since 1.0 - */ -public class ResourceListProperty extends Property { - - public ResourceListProperty(String name, Class type) { - super(name, type); - } -} \ No newline at end of file diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/ResourceReference.java b/impl/src/main/java/com/okta/sdk/impl/resource/ResourceReference.java deleted file mode 100644 index b698842b74b..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/ResourceReference.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.resource.Resource; - -/** - * @since 0.5.0 - */ -public class ResourceReference extends Property { - - private final boolean createOnAccess; - - public ResourceReference(String name, Class type) { - this(name, type, false); - } - - public ResourceReference(String name, Class type, boolean createOnAccess) { - super(name, type); - this.createOnAccess = createOnAccess; - } - - public boolean isCreateOnAccess() { - return createOnAccess; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/StringProperty.java b/impl/src/main/java/com/okta/sdk/impl/resource/StringProperty.java deleted file mode 100644 index f6b389ad350..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/StringProperty.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -/** - * @since 0.5.0 - */ -public class StringProperty extends Property { - - public StringProperty(String name) { - super(name, String.class); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/URIParseException.java b/impl/src/main/java/com/okta/sdk/impl/resource/URIParseException.java deleted file mode 100644 index 1e5ade7d61c..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/URIParseException.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -public class URIParseException extends RuntimeException { - - public URIParseException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/event/hook/DefaultEventHookBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/event/hook/DefaultEventHookBuilder.java deleted file mode 100644 index c6728089516..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/event/hook/DefaultEventHookBuilder.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.event.hook; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.net.HttpHeaders; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.event.hook.EventHook; -import com.okta.sdk.resource.event.hook.EventHookBuilder; -import com.okta.sdk.resource.event.hook.EventHookChannel; -import com.okta.sdk.resource.event.hook.EventHookChannelConfig; -import com.okta.sdk.resource.event.hook.EventHookChannelConfigHeader; -import com.okta.sdk.resource.event.hook.EventHookChannelConfigAuthScheme; -import com.okta.sdk.resource.event.hook.EventHookChannelConfigAuthSchemeType; -import com.okta.sdk.resource.event.hook.EventSubscriptions; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * Builder for {@link EventHook}. - * @since 2.0.0 - */ -public class DefaultEventHookBuilder implements EventHookBuilder { - - private static final String LIFECYCLE_EVENT_CREATE = "user.lifecycle.create"; - private static final String LIFECYCLE_EVENT_ACTIVATE = "user.lifecycle.activate"; - - private static final String VERSION = "1.0.0"; - - private String name; - private String url; - private String authorizationHeaderValue; - private Map headerMap = Maps.newHashMap(); - - @Override - public EventHookBuilder setName(String name) { - this.name = name; - return this; - } - - @Override - public EventHookBuilder setUrl(String url) { - this.url = url; - return this; - } - - @Override - public EventHookBuilder setAuthorizationHeaderValue(String authorizationHeaderValue) { - this.authorizationHeaderValue = authorizationHeaderValue; - return this; - } - - @Override - public EventHookBuilder addHeader(String name, String value) { - headerMap.put(name, value); - return this; - } - - @Override - public EventHook buildAndCreate(Client client) { - - EventSubscriptions eventSubscriptions = client.instantiate(EventSubscriptions.class) - .setType(EventSubscriptions.TypeEnum.EVENT_TYPE) - .setItems(Arrays.asList(LIFECYCLE_EVENT_CREATE, LIFECYCLE_EVENT_ACTIVATE)); - - EventHookChannelConfigAuthScheme eventHookChannelConfigAuthScheme = - client.instantiate(EventHookChannelConfigAuthScheme.class) - .setType(EventHookChannelConfigAuthSchemeType.HEADER) - .setKey(HttpHeaders.AUTHORIZATION) - .setValue(authorizationHeaderValue); - - List headers = Lists.newArrayList(); - - for (Map.Entry entry : headerMap.entrySet()) { - headers.add(client.instantiate(EventHookChannelConfigHeader.class) - .setKey(entry.getKey()) - .setValue(entry.getValue())); - } - - EventHookChannelConfig eventHookChannelConfig = client.instantiate(EventHookChannelConfig.class) - .setUri(url) - .setHeaders(headers) - .setAuthScheme(eventHookChannelConfigAuthScheme); - - EventHookChannel eventHookChannel = client.instantiate(EventHookChannel.class) - .setType(EventHookChannel.TypeEnum.HTTP) - .setVersion(VERSION) - .setConfig(eventHookChannelConfig); - - EventHook createdEventHook = client.createEventHook(client.instantiate(EventHook.class) - .setName(name) - .setEvents(eventSubscriptions) - .setChannel(eventHookChannel)); - - return createdEventHook; - } - -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/DefaultIdentityProviderBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/DefaultIdentityProviderBuilder.java deleted file mode 100644 index 11b14cf7fcd..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/DefaultIdentityProviderBuilder.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.identity.provider; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.identity.provider.IdentityProvider; -import com.okta.sdk.resource.identity.provider.IdentityProviderBuilder; -import com.okta.sdk.resource.policy.PolicySubjectMatchType; - -import java.util.List; - -@SuppressWarnings("rawtypes") -public class DefaultIdentityProviderBuilder implements IdentityProviderBuilder { - - protected String name; - protected String clientId; - protected String clientSecret; - protected List scopes; - protected Integer maxClockSkew; - protected String userName; - protected PolicySubjectMatchType matchType; - protected Boolean isProfileMaster; - - @Override - public T setName(String name) { - this.name = name; - return self(); - } - - @Override - public T setClientId(String clientId) { - this.clientId = clientId; - return self(); - } - - @Override - public T setClientSecret(String clientSecret) { - this.clientSecret = clientSecret; - return self(); - } - - @Override - public T setScopes(List scopes) { - this.scopes = scopes; - return self(); - } - - @Override - public T setMaxClockSkew(Integer maxClockSkew) { - this.maxClockSkew = maxClockSkew; - return self(); - } - - @Override - public T setUserName(String userName) { - this.userName = userName; - return self(); - } - - @Override - public T setMatchType(PolicySubjectMatchType matchType) { - this.matchType = matchType; - return self(); - } - - @Override - public T setIsProfileMaster(Boolean isProfileMaster) { - this.isProfileMaster = isProfileMaster; - return self(); - } - - @Override - public T isProfileMaster(Boolean isProfileMaster) { - return setIsProfileMaster(isProfileMaster); - } - - @Override - public IdentityProvider buildAndCreate(Client client) { - return client.createIdentityProvider(client.instantiate(IdentityProvider.class)); - } - - @SuppressWarnings("unchecked") - protected T self() { - return (T) this; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/FacebookIdentityProviderBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/FacebookIdentityProviderBuilder.java deleted file mode 100644 index 7929c3c034d..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/FacebookIdentityProviderBuilder.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.identity.provider; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.identity.provider.IdentityProvider; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentials; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentialsClient; -import com.okta.sdk.resource.identity.provider.Protocol; -import com.okta.sdk.resource.identity.provider.Provisioning; -import com.okta.sdk.resource.identity.provider.ProvisioningConditions; -import com.okta.sdk.resource.identity.provider.ProvisioningDeprovisionedCondition; -import com.okta.sdk.resource.identity.provider.ProvisioningGroups; -import com.okta.sdk.resource.identity.provider.ProvisioningSuspendedCondition; -import com.okta.sdk.resource.policy.IdentityProviderPolicy; -import com.okta.sdk.resource.policy.PolicyAccountLink; -import com.okta.sdk.resource.policy.PolicySubject; -import com.okta.sdk.resource.policy.PolicyUserNameTemplate; - -public class FacebookIdentityProviderBuilder extends DefaultIdentityProviderBuilder { - - @Override - public IdentityProvider buildAndCreate(Client client) { - - IdentityProvider createdIdp = client.createIdentityProvider(client.instantiate(IdentityProvider.class) - .setType(IdentityProvider.TypeValues.FACEBOOK) - .setName(name) - .setProtocol(client.instantiate(Protocol.class) - .setType(Protocol.TypeEnum.OAUTH2) - .setScopes(scopes) - .setCredentials(client.instantiate(IdentityProviderCredentials.class) - .setClient(client.instantiate(IdentityProviderCredentialsClient.class) - .setClientId(clientId) - .setClientSecret(clientSecret)))) - .setPolicy(client.instantiate(IdentityProviderPolicy.class) - .setProvisioning(client.instantiate(Provisioning.class) - .setAction(Provisioning.ActionEnum.AUTO) - .setProfileMaster(isProfileMaster) - .setGroups(client.instantiate(ProvisioningGroups.class) - .setAction(ProvisioningGroups.ActionEnum.NONE)) - .setConditions(client.instantiate(ProvisioningConditions.class) - .setDeprovisioned(client.instantiate(ProvisioningDeprovisionedCondition.class) - .setAction(ProvisioningDeprovisionedCondition.ActionEnum.NONE)) - .setSuspended(client.instantiate(ProvisioningSuspendedCondition.class) - .setAction(ProvisioningSuspendedCondition.ActionEnum.NONE)))) - .setAccountLink(client.instantiate(PolicyAccountLink.class) - .setFilter(null) - .setAction(PolicyAccountLink.ActionEnum.AUTO)) - .setSubject(client.instantiate(PolicySubject.class) - .setUserNameTemplate(client.instantiate(PolicyUserNameTemplate.class) - .setTemplate(userName)) - .setMatchType(matchType)) - .setMaxClockSkew(maxClockSkew))); - - return createdIdp; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/GoogleIdentityProviderBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/GoogleIdentityProviderBuilder.java deleted file mode 100644 index 2b7eb4f587f..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/GoogleIdentityProviderBuilder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.identity.provider; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.identity.provider.IdentityProvider; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentials; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentialsClient; -import com.okta.sdk.resource.identity.provider.Protocol; -import com.okta.sdk.resource.identity.provider.Provisioning; -import com.okta.sdk.resource.identity.provider.ProvisioningConditions; -import com.okta.sdk.resource.identity.provider.ProvisioningDeprovisionedCondition; -import com.okta.sdk.resource.identity.provider.ProvisioningGroups; -import com.okta.sdk.resource.identity.provider.ProvisioningSuspendedCondition; -import com.okta.sdk.resource.policy.IdentityProviderPolicy; -import com.okta.sdk.resource.policy.PolicyAccountLink; -import com.okta.sdk.resource.policy.PolicySubject; -import com.okta.sdk.resource.policy.PolicyUserNameTemplate; - -public class GoogleIdentityProviderBuilder extends DefaultIdentityProviderBuilder { - - @Override - public IdentityProvider buildAndCreate(Client client) { - - return client.createIdentityProvider(client.instantiate(IdentityProvider.class) - .setType(IdentityProvider.TypeValues.GOOGLE) - .setName(name) - .setProtocol(client.instantiate(Protocol.class) - .setType(Protocol.TypeEnum.OIDC) - .setScopes(scopes) - .setCredentials(client.instantiate(IdentityProviderCredentials.class) - .setClient(client.instantiate(IdentityProviderCredentialsClient.class) - .setClientId(clientId) - .setClientSecret(clientSecret)))) - .setPolicy(client.instantiate(IdentityProviderPolicy.class) - .setProvisioning(client.instantiate(Provisioning.class) - .setAction(Provisioning.ActionEnum.AUTO) - .setProfileMaster(isProfileMaster) - .setGroups(client.instantiate(ProvisioningGroups.class) - .setAction(ProvisioningGroups.ActionEnum.NONE)) - .setConditions(client.instantiate(ProvisioningConditions.class) - .setDeprovisioned(client.instantiate(ProvisioningDeprovisionedCondition.class) - .setAction(ProvisioningDeprovisionedCondition.ActionEnum.NONE)) - .setSuspended(client.instantiate(ProvisioningSuspendedCondition.class) - .setAction(ProvisioningSuspendedCondition.ActionEnum.NONE)))) - .setAccountLink(client.instantiate(PolicyAccountLink.class) - .setFilter(null) - .setAction(PolicyAccountLink.ActionEnum.AUTO)) - .setSubject(client.instantiate(PolicySubject.class) - .setUserNameTemplate(client.instantiate(PolicyUserNameTemplate.class) - .setTemplate(userName)) - .setMatchType(matchType)) - .setMaxClockSkew(maxClockSkew))); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/LinkedInIdentityProviderBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/LinkedInIdentityProviderBuilder.java deleted file mode 100644 index fdce840e301..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/LinkedInIdentityProviderBuilder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.identity.provider; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.identity.provider.IdentityProvider; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentials; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentialsClient; -import com.okta.sdk.resource.identity.provider.Protocol; -import com.okta.sdk.resource.identity.provider.Provisioning; -import com.okta.sdk.resource.identity.provider.ProvisioningConditions; -import com.okta.sdk.resource.identity.provider.ProvisioningDeprovisionedCondition; -import com.okta.sdk.resource.identity.provider.ProvisioningGroups; -import com.okta.sdk.resource.identity.provider.ProvisioningSuspendedCondition; -import com.okta.sdk.resource.policy.IdentityProviderPolicy; -import com.okta.sdk.resource.policy.PolicyAccountLink; -import com.okta.sdk.resource.policy.PolicySubject; -import com.okta.sdk.resource.policy.PolicyUserNameTemplate; - -public class LinkedInIdentityProviderBuilder extends DefaultIdentityProviderBuilder { - - @Override - public IdentityProvider buildAndCreate(Client client) { - - return client.createIdentityProvider(client.instantiate(IdentityProvider.class) - .setType(IdentityProvider.TypeValues.LINKEDIN) - .setName(name) - .setProtocol(client.instantiate(Protocol.class) - .setType(Protocol.TypeEnum.OAUTH2) - .setScopes(scopes) - .setCredentials(client.instantiate(IdentityProviderCredentials.class) - .setClient(client.instantiate(IdentityProviderCredentialsClient.class) - .setClientId(clientId) - .setClientSecret(clientSecret)))) - .setPolicy(client.instantiate(IdentityProviderPolicy.class) - .setProvisioning(client.instantiate(Provisioning.class) - .setAction(Provisioning.ActionEnum.AUTO) - .setProfileMaster(isProfileMaster) - .setGroups(client.instantiate(ProvisioningGroups.class) - .setAction(ProvisioningGroups.ActionEnum.NONE)) - .setConditions(client.instantiate(ProvisioningConditions.class) - .setDeprovisioned(client.instantiate(ProvisioningDeprovisionedCondition.class) - .setAction(ProvisioningDeprovisionedCondition.ActionEnum.NONE)) - .setSuspended(client.instantiate(ProvisioningSuspendedCondition.class) - .setAction(ProvisioningSuspendedCondition.ActionEnum.NONE)))) - .setAccountLink(client.instantiate(PolicyAccountLink.class) - .setFilter(null) - .setAction(PolicyAccountLink.ActionEnum.AUTO)) - .setSubject(client.instantiate(PolicySubject.class) - .setUserNameTemplate(client.instantiate(PolicyUserNameTemplate.class) - .setTemplate(userName)) - .setMatchType(matchType)) - .setMaxClockSkew(maxClockSkew))); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/MicrosoftIdentityProviderBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/MicrosoftIdentityProviderBuilder.java deleted file mode 100644 index e6da9088fbe..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/MicrosoftIdentityProviderBuilder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.identity.provider; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.identity.provider.IdentityProvider; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentials; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentialsClient; -import com.okta.sdk.resource.identity.provider.Protocol; -import com.okta.sdk.resource.identity.provider.Provisioning; -import com.okta.sdk.resource.identity.provider.ProvisioningConditions; -import com.okta.sdk.resource.identity.provider.ProvisioningDeprovisionedCondition; -import com.okta.sdk.resource.identity.provider.ProvisioningGroups; -import com.okta.sdk.resource.identity.provider.ProvisioningSuspendedCondition; -import com.okta.sdk.resource.policy.IdentityProviderPolicy; -import com.okta.sdk.resource.policy.PolicyAccountLink; -import com.okta.sdk.resource.policy.PolicySubject; -import com.okta.sdk.resource.policy.PolicyUserNameTemplate; - -public class MicrosoftIdentityProviderBuilder extends DefaultIdentityProviderBuilder { - - @Override - public IdentityProvider buildAndCreate(Client client) { - - return client.createIdentityProvider(client.instantiate(IdentityProvider.class) - .setType(IdentityProvider.TypeValues.MICROSOFT) - .setName(name) - .setProtocol(client.instantiate(Protocol.class) - .setType(Protocol.TypeEnum.OIDC) - .setScopes(scopes) - .setCredentials(client.instantiate(IdentityProviderCredentials.class) - .setClient(client.instantiate(IdentityProviderCredentialsClient.class) - .setClientId(clientId) - .setClientSecret(clientSecret)))) - .setPolicy(client.instantiate(IdentityProviderPolicy.class) - .setProvisioning(client.instantiate(Provisioning.class) - .setAction(Provisioning.ActionEnum.AUTO) - .setProfileMaster(isProfileMaster) - .setGroups(client.instantiate(ProvisioningGroups.class) - .setAction(ProvisioningGroups.ActionEnum.NONE)) - .setConditions(client.instantiate(ProvisioningConditions.class) - .setDeprovisioned(client.instantiate(ProvisioningDeprovisionedCondition.class) - .setAction(ProvisioningDeprovisionedCondition.ActionEnum.NONE)) - .setSuspended(client.instantiate(ProvisioningSuspendedCondition.class) - .setAction(ProvisioningSuspendedCondition.ActionEnum.NONE)))) - .setAccountLink(client.instantiate(PolicyAccountLink.class) - .setFilter(null) - .setAction(PolicyAccountLink.ActionEnum.AUTO)) - .setSubject(client.instantiate(PolicySubject.class) - .setUserNameTemplate(client.instantiate(PolicyUserNameTemplate.class) - .setTemplate(userName)) - .setMatchType(matchType)) - .setMaxClockSkew(maxClockSkew))); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/OidcIdentityProviderBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/OidcIdentityProviderBuilder.java deleted file mode 100644 index a9fabd435e1..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/OidcIdentityProviderBuilder.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.identity.provider; - -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.identity.provider.IdentityProvider; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentials; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentialsClient; -import com.okta.sdk.resource.identity.provider.OIDCIdentityProviderBuilder; -import com.okta.sdk.resource.identity.provider.Protocol; -import com.okta.sdk.resource.identity.provider.ProtocolAlgorithmType; -import com.okta.sdk.resource.identity.provider.ProtocolAlgorithmTypeSignature; -import com.okta.sdk.resource.identity.provider.ProtocolAlgorithms; -import com.okta.sdk.resource.identity.provider.ProtocolEndpoint; -import com.okta.sdk.resource.identity.provider.ProtocolEndpoints; -import com.okta.sdk.resource.identity.provider.Provisioning; -import com.okta.sdk.resource.identity.provider.ProvisioningConditions; -import com.okta.sdk.resource.identity.provider.ProvisioningDeprovisionedCondition; -import com.okta.sdk.resource.identity.provider.ProvisioningGroups; -import com.okta.sdk.resource.identity.provider.ProvisioningSuspendedCondition; -import com.okta.sdk.resource.policy.IdentityProviderPolicy; -import com.okta.sdk.resource.policy.PolicyAccountLink; -import com.okta.sdk.resource.policy.PolicySubject; -import com.okta.sdk.resource.policy.PolicySubjectMatchType; -import com.okta.sdk.resource.policy.PolicyUserNameTemplate; - -public class OidcIdentityProviderBuilder extends DefaultIdentityProviderBuilder - implements OIDCIdentityProviderBuilder { - - private IdentityProvider.IssuerModeEnum issuerMode; - private String requestSignatureAlgorithm; - private ProtocolAlgorithmTypeSignature.ScopeEnum requestSignatureScope; - private String responseSignatureAlgorithm; - private ProtocolAlgorithmTypeSignature.ScopeEnum responseSignatureScope; - private ProtocolEndpoint.BindingEnum acsEndpointBinding; - private ProtocolEndpoint.TypeEnum acsEndpointType; - private ProtocolEndpoint.BindingEnum authorizationEndpointBinding; - private String authorizationEndpointUrl; - private ProtocolEndpoint.BindingEnum tokenEndpointBinding; - private String tokenEndpointUrl; - private ProtocolEndpoint.BindingEnum userInfoEndpointBinding; - private String userInfoEndpointUrl; - private ProtocolEndpoint.BindingEnum jwksEndpointBinding; - private String jwksEndpointUrl; - private String issuerUrl; - private String userName; - private PolicySubjectMatchType matchType; - - @Override - public OidcIdentityProviderBuilder setIssuerMode(IdentityProvider.IssuerModeEnum issuerMode) { - this.issuerMode = issuerMode; - return this; - } - - @Override - public OidcIdentityProviderBuilder setRequestSignatureAlgorithm(String requestSignatureAlgorithm) { - this.requestSignatureAlgorithm = requestSignatureAlgorithm; - return this; - } - - @Override - public OidcIdentityProviderBuilder setRequestSignatureScope(ProtocolAlgorithmTypeSignature.ScopeEnum requestSignatureScope) { - this.requestSignatureScope = requestSignatureScope; - return this; - } - - @Override - public OidcIdentityProviderBuilder setResponseSignatureAlgorithm(String responseSignatureAlgorithm) { - this.responseSignatureAlgorithm = responseSignatureAlgorithm; - return this; - } - - @Override - public OidcIdentityProviderBuilder setResponseSignatureScope(ProtocolAlgorithmTypeSignature.ScopeEnum responseSignatureScope) { - this.responseSignatureScope = responseSignatureScope; - return this; - } - - @Override - public OidcIdentityProviderBuilder setAcsEndpointBinding(ProtocolEndpoint.BindingEnum acsEndpointBinding) { - this.acsEndpointBinding = acsEndpointBinding; - return this; - } - - @Override - public OidcIdentityProviderBuilder setAcsEndpointType(ProtocolEndpoint.TypeEnum acsEndpointType) { - this.acsEndpointType = acsEndpointType; - return this; - } - - @Override - public OidcIdentityProviderBuilder setAuthorizationEndpointBinding(ProtocolEndpoint.BindingEnum authorizationEndpointBinding) { - this.authorizationEndpointBinding = authorizationEndpointBinding; - return this; - } - - @Override - public OidcIdentityProviderBuilder setAuthorizationEndpointUrl(String authorizationEndpointUrl) { - this.authorizationEndpointUrl = authorizationEndpointUrl; - return this; - } - - @Override - public OidcIdentityProviderBuilder setTokenEndpointBinding(ProtocolEndpoint.BindingEnum tokenEndpointBinding) { - this.tokenEndpointBinding = tokenEndpointBinding; - return this; - } - - @Override - public OidcIdentityProviderBuilder setTokenEndpointUrl(String tokenEndpointUrl) { - this.tokenEndpointUrl = tokenEndpointUrl; - return this; - } - - @Override - public OidcIdentityProviderBuilder setUserInfoEndpointBinding(ProtocolEndpoint.BindingEnum userInfoEndpointBinding) { - this.userInfoEndpointBinding = userInfoEndpointBinding; - return this; - } - - @Override - public OidcIdentityProviderBuilder setUserInfoEndpointUrl(String userInfoEndpointUrl) { - this.userInfoEndpointUrl = userInfoEndpointUrl; - return this; - } - - @Override - public OidcIdentityProviderBuilder setJwksEndpointBinding(ProtocolEndpoint.BindingEnum jwksEndpointBinding) { - this.jwksEndpointBinding = jwksEndpointBinding; - return this; - } - - @Override - public OidcIdentityProviderBuilder setJwksEndpointUrl(String jwksEndpointUrl) { - this.jwksEndpointUrl = jwksEndpointUrl; - return this; - } - - @Override - public OidcIdentityProviderBuilder setIssuerUrl(String issuerUrl) { - this.issuerUrl = issuerUrl; - return this; - } - - @Override - public OidcIdentityProviderBuilder setUserName(String userName) { - this.userName = userName; - return this; - } - - @Override - public OidcIdentityProviderBuilder setMatchType(PolicySubjectMatchType matchType) { - this.matchType = matchType; - return this; - } - - @Override - public IdentityProvider buildAndCreate(Client client) { - return client.createIdentityProvider(client.instantiate(IdentityProvider.class) - .setType(IdentityProvider.TypeValues.OIDC) - .setName(name) - .setIssuerMode(issuerMode) - .setProtocol(client.instantiate(Protocol.class) - .setAlgorithms(client.instantiate(ProtocolAlgorithms.class) - .setRequest(client.instantiate(ProtocolAlgorithmType.class) - .setSignature(client.instantiate(ProtocolAlgorithmTypeSignature.class) - .setAlgorithm(requestSignatureAlgorithm) - .setScope(requestSignatureScope))) - .setResponse(client.instantiate(ProtocolAlgorithmType.class) - .setSignature(client.instantiate(ProtocolAlgorithmTypeSignature.class) - .setAlgorithm(responseSignatureAlgorithm) - .setScope(responseSignatureScope)))) - .setEndpoints(client.instantiate(ProtocolEndpoints.class) - .setAcs(client.instantiate(ProtocolEndpoint.class) - .setBinding(acsEndpointBinding) - .setType(acsEndpointType)) - .setAuthorization(client.instantiate(ProtocolEndpoint.class) - .setBinding(authorizationEndpointBinding) - .setUrl(authorizationEndpointUrl)) - .setToken(client.instantiate(ProtocolEndpoint.class) - .setBinding(tokenEndpointBinding) - .setUrl(tokenEndpointUrl)) - .setUserInfo(client.instantiate(ProtocolEndpoint.class) - .setBinding(userInfoEndpointBinding) - .setUrl(userInfoEndpointUrl)) - .setJwks(client.instantiate(ProtocolEndpoint.class) - .setBinding(jwksEndpointBinding) - .setUrl(jwksEndpointUrl))) - .setScopes(scopes) - .setType(Protocol.TypeEnum.OIDC) - .setCredentials(client.instantiate(IdentityProviderCredentials.class) - .setClient(client.instantiate(IdentityProviderCredentialsClient.class) - .setClientId(clientId) - .setClientSecret(clientSecret))) - .setIssuer(client.instantiate(ProtocolEndpoint.class) - .setUrl(issuerUrl))) - .setPolicy(client.instantiate(IdentityProviderPolicy.class) - .setAccountLink(client.instantiate(PolicyAccountLink.class) - .setAction(PolicyAccountLink.ActionEnum.AUTO) - .setFilter(null)) - .setProvisioning(client.instantiate(Provisioning.class) - .setAction(Provisioning.ActionEnum.AUTO) - .setConditions(client.instantiate(ProvisioningConditions.class) - .setDeprovisioned(client.instantiate(ProvisioningDeprovisionedCondition.class) - .setAction(ProvisioningDeprovisionedCondition.ActionEnum.NONE)) - .setSuspended(client.instantiate(ProvisioningSuspendedCondition.class) - .setAction(ProvisioningSuspendedCondition.ActionEnum.NONE))) - .setGroups(client.instantiate(ProvisioningGroups.class) - .setAction(ProvisioningGroups.ActionEnum.NONE))) - .setMaxClockSkew(maxClockSkew) - .setSubject(client.instantiate(PolicySubject.class) - .setUserNameTemplate(client.instantiate(PolicyUserNameTemplate.class) - .setTemplate(userName)) - .setMatchType(matchType)))); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/StringTypeIdentityProviderBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/StringTypeIdentityProviderBuilder.java deleted file mode 100644 index 451cfacfa98..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/identity/provider/StringTypeIdentityProviderBuilder.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.identity.provider; - -import com.okta.commons.lang.Assert; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.identity.provider.IdentityProvider; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentials; -import com.okta.sdk.resource.identity.provider.IdentityProviderCredentialsClient; -import com.okta.sdk.resource.identity.provider.Protocol; -import com.okta.sdk.resource.identity.provider.Provisioning; -import com.okta.sdk.resource.identity.provider.ProvisioningConditions; -import com.okta.sdk.resource.identity.provider.ProvisioningDeprovisionedCondition; -import com.okta.sdk.resource.identity.provider.ProvisioningGroups; -import com.okta.sdk.resource.identity.provider.ProvisioningSuspendedCondition; -import com.okta.sdk.resource.policy.IdentityProviderPolicy; -import com.okta.sdk.resource.policy.PolicyAccountLink; -import com.okta.sdk.resource.policy.PolicySubject; -import com.okta.sdk.resource.policy.PolicyUserNameTemplate; - -public class StringTypeIdentityProviderBuilder extends DefaultIdentityProviderBuilder { - - private String type; - - public StringTypeIdentityProviderBuilder(String type) { - this.type = type; - } - - @Override - public IdentityProvider buildAndCreate(Client client) { - - Assert.notNull(type, "type cannot be empty"); - - return client.createIdentityProvider(client.instantiate(IdentityProvider.class) - .setType(type) - .setName(name) - .setProtocol(client.instantiate(Protocol.class) - .setType(Protocol.TypeEnum.OAUTH2) - .setScopes(scopes) - .setCredentials(client.instantiate(IdentityProviderCredentials.class) - .setClient(client.instantiate(IdentityProviderCredentialsClient.class) - .setClientId(clientId) - .setClientSecret(clientSecret)))) - .setPolicy(client.instantiate(IdentityProviderPolicy.class) - .setProvisioning(client.instantiate(Provisioning.class) - .setAction(Provisioning.ActionEnum.AUTO) - .setProfileMaster(isProfileMaster) - .setGroups(client.instantiate(ProvisioningGroups.class) - .setAction(ProvisioningGroups.ActionEnum.NONE)) - .setConditions(client.instantiate(ProvisioningConditions.class) - .setDeprovisioned(client.instantiate(ProvisioningDeprovisionedCondition.class) - .setAction(ProvisioningDeprovisionedCondition.ActionEnum.NONE)) - .setSuspended(client.instantiate(ProvisioningSuspendedCondition.class) - .setAction(ProvisioningSuspendedCondition.ActionEnum.NONE)))) - .setAccountLink(client.instantiate(PolicyAccountLink.class) - .setFilter(null) - .setAction(PolicyAccountLink.ActionEnum.AUTO)) - .setSubject(client.instantiate(PolicySubject.class) - .setUserNameTemplate(client.instantiate(PolicyUserNameTemplate.class) - .setTemplate(userName)) - .setMatchType(matchType)) - .setMaxClockSkew(maxClockSkew))); - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/resource/inline/hook/DefaultInlineHookBuilder.java b/impl/src/main/java/com/okta/sdk/impl/resource/inline/hook/DefaultInlineHookBuilder.java deleted file mode 100644 index 09c4b84f4a8..00000000000 --- a/impl/src/main/java/com/okta/sdk/impl/resource/inline/hook/DefaultInlineHookBuilder.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.inline.hook; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.net.HttpHeaders; -import com.okta.sdk.client.Client; -import com.okta.sdk.resource.inline.hook.InlineHook; -import com.okta.sdk.resource.inline.hook.InlineHookBuilder; -import com.okta.sdk.resource.inline.hook.InlineHookChannel; -import com.okta.sdk.resource.inline.hook.InlineHookChannelConfig; -import com.okta.sdk.resource.inline.hook.InlineHookChannelConfigAuthScheme; -import com.okta.sdk.resource.inline.hook.InlineHookChannelConfigHeaders; -import com.okta.sdk.resource.inline.hook.InlineHookType; - -import java.util.List; -import java.util.Map; - -/** - * Builder for {@link InlineHook}. - * @since 2.0.0 - */ -public class DefaultInlineHookBuilder implements InlineHookBuilder { - - private static final String VERSION = "1.0.0"; - - private String name; - private InlineHookType hookType; - private InlineHookChannel.TypeEnum channelType; - private String url; - private String authorizationHeaderValue; - private Map headerMap = Maps.newHashMap(); - - @Override - public InlineHookBuilder setName(String name) { - this.name = name; - return this; - } - - @Override - public InlineHookBuilder setHookType(InlineHookType hookType) { - this.hookType = hookType; - return this; - } - - @Override - public InlineHookBuilder setChannelType(InlineHookChannel.TypeEnum channelType) { - this.channelType = channelType; - return this; - } - - @Override - public InlineHookBuilder setUrl(String url) { - this.url = url; - return this; - } - - @Override - public InlineHookBuilder setAuthorizationHeaderValue(String authorizationHeaderValue) { - this.authorizationHeaderValue = authorizationHeaderValue; - return this; - } - - @Override - public InlineHookBuilder addHeader(String name, String value) { - headerMap.put(name, value); - return this; - } - - @Override - public InlineHook buildAndCreate(Client client) { - List headers = Lists.newArrayList(); - - for (Map.Entry entry : headerMap.entrySet()) { - headers.add(client.instantiate(InlineHookChannelConfigHeaders.class) - .setKey(entry.getKey()) - .setValue(entry.getValue())); - } - - InlineHookChannelConfigAuthScheme inlineHookChannelConfigAuthScheme = - client.instantiate(InlineHookChannelConfigAuthScheme.class) - .setType("HEADER") - .setKey(HttpHeaders.AUTHORIZATION) - .setValue(authorizationHeaderValue); - - InlineHookChannelConfig inlineHookChannelConfig = client.instantiate(InlineHookChannelConfig.class) - .setUri(url) - .setHeaders(headers) - .setAuthScheme(inlineHookChannelConfigAuthScheme); - - InlineHookChannel inlineHookChannel = client.instantiate(InlineHookChannel.class) - .setType(channelType) - .setVersion(VERSION) - .setConfig(inlineHookChannelConfig); - - InlineHook createdInlineHook = client.createInlineHook(client.instantiate(InlineHook.class) - .setName(name) - .setType(hookType) - .setVersion(VERSION) - .setChannel(inlineHookChannel)); - - return createdInlineHook; - } -} diff --git a/impl/src/main/java/com/okta/sdk/impl/serializer/UserProfileSerializer.java b/impl/src/main/java/com/okta/sdk/impl/serializer/UserProfileSerializer.java new file mode 100644 index 00000000000..cd1b94eb6b0 --- /dev/null +++ b/impl/src/main/java/com/okta/sdk/impl/serializer/UserProfileSerializer.java @@ -0,0 +1,148 @@ +/* + * Copyright 2022-Present Okta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.okta.sdk.impl.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.okta.commons.lang.Strings; +import org.openapitools.client.model.UserProfile; + +import java.io.IOException; +import java.util.Map; +import java.util.Objects; + +public class UserProfileSerializer extends StdSerializer { + + private static final long serialVersionUID = -1159312306772670042L; + + public UserProfileSerializer() { + this(null); + } + + public UserProfileSerializer(Class t) { + super(t); + } + + @Override + public void serialize(UserProfile userProfile, JsonGenerator jgen, SerializerProvider provider) throws IOException { + + jgen.writeStartObject(); + + if (Strings.hasText(userProfile.getCity())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_CITY, userProfile.getCity()); + + if (Strings.hasText(userProfile.getCostCenter())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_COST_CENTER, userProfile.getCostCenter()); + + if (Strings.hasText(userProfile.getCountryCode())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_COUNTRY_CODE, userProfile.getCountryCode()); + + if (Strings.hasText(userProfile.getDepartment())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_DEPARTMENT, userProfile.getDepartment()); + + if (Strings.hasText(userProfile.getDisplayName())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_DISPLAY_NAME, userProfile.getDisplayName()); + + if (Strings.hasText(userProfile.getDivision())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_DIVISION, userProfile.getDivision()); + + if (Strings.hasText(userProfile.getEmail())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_EMAIL, userProfile.getEmail()); + + if (Strings.hasText(userProfile.getEmployeeNumber())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_EMPLOYEE_NUMBER, userProfile.getEmployeeNumber()); + + if (Strings.hasText(userProfile.getFirstName())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_FIRST_NAME, userProfile.getFirstName()); + + if (Strings.hasText(userProfile.getHonorificPrefix())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_HONORIFIC_PREFIX, userProfile.getHonorificPrefix()); + + if (Strings.hasText(userProfile.getHonorificSuffix())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_HONORIFIC_SUFFIX, userProfile.getHonorificSuffix()); + + if (Strings.hasText(userProfile.getLastName())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_LAST_NAME, userProfile.getLastName()); + + if (Strings.hasText(userProfile.getLocale())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_LOCALE, userProfile.getLocale()); + + if (Strings.hasText(userProfile.getLogin())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_LOGIN, userProfile.getLogin()); + + if (Strings.hasText(userProfile.getManager())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_MANAGER, userProfile.getManager()); + + if (Strings.hasText(userProfile.getManagerId())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_MANAGER_ID, userProfile.getManagerId()); + + if (Strings.hasText(userProfile.getMiddleName())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_MIDDLE_NAME, userProfile.getMiddleName()); + + if (Strings.hasText(userProfile.getMobilePhone())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_MOBILE_PHONE, userProfile.getMobilePhone()); + + if (Strings.hasText(userProfile.getNickName())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_NICK_NAME, userProfile.getNickName()); + + if (Strings.hasText(userProfile.getOrganization())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_ORGANIZATION, userProfile.getOrganization()); + + if (Strings.hasText(userProfile.getPostalAddress())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_POSTAL_ADDRESS, userProfile.getPostalAddress()); + + if (Strings.hasText(userProfile.getPreferredLanguage())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_PREFERRED_LANGUAGE, userProfile.getPreferredLanguage()); + + if (Strings.hasText(userProfile.getPrimaryPhone())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_PRIMARY_PHONE, userProfile.getPrimaryPhone()); + + if (Strings.hasText(userProfile.getProfileUrl())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_PROFILE_URL, userProfile.getProfileUrl()); + + if (Strings.hasText(userProfile.getSecondEmail())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_SECOND_EMAIL, userProfile.getSecondEmail()); + + if (Strings.hasText(userProfile.getState())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_STATE, userProfile.getState()); + + if (Strings.hasText(userProfile.getStreetAddress())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_STREET_ADDRESS, userProfile.getStreetAddress()); + + if (Strings.hasText(userProfile.getTimezone())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_TIMEZONE, userProfile.getTimezone()); + + if (Strings.hasText(userProfile.getTitle())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_TITLE, userProfile.getTitle()); + + if (Strings.hasText(userProfile.getUserType())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_USER_TYPE, userProfile.getUserType()); + + if (Strings.hasText(userProfile.getZipCode())) + jgen.writeStringField(UserProfile.JSON_PROPERTY_ZIP_CODE, userProfile.getZipCode()); + + Map additionalProperties = userProfile.getAdditionalProperties(); + + if (Objects.nonNull(additionalProperties) && !additionalProperties.isEmpty()) { + for (Map.Entry entry : additionalProperties.entrySet()) { + jgen.writeObjectField(entry.getKey(), entry.getValue()); + } + } + + jgen.writeEndObject(); + } +} diff --git a/impl/src/test/groovy/com/okta/sdk/extensibleresource/CustomResource.java b/impl/src/test/groovy/com/okta/sdk/extensibleresource/CustomResource.java deleted file mode 100644 index dd6be37d2b6..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/extensibleresource/CustomResource.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2021-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.extensibleresource; - -import com.okta.sdk.resource.Resource; - -/** - * Customizable Resource - */ -public interface CustomResource extends Resource { -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/cache/CachesTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/cache/CachesTest.groovy index 828dfbbd178..f5fbc8eee49 100644 --- a/impl/src/test/groovy/com/okta/sdk/impl/cache/CachesTest.groovy +++ b/impl/src/test/groovy/com/okta/sdk/impl/cache/CachesTest.groovy @@ -17,9 +17,9 @@ package com.okta.sdk.impl.cache import com.okta.sdk.cache.CacheManager -import java.time.Duration import org.testng.annotations.Test +import java.time.Duration import java.util.concurrent.TimeUnit import static com.okta.sdk.cache.Caches.* diff --git a/impl/src/test/groovy/com/okta/sdk/impl/cache/DefaultCacheManagerTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/cache/DefaultCacheManagerTest.groovy index 14be3d979ef..43a25a71f63 100644 --- a/impl/src/test/groovy/com/okta/sdk/impl/cache/DefaultCacheManagerTest.groovy +++ b/impl/src/test/groovy/com/okta/sdk/impl/cache/DefaultCacheManagerTest.groovy @@ -17,11 +17,12 @@ package com.okta.sdk.impl.cache import com.okta.sdk.cache.Cache -import java.time.Duration import groovy.json.JsonSlurper import org.testng.annotations.BeforeTest import org.testng.annotations.Test +import java.time.Duration + import static org.testng.Assert.* /** diff --git a/impl/src/test/groovy/com/okta/sdk/impl/cache/DefaultCacheTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/cache/DefaultCacheTest.groovy index 1477c49975f..30a12e2f6f9 100644 --- a/impl/src/test/groovy/com/okta/sdk/impl/cache/DefaultCacheTest.groovy +++ b/impl/src/test/groovy/com/okta/sdk/impl/cache/DefaultCacheTest.groovy @@ -16,10 +16,11 @@ */ package com.okta.sdk.impl.cache -import java.time.Duration import groovy.json.JsonSlurper import org.testng.annotations.Test +import java.time.Duration + import static org.testng.Assert.* /** @@ -168,7 +169,7 @@ class DefaultCacheTest { assertEquals cache.get(key), value2 } - @Test + @Test(enabled = false) // TODO: flaky test, need to fix void testTimeToLive() { def cache = new DefaultCache('foo', [:], Duration.ofMillis(10), null) @@ -191,7 +192,7 @@ class DefaultCacheTest { assertEquals cache.size(), 0 } - @Test + @Test(enabled = false) // TODO: flaky test, need to fix void testTimeToIdle() { def cache = new DefaultCache('foo', [:], null, Duration.ofMillis(50)) @@ -219,7 +220,7 @@ class DefaultCacheTest { assertEquals cache.size(), 0 } - @Test + @Test(enabled = false) // TODO: flaky test, need to fix void testTimeToLiveAndTimeToIdle() { def cache = new DefaultCache('foo', [:], Duration.ofMillis(100), Duration.ofMillis(40)) diff --git a/impl/src/test/groovy/com/okta/sdk/impl/client/BaseClientTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/client/BaseClientTest.groovy deleted file mode 100644 index a83eddd9288..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/client/BaseClientTest.groovy +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.client - -import com.okta.sdk.cache.CacheManager -import com.okta.sdk.client.AuthenticationScheme -import com.okta.sdk.impl.api.ClientCredentialsResolver -import com.okta.sdk.impl.config.ClientConfiguration -import com.okta.sdk.impl.ds.InternalDataStore -import com.okta.commons.http.RequestExecutor -import com.okta.commons.http.config.BaseUrlResolver -import com.okta.sdk.impl.http.authc.RequestAuthenticatorFactory -import com.okta.sdk.resource.Resource -import org.testng.annotations.Test - -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.verify -import static org.mockito.Mockito.verifyNoMoreInteractions - -class BaseClientTest { - - @Test - void getResourceTest() { - def client = getClient() - def dataStore = client.getDataStore() - def url = "http://example.com/getResourceTest" - - client.getResource(url, Resource) - verify(dataStore).getResource(url, Resource) - verifyNoMoreInteractions(dataStore) - } - - @Test - void saveTest() { - def client = getClient() - def dataStore = client.getDataStore() - def resource = mock(Resource) - def url = "http://example.com/saveTest" - - client.save(url, resource) - verify(dataStore).save(url, resource) - verifyNoMoreInteractions(dataStore) - } - - @Test - void deleteTest() { - def client = getClient() - def dataStore = client.getDataStore() - def resource = mock(Resource) - def url = "http://example.com/deleteTest" - - client.delete(url, resource) - verify(dataStore).delete(url, resource) - verifyNoMoreInteractions(dataStore) - } - - @Test - void createTest() { - def client = getClient() - def dataStore = client.getDataStore() - def resource = mock(Resource) - def url = "http://example.com/createTest" - - client.create(url, resource) - verify(dataStore).create(url, resource) - verifyNoMoreInteractions(dataStore) - } - - private BaseClient getClient() { - def apiKeyResolver = mock(ClientCredentialsResolver) - def cacheManager = mock(CacheManager) - def requestAuthenticatorFactory = mock(RequestAuthenticatorFactory) - def baseUrlResolver = mock(BaseUrlResolver) - - def clientConfiguration = new ClientConfiguration() - clientConfiguration.setClientCredentialsResolver(apiKeyResolver) - clientConfiguration.setRequestAuthenticatorFactory(requestAuthenticatorFactory) - clientConfiguration.setAuthenticationScheme(AuthenticationScheme.NONE) - clientConfiguration.setBaseUrlResolver(baseUrlResolver) - - return new BaseClient(clientConfiguration, cacheManager) { - @Override - protected InternalDataStore createDataStore(RequestExecutor requestExecutor, BaseUrlResolver baseUrlResolver1, ClientCredentialsResolver clientCredentialsResolver, CacheManager cacheManager1) { - return mock(InternalDataStore) - } - } - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientBuilderTest.groovy deleted file mode 100644 index 06a1738b0ea..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientBuilderTest.groovy +++ /dev/null @@ -1,579 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.client - -import com.okta.commons.http.DefaultResponse -import com.okta.commons.http.RequestExecutor -import com.okta.commons.http.RequestExecutorFactory -import com.okta.commons.http.config.BaseUrlResolver -import com.okta.sdk.authc.credentials.TokenClientCredentials -import com.okta.sdk.client.AuthenticationScheme -import com.okta.sdk.client.AuthorizationMode -import com.okta.sdk.client.Client -import com.okta.sdk.client.ClientBuilder -import com.okta.sdk.client.Clients -import com.okta.sdk.impl.Util -import com.okta.sdk.impl.io.DefaultResourceFactory -import com.okta.sdk.impl.io.Resource -import com.okta.sdk.impl.io.ResourceFactory -import com.okta.sdk.impl.oauth2.OAuth2TokenRetrieverException -import com.okta.sdk.impl.test.RestoreEnvironmentVariables -import com.okta.sdk.impl.test.RestoreSystemProperties -import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer -import org.testng.annotations.Listeners -import org.testng.annotations.Test - -import java.nio.file.Path -import java.security.KeyPair -import java.security.KeyPairGenerator -import java.security.PrivateKey -import java.util.stream.Collectors - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.is -import static org.hamcrest.Matchers.nullValue -import static org.mockito.ArgumentMatchers.anyString -import static org.mockito.Mockito.* -import static org.testng.Assert.assertEquals -import static org.testng.Assert.assertTrue - -@Listeners([RestoreSystemProperties, RestoreEnvironmentVariables]) -class DefaultClientBuilderTest { - - /** - * This method MUST be called from each test in order to work with with the Listeners defined above. - * If this method is invoked with an @BeforeMethod annotation the Listener will be invoked before and after this - * method as well. - */ - void clearOktaEnvAndSysProps() { - System.clearProperty("okta.client.token") - System.clearProperty("okta.client.orgUrl") - System.clearProperty("okta.client.authorizationMode") - System.clearProperty("okta.client.clientId") - System.clearProperty("okta.client.kid") - System.clearProperty("okta.client.scopes") - System.clearProperty("okta.client.privateKey") - System.clearProperty("okta.client.connectionTimeout") - - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_TOKEN", null) - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_ORGURL", null) - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_AUTHORIZATIONMODE", null) - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_CLIENTID", null) - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_KID", null) - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_SCOPES", null) - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_PRIVATEKEY", null) - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_CONNECTIONTIMEOUT", null) - } - - @Test - void testBuilder() { - assertTrue(Clients.builder() instanceof DefaultClientBuilder) - } - - @Test - void testConfigureApiKey() { - clearOktaEnvAndSysProps() - // remove key.txt from src/test/resources and this test will fail - def client = new DefaultClientBuilder(noDefaultYamlResourceFactory()).build() - assertEquals client.dataStore.getClientCredentials().getCredentials(), "13" - } - - @Test - void testConfigureBaseProperties() { - clearOktaEnvAndSysProps() - def builder = new DefaultClientBuilder(noDefaultYamlResourceFactory()) - DefaultClientBuilder clientBuilder = (DefaultClientBuilder) builder - assertEquals clientBuilder.clientConfiguration.baseUrl, "https://api.okta.com/v42" - assertEquals clientBuilder.clientConfiguration.connectionTimeout, 10 - assertEquals clientBuilder.clientConfiguration.authenticationScheme, AuthenticationScheme.SSWS - } - - @Test - void testConfigureProxy() { - clearOktaEnvAndSysProps() - def builder = Clients.builder() - DefaultClientBuilder clientBuilder = (DefaultClientBuilder) builder - assertThat clientBuilder.clientConfiguration.proxyHost, is("proxyyaml") // from yaml - assertThat clientBuilder.clientConfiguration.proxyPort, is(9009) // from yaml - assertThat clientBuilder.clientConfiguration.proxyUsername, is("fooyaml") // from yaml - assertThat clientBuilder.clientConfiguration.proxyPassword, is("bar") // from properties - - def proxy = clientBuilder.clientConfiguration.getProxy() - assertThat proxy.host, is("proxyyaml") - assertThat proxy.port, is(9009) - assertThat proxy.username, is("fooyaml") - assertThat proxy.password, is("bar") - } - - @Test - void testConfigureProxyWithoutPassword() { - clearOktaEnvAndSysProps() - def builder = Clients.builder() - DefaultClientBuilder clientBuilder = (DefaultClientBuilder) builder - clientBuilder.clientConfiguration.setProxyPassword(null) // override config from properties - clientBuilder.clientConfiguration.setProxyUsername(null) - assertThat clientBuilder.clientConfiguration.proxyHost, is("proxyyaml") // from yaml - assertThat clientBuilder.clientConfiguration.proxyPort, is(9009) // from yaml - - def proxy = clientBuilder.clientConfiguration.getProxy() - assertThat proxy.host, is("proxyyaml") - assertThat proxy.port, is(9009) - assertThat proxy.username, nullValue() - assertThat proxy.password, nullValue() - } - - @Test - void testConfigureBaseUrlResolver(){ - clearOktaEnvAndSysProps() - BaseUrlResolver baseUrlResolver = new BaseUrlResolver() { - @Override - String getBaseUrl() { - return "test" - } - } - - def testClient = new DefaultClientBuilder().setBaseUrlResolver(baseUrlResolver).build() - - assertEquals(testClient.dataStore.baseUrlResolver.getBaseUrl(), "test") - } - - @Test - void testDefaultBaseUrlResolver(){ - clearOktaEnvAndSysProps() - def client = new DefaultClientBuilder(noDefaultYamlResourceFactory()).build() - assertEquals(client.dataStore.baseUrlResolver.getBaseUrl(), "https://api.okta.com/v42") - } - - @Test - void testNullBaseUrl() { - clearOktaEnvAndSysProps() - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setClientCredentials(new TokenClientCredentials("some-token")) - .build() - } - } - - @Test - void testHttpBaseUrlForTesting() { - clearOktaEnvAndSysProps() - System.setProperty(ClientBuilder.DEFAULT_CLIENT_TESTING_DISABLE_HTTPS_CHECK_PROPERTY_NAME, "true") - // shouldn't throw IllegalArgumentException - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("http://okta.example.com") - .setClientCredentials(new TokenClientCredentials("some-token")) - .build() - } - - @Test - void testHttpBaseUrlForTestingDisabled() { - clearOktaEnvAndSysProps() - System.setProperty(ClientBuilder.DEFAULT_CLIENT_TESTING_DISABLE_HTTPS_CHECK_PROPERTY_NAME, "false") - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("http://okta.example.com") - .setClientCredentials(new TokenClientCredentials("some-token")) - .build() - } - } - - @Test - void testNullApiToken() { - clearOktaEnvAndSysProps() - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .build() - } - } - - @Test - void testOAuth2NullClientId() { - clearOktaEnvAndSysProps() - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .build() - } - } - - @Test - void testOAuth2NullScopes() { - clearOktaEnvAndSysProps() - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .build() - } - } - - @Test - void testOAuth2EmptyScopes() { - clearOktaEnvAndSysProps() - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes([] as Set) - .build() - } - } - - @Test - void testOAuth2NullPrivateKey() { - clearOktaEnvAndSysProps() - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read"] as Set) - .setPrivateKey(null as Path) - .build() - } - } - - @Test - void testOAuth2InvalidPrivateKey_PemFilePath() { - clearOktaEnvAndSysProps() - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read"] as Set) - .setPrivateKey("/some/invalid/path/privateKey.pem") - .build() - } - } - - @Test - void testOAuth2InvalidPrivateKey_PemFileContent() { - clearOktaEnvAndSysProps() - File privateKeyFile = File.createTempFile("tmp",".pem") - privateKeyFile.write("-----INVALID PEM CONTENT-----") - Util.expect(IllegalArgumentException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read"] as Set) - .setPrivateKey(privateKeyFile.text) - .build() - } - - privateKeyFile.delete() - } - - @Test - void testOAuth2UnsupportedPrivateKeyAlgorithm() { - clearOktaEnvAndSysProps() - - // DSA algorithm is unsupported (we support only RSA & EC) - File privateKeyFile = generatePrivateKey("DSA", 2048, "privateKey", ".pem") - - Util.expect(OAuth2TokenRetrieverException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read", "okta.apps.manage"] as Set) - .setPrivateKey(privateKeyFile.path) - .build() - } - - privateKeyFile.delete() - } - - @Test - void testOAuth2SemanticallyValidInputParams_withPrivateKeyPemFilePath() { - clearOktaEnvAndSysProps() - - File privateKeyFile = generatePrivateKey("RSA", 2048, "privateKey", ".pem") - - // expected because the URL is not an actual endpoint - Util.expect(OAuth2TokenRetrieverException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read", "okta.apps.manage"] as Set) - .setPrivateKey(privateKeyFile.path) - .build() - } - - privateKeyFile.delete() - } - - @Test - void testOAuth2SemanticallyValidInputParams_withPrivateKeyPemFileContent() { - clearOktaEnvAndSysProps() - - File privateKeyFile = generatePrivateKey("RSA", 2048, "anotherPrivateKey", ".pem") - - // expected because the URL is not an actual endpoint - Util.expect(OAuth2TokenRetrieverException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read", "okta.apps.manage"] as Set) - .setPrivateKey(privateKeyFile.text) - .build() - } - - privateKeyFile.delete() - } - - @Test - void testOAuth2SemanticallyValidInputParams_withPrivateKeyPemPath() { - clearOktaEnvAndSysProps() - - File privateKeyFile = generatePrivateKey("RSA", 2048, "anotherPrivateKey", ".pem") - - // expected because the URL is not an actual endpoint - Util.expect(OAuth2TokenRetrieverException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read", "okta.apps.manage"] as Set) - .setPrivateKey(privateKeyFile.toPath()) - .build() - } - - privateKeyFile.delete() - } - - @Test - void testOAuth2SemanticallyValidInputParams_withPrivateKeyPemInputStream() { - clearOktaEnvAndSysProps() - - File privateKeyFile = generatePrivateKey("RSA", 2048, "anotherPrivateKey", ".pem") - InputStream privateKeyFileInputStream = new FileInputStream(privateKeyFile); - - // expected because the URL is not an actual endpoint - Util.expect(OAuth2TokenRetrieverException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read", "okta.apps.manage"] as Set) - .setPrivateKey(privateKeyFileInputStream) - .build() - } - - privateKeyFile.delete() - } - - @Test - void testOAuth2SemanticallyValidInputParams_withPrivateKeyRSA() { - clearOktaEnvAndSysProps() - - PrivateKey privateKey = generatePrivateKey("RSA", 2048) - - // expected because the URL is not an actual endpoint - Util.expect(OAuth2TokenRetrieverException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read", "okta.apps.manage"] as Set) - .setPrivateKey(privateKey) - .build() - } - } - - @Test - void testOAuth2SemanticallyValidInputParams_withPrivateKeyEC() { - clearOktaEnvAndSysProps() - - PrivateKey privateKey = generatePrivateKey("EC", 256) - - // expected because the URL is not an actual endpoint - Util.expect(OAuth2TokenRetrieverException) { - new DefaultClientBuilder(noDefaultYamlNoAppYamlResourceFactory()) - .setOrgUrl("https://okta.example.com") - .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) - .setClientId("client12345") - .setScopes(["okta.apps.read", "okta.apps.manage"] as Set) - .setPrivateKey(privateKey) - .build() - } - } - - @Test - void testOAuth2WithEnvVariables() { - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_ORGURL", - "https://okta.example.com") - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_AUTHORIZATIONMODE", - AuthorizationMode.PRIVATE_KEY.getLabel()) // "PrivateKey" - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_CLIENTID", - "client12345") - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_SCOPES", - "okta.users.read okta.users.manage okta.apps.read okta.apps.manage") - - File privateKeyFile = generatePrivateKey("RSA", 2048, "privateKey", ".pem") - - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_PRIVATEKEY", privateKeyFile.path) - - // expected because the URL is not an actual endpoint - Util.expect(OAuth2TokenRetrieverException) { - new DefaultClientBuilder().build() - } - - privateKeyFile.delete() - } - - @Test - void testRequestExecutorParamsFromSystemProperties() { - System.setProperty("okta.client.requestExecutor.maxConnectionsPerRoute", "2500") - System.setProperty("okta.client.requestExecutor.maxConnectionsTotal", "5000") - System.setProperty("okta.client.requestExecutor.validateAfterInactivity", "3600") - System.setProperty("okta.client.requestExecutor.timeToLive", "4500") - def builder = Clients.builder() - DefaultClientBuilder clientBuilder = (DefaultClientBuilder) builder - def params = clientBuilder.clientConfiguration.getRequestExecutorParams() - assertThat params.get("maxConnectionsPerRoute"), is("2500") - assertThat params.get("maxConnectionsTotal"), is("5000") - assertThat params.get("validateAfterInactivity"), is("3600") - assertThat params.get("timeToLive"), is("4500") - } - - @Test - void testRequestExecutorParamsFromEnvironmentVariables() { - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_REQUESTEXECUTOR_MAX_CONNECTIONS_PER_ROUTE", "2501") - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_REQUESTEXECUTOR_MAX_CONNECTIONS_TOTAL", "5001") - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_REQUESTEXECUTOR_VALIDATE_AFTER_INACTIVITY", "3601") - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_REQUESTEXECUTOR_TIME_TO_LIVE", "4501") - def builder = Clients.builder() - DefaultClientBuilder clientBuilder = (DefaultClientBuilder) builder - def params = clientBuilder.clientConfiguration.getRequestExecutorParams() - assertThat params.get("maxConnectionsPerRoute"), is("2501") - assertThat params.get("maxConnectionsTotal"), is("5001") - assertThat params.get("validateAfterInactivity"), is("3601") - assertThat params.get("timeToLive"), is("4501") - } - - @Test - void testRequestExecutorParamsFromMultipleSources() { - //Testing https://github.com/okta/okta-sdk-java#configuration-reference - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_REQUESTEXECUTOR_MAX_CONNECTIONS_PER_ROUTE", "2501") - System.setProperty("okta.client.requestExecutor.maxConnectionsPerRoute", "2500") - def builder = Clients.builder() - DefaultClientBuilder clientBuilder = (DefaultClientBuilder) builder - def params = clientBuilder.clientConfiguration.getRequestExecutorParams() - assertThat params.get("maxConnectionsPerRoute"), is("2500") - } - - @Test - void testEnvironmentValueKid() { - clearOktaEnvAndSysProps() - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_KID", "kid-value") - DefaultClientBuilder clientBuilder = (DefaultClientBuilder) Clients.builder() - assertThat clientBuilder.clientConfiguration.getKid(), is("kid-value") - } - - @Test - void testSystemPropertyKid() { - clearOktaEnvAndSysProps() - System.setProperty("okta.client.kid", "kid-value") - DefaultClientBuilder clientBuilder = (DefaultClientBuilder) Clients.builder() - assertThat clientBuilder.clientConfiguration.getKid(), is("kid-value") - } - - @Test - void testRequestExecutorFactorySetter() { - DefaultResponse defaultResponse = new DefaultResponse(200, null, new ByteArrayInputStream("custom_response".getBytes()), 0) - RequestExecutor requestExecutor = { request -> defaultResponse } - RequestExecutorFactory customRequestExecutorFactory = { clientConfiguration -> requestExecutor } - - Client client = Clients.builder() - .setRequestExecutorFactory(customRequestExecutorFactory) - .build() - - InputStream response = client.http().getRaw("www.example.com") - String result = new BufferedReader(new InputStreamReader(response)).lines().collect(Collectors.joining()) - - assertEquals result, "custom_response" - } - - // helper methods - - static generatePrivateKey(String algorithm, int keySize, String fileNamePrefix, String fileNameSuffix) { - KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm) - keyGen.initialize(keySize) - KeyPair key = keyGen.generateKeyPair() - PrivateKey privateKey = key.getPrivate() - String encodedString = "-----BEGIN PRIVATE KEY-----\n" - encodedString = encodedString + Base64.getEncoder().encodeToString(privateKey.getEncoded()) + "\n" - encodedString = encodedString + "-----END PRIVATE KEY-----\n" - File file = File.createTempFile(fileNamePrefix,fileNameSuffix) - file.write(encodedString) - return file - } - - static generatePrivateKey(String algorithm, int keySize) { - KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm) - keyGen.initialize(keySize) - KeyPair key = keyGen.generateKeyPair() - PrivateKey privateKey = key.getPrivate() - return privateKey - } - - static ResourceFactory noDefaultYamlNoAppYamlResourceFactory() { - def resourceFactory = spy(new DefaultResourceFactory()) - doAnswer(new Answer() { - @Override - Resource answer(InvocationOnMock invocation) throws Throwable { - String arg = invocation.arguments[0].toString(); - if (arg.endsWith("/.okta/okta.yaml") || arg.equals("classpath:okta.yaml")) { - return mock(Resource) - } - else { - return invocation.callRealMethod() - } - } - }) - .when(resourceFactory).createResource(anyString()) - - return resourceFactory - } - - static ResourceFactory noDefaultYamlResourceFactory() { - def resourceFactory = spy(new DefaultResourceFactory()) - doAnswer(new Answer() { - @Override - Resource answer(InvocationOnMock invocation) throws Throwable { - if (invocation.arguments[0].toString().endsWith("/.okta/okta.yaml")) { - return mock(Resource) - } - else { - return invocation.callRealMethod() - } - } - }) - .when(resourceFactory).createResource(anyString()) - - return resourceFactory - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientBuilderTestCustomCredentialsTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientBuilderTestCustomCredentialsTest.groovy deleted file mode 100644 index c32344f624d..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientBuilderTestCustomCredentialsTest.groovy +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.client - -import com.okta.sdk.authc.credentials.ClientCredentials -import com.okta.sdk.impl.api.DefaultClientCredentialsResolver -import com.okta.sdk.authc.credentials.TokenClientCredentials -import com.okta.sdk.impl.test.RestoreEnvironmentVariables -import org.testng.annotations.BeforeMethod -import org.testng.annotations.Test - -import static org.testng.Assert.* - -class DefaultClientBuilderTestCustomCredentialsTest { - - def builder, client, clientCredentials, id, secret - - @BeforeMethod - void before() { - clearOktaEnvAndSysProps() - - id = UUID.randomUUID().toString() - secret = UUID.randomUUID().toString() - - clientCredentials = new TokenClientCredentials(secret) - - builder = new DefaultClientBuilder() - builder.setClientCredentials(clientCredentials) - client = builder.build() - } - - @Test - void testConfigureCredentials() { - assertEquals client.dataStore.getClientCredentials().getCredentials(), secret - } - - @Test - void testCustomClientCredentialsAllowedWithApiKeyResolver(){ - clearOktaEnvAndSysProps() - - def credentialsSecret = UUID.randomUUID().toString() - - ClientCredentials customCredentials = new ClientCredentials() { - @Override - String getCredentials() { - return credentialsSecret - } - } - - def keySecret = UUID.randomUUID().toString() - - def apiKey = new TokenClientCredentials(keySecret) - def apiKeyResolver = new DefaultClientCredentialsResolver(apiKey) - - builder = new DefaultClientBuilder() - builder.setClientCredentials(customCredentials) - builder.setClientCredentialsResolver(apiKeyResolver) - - def testClient = builder.build() - - assertEquals testClient.dataStore.clientCredentials.credentials, keySecret - } - - void clearOktaEnvAndSysProps() { - System.clearProperty("okta.client.authorizationMode") - RestoreEnvironmentVariables.setEnvironmentVariable("OKTA_CLIENT_AUTHORIZATIONMODE", null) - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientTest.groovy deleted file mode 100644 index 2b9d6d97e5e..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/client/DefaultClientTest.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.client - -import com.okta.commons.http.RequestExecutorFactory -import com.okta.commons.http.config.BaseUrlResolver -import com.okta.sdk.cache.CacheManager -import com.okta.sdk.client.AuthenticationScheme -import com.okta.commons.lang.Classes -import com.okta.sdk.impl.api.ClientCredentialsResolver -import com.okta.sdk.impl.config.ClientConfiguration -import com.okta.sdk.impl.http.authc.RequestAuthenticatorFactory -import org.mockito.Mock -import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer -import org.powermock.core.classloader.annotations.PrepareForTest -import org.powermock.modules.testng.PowerMockTestCase -import org.testng.annotations.Test - - -import static org.mockito.Mockito.* -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.is -import static org.testng.Assert.fail -import static org.powermock.api.mockito.PowerMockito.mockStatic - -/** - * @since 0.5.0 - */ - -@PrepareForTest(Classes.class) -class DefaultClientTest extends PowerMockTestCase { - - @Mock - private ServiceLoader mockServiceLoader - - @Test - void testCreateRequestExecutor() { - - mockStatic(Classes.class) - when(Classes.loadFromService(eq(RequestExecutorFactory), any(String))).then(new Answer() { - @Override - Object answer(InvocationOnMock invocation) throws Throwable { - throw new IllegalStateException(invocation.getArgument(1)) - } - }) - - def apiKeyResolver = mock(ClientCredentialsResolver) - def cacheManager = mock(CacheManager) - def requestAuthenticatorFactory = mock(RequestAuthenticatorFactory) - def baseUrlResolver = mock(BaseUrlResolver) - def className = RequestExecutorFactory.name - - ClientConfiguration clientConfiguration = new ClientConfiguration() - clientConfiguration.setClientCredentialsResolver(apiKeyResolver) - clientConfiguration.setRequestAuthenticatorFactory(requestAuthenticatorFactory) - clientConfiguration.setBaseUrlResolver(baseUrlResolver) - clientConfiguration.setConnectionTimeout(3600) - clientConfiguration.setAuthenticationScheme(AuthenticationScheme.SSWS) - - try { - new DefaultClient(clientConfiguration, cacheManager) - fail("shouldn't be here") - } catch (Exception e) { - assertThat e.getMessage(), is(("Unable to find a '${className}' " + - "implementation on the classpath. Please ensure you " + - "have added the okta-sdk-httpclient.jar file to your runtime classpath.").toString()) - } - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/client/MockClient.groovy b/impl/src/test/groovy/com/okta/sdk/impl/client/MockClient.groovy deleted file mode 100644 index e7040c6d13f..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/client/MockClient.groovy +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.client - -import com.okta.commons.http.DefaultResponse -import com.okta.commons.http.MediaType -import com.okta.commons.http.Request -import com.okta.commons.http.RequestExecutor -import com.okta.commons.http.Response -import com.okta.sdk.authc.credentials.TokenClientCredentials -import com.okta.sdk.impl.api.DefaultClientCredentialsResolver -import com.okta.sdk.impl.cache.DisabledCacheManager -import com.okta.sdk.impl.config.ClientConfiguration -import com.okta.sdk.impl.util.DefaultBaseUrlResolver -import org.mockito.Mockito - -import java.nio.charset.StandardCharsets - -import static org.mockito.Mockito.when - -class MockClient extends DefaultClient { - - static RequestExecutor mockRequestExecutor - - static ClientConfiguration defaultClientConfig = new ClientConfiguration() {{ - setBaseUrlResolver(new DefaultBaseUrlResolver("https://okta.example.com")) - setClientCredentialsResolver(new DefaultClientCredentialsResolver(new TokenClientCredentials("api_client_key"))) - }} - - - MockClient(ClientConfiguration clientConfig = defaultClientConfig) { - super(clientConfig, new DisabledCacheManager(), mockRequestExecutor = Mockito.mock(RequestExecutor)) - } - - MockClient withMockResponse(Request request, Response response) { - when(mockRequestExecutor.executeRequest(request)).thenReturn(response) - return this - } - - MockClient withMockResponse(Request request, String jsonFilePath) { - - String content = this.getClass().getResource(jsonFilePath).text - return withMockResponse(request, new DefaultResponse(200, - MediaType.APPLICATION_JSON, - new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)), - content.size())) - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/config/DefaultEnvVarNameConverterTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/config/DefaultEnvVarNameConverterTest.groovy index 463878ffbee..7769e858f5b 100644 --- a/impl/src/test/groovy/com/okta/sdk/impl/config/DefaultEnvVarNameConverterTest.groovy +++ b/impl/src/test/groovy/com/okta/sdk/impl/config/DefaultEnvVarNameConverterTest.groovy @@ -17,11 +17,11 @@ package com.okta.sdk.impl.config import com.okta.sdk.client.ClientBuilder +import org.hamcrest.MatcherAssert import org.testng.annotations.Test import java.lang.reflect.Modifier -import static org.hamcrest.MatcherAssert.assertThat import static org.hamcrest.Matchers.is class DefaultEnvVarNameConverterTest { @@ -30,35 +30,35 @@ class DefaultEnvVarNameConverterTest { void testToEnvVarName() { def converter = new DefaultEnvVarNameConverter() def envVarName = converter.toEnvVarName('okta.client.apiKey.id') - assertThat envVarName, is('OKTA_CLIENT_APIKEY_ID') + MatcherAssert.assertThat envVarName, is('OKTA_CLIENT_APIKEY_ID') } @Test void testPropNameForApiKeyIdEnvVar() { def converter = new DefaultEnvVarNameConverter() def propName = converter.toDottedPropertyName('OKTA_API_KEY_ID') - assertThat propName, is('okta.api.key.id') + MatcherAssert.assertThat propName, is('okta.api.key.id') } @Test void testPropNameForApiKeySecretEnvVar() { def converter = new DefaultEnvVarNameConverter() def propName = converter.toDottedPropertyName('OKTA_CLIENT_TOKEN') - assertThat propName, is('okta.client.token') + MatcherAssert.assertThat propName, is('okta.client.token') } @Test void testPropNameForApiKeyFileEnvVar() { def converter = new DefaultEnvVarNameConverter() def propName = converter.toDottedPropertyName('OKTA_CONFIG_FILE') - assertThat propName, is('okta.config.file') + MatcherAssert.assertThat propName, is('okta.config.file') } @Test void testPropNameForNormalEnvVar() { def converter = new DefaultEnvVarNameConverter() def propName = converter.toDottedPropertyName('OKTA_CLIENT_AUTHENTICATIONSCHEME') - assertThat propName, is('okta.client.authenticationScheme') + MatcherAssert.assertThat propName, is('okta.client.authenticationScheme') } @Test @@ -74,7 +74,7 @@ class DefaultEnvVarNameConverterTest { // we want to round trip these properties def env = converter.toEnvVarName(it) def backToDotted = converter.toDottedPropertyName(env) - assertThat backToDotted, is(it) + MatcherAssert.assertThat backToDotted, is(it) } } } diff --git a/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultCacheKeyTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultCacheKeyTest.groovy deleted file mode 100644 index 99e361004b5..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultCacheKeyTest.groovy +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds - -import com.okta.commons.http.QueryString -import org.testng.annotations.Test - -import java.time.Instant -import java.time.format.DateTimeFormatter - -import static org.testng.Assert.* - -/** - * @since 0.5.0 - */ -class DefaultCacheKeyTest { - - @Test - void testWithQueryString() { - - def qs = new QueryString([ - "key_one":"value_one", - "key_two":"value_two" - ]) - def cacheKey = new DefaultCacheKey("https://mysite.com", qs) - - assertEquals cacheKey.toString(), "https://mysite.com?key_one=value_one&key_two=value_two" - } - - @Test - void testWithQueryStringOnURl() { - - // saved as alpha order - def qs = new QueryString([ - "key_three":"value_three", - "key_two":"value_two" - ]) - def cacheKey = new DefaultCacheKey("https://mysite.com?key_one=value_one", qs) - - assertEquals cacheKey.toString(), "https://mysite.com?key_one=value_one&key_three=value_three&key_two=value_two" - } - - @Test - void testWithDateInQueryString() { - def isoDateString = "2017-11-30T21:15:16.838Z" - Date date = Date.from(Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse(isoDateString))) - - def qs = new QueryString([ - "key_one": date - ]) - def cacheKey = new DefaultCacheKey("https://mysite.com", qs) - - assertEquals cacheKey.toString(), "https://mysite.com?key_one=" + URLEncoder.encode(isoDateString, "UTF-8") - } - - @Test - void testHashCode() { - - def qs = new QueryString(["key_one":"value_one"]) - def cacheKey = new DefaultCacheKey("https://mysite.com", qs) - - assertEquals cacheKey.hashCode(), "https://mysite.com?key_one=value_one".hashCode() - } - - @Test - void testEquals() { - - def qs = new QueryString(["key_one":"value_one"]) - def cacheKey1 = new DefaultCacheKey("https://mysite.com", qs) - assertTrue cacheKey1.equals(cacheKey1) - - def cacheKey2 = new DefaultCacheKey("https://mysite.com", qs) - assertTrue cacheKey1.equals(cacheKey2) - - assertFalse cacheKey1.equals("not the right type") - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultDataStoreTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultDataStoreTest.groovy deleted file mode 100644 index e7832027177..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultDataStoreTest.groovy +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds - -import com.okta.commons.http.HttpException -import com.okta.commons.http.HttpHeaders -import com.okta.commons.http.MediaType -import com.okta.commons.http.Request -import com.okta.commons.http.RequestExecutor -import com.okta.commons.http.Response -import com.okta.sdk.authc.credentials.ClientCredentials -import com.okta.sdk.impl.api.ClientCredentialsResolver -import com.okta.sdk.impl.http.HttpHeadersHolder -import com.okta.sdk.impl.resource.TestResource -import com.okta.sdk.impl.util.StringInputStream -import org.mockito.ArgumentCaptor -import org.mockito.Mockito -import org.testng.annotations.AfterTest -import org.testng.annotations.Test - -import static org.mockito.Mockito.* -import static org.testng.Assert.* -import static org.hamcrest.Matchers.* -import static org.hamcrest.MatcherAssert.* - -/** - * @since 0.5.0 - */ -class DefaultDataStoreTest { - - @AfterTest - void cleanUpHeaders() { - HttpHeadersHolder.clear(); - } - - @Test - void testApiKeyResolverReturnsCorrectApiKey() { - def requestExecutor = mock(RequestExecutor) - def clientCredentialsResolver = mock(ClientCredentialsResolver) - def clientCredentials = mock(ClientCredentials) - - when(clientCredentialsResolver.getClientCredentials()).thenReturn(clientCredentials) - - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com/v1", clientCredentialsResolver) - - assertEquals(defaultDataStore.getClientCredentials(), clientCredentials) - assertNotEquals(defaultDataStore.getClientCredentials(), clientCredentialsResolver) - } - - @Test - void testSetHrefOnGetResource() { - - def resourceHref = "https://api.okta.com/v1/testResource" - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def responseBody = '{"name": "jcoder"}' - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com/v1", apiKeyResolver) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(Mockito.any())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - when(response.getBody()).thenReturn(new StringInputStream(responseBody)) - when(response.getHeaders()).thenReturn(headers) - - def testResource = defaultDataStore.getResource(resourceHref, TestResource) - assertThat testResource.getResourceHref(), is(resourceHref) - } - - @Test - void testSettingRequestParamsForGetResource() { - - def resourceHref = "https://api.okta.com/v1/testResource" - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def responseBody = '{"name": "jcoder"}' - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com/v1", apiKeyResolver) - def requestCapture = ArgumentCaptor.forClass(Request) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - when(response.getBody()).thenReturn(new StringInputStream(responseBody)) - when(response.getHeaders()).thenReturn(headers) - - defaultDataStore.getResource(resourceHref, TestResource, [query1: "query-value1", query2: "query-value2"], - [header1: ["header-value1"], header2: ["header2-valueA", "header2-valueB"]]) - - def request = requestCapture.getValue() - assertThat request.headers, allOf(hasEntry("header1", ["header-value1"]), - hasEntry("header2", ["header2-valueA", "header2-valueB"])) - assertThat request.queryString, allOf(hasEntry("query1", "query-value1"), - hasEntry("query2", "query-value2")) - } - - @Test - void testSettingRequestParamsForDeleteResource() { - - def resourceHref = "https://api.okta.com/v1/testResource" - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com/v1", apiKeyResolver) - def requestCapture = ArgumentCaptor.forClass(Request) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(false) - when(response.getHeaders()).thenReturn(new HttpHeaders()) - - defaultDataStore.delete(resourceHref, [query1: "query-value1", query2: "query-value2"], - [header1: ["header-value1"], header2: ["header2-valueA", "header2-valueB"]]) - - def request = requestCapture.getValue() - assertThat request.headers, allOf(hasEntry("header1", ["header-value1"]), - hasEntry("header2", ["header2-valueA", "header2-valueB"])) - assertThat request.queryString, allOf(hasEntry("query1", "query-value1"), - hasEntry("query2", "query-value2")) - } - - @Test - void testSettingRequestParamsForPostResource() { - - def resourceHref = "https://api.okta.com/v1/testResource" - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def responseBody = '{"name": "jcoder"}' - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com/v1", apiKeyResolver) - def requestCapture = ArgumentCaptor.forClass(Request) - def resource = new TestResource(null, null) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - when(response.getBody()).thenReturn(new StringInputStream(responseBody)) - when(response.getHeaders()).thenReturn(headers) - - defaultDataStore.save(resourceHref, resource, null, [query1: "query-value1", query2: "query-value2"], - [header1: ["header-value1"], header2: ["header2-valueA", "header2-valueB"]]) - - def request = requestCapture.getValue() - assertThat request.headers, allOf(hasEntry("header1", ["header-value1"]), - hasEntry("header2", ["header2-valueA", "header2-valueB"])) - assertThat request.queryString, allOf(hasEntry("query1", "query-value1"), - hasEntry("query2", "query-value2")) - } - - @Test - void testOverrideUserAgentTest() { - def resourceHref = "https://api.okta.com/v1/testResource" - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def responseBody = '{"name": "jcoder"}' - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com/v1", apiKeyResolver) - def requestCapture = ArgumentCaptor.forClass(Request) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - when(response.getBody()).thenReturn(new StringInputStream(responseBody)) - when(response.getHeaders()).thenReturn(headers) - - defaultDataStore.getResource(resourceHref, TestResource, null, - ["User-Agent": ["test-value"]]) - - def request = requestCapture.getValue() - assertThat request.headers, hasEntry("User-Agent", ["test-value"]) - assertThat request.headers.get("X-Okta-User-Agent-Extended"), hasSize(1) - assertThat request.headers.getFirst("X-Okta-User-Agent-Extended"), allOf( - containsString("okta-sdk-java/"), - containsString("java/${System.getProperty("java.version")}"), - containsString("${System.getProperty("os.name")}/${System.getProperty("os.version")}")) - } - - @Test - void testAdditionalHeaders() { - def resourceHref = "https://api.okta.com/v1/testResource" - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def responseBody = '{"name": "jcoder"}' - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com/v1", apiKeyResolver) - def requestCapture = ArgumentCaptor.forClass(Request) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - when(response.getBody()).thenReturn(new StringInputStream(responseBody)) - when(response.getHeaders()).thenReturn(headers) - - HttpHeadersHolder.set([ - "threaded-header1": ["value1", "value2"], - "threaded-header2": ["single-value"] - ]) - - defaultDataStore.getResource(resourceHref, TestResource, null, - ["Foo-Bar": ["test-value"]]) - - def request = requestCapture.getValue() - // from the request arg - assertThat request.headers, hasEntry("Foo-Bar", ["test-value"]) - // thread local - assertThat request.headers, hasEntry("threaded-header1", ["value1", "value2"]) - assertThat request.headers, hasEntry("threaded-header2", ["single-value"]) - // default headers - assertThat request.headers.get("User-Agent"), hasSize(1) - assertThat request.headers.getFirst("User-Agent"), allOf( - containsString("okta-sdk-java/"), - containsString("java/${System.getProperty("java.version")}"), - containsString("${System.getProperty("os.name")}/${System.getProperty("os.version")}")) - } - - @Test - void testIsReadyTrue() { - def response = mock(Response) - def requestExecutor = mock(RequestExecutor) - def clientCredentialsResolver = mock(ClientCredentialsResolver) - - when(requestExecutor.executeRequest(any())).thenReturn(response) - when(response.getBody()).thenReturn(new StringInputStream('{"name": "web app"}')) - - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.example.com/v1", clientCredentialsResolver) - - assertTrue(defaultDataStore.isReady({ -> defaultDataStore.getRawResponse("/api/v1/apps", null, null) })) - } - - @Test - void testIsReadyFalse() { - def requestExecutor = mock(RequestExecutor) - def clientCredentialsResolver = mock(ClientCredentialsResolver) - - when(requestExecutor.executeRequest(any())).thenThrow(new HttpException("Unable to execute HTTP request")) - - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.example.com/v1", clientCredentialsResolver) - - assertFalse(defaultDataStore.isReady({ -> defaultDataStore.getRawResponse("/api/v1/apps", null, null) })) - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultRequestBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultRequestBuilderTest.groovy deleted file mode 100644 index 7e36d892dfa..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultRequestBuilderTest.groovy +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright 2018-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds - -import com.okta.sdk.resource.ExtensibleResource -import com.okta.sdk.resource.Resource -import com.okta.sdk.resource.VoidResource -import org.testng.annotations.Test - -import static org.mockito.Mockito.* -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@link DefaultRequestBuilder}. - * @since 1.2.0 - */ -class DefaultRequestBuilderTest { - - @Test - void testConstruct() { - - def dataStore = mock(InternalDataStore) - def voidResource = mock(VoidResource) - when(dataStore.instantiate(VoidResource)).thenReturn(voidResource) - def requestBuilder = new DefaultRequestBuilder(dataStore) - - assertThat requestBuilder.body, sameInstance(voidResource) - assertThat requestBuilder.queryParameters, anEmptyMap() - } - - @Test - void testSetBody() { - - def resource = mock(Resource) - def requestBuilder = createRequestBuilder() - - requestBuilder.setBody(resource) - assertThat requestBuilder.body, sameInstance(resource) - - requestBuilder.setBody(null) - assertThat requestBuilder.body, nullValue() - } - - @Test - void testAddQueryParameter() { - - def requestBuilder = createRequestBuilder() - - requestBuilder.addQueryParameter("key1", "value1") - requestBuilder.addQueryParameter("key2", "value2") - requestBuilder.addQueryParameter("key3", null) - assertThat requestBuilder.queryParameters, equalTo([ - key1: "value1", - key2: "value2", - key3: null - ]) - } - - @Test - void testAddQueryParameters() { - - def requestBuilder = createRequestBuilder() - def params = [ - key1: "value1", - key2: "value2", - key3: null - ] - requestBuilder.setQueryParameters(params) - assertThat requestBuilder.queryParameters, equalTo([ - key1: "value1", - key2: "value2", - key3: null - ]) - - requestBuilder.setQueryParameters(null) - assertThat requestBuilder.queryParameters, anEmptyMap() - } - - @Test - void testAddHeaderParameter() { - - def requestBuilder = createRequestBuilder() - - requestBuilder.addHeaderParameter("key1", "value1") - requestBuilder.addHeaderParameter("key2", ["value21", "value22"]) - requestBuilder.addHeaderParameter("key3", null) - - assertThat requestBuilder.headerParameters.get("key1"), is(["value1"]) - assertThat requestBuilder.headerParameters.get("key2"), is(["value21", "value22"]) - assertThat requestBuilder.headerParameters.get("key3"), nullValue() - assertThat requestBuilder.headerParameters, aMapWithSize(3) - } - - @Test - void testAddHeaderParameters() { - - def requestBuilder = createRequestBuilder() - def params = [ - key1: ["value1"], - key2: ["value21", "value22"], - key3: null - ] - requestBuilder.setHeaderParameters(params) - - assertThat requestBuilder.headerParameters.get("key1"), is(["value1"]) - assertThat requestBuilder.headerParameters.get("key2"), is(["value21", "value22"]) - assertThat requestBuilder.headerParameters.get("key3"), nullValue() - assertThat requestBuilder.headerParameters, aMapWithSize(3) - - requestBuilder.setHeaderParameters(null) - assertThat requestBuilder.headerParameters, anEmptyMap() - } - - @Test - void testGet() { - - def href = "/api/v1/foobar" - def queryParams = [ - key1: "value1", - key2: "value2", - key3: null - ] - def headerParams = [ - header1: ["value1"], - header2: ["value21", "value22"], - ] - def dataStore = mock(InternalDataStore) - def resource = mock(VoidResource) - def returnValue = mock(ExtensibleResource) - when(dataStore.instantiate(VoidResource)).thenReturn(resource) - when(dataStore.getResource(href, ExtensibleResource, queryParams, headerParams)).thenReturn(returnValue) - - def requestBuilder = new DefaultRequestBuilder(dataStore) - .setQueryParameters(queryParams) - .setHeaderParameters(headerParams) - def result = requestBuilder.get(href, ExtensibleResource) - assertThat result, sameInstance(returnValue) - } - - @Test - void testGetRaw() { - def href = "/api/v1/apps/clientId/sso/saml/metadata" - def queryParams = [ - key1: "value1" - ] - def headerParams = [ - header1: ["value1"] - ] - def dataStore = mock(InternalDataStore) - def returnValue = mock(InputStream) - when(dataStore.getRawResponse(href, queryParams, headerParams)).thenReturn(returnValue) - - def result = new DefaultRequestBuilder(dataStore) - .setQueryParameters(queryParams) - .setHeaderParameters(headerParams) - .getRaw(href) - - assertThat result, sameInstance(returnValue) - } - - @Test - void testPut() { - - def href = "/api/v1/foobar" - def queryParams = [ - key1: "value1", - key2: "value2", - key3: null - ] - def headerParams = [ - header1: ["value1"], - header2: ["value21", "value22"], - ] - def dataStore = mock(InternalDataStore) - def resource = mock(VoidResource) - def putResource = mock(ExtensibleResource) - when(dataStore.instantiate(VoidResource)).thenReturn(resource) - - def requestBuilder = new DefaultRequestBuilder(dataStore) - .setBody(putResource) - .setQueryParameters(queryParams) - .setHeaderParameters(headerParams) - requestBuilder.put(href) - verify(dataStore).save(href, putResource, null, queryParams, headerParams) - } - - @Test - void testPostWithType() { - - def href = "/api/v1/foobar" - def queryParams = [ - key1: "value1", - key2: "value2", - key3: null - ] - def headerParams = [ - header1: ["value1"], - header2: ["value21", "value22"], - ] - def dataStore = mock(InternalDataStore) - def resource = mock(VoidResource) - def postResource = mock(ExtensibleResource) - def returnValue = mock(ExtensibleResource) - when(dataStore.instantiate(VoidResource)).thenReturn(resource) - when(dataStore.create(href, postResource, null, ExtensibleResource, queryParams, headerParams)).thenReturn(returnValue) - - def result = new DefaultRequestBuilder(dataStore) - .setBody(postResource) - .setQueryParameters(queryParams) - .setHeaderParameters(headerParams) - .post(href, ExtensibleResource) - - assertThat result, sameInstance(returnValue) - } - - @Test - void testPost() { - - def href = "/api/v1/foobar" - def queryParams = [ - key1: "value1", - key2: "value2", - key3: null - ] - def headerParams = [ - header1: ["value1"], - header2: ["value21", "value22"], - ] - def dataStore = mock(InternalDataStore) - def resource = mock(VoidResource) - def postResource = mock(ExtensibleResource) - when(dataStore.instantiate(VoidResource)).thenReturn(resource) - - new DefaultRequestBuilder(dataStore) - .setBody(postResource) - .setQueryParameters(queryParams) - .setHeaderParameters(headerParams) - .post(href) - - verify(dataStore).create(href, postResource, null, VoidResource, queryParams, headerParams) - } - - @Test - void testDelete() { - - def href = "/api/v1/foobar" - def queryParams = [ - key1: "value1", - key2: "value2", - key3: null - ] - def headerParams = [ - header1: ["value1"], - header2: ["value21", "value22"], - ] - def dataStore = mock(InternalDataStore) - def resource = mock(VoidResource) - when(dataStore.instantiate(VoidResource)).thenReturn(resource) - - new DefaultRequestBuilder(dataStore) - .setQueryParameters(queryParams) - .setHeaderParameters(headerParams) - .delete(href) - - verify(dataStore).delete(href, queryParams, headerParams) - } - - private def createRequestBuilder() { - - def dataStore = mock(InternalDataStore) - def voidResource = mock(VoidResource) - when(dataStore.instantiate(VoidResource)).thenReturn(voidResource) - - return new DefaultRequestBuilder(dataStore) - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultResourceFactoryTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultResourceFactoryTest.groovy deleted file mode 100644 index 7b756734b61..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/ds/DefaultResourceFactoryTest.groovy +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds - -import com.okta.sdk.resource.Resource -import com.okta.sdk.resource.user.factor.UserFactor -import com.okta.sdk.resource.user.factor.FactorType -import com.okta.sdk.resource.user.factor.TotpUserFactor -import org.testng.annotations.Test - -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.instanceOf -import static org.hamcrest.MatcherAssert.assertThat - -/** - * Tests for {@link DefaultResourceFactory}. - */ -class DefaultResourceFactoryTest { - - /** - * @since 0.8.1 - */ - @Test - void discriminatorTest() { - DefaultResourceFactory resourceFactory = new DefaultResourceFactory(null) - - def map = [ - factorType: "token:software:totp" - ] - UserFactor factor = resourceFactory.instantiate(UserFactor, map) - assertThat factor, instanceOf(TotpUserFactor) - assertThat factor.getFactorType(), equalTo(FactorType.TOKEN_SOFTWARE_TOTP) - } - - @Test - void implClassFqcnTest() { - String implClassFqcn = DefaultResourceFactory.constructImplFqcn("com.okta.sdk.resource.VoidResource" as Class) - assertThat implClassFqcn, equalTo("com.okta.sdk.impl.resource.DefaultVoidResource") - - implClassFqcn = DefaultResourceFactory.constructImplFqcn("com.okta.sdk.extensibleresource.CustomResource" as Class) - assertThat implClassFqcn, equalTo("com.okta.sdk.impl.extensibleresource.DefaultCustomResource") - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/ds/JacksonMapMarshallerTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/ds/JacksonMapMarshallerTest.groovy deleted file mode 100644 index d2c7578d9a4..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/ds/JacksonMapMarshallerTest.groovy +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds - -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.databind.SerializationFeature -import com.okta.sdk.impl.resource.AbstractResource -import com.okta.sdk.impl.resource.CharacterArrayProperty -import com.okta.sdk.impl.resource.Property -import com.okta.sdk.impl.resource.ReferenceFactory -import com.okta.sdk.impl.resource.StringProperty -import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer -import org.testng.annotations.Test - -import static org.mockito.Mockito.* -import static org.testng.Assert.* -import static org.hamcrest.Matchers.* -import static org.hamcrest.MatcherAssert.assertThat - -/** - * @since 0.5.0 - */ -class JacksonMapMarshallerTest { - - @Test - void testGetAndSetObjectMapper() { - - JacksonMapMarshaller mapMarshaller = new JacksonMapMarshaller() - def objectMapper = new ObjectMapper() - mapMarshaller.setObjectMapper(objectMapper) - - assertEquals mapMarshaller.getObjectMapper(), objectMapper - } - - @Test - void testSetPrettyPrint() { - - JacksonMapMarshaller mapMarshaller = new JacksonMapMarshaller() - def objectMapper = new ObjectMapper() - mapMarshaller.setObjectMapper(objectMapper) - - mapMarshaller.setPrettyPrint(true) - - assertTrue objectMapper.getSerializationConfig().isEnabled(SerializationFeature.INDENT_OUTPUT) - assertTrue mapMarshaller.isPrettyPrint() - } - - @Test - void testMarshalException() { - - JacksonMapMarshaller mapMarshaller = new JacksonMapMarshaller() - def objectMapper = mock(ObjectMapper) - when(objectMapper.writeValueAsString(null)).then(new Answer() { - @Override - String answer(InvocationOnMock invocation) throws Throwable { - throw new IOException("kaboom") - } - }) - mapMarshaller.setObjectMapper(objectMapper) - - try { - ByteArrayOutputStream out = new ByteArrayOutputStream() - mapMarshaller.marshal(out, null) - fail("shouldn't be here") - } catch (MarshalingException e) { - assertEquals e.getMessage(), "Cannot convert null to JSON." - } - } - - @Test - void testUnmarshalInputStreamException() { - - JacksonMapMarshaller mapMarshaller = new JacksonMapMarshaller() - def objectMapper = mock(ObjectMapper) - def inputStream = mock(InputStream) - when(objectMapper.readValue((InputStream)eq(inputStream), (Class)eq(Object.class))) - .then(new Answer() { - @Override - Map answer(InvocationOnMock invocation) throws Throwable { - throw new IOException("kaboom") - } - }) - mapMarshaller.setObjectMapper(objectMapper) - - try { - mapMarshaller.unmarshal(inputStream, null) - fail("shouldn't be here") - } catch (MarshalingException e) { - assertEquals e.getMessage(), "Unable to convert InputStream String to Map." - } - } - - @Test - void testMapContainingList() { - - def testMap = [ - "test1": "value1", - "simpleListKey": ["one", "two", "three"], - "complexResourceList": [new FooResource(null, [foo: "bar1"]), - new FooResource(null, [foo: "bar2"])] - ] - - ByteArrayOutputStream out = new ByteArrayOutputStream() - new JacksonMapMarshaller().marshal(out, testMap) - String result = out.toString() - - assertThat result, not(containsString("dirty")) - assertThat result, containsString('"complexResourceList":[{"foo":"bar1"},{"foo":"bar2"}]') - assertThat result, containsString('"simpleListKey":["one","two","three"]') - assertThat result, containsString('"test1":"value1"') - } - - @Test - void testCharArrayPropertyConvertedToJsonString() { - - FooResource foo = new FooResource(null, null) - foo.setBar("MyPassword".toCharArray()) - - ResourceConverter resourceConverter = new DefaultResourceConverter(new ReferenceFactory()) - final Map map = resourceConverter.convert(foo, false) - - ByteArrayOutputStream out = new ByteArrayOutputStream() - new JacksonMapMarshaller().marshal(out, map) - assertThat out.toString(), containsString("\"MyPassword\"") - } - - static class FooResource extends AbstractResource { - - private final static StringProperty FOO_PROPERTY = new StringProperty("foo") - private final static CharacterArrayProperty BAR_PROPERTY = new CharacterArrayProperty("bar") - - private final static Map PROPERTY_DESCRIPTORS = createPropertyDescriptorMap(FOO_PROPERTY, BAR_PROPERTY) - - FooResource(InternalDataStore dataStore) { - super(dataStore) - } - - FooResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties) - } - - @Override - Map getPropertyDescriptors() { - return PROPERTY_DESCRIPTORS - } - - String getFoo() { - return getString(FOO_PROPERTY) - } - - FooResource setFoo(String foo) { - setProperty(FOO_PROPERTY, foo) - return this - } - - char[] getBar() { - return getCharArray(BAR_PROPERTY) - } - - FooResource setBar(char[] bar) { - setProperty(BAR_PROPERTY, bar) - return this - } - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/ds/MarshalingExceptionTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/ds/MarshalingExceptionTest.groovy deleted file mode 100644 index 39d0e759946..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/ds/MarshalingExceptionTest.groovy +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds - -import org.testng.annotations.Test - -import static org.testng.Assert.assertEquals - -/** - * @since 0.5.0 - */ -class MarshalingExceptionTest { - - @Test - void testConstructWithString() { - - def marshalingException = new MarshalingException("kaboom") - assertEquals marshalingException.getMessage(), "kaboom" - } - - @Test - void testConstructWithThrowable() { - - def marshalingException = new MarshalingException(new IOException()) - assertEquals marshalingException.getCause().class, IOException - } - - @Test - void testConstructorWithStringAndThrowable() { - - def marshalingException = new MarshalingException("kaboom", new IOException()) - assertEquals marshalingException.getCause().class, IOException - assertEquals marshalingException.getMessage(), "kaboom" - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/ds/WriteCacheFilterTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/ds/WriteCacheFilterTest.groovy deleted file mode 100644 index e4a1d434142..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/ds/WriteCacheFilterTest.groovy +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds - -import com.okta.sdk.cache.CacheManager -import com.okta.sdk.impl.cache.DefaultCacheManager -import com.okta.sdk.impl.ds.cache.CacheResolver -import com.okta.sdk.impl.ds.cache.DefaultCacheResolver -import com.okta.sdk.impl.ds.cache.DefaultResourceCacheStrategy -import com.okta.sdk.impl.ds.cache.ResourceCacheStrategy -import com.okta.sdk.impl.ds.cache.WriteCacheFilter -import com.okta.commons.http.QueryString -import com.okta.sdk.impl.http.support.DefaultCanonicalUri -import com.okta.sdk.impl.resource.HalResourceHrefResolver -import com.okta.sdk.impl.resource.StubEnum -import com.okta.sdk.impl.resource.StubResource -import org.testng.annotations.Test - -import static org.mockito.Mockito.* -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -class WriteCacheFilterTest { - - @Test - void simpleCacheGetTest() { - - String baseUrl = "https://okta.example.com/cache-test" - String resourceUrl = "${baseUrl}/cache-me" - - CacheManager cacheManager = new DefaultCacheManager() - CacheRegionNameResolver cacheRegionNameResolver = mock(CacheRegionNameResolver) - when(cacheRegionNameResolver.getCacheRegionName(StubResource)).thenReturn(StubResource.getName()) - CacheResolver cacheResolver = new DefaultCacheResolver(cacheManager, cacheRegionNameResolver) - - ResourceCacheStrategy cacheStrategy = new DefaultResourceCacheStrategy(new HalResourceHrefResolver(), cacheResolver) - WriteCacheFilter cacheFilter = new WriteCacheFilter(cacheStrategy) - - Map payload = [ - booleanPropKey: true, - enumPropKey: StubEnum.VALUE_1, - intPropKey: 123, - stringPropKey: "foo", - _links: [ - self: [ - href: resourceUrl - ] - ] - ] - - DefaultCanonicalUri canonicalUri = new DefaultCanonicalUri(resourceUrl, QueryString.create("")) - ResourceDataRequest dataRequest = new DefaultResourceDataRequest(ResourceAction.READ, canonicalUri, StubResource, Collections.emptyMap()) - ResourceDataResult resourceDataResult = new DefaultResourceDataResult(ResourceAction.READ, canonicalUri, StubResource, payload) - FilterChain filterChain = mock(FilterChain) - when(filterChain.filter(any(ResourceDataRequest))).thenReturn(resourceDataResult) - def result = cacheFilter.filter(dataRequest, filterChain) - - assertThat result, sameInstance(resourceDataResult) - def cachedItem = cacheResolver.getCache(StubResource).get(resourceUrl) - assertThat cachedItem, notNullValue() - assertThat cachedItem, equalTo(payload) - } - - @Test - void getThenUpdateTest() { - - String baseUrl = "https://okta.example.com/cache-test" - String resourceUrl = "${baseUrl}/cache-me" - - CacheManager cacheManager = new DefaultCacheManager() - CacheRegionNameResolver cacheRegionNameResolver = mock(CacheRegionNameResolver) - when(cacheRegionNameResolver.getCacheRegionName(StubResource)).thenReturn(StubResource.getName()) - CacheResolver cacheResolver = new DefaultCacheResolver(cacheManager, cacheRegionNameResolver) - - ResourceCacheStrategy cacheStrategy = new DefaultResourceCacheStrategy(new HalResourceHrefResolver(), cacheResolver) - WriteCacheFilter cacheFilter = new WriteCacheFilter(cacheStrategy) - - Map initialGetPayload = [ - booleanPropKey: true, - enumPropKey: StubEnum.VALUE_1, - intPropKey: 123, - stringPropKey: "foo", - _links: [ - self: [ - href: resourceUrl - ] - ] - ] - - Map updatePayload = [ - booleanPropKey: false, - enumPropKey: StubEnum.VALUE_2, - intPropKey: 123456, - stringPropKey: "foobar" - ] - - Map updatePayloadResponse = [ - booleanPropKey: false, - enumPropKey: StubEnum.VALUE_2, - intPropKey: 123456, - stringPropKey: "foobar", - extraProperty: "extra-extra", - _links: [ - self: [ - href: resourceUrl - ] - ] - ] - - DefaultCanonicalUri canonicalUri = new DefaultCanonicalUri(resourceUrl, QueryString.create("")) - - // GET - ResourceDataRequest getDataRequest = new DefaultResourceDataRequest(ResourceAction.READ, canonicalUri, StubResource, Collections.emptyMap()) - ResourceDataResult getResourceDataResult = new DefaultResourceDataResult(ResourceAction.READ, canonicalUri, StubResource, initialGetPayload) - - // UPDATE - ResourceDataRequest updateDataRequest = new DefaultResourceDataRequest(ResourceAction.UPDATE, canonicalUri, StubResource, updatePayload) - ResourceDataResult updateResourceDataResult = new DefaultResourceDataResult(ResourceAction.UPDATE, canonicalUri, StubResource, updatePayloadResponse) - - FilterChain filterChain = mock(FilterChain) - when(filterChain.filter(any(ResourceDataRequest))) - .thenReturn(getResourceDataResult) - .thenReturn(updateResourceDataResult) - - // do READ - def initialGetResult = cacheFilter.filter(getDataRequest, filterChain) - // validate initial cache of the get - assertThat initialGetResult, sameInstance(getResourceDataResult) - def getCachedItem = cacheResolver.getCache(StubResource).get(resourceUrl) - assertThat getCachedItem, notNullValue() - assertThat getCachedItem, equalTo(initialGetPayload) - - // do UPDATE - def updateResult = cacheFilter.filter(updateDataRequest, filterChain) - // validate the updated cache - assertThat updateResult, sameInstance(updateResourceDataResult) - def updatedCachedItem = cacheResolver.getCache(StubResource).get(resourceUrl) - assertThat updatedCachedItem, notNullValue() - assertThat updatedCachedItem, equalTo(updatePayloadResponse) - } - - @Test - void getThenDeleteTest() { - - String baseUrl = "https://okta.example.com/cache-test" - String resourceUrl = "${baseUrl}/cache-me" - - CacheManager cacheManager = new DefaultCacheManager() - CacheRegionNameResolver cacheRegionNameResolver = mock(CacheRegionNameResolver) - when(cacheRegionNameResolver.getCacheRegionName(StubResource)).thenReturn(StubResource.getName()) - CacheResolver cacheResolver = new DefaultCacheResolver(cacheManager, cacheRegionNameResolver) - - ResourceCacheStrategy cacheStrategy = new DefaultResourceCacheStrategy(new HalResourceHrefResolver(), cacheResolver) - WriteCacheFilter cacheFilter = new WriteCacheFilter(cacheStrategy) - - Map initialGetPayload = [ - booleanPropKey: true, - enumPropKey: StubEnum.VALUE_1, - intPropKey: 123, - stringPropKey: "foo", - _links: [ - self: [ - href: resourceUrl - ] - ] - ] - - DefaultCanonicalUri canonicalUri = new DefaultCanonicalUri(resourceUrl, QueryString.create("")) - - // GET - ResourceDataRequest getDataRequest = new DefaultResourceDataRequest(ResourceAction.READ, canonicalUri, StubResource, Collections.emptyMap()) - ResourceDataResult getResourceDataResult = new DefaultResourceDataResult(ResourceAction.READ, canonicalUri, StubResource, initialGetPayload) - - // DELETE - ResourceDataRequest deleteDataRequest = new DefaultResourceDataRequest(ResourceAction.DELETE, canonicalUri, StubResource, Collections.emptyMap()) - ResourceDataResult deleteResourceDataResult = new DefaultResourceDataResult(ResourceAction.DELETE, canonicalUri, StubResource, Collections.emptyMap()) - - FilterChain filterChain = mock(FilterChain) - when(filterChain.filter(any(ResourceDataRequest))) - .thenReturn(getResourceDataResult) - .thenReturn(deleteResourceDataResult) - - // do READ - def initialGetResult = cacheFilter.filter(getDataRequest, filterChain) - // validate initial cache of the get - assertThat initialGetResult, sameInstance(getResourceDataResult) - def getCachedItem = cacheResolver.getCache(StubResource).get(resourceUrl) - assertThat getCachedItem, notNullValue() - assertThat getCachedItem, equalTo(initialGetPayload) - - // do DELETE - def deleteResult = cacheFilter.filter(deleteDataRequest, filterChain) - // validate the cached item has been removed - assertThat deleteResult, sameInstance(deleteResourceDataResult) - def deletedCachedItem = cacheResolver.getCache(StubResource).get(resourceUrl) - assertThat deletedCachedItem, nullValue() - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/ds/cache/DefaultResourceCacheStrategyTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/ds/cache/DefaultResourceCacheStrategyTest.groovy deleted file mode 100644 index 4a36d5d3cea..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/ds/cache/DefaultResourceCacheStrategyTest.groovy +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.ds.cache - -import com.okta.sdk.cache.Cache -import com.okta.sdk.cache.CacheManager -import com.okta.sdk.impl.cache.DefaultCacheManager -import com.okta.sdk.impl.ds.CacheRegionNameResolver -import com.okta.sdk.impl.ds.DefaultResourceDataRequest -import com.okta.sdk.impl.ds.DefaultResourceDataResult -import com.okta.sdk.impl.ds.ResourceAction -import com.okta.sdk.impl.ds.ResourceDataRequest -import com.okta.sdk.impl.ds.ResourceDataResult -import com.okta.commons.http.QueryString -import com.okta.sdk.impl.http.support.DefaultCanonicalUri -import com.okta.sdk.impl.resource.HalResourceHrefResolver -import com.okta.sdk.impl.resource.StubEnum -import com.okta.sdk.impl.resource.StubResource -import com.okta.sdk.resource.VoidResource -import org.testng.annotations.Test - -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.verify -import static org.mockito.Mockito.verifyNoMoreInteractions -import static org.mockito.Mockito.when - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -class DefaultResourceCacheStrategyTest { - - @Test - void basicCacheTest() { - - String baseUrl = "https://okta.example.com/cache-strategy-test" - String resourceUrl = "${baseUrl}/cache-me" - - CacheManager cacheManager = new DefaultCacheManager() - CacheRegionNameResolver cacheRegionNameResolver = mock(CacheRegionNameResolver) - when(cacheRegionNameResolver.getCacheRegionName(StubResource)).thenReturn(StubResource.getName()) - CacheResolver cacheResolver = new DefaultCacheResolver(cacheManager, cacheRegionNameResolver) - - ResourceCacheStrategy cacheStrategy = new DefaultResourceCacheStrategy(new HalResourceHrefResolver(), cacheResolver) - - DefaultCanonicalUri canonicalUri = new DefaultCanonicalUri(resourceUrl, QueryString.create("")) - ResourceDataRequest dataRequest = new DefaultResourceDataRequest(ResourceAction.READ, canonicalUri, StubResource, Collections.emptyMap()) - def payload = createCacheableResourceData(resourceUrl) - ResourceDataResult resourceDataResult = new DefaultResourceDataResult(ResourceAction.READ, canonicalUri, StubResource, payload) - - // nothing in cache, value should be null - assertThat cacheStrategy.readFromCache(dataRequest), nullValue() - - // cache value - cacheStrategy.cache(dataRequest, resourceDataResult) - def cachedValue = cacheManager.getCache(StubResource.getName()).get(resourceUrl) - assertThat cachedValue, notNullValue() - assertThat cachedValue, equalTo(payload) - - // read will return the cached object - ResourceDataResult readCacheResult = cacheStrategy.readFromCache(dataRequest) - assertThat readCacheResult.getData(), equalTo(payload) - - // now a delete request - ResourceDataRequest deleteDataRequest = new DefaultResourceDataRequest(ResourceAction.DELETE, canonicalUri, StubResource, Collections.emptyMap()) - ResourceDataResult deleteDataResult = new DefaultResourceDataResult(ResourceAction.DELETE, canonicalUri, StubResource, Collections.emptyMap()) - - // read should return null because this is a delete request - assertThat cacheStrategy.readFromCache(deleteDataRequest), nullValue() - // cache should be unaffected - assertThat cacheManager.getCache(StubResource.getName()).get(resourceUrl), equalTo(payload) - - // now cache the delete request - cacheStrategy.cache(deleteDataRequest, deleteDataResult) - assertThat cacheManager.getCache(StubResource.getName()).get(resourceUrl), nullValue() - } - - @Test - void testUncacheRPC() { - - String baseUrl = "https://okta.example.com/cache-strategy-test" - String resourceUrl = "${baseUrl}/cache-me" - - Cache cache = mock(Cache) - CacheManager cacheManager = mock(CacheManager) - when(cacheManager.getCache(StubResource.getName())).thenReturn(cache) - CacheRegionNameResolver cacheRegionNameResolver = mock(CacheRegionNameResolver) - when(cacheRegionNameResolver.getCacheRegionName(StubResource)).thenReturn(StubResource.getName()) - CacheResolver cacheResolver = new DefaultCacheResolver(cacheManager, cacheRegionNameResolver) - - ResourceCacheStrategy cacheStrategy = new DefaultResourceCacheStrategy(new HalResourceHrefResolver(), cacheResolver) - - DefaultCanonicalUri canonicalUri = new DefaultCanonicalUri(resourceUrl, QueryString.create("")) - ResourceDataRequest dataRequest = new DefaultResourceDataRequest(ResourceAction.READ, canonicalUri, StubResource, Collections.emptyMap()) - def payload = createCacheableResourceData(resourceUrl) - ResourceDataResult resourceDataResult = new DefaultResourceDataResult(ResourceAction.READ, canonicalUri, StubResource, payload) - - // cache value - cacheStrategy.cache(dataRequest, resourceDataResult) - - DefaultCanonicalUri rpcActionUri = new DefaultCanonicalUri("${resourceUrl}/lifecycle/foobar", QueryString.create("")) - ResourceDataRequest rpcActionDataRequest = new DefaultResourceDataRequest(ResourceAction.UPDATE, rpcActionUri, canonicalUri, VoidResource, StubResource, Collections.emptyMap(), null) - ResourceDataResult rpcActionDataResult = new DefaultResourceDataResult(ResourceAction.UPDATE, rpcActionUri, StubResource, Collections.emptyMap()) - - // hit the cache again with the RPC request - cacheStrategy.cache(rpcActionDataRequest, rpcActionDataResult) - - verify(cache).remove(resourceUrl) - } - - @Test - void nonCacheableObjectTest() { - - String baseUrl = "https://okta.example.com/cache-strategy-test" - String resourceUrl = "${baseUrl}/cache-me" - - CacheManager cacheManager = mock(CacheManager) - CacheRegionNameResolver cacheRegionNameResolver = mock(CacheRegionNameResolver) - when(cacheRegionNameResolver.getCacheRegionName(StubResource)).thenReturn(StubResource.getName()) - CacheResolver cacheResolver = new DefaultCacheResolver(cacheManager, cacheRegionNameResolver) - - ResourceCacheStrategy cacheStrategy = new DefaultResourceCacheStrategy(new HalResourceHrefResolver(), cacheResolver) - - DefaultCanonicalUri canonicalUri = new DefaultCanonicalUri(resourceUrl, QueryString.create("")) - ResourceDataRequest dataRequest = new DefaultResourceDataRequest(ResourceAction.READ, canonicalUri, StubResource, Collections.emptyMap()) - def payload = createNonResourceData() - ResourceDataResult resourceDataResult = new DefaultResourceDataResult(ResourceAction.READ, canonicalUri, StubResource, payload) - - // cache value - cacheStrategy.cache(dataRequest, resourceDataResult) - - // getCache was never called - verifyNoMoreInteractions(cacheManager) - } - - def createCacheableResourceData(String href) { - return [ - booleanPropKey: true, - enumPropKey: StubEnum.VALUE_1, - intPropKey: 123, - stringPropKey: "foo", - _links: [ - self: [ - href: href - ] - ] - ] - } - - def createNonResourceData() { - return [ - booleanPropKey: true, - enumPropKey: StubEnum.VALUE_1, - intPropKey: 123, - stringPropKey: "foo" - ] - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/error/DefaultErrorTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/error/DefaultErrorTest.groovy deleted file mode 100644 index ca562e3b5df..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/error/DefaultErrorTest.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.error - -import org.testng.annotations.Test - -import static org.testng.Assert.assertEquals -import static org.testng.Assert.assertTrue - -/** - * @since 0.5.0 - */ -class DefaultErrorTest { - - @Test - void testGetPropertyDescriptors() { - def defaultError = new DefaultError(new HashMap()) - finishTest(defaultError) - } - - /** - * see https://github.com/stormpath/stormpath-sdk-java/pull/770 - */ - @Test - void testtestGetPropertyDescriptorsDefaultConstructor() { - def defaultError = new DefaultError() - finishTest(defaultError) - } - - private void finishTest(DefaultError defaultError) { - assertEquals defaultError.getPropertyDescriptors().keySet().size(), 6 - [ - DefaultError.STATUS, DefaultError.CODE, DefaultError.CAUSES, DefaultError.MESSAGE, DefaultError.ERROR_ID - ].each { - assertTrue defaultError.getPropertyDescriptors().keySet().contains(it.name) - } - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/http/OAuth2RequestAuthenticatorConcurrencyTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/http/OAuth2RequestAuthenticatorConcurrencyTest.groovy deleted file mode 100644 index 50e1aa2f5ee..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/http/OAuth2RequestAuthenticatorConcurrencyTest.groovy +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http - -import com.okta.commons.http.HttpHeaders -import com.okta.commons.http.Request -import com.okta.commons.http.authc.RequestAuthenticator - -import com.okta.sdk.impl.http.authc.OAuth2RequestAuthenticator -import com.okta.sdk.impl.oauth2.AccessTokenRetrieverService -import com.okta.sdk.impl.oauth2.OAuth2AccessToken -import com.okta.sdk.impl.oauth2.OAuth2ClientCredentials - -import org.testng.annotations.AfterTest -import org.testng.annotations.BeforeTest -import org.testng.annotations.Test - -import static org.mockito.Mockito.when -import static org.mockito.Mockito.verify -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.times - -/** - * Concurreny test for {@link com.okta.sdk.impl.http.authc.OAuth2RequestAuthenticator} class - * - * @since 1.6.0 - */ -class OAuth2RequestAuthenticatorConcurrencyTest { - - OAuth2RequestAuthenticator oAuth2RequestAuthenticator - - def initialAccessTokenStr = "initial-token-12345" - def refreshedAccessTokenStr = "refreshed-token-12345" - - def request = mock(Request) - def clientCredentials = mock(OAuth2ClientCredentials) - def accessTokenRetrievalService = mock(AccessTokenRetrieverService) - def initialAccessTokenObj = mock(OAuth2AccessToken) - def refreshedAccessTokenObj = mock(OAuth2AccessToken) - def httpHeaders = mock(HttpHeaders) - - @BeforeTest - void initialize() { - oAuth2RequestAuthenticator = new OAuth2RequestAuthenticator(clientCredentials) - - when(initialAccessTokenObj.getAccessToken()).thenReturn(initialAccessTokenStr) - when(initialAccessTokenObj.hasExpired()).thenReturn(true) - - when(refreshedAccessTokenObj.getAccessToken()).thenReturn(refreshedAccessTokenStr) - - when(clientCredentials.getCredentials()).thenReturn(initialAccessTokenObj) - when(clientCredentials.getAccessTokenRetrieverService()).thenReturn(accessTokenRetrievalService) - when(accessTokenRetrievalService.getOAuth2AccessToken()).thenReturn(refreshedAccessTokenObj) - - when(request.getHeaders()).thenReturn(httpHeaders) - } - - @Test(threadPoolSize = 5, invocationCount = 10) - void testAuthenticateRequestWithExpiredInitialToken() { - oAuth2RequestAuthenticator.authenticate(request) - Thread.sleep((long)(Math.random() * 1000)) /* sleep random time (max 1000 ms) */ - } - - @AfterTest - void verifyMocks() { - verify(clientCredentials, times(10)).getCredentials() - verify(initialAccessTokenObj, times(20)).hasExpired() // double locking - verify(accessTokenRetrievalService, times(10)).getOAuth2AccessToken() - verify(clientCredentials, times(10)).setCredentials(refreshedAccessTokenObj) - verify(request.getHeaders(), times(10)) - .set(RequestAuthenticator.AUTHORIZATION_HEADER, "Bearer " + refreshedAccessTokenStr) - } - -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/http/OAuth2RequestAuthenticatorTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/http/OAuth2RequestAuthenticatorTest.groovy deleted file mode 100644 index d835831e280..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/http/OAuth2RequestAuthenticatorTest.groovy +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http - -import com.okta.commons.http.HttpHeaders -import com.okta.commons.http.Request -import com.okta.commons.http.authc.RequestAuthenticator -import com.okta.sdk.impl.Util -import com.okta.sdk.impl.http.authc.OAuth2RequestAuthenticator -import com.okta.sdk.impl.oauth2.AccessTokenRetrieverService -import com.okta.sdk.impl.oauth2.OAuth2AccessToken -import com.okta.sdk.impl.oauth2.OAuth2ClientCredentials -import com.okta.sdk.impl.oauth2.OAuth2TokenRetrieverException - -import org.testng.annotations.Test - -import java.security.InvalidKeyException - -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.never -import static org.mockito.Mockito.reset -import static org.mockito.Mockito.times -import static org.mockito.Mockito.verify -import static org.mockito.Mockito.when - -/** - * Test for {@link com.okta.sdk.impl.http.authc.OAuth2RequestAuthenticator} class - * - * @since 1.6.0 - */ -class OAuth2RequestAuthenticatorTest { - - @Test - void testInstantiationWithNullClientCredentials() { - Util.expect(IllegalArgumentException) { - new OAuth2RequestAuthenticator(null) - } - } - - @Test - void testAuthenticateRequestWithUnexpiredInitialToken() { - def initialAccessTokenStr = "initial-token-12345" - - def request = mock(Request) - - def clientCredentials = mock(OAuth2ClientCredentials) - def accessTokenRetrievalService = mock(AccessTokenRetrieverService) - def initialAccessTokenObj = mock(OAuth2AccessToken) - - def httpHeaders = mock(HttpHeaders) - - when(initialAccessTokenObj.getAccessToken()).thenReturn(initialAccessTokenStr) - when(initialAccessTokenObj.hasExpired()).thenReturn(false) - - when(clientCredentials.getCredentials()).thenReturn(initialAccessTokenObj) - when(clientCredentials.getAccessTokenRetrieverService()).thenReturn(accessTokenRetrievalService) - - when(request.getHeaders()).thenReturn(httpHeaders) - - new OAuth2RequestAuthenticator(clientCredentials).authenticate(request) - - verify(clientCredentials, times(1)).getCredentials() - verify(initialAccessTokenObj, times(1)).hasExpired() - verify(request.getHeaders(), times(1)) - .set(RequestAuthenticator.AUTHORIZATION_HEADER, "Bearer " + initialAccessTokenStr) - } - - @Test - void testAuthenticateRequestWithExpiredInitialToken() { - def initialAccessTokenStr = "initial-token-12345" - def refreshedAccessTokenStr = "refreshed-token-12345" - - def request = mock(Request) - - def clientCredentials = mock(OAuth2ClientCredentials) - def accessTokenRetrievalService = mock(AccessTokenRetrieverService) - def initialAccessTokenObj = mock(OAuth2AccessToken) - def refreshedAccessTokenObj = mock(OAuth2AccessToken) - - def httpHeaders = mock(HttpHeaders) - - when(initialAccessTokenObj.getAccessToken()).thenReturn(initialAccessTokenStr) - when(initialAccessTokenObj.hasExpired()).thenReturn(true) - - when(refreshedAccessTokenObj.getAccessToken()).thenReturn(refreshedAccessTokenStr) - - when(clientCredentials.getCredentials()).thenReturn(initialAccessTokenObj) - when(clientCredentials.getAccessTokenRetrieverService()).thenReturn(accessTokenRetrievalService) - when(accessTokenRetrievalService.getOAuth2AccessToken()).thenReturn(refreshedAccessTokenObj) - - when(request.getHeaders()).thenReturn(httpHeaders) - - new OAuth2RequestAuthenticator(clientCredentials).authenticate(request) - - verify(clientCredentials, times(1)).getCredentials() - verify(initialAccessTokenObj, times(2)).hasExpired() // double locking - verify(accessTokenRetrievalService, times(1)).getOAuth2AccessToken() - verify(clientCredentials, times(1)).setCredentials(refreshedAccessTokenObj) - verify(request.getHeaders(), times(1)) - .set(RequestAuthenticator.AUTHORIZATION_HEADER, "Bearer " + refreshedAccessTokenStr) - } - - @Test(expectedExceptions = OAuth2TokenRetrieverException) - void testRefreshTokenFetchException() { - def initialAccessTokenStr = "initial-token-12345" - - def request = mock(Request) - - def clientCredentials = mock(OAuth2ClientCredentials) - def accessTokenRetrievalService = mock(AccessTokenRetrieverService) - def initialAccessTokenObj = mock(OAuth2AccessToken) - - when(initialAccessTokenObj.getAccessToken()).thenReturn(initialAccessTokenStr) - when(initialAccessTokenObj.hasExpired()).thenReturn(true) - - when(clientCredentials.getCredentials()).thenReturn(initialAccessTokenObj) - when(clientCredentials.getAccessTokenRetrieverService()).thenReturn(accessTokenRetrievalService) - when(accessTokenRetrievalService.getOAuth2AccessToken()) - .thenThrow(new OAuth2TokenRetrieverException("Failed to renew expired OAuth2 access token")) - - new OAuth2RequestAuthenticator(clientCredentials).authenticate(request) - - verify(clientCredentials, times(1)).getCredentials() - verify(initialAccessTokenObj, times(2)).hasExpired() // double locking - verify(clientCredentials, never()).setCredentials(mock(OAuth2AccessToken)) - verify(request.getHeaders(), never()) - .set(RequestAuthenticator.AUTHORIZATION_HEADER, "Bearer " + any(String.class)) - } - - @Test(expectedExceptions = OAuth2TokenRetrieverException) - void testRefreshTokenFetchInvalidKeyException() { - def initialAccessTokenStr = "initial-token-12345" - - def request = mock(Request) - - def clientCredentials = mock(OAuth2ClientCredentials) - def accessTokenRetrievalService = mock(AccessTokenRetrieverService) - def initialAccessTokenObj = mock(OAuth2AccessToken) - - when(initialAccessTokenObj.getAccessToken()).thenReturn(initialAccessTokenStr) - when(initialAccessTokenObj.hasExpired()).thenReturn(true) - - when(clientCredentials.getCredentials()).thenReturn(initialAccessTokenObj) - when(clientCredentials.getAccessTokenRetrieverService()).thenReturn(accessTokenRetrievalService) - when(accessTokenRetrievalService.getOAuth2AccessToken()) - .thenThrow(new InvalidKeyException("Failed to renew expired OAuth2 access token")) - - new OAuth2RequestAuthenticator(clientCredentials).authenticate(request) - - verify(clientCredentials, times(1)).getCredentials() - verify(initialAccessTokenObj, times(2)).hasExpired() // double locking - verify(clientCredentials, never()).setCredentials(mock(OAuth2AccessToken)) - verify(request.getHeaders(), never()) - .set(RequestAuthenticator.AUTHORIZATION_HEADER, "Bearer " + any(String.class)) - } - - @Test - void testRefreshTokenFetchWithTokenReuse() { - def initialAccessTokenStr = "initial-token-12345" - def refreshedAccessTokenStr = "refreshed-token-12345" - - def request = mock(Request) - - def clientCredentials = mock(OAuth2ClientCredentials) - def accessTokenRetrievalService = mock(AccessTokenRetrieverService) - def initialAccessTokenObj = mock(OAuth2AccessToken) - def refreshedAccessTokenObj = mock(OAuth2AccessToken) - - def httpHeaders = mock(HttpHeaders) - - when(initialAccessTokenObj.getAccessToken()).thenReturn(initialAccessTokenStr) - when(initialAccessTokenObj.hasExpired()).thenReturn(true) - - when(refreshedAccessTokenObj.getAccessToken()).thenReturn(refreshedAccessTokenStr) - - when(clientCredentials.getCredentials()).thenReturn(initialAccessTokenObj) - when(clientCredentials.getAccessTokenRetrieverService()).thenReturn(accessTokenRetrievalService) - when(accessTokenRetrievalService.getOAuth2AccessToken()).thenReturn(refreshedAccessTokenObj) - - when(request.getHeaders()).thenReturn(httpHeaders) - - new OAuth2RequestAuthenticator(clientCredentials).authenticate(request) - - verify(clientCredentials, times(1)).getCredentials() - verify(initialAccessTokenObj, times(2)).hasExpired() // double locking - verify(accessTokenRetrievalService, times(1)).getOAuth2AccessToken() - verify(clientCredentials, times(1)).setCredentials(refreshedAccessTokenObj) - verify(request.getHeaders(), times(1)) - .set(RequestAuthenticator.AUTHORIZATION_HEADER, "Bearer " + refreshedAccessTokenStr) - - // reset mocks - reset(request, clientCredentials, accessTokenRetrievalService, initialAccessTokenObj, refreshedAccessTokenObj, httpHeaders) - - // reuse the refreshed token which we got above (do not expire it) - when(request.getHeaders()).thenReturn(httpHeaders) - when(clientCredentials.getCredentials()).thenReturn(refreshedAccessTokenObj) - when(refreshedAccessTokenObj.getAccessToken()).thenReturn(refreshedAccessTokenStr) - when(refreshedAccessTokenObj.hasExpired()).thenReturn(false) - - new OAuth2RequestAuthenticator(clientCredentials).authenticate(request) - - verify(clientCredentials, times(1)).getCredentials() - verify(refreshedAccessTokenObj, times(1)).hasExpired() - verify(accessTokenRetrievalService, never()).getOAuth2AccessToken() - verify(clientCredentials, never()).setCredentials(refreshedAccessTokenObj) - verify(request.getHeaders(), times(1)) - .set(RequestAuthenticator.AUTHORIZATION_HEADER, "Bearer " + refreshedAccessTokenStr) - } - -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/http/stub/StubRequestExecutor.groovy b/impl/src/test/groovy/com/okta/sdk/impl/http/stub/StubRequestExecutor.groovy deleted file mode 100644 index ad9da9372a1..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/http/stub/StubRequestExecutor.groovy +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http.stub - -import com.okta.commons.http.HttpException -import com.okta.commons.http.Request -import com.okta.commons.http.RequestExecutor -import com.okta.commons.http.Response -import com.okta.commons.http.config.HttpClientConfiguration -/** - * - * ### For testing purposes only ### - * - * {@code RequestExecutor} stub to allow a AbstractClient to be instantiated in a unit test. - * - * @since 0.5.0 - */ -class StubRequestExecutor implements RequestExecutor { - - @Override - Response executeRequest(Request request) throws HttpException { - return null - } - - StubRequestExecutor(HttpClientConfiguration clientConfiguration) {} -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/http/stub/StubRequestExecutorFactory.groovy b/impl/src/test/groovy/com/okta/sdk/impl/http/stub/StubRequestExecutorFactory.groovy deleted file mode 100644 index 99fffe40a8b..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/http/stub/StubRequestExecutorFactory.groovy +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2018-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.http.stub - -import com.okta.commons.http.RequestExecutor -import com.okta.commons.http.RequestExecutorFactory -import com.okta.commons.http.config.HttpClientConfiguration - -class StubRequestExecutorFactory implements RequestExecutorFactory { - - @Override - RequestExecutor create(HttpClientConfiguration clientConfiguration) { - return new StubRequestExecutor(clientConfiguration) - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/oauth2/AccessTokenRetrieverServiceImplTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/oauth2/AccessTokenRetrieverServiceImplTest.groovy index a404c66a21f..8b682fd2627 100644 --- a/impl/src/test/groovy/com/okta/sdk/impl/oauth2/AccessTokenRetrieverServiceImplTest.groovy +++ b/impl/src/test/groovy/com/okta/sdk/impl/oauth2/AccessTokenRetrieverServiceImplTest.groovy @@ -19,17 +19,23 @@ import com.nimbusds.jose.jwk.RSAKey import com.okta.commons.http.config.BaseUrlResolver import com.okta.sdk.client.AuthorizationMode import com.okta.sdk.client.Clients -import com.okta.sdk.ds.RequestBuilder +import com.okta.sdk.error.Error +import com.okta.sdk.error.ErrorCause +import com.okta.sdk.error.ResourceException import com.okta.sdk.impl.Util import com.okta.sdk.impl.api.DefaultClientCredentialsResolver import com.okta.sdk.impl.client.DefaultClientBuilder import com.okta.sdk.impl.config.ClientConfiguration -import com.okta.sdk.impl.error.DefaultError -import com.okta.sdk.resource.ResourceException import io.jsonwebtoken.Claims import io.jsonwebtoken.Header import io.jsonwebtoken.Jwts import org.bouncycastle.openssl.PEMException +import org.hamcrest.MatcherAssert +import org.mockito.ArgumentMatchers +import org.openapitools.client.ApiClient +import org.springframework.http.HttpHeaders +import org.springframework.http.MediaType +import org.springframework.util.MultiValueMap import org.testng.annotations.Test import java.security.KeyPair @@ -39,12 +45,8 @@ import java.security.PrivateKey import static org.hamcrest.MatcherAssert.assertThat import static org.hamcrest.Matchers.is import static org.hamcrest.Matchers.notNullValue -import static org.mockito.ArgumentMatchers.any -import static org.mockito.ArgumentMatchers.anyString -import static org.mockito.Mockito.when -import static org.mockito.Mockito.verify -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.times +import static org.mockito.ArgumentMatchers.* +import static org.mockito.Mockito.* import static org.testng.Assert.assertEquals /** @@ -82,6 +84,7 @@ class AccessTokenRetrieverServiceImplTest { "8zZeebOsKqNB3Nlm8wNrYbJJvpTEyt6kpZi+YJ/S4mQ/0CzIpmq6014aKm16NJxv" + "AHYKHuDUvhiDFwadf8Q7kSK5KA==\n" + "-----END PRIVATE KEY-----" + private static final String RSA_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpQIBAAKCAQEAx9GOO2vMP04Ir1eJsrYwUkf+RyLvj+fP794OoG2L8QvzVj8z" + "2d4Y03kbJCaQdQHzcJueawIY0g/fXeGYh1jBBYxHkiiGhLTMQz1NaYNt0f3vrAE1" + @@ -113,46 +116,55 @@ class AccessTokenRetrieverServiceImplTest { @Test void testInstantiationWithNullClientConfig() { Util.expect(IllegalArgumentException) { - new AccessTokenRetrieverServiceImpl(null) + new AccessTokenRetrieverServiceImpl(null, null) } } @Test void testGetPrivateKeyFromPem() { + def clientConfiguration = mock(ClientConfiguration) + def apiClient = mock(ApiClient) + PrivateKey generatedPrivateKey = generatePrivateKey("RSA", 2048) File privateKeyPemFile = writePrivateKeyToPemFile(generatedPrivateKey, "privateKey") // Now test the pem -> private key conversion function of getPrivateKeyFromPem method Reader pemFileReader = new FileReader(privateKeyPemFile) - PrivateKey resultPrivateKey = getAccessTokenRetrieverServiceInstance().getPrivateKeyFromPEM(pemFileReader) + PrivateKey resultPrivateKey = getAccessTokenRetrieverServiceInstance(clientConfiguration, apiClient).getPrivateKeyFromPEM(pemFileReader) privateKeyPemFile.deleteOnExit() assertThat(resultPrivateKey, notNullValue()) - assertThat(resultPrivateKey.getAlgorithm(), is("RSA")) - assertThat(resultPrivateKey.getFormat(), is("PKCS#8")) + MatcherAssert.assertThat(resultPrivateKey.getAlgorithm(), is("RSA")) + MatcherAssert.assertThat(resultPrivateKey.getFormat(), is("PKCS#8")) } @Test void testParsePrivateKey() { + + def apiClient = mock(ApiClient) + def clientConfiguration = mock(ClientConfiguration) + PrivateKey generatedPrivateKey = generatePrivateKey("RSA", 2048) File privateKeyPemFile = writePrivateKeyToPemFile(generatedPrivateKey, "privateKey") Reader reader = new BufferedReader(new FileReader(privateKeyPemFile)) - PrivateKey parsedPrivateKey = getAccessTokenRetrieverServiceInstance().parsePrivateKey(reader) + PrivateKey parsedPrivateKey = getAccessTokenRetrieverServiceInstance(clientConfiguration, apiClient).parsePrivateKey(reader) privateKeyPemFile.deleteOnExit() assertThat(parsedPrivateKey, notNullValue()) - assertThat(parsedPrivateKey.getAlgorithm(), is("RSA")) - assertThat(parsedPrivateKey.getFormat(), is("PKCS#8")) + MatcherAssert.assertThat(parsedPrivateKey.getAlgorithm(), is("RSA")) + MatcherAssert.assertThat(parsedPrivateKey.getFormat(), is("PKCS#8")) } @Test void testCreateSignedJWT() { + def clientConfig = mock(ClientConfiguration) + def apiClient = mock(ApiClient) PrivateKey generatedPrivateKey = generatePrivateKey("RSA", 2048) File privateKeyPemFile = writePrivateKeyToPemFile(generatedPrivateKey, "privateKey") @@ -173,7 +185,7 @@ class AccessTokenRetrieverServiceImplTest { when(clientConfig.getClientCredentialsResolver()).thenReturn( new DefaultClientCredentialsResolver({ -> Optional.empty() })) - String signedJwt = getAccessTokenRetrieverServiceInstance(clientConfig).createSignedJWT() + String signedJwt = getAccessTokenRetrieverServiceInstance(clientConfig, apiClient).createSignedJWT() privateKeyPemFile.deleteOnExit() @@ -190,7 +202,7 @@ class AccessTokenRetrieverServiceImplTest { assertEquals(claims.get("aud"), clientConfig.getBaseUrl() + "/oauth2/v1/token") assertThat(claims.get("iat"), notNullValue()) assertThat(claims.get("exp"), notNullValue()) - assertEquals(Integer.valueOf(claims.get("exp")) - Integer.valueOf(claims.get("iat")), 3000, + assertEquals(Integer.valueOf(claims.get("exp") as String) - Integer.valueOf(claims.get("iat") as String), 3000, "token expiry time is not 50 minutes") assertThat(claims.get("iss"), notNullValue()) assertEquals(claims.get("iss"), clientConfig.getClientId(), "iss must be equal to client id") @@ -209,6 +221,8 @@ class AccessTokenRetrieverServiceImplTest { @Test void testCreateSignedJWTUsingPrivateKeyFromString() { + + def apiClient = mock(ApiClient) def clientConfig = mock(ClientConfiguration) PrivateKey generatedPrivateKey = generatePrivateKey("RSA", 2048) @@ -228,15 +242,15 @@ class AccessTokenRetrieverServiceImplTest { when(clientConfig.getClientCredentialsResolver()).thenReturn( new DefaultClientCredentialsResolver({ -> Optional.empty() })) - String signedJwt = getAccessTokenRetrieverServiceInstance(clientConfig).createSignedJWT() + String signedJwt = getAccessTokenRetrieverServiceInstance(clientConfig, apiClient).createSignedJWT() assertThat(signedJwt, notNullValue()) } @Test(expectedExceptions = OAuth2TokenRetrieverException.class) void testGetOAuth2TokenRetrieverRuntimeException() { - def tokenClient = mock(OAuth2TokenClient) - def requestBuilder = mock(RequestBuilder) + + def tokenClient = mock(ApiClient) def clientConfig = mock(ClientConfiguration) PrivateKey generatedPrivateKey = generatePrivateKey("RSA", 2048) @@ -257,24 +271,16 @@ class AccessTokenRetrieverServiceImplTest { when(clientConfig.getClientCredentialsResolver()).thenReturn( new DefaultClientCredentialsResolver({ -> Optional.empty() })) - when(tokenClient.http()).thenReturn(requestBuilder) - - when(requestBuilder.addHeaderParameter(anyString(), anyString())).thenReturn(requestBuilder) - when(requestBuilder.addQueryParameter(anyString(), anyString())).thenReturn(requestBuilder) - - when(requestBuilder.post(anyString(), any())).thenThrow(new RuntimeException("Unexpected runtime error")) - def accessTokenRetrieverService = new AccessTokenRetrieverServiceImpl(clientConfig, tokenClient) accessTokenRetrieverService.getOAuth2AccessToken() - verify(tokenClient, times(1)).http() - verify(requestBuilder, times(1)).post() + verify(tokenClient, times(1)) } @Test(expectedExceptions = OAuth2HttpException.class) void testGetOAuth2ResourceException() { - def tokenClient = mock(OAuth2TokenClient) - def requestBuilder = mock(RequestBuilder) + + def apiClient = mock(ApiClient) def clientConfig = mock(ClientConfiguration) PrivateKey generatedPrivateKey = generatePrivateKey("RSA", 2048) @@ -295,25 +301,57 @@ class AccessTokenRetrieverServiceImplTest { when(clientConfig.getClientCredentialsResolver()).thenReturn( new DefaultClientCredentialsResolver({ -> Optional.empty() })) - when(tokenClient.http()).thenReturn(requestBuilder) + Error defaultError = new Error() { + @Override + int getStatus() { + return 401 + } + + @Override + String getCode() { + return null + } + + @Override + String getMessage() { + return "Unauthorized" + } - when(requestBuilder.addHeaderParameter(anyString(), anyString())).thenReturn(requestBuilder) - when(requestBuilder.addQueryParameter(anyString(), anyString())).thenReturn(requestBuilder) + @Override + String getId() { + return null + } - DefaultError defaultError = new DefaultError() - defaultError.setStatus(401) - defaultError.setProperty(OAuth2AccessToken.ERROR_KEY, "error key") - defaultError.setProperty(OAuth2AccessToken.ERROR_DESCRIPTION, "error desc") + @Override + List getCauses() { + return null + } - ResourceException resourceException = new ResourceException(defaultError) + @Override + Map> getHeaders() { + return null + } + } - when(requestBuilder.post(anyString(), any())).thenThrow(resourceException) + ResourceException resourceException = new ResourceException(defaultError) - def accessTokenRetrieverService = new AccessTokenRetrieverServiceImpl(clientConfig, tokenClient) + when(apiClient.invokeAPI(anyString(), + anyObject(), + ArgumentMatchers.any() as Map, + ArgumentMatchers.any() as MultiValueMap, + any(), + ArgumentMatchers.any() as HttpHeaders, + ArgumentMatchers.any() as MultiValueMap, + ArgumentMatchers.any() as MultiValueMap, + ArgumentMatchers.any() as List, + ArgumentMatchers.any() as MediaType, + ArgumentMatchers.any() as String[], + any())).thenThrow(resourceException) + + def accessTokenRetrieverService = new AccessTokenRetrieverServiceImpl(clientConfig, apiClient) accessTokenRetrieverService.getOAuth2AccessToken() - verify(tokenClient, times(1)).http() - verify(requestBuilder, times(1)).post() + verify(apiClient, times(1)).invokeAPI() } // helper methods @@ -339,7 +377,7 @@ class AccessTokenRetrieverServiceImplTest { return privateKeyPemFile } - AccessTokenRetrieverServiceImpl getAccessTokenRetrieverServiceInstance(ClientConfiguration clientConfiguration) { + AccessTokenRetrieverServiceImpl getAccessTokenRetrieverServiceInstance(ClientConfiguration clientConfiguration, ApiClient apiClient) { if (clientConfiguration == null) { ClientConfiguration cc = new ClientConfiguration() cc.setBaseUrlResolver(new BaseUrlResolver() { @@ -349,16 +387,18 @@ class AccessTokenRetrieverServiceImplTest { } }) cc.setClientCredentialsResolver(new DefaultClientCredentialsResolver({ -> Optional.empty() })) - return new AccessTokenRetrieverServiceImpl(cc) + return new AccessTokenRetrieverServiceImpl(cc, apiClient) } - return new AccessTokenRetrieverServiceImpl(clientConfiguration) + return new AccessTokenRetrieverServiceImpl(clientConfiguration, apiClient) } @Test void testConvertPemKeyToRsaPrivateKey() { + ApiClient apiClient = mock(ApiClient) + DefaultClientBuilder oktaClient = (DefaultClientBuilder) Clients.builder() - .setBaseUrlResolver({ -> "https://sample.okta.com" }) + .setOrgUrl("https://sample.okta.com") .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) .setPrivateKey(RSAKey.parseFromPEMEncodedObjects(PRIVATE_KEY).toRSAKey().toPrivateKey()) @@ -366,29 +406,33 @@ class AccessTokenRetrieverServiceImplTest { assertEquals(clientConfiguration.getPrivateKey(), RSA_PRIVATE_KEY) - String signedJwt = getAccessTokenRetrieverServiceInstance(clientConfiguration).createSignedJWT() + String signedJwt = getAccessTokenRetrieverServiceInstance(clientConfiguration, apiClient).createSignedJWT() assertThat(signedJwt, notNullValue()) } @Test void testParseRsaPrivateKey() { + ApiClient apiClient = mock(ApiClient) + DefaultClientBuilder oktaClient = (DefaultClientBuilder) Clients.builder() - .setBaseUrlResolver({ -> "https://sample.okta.com" }) + .setOrgUrl("https://sample.okta.com") .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY) .setPrivateKey(RSAKey.parseFromPEMEncodedObjects(RSA_PRIVATE_KEY).toRSAKey().toPrivateKey()) - String signedJwt = getAccessTokenRetrieverServiceInstance(oktaClient.getClientConfiguration()).createSignedJWT() + String signedJwt = getAccessTokenRetrieverServiceInstance(oktaClient.getClientConfiguration(), apiClient).createSignedJWT() assertThat(signedJwt, notNullValue()) } @Test(expectedExceptions = PEMException.class) void testParsePemKeyAsRsaPrivateKey() { ClientConfiguration clientConfigMock = mock(ClientConfiguration) + ApiClient apiClient = mock(ApiClient) + BaseUrlResolver baseUrlResolver = { -> "https://sample.okta.com" } when(clientConfigMock.getBaseUrlResolver()).thenReturn(baseUrlResolver) when(clientConfigMock.getPrivateKey()).thenReturn(PRIVATE_KEY.replaceAll(" PRIVATE ", " RSA PRIVATE ")) - String signedJwt = getAccessTokenRetrieverServiceInstance(clientConfigMock).createSignedJWT() + String signedJwt = getAccessTokenRetrieverServiceInstance(clientConfigMock, apiClient).createSignedJWT() assertThat(signedJwt, notNullValue()) } } \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractCollectionResourceTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractCollectionResourceTest.groovy deleted file mode 100644 index e3b575a04dc..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractCollectionResourceTest.groovy +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.impl.ds.InternalDataStore -import org.mockito.Mockito -import org.testng.annotations.Test - -import static org.mockito.Mockito.* -import static org.hamcrest.Matchers.* -import static org.hamcrest.MatcherAssert.* - -/** - * Tests for {@link AbstractCollectionResource}. - */ -class AbstractCollectionResourceTest { - - @Test - void testPagedCollection() { - - InternalDataStore ds = mock(InternalDataStore) - when(ds.getBaseUrl()).thenReturn("https://example.com/") - - def page1 = createTestPage(0, 200, "https://example.com/resource?nextPage=1") - def page2 = createTestPage(200, 200, "https://example.com/resource?nextPage=2") - def page3 = createTestPage(400, 13, null) - - def collectionResource1 = new TestCollectionResource(ds, page1) - expectPage(page1, ds) - def collectionResource2 = new TestCollectionResource(ds, page2) - when(ds.getResource(collectionResource1.getNextPageUrl(), TestCollectionResource)).thenReturn(collectionResource2) - expectPage(page2, ds) - def collectionResource3 = new TestCollectionResource(ds, page3) - when(ds.getResource(collectionResource2.getNextPageUrl(), TestCollectionResource)).thenReturn(collectionResource3) - expectPage(page3, ds) - - verifyCollection(new TestCollectionResource(ds, page1), 413) - } - - @Test - void testSinglePagedCollection() { - - InternalDataStore ds = mock(InternalDataStore) - when(ds.getBaseUrl()).thenReturn("https://example.com/") - - def page1 = createTestPage(0, 13, null) - - expectPage(page1, ds) - - verifyCollection(new TestCollectionResource(ds, page1), 13) - } - - @Test - void testSamePageForIteratorAndSingle() { - - InternalDataStore ds = mock(InternalDataStore) - when(ds.getBaseUrl()).thenReturn("https://example.com/") - - def page1 = createTestPage(0, 1, null) - - expectPage(page1, ds) - - def collectionResource = spy(new TestCollectionResource(ds, page1)) - - collectionResource.iterator().hasNext() - def single = collectionResource.single() - assertThat single.getName(), is("Name-0") - - // make sure the current page is used for the call to the first iterator, and then again to the call to single() - verify(collectionResource, times(2)).getCurrentPage() - } - - @Test - void testIsEmptyCall() { - - InternalDataStore ds = mock(InternalDataStore) - when(ds.getBaseUrl()).thenReturn("https://example.com/") - - def pageNotEmpty = createTestPage(0, 3, null) - expectPage(pageNotEmpty, ds) - assertThat "Expected TestCollectionResource.isEmpty() to return false", !new TestCollectionResource(ds, pageNotEmpty).isEmpty() - - def pageEmpty = createTestPage(0, 0, null) - expectPage(pageEmpty, ds) - assertThat "Expected TestCollectionResource.isEmpty() to return true", new TestCollectionResource(ds, pageEmpty).isEmpty() - } - - @Test - void testIteratorAndIsEmptyUseSamePage() { - - InternalDataStore ds = mock(InternalDataStore) - when(ds.getBaseUrl()).thenReturn("https://example.com/") - - def pageNotEmpty = createTestPage(0, 3, null) - expectPage(pageNotEmpty, ds) - def nonEmptyResource = spy(new TestCollectionResource(ds, pageNotEmpty)) - assertThat "TestCollectionResource.iterator.hasNext() returns true", nonEmptyResource.iterator().hasNext() - assertThat "Expected TestCollectionResource.isEmpty() to return false", !nonEmptyResource.isEmpty() - verify(nonEmptyResource, times(2)).getCurrentPage() - - def pageEmpty = createTestPage(0, 0, null) - expectPage(pageEmpty, ds) - def emptyResource = spy(new TestCollectionResource(ds, pageEmpty)) - assertThat "TestCollectionResource.iterator.hasNext() returns false", !emptyResource.iterator().hasNext() - assertThat "Expected TestCollectionResource.isEmpty() to return true", emptyResource.isEmpty() - verify(emptyResource, times(2)).getCurrentPage() - } - - @Test - void testEmptyLastPagedCollection() { - - InternalDataStore ds = mock(InternalDataStore) - when(ds.getBaseUrl()).thenReturn("https://example.com/") - - def page1 = createTestPage(0, 200, "https://example.com/resource?nextPage=1") - def page2 = createTestPage(200, 0, null) - - expectPage(page1, ds) - def collectionResource = new TestCollectionResource(ds, page2) - when(ds.getResource("https://example.com/resource?nextPage=1", TestCollectionResource)).thenReturn(collectionResource) - expectPage(page2, ds) - - verifyCollection(new TestCollectionResource(ds, page1), 200) - } - - def verifyCollection(AbstractCollectionResource collectionResource, int size) { - def counter = 0 - for (Iterator iter = collectionResource.iterator(); iter.hasNext();) { - TestResource r = iter.next() - assertThat r.getName(), is("Name-${counter}".toString()) - counter++ - } - assertThat counter, is(size) - } - - def expectPage(def page, InternalDataStore ds) { - for (def item : page["items"]) { - def resource = new TestResource(ds, item) - when(ds.instantiate(TestResource, item)).thenReturn(resource) - } - } - - def createTestPage(int startIndex, int pageSize, String nextHref) { - - def itemArray = [] - for (int ii = startIndex; ii < startIndex + pageSize; ii++) { - - def item = ['name': "Name-${ii}", - 'description': "Description-${ii}"] - itemArray.add(item) - } - - return [items : itemArray, - nextPage : nextHref] - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractInstanceResourceTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractInstanceResourceTest.groovy deleted file mode 100644 index 747e7c453b7..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractInstanceResourceTest.groovy +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.impl.api.ClientCredentialsResolver -import com.okta.sdk.impl.ds.DefaultDataStore -import com.okta.sdk.impl.ds.InternalDataStore -import com.okta.commons.http.RequestExecutor -import com.okta.sdk.resource.Resource -import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer -import org.testng.annotations.Test - -import java.lang.reflect.Field - -import static org.mockito.Mockito.* -import static org.testng.Assert.* - -/** - * @since 0.5.0 - */ -class AbstractInstanceResourceTest { - - /** - * Asserts that the InternalDataStore is not invoked if the dirty properties can satisfy a getProperty request. - */ - @Test - void testNonMaterializedResourceGetDirtyPropertyDoesNotMaterialize() { - - def props = ['href': 'http://foo.com/test/123'] - InternalDataStore ds = mock(InternalDataStore) - - TestResource resource = new TestResource(ds, props) - - resource.setName('New Value') - - assertEquals 'New Value', resource.getName() - } - - @Test - void testMapProperty() { - - def props = [ - href : "https://api.okta.com/v1/emailTemplates/3HEMybJjMO2za0YmfTubDI", - name : "Default Password Reset Email Template", - description : "This is the password reset email template that is associated with the directory", - fromName : "Test Name", - fromEmailAddress: "test@testmail.okta.com", - subject : "Reset your Password", - textBody : "Forgot your password?\n\nWe've received a request to reset the password for this email address.", - htmlBody : "

    Forgot your password?



    We've received a request to reset the password for this email address.", - mimeType : "text/plain", - defaultModel : [ - linkBaseUrl: "https://api.okta.com/passwordReset" - ] - ] - InternalDataStore ds = mock(InternalDataStore) - - def testResource = new TestResource(ds, props) - - def linkBaseUrl = testResource.getMapProperty("defaultModel").get('linkBaseUrl') - - assertEquals(linkBaseUrl, "https://api.okta.com/passwordReset") - - assertNull testResource.getMapProperty("nonExistentMapProperty") - - try { - testResource.getMapProperty("name") - fail("Should have thrown") - } catch (IllegalArgumentException e) { - assertEquals(e.getMessage(), "'name' property value type does not match the specified type. Specified type: Map. Existing type: java.lang.String. Value: Default Password Reset Email Template") - } - } - - - @Test - void testMethods() { - int defaultPropertiesSize = 1 - - def properties = [myProp: "myValue"] - - def internalDataStore = mock(InternalDataStore) - def testResource = new TestResource(internalDataStore, properties) - - doAnswer(new Answer() { - @Override - Object answer(InvocationOnMock invocation) throws Throwable { - new DefaultDataStoreDelegateTo(mock(RequestExecutor), testResource).save((Resource)invocation.arguments[0]) - return null - } - }).when(internalDataStore).save(testResource) - - testResource.japaneseCharacters = "アナリストは「Apacheの史郎は、今日日本のソフトウェアエンジニアのた" - testResource.spanishCharacters = "El niño está usando Stormpath para su aplicación." - testResource.trueProperty = true - - assertEquals testResource.size(), defaultPropertiesSize + 3 - - assertFalse testResource.isEmpty() - - assertTrue testResource.containsKey("trueProperty") - - assertFalse testResource.containsKey("notinthere") - - assertTrue testResource.trueProperty - - assertEquals testResource.getProperty("spanishCharacters"), "El niño está usando Stormpath para su aplicación." - - assertNotNull testResource.entrySet() - - testResource.putAll(["falseProperty": false, "integerProperty": 1234]) - - assertEquals testResource.keySet().size(), defaultPropertiesSize + 5 - - assertEquals testResource.values().size(), defaultPropertiesSize + 5 - - assertTrue testResource.containsValue("アナリストは「Apacheの史郎は、今日日本のソフトウェアエンジニアのた") - - testResource.remove("trueProperty") - - testResource.save() - - assertEquals defaultPropertiesSize + 4, testResource.values().size() - - testResource.clear() - - assertEquals testResource.size(), 0 // okta objects do NOT contain properties like HREF, like the Stormpath ones did - - testResource.delete() - - verify(internalDataStore).delete(testResource) - verify(internalDataStore).save(testResource) - - } - - //@since 1.0.RC3 - @Test - void testMapManipulation() { - def ds = mock(InternalDataStore) - def TestResource = new TestResource(ds) - setValue(AbstractResource, TestResource, "materialized", true) - - assertEquals(TestResource.size(), 0) - assertFalse(TestResource.containsValue("aValue")) - TestResource.put("aKey", "aValue") - assertEquals(TestResource.size(), 1) - assertTrue(TestResource.containsKey("aKey")) - assertTrue(TestResource.containsValue("aValue")) - TestResource.remove("aKey") - assertEquals(TestResource.size(), 0) - assertFalse(TestResource.containsKey("aKey")) - assertFalse(TestResource.containsValue("aValue")) - TestResource.put("anotherKey", "aValue") - assertEquals(TestResource.size(), 1) - assertTrue(TestResource.containsValue("aValue")) - assertFalse(TestResource.containsKey("aKey")) - assertTrue(TestResource.containsKey("anotherKey")) - assertEquals(TestResource.entrySet().size(), 1) - assertEquals(TestResource.keySet().size(), 1) - assertEquals(TestResource.values().size(), 1) - TestResource.clear() - assertFalse(TestResource.containsKey("aKey")) - assertFalse(TestResource.containsKey("anotherKey")) - assertFalse(TestResource.containsValue("aValue")) - assertEquals(TestResource.entrySet().size(), 0) - assertEquals(TestResource.keySet().size(), 0) - assertEquals(TestResource.values().size(), 0) - assertEquals(TestResource.size(), 0) - TestResource.remove("aKey") - assertEquals(TestResource.size(), 0) - - TestResource.put("newKey", "someValue") - TestResource.remove("newKey") - assertEquals(TestResource.size(), 0) - TestResource.put("newKey", "newValue00") - assertEquals(TestResource.size(), 1) - assertEquals(TestResource.get("newKey"), "newValue00") - TestResource.put("newKey", "newValue01") - assertEquals(TestResource.size(), 1) - assertEquals(TestResource.get("newKey"), "newValue01") - - TestResource = new TestResource(ds, ["aKey": "aValue"]) - - assertEquals(TestResource.size(), 1) - assertTrue(TestResource.containsKey("aKey")) - assertTrue(TestResource.containsValue("aValue")) - assertEquals(TestResource.entrySet().size(), 1) - assertEquals(TestResource.keySet().size(), 1) - assertEquals(TestResource.values().size(), 1) - TestResource.put("aKey", "newValue") - assertEquals(TestResource.size(), 1) - assertTrue(TestResource.containsKey("aKey")) - assertFalse(TestResource.containsValue("aValue")) - assertTrue(TestResource.containsValue("newValue")) - assertEquals(TestResource.entrySet().size(), 1) - assertEquals(TestResource.keySet().size(), 1) - assertEquals(TestResource.values().size(), 1) - TestResource.remove("aKey") - assertEquals(TestResource.size(), 0) - assertFalse(TestResource.containsKey("aKey")) - assertFalse(TestResource.containsValue("aValue")) - assertFalse(TestResource.containsValue("newValue")) - assertEquals(TestResource.entrySet().size(), 0) - assertEquals(TestResource.keySet().size(), 0) - assertEquals(TestResource.values().size(), 0) - TestResource.put("newKey", "aValue") - assertFalse(TestResource.containsKey("aKey")) - assertTrue(TestResource.containsKey("newKey")) - assertTrue(TestResource.containsValue("aValue")) - assertEquals(TestResource.size(), 1) - assertEquals(TestResource.entrySet().size(), 1) - assertEquals(TestResource.keySet().size(), 1) - assertEquals(TestResource.values().size(), 1) - - TestResource.putAll(["aK": "aV", "bK": "bV", "cK": "cV", "dK": "dV"]) - assertTrue(TestResource.containsKey("dK")) - assertEquals(TestResource.size(), 5) - assertEquals(TestResource.keySet().size(), 5) - assertTrue(TestResource.keySet().contains("newKey")) - assertTrue(TestResource.keySet().contains("bK")) - assertEquals(TestResource.values().size(), 5) - assertTrue(TestResource.values().contains("aValue")) - assertTrue(TestResource.values().contains("cV")) - assertEquals(TestResource.entrySet().size(), 5) - } - - private void setValue(Class clazz, Object object, String fieldName, value) { - Field field = clazz.getDeclaredField(fieldName) - field.setAccessible(true) - field.set(object, value) - } - - class DefaultDataStoreDelegateTo extends DefaultDataStore { - - private TestResource TestResource; - - DefaultDataStoreDelegateTo(RequestExecutor requestExecutor, TestResource TestResource) { - super(requestExecutor, "https://api.stormpath.com/v1", mock(ClientCredentialsResolver)) - this.TestResource = TestResource - } - - void save(Resource resource) { - Map properties = getValue(AbstractResource, TestResource, "properties") - Map dirtyProperties = getValue(AbstractResource, TestResource, "dirtyProperties") - HashSet deletedPropertyNames = getValue(AbstractResource, TestResource, "deletedPropertyNames") - properties.putAll(dirtyProperties) - setValue(AbstractResource, TestResource, "properties", properties) - dirtyProperties.clear() - setValue(AbstractResource, TestResource, "dirtyProperties", dirtyProperties) - deletedPropertyNames.clear(); - setValue(AbstractResource, TestResource, "deletedPropertyNames", deletedPropertyNames) - } - - private Object getValue(Class clazz, Object object, String fieldName) { - Field field = clazz.getDeclaredField(fieldName) - field.setAccessible(true) - return field.get(object) - } - - private void setValue(Class clazz, Object object, String fieldName, value) { - Field field = clazz.getDeclaredField(fieldName) - field.setAccessible(true) - field.set(object, value) - } - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractPropertyRetrieverTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractPropertyRetrieverTest.groovy deleted file mode 100644 index 6af497d5557..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractPropertyRetrieverTest.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2021-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.impl.ds.InternalDataStore -import com.okta.sdk.resource.application.ApplicationSignOnMode -import org.testng.annotations.DataProvider -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.is -import static org.mockito.Mockito.* - -class AbstractPropertyRetrieverTest { - - @Test(dataProvider = "signOnModes") - void ApplicationSignOnModeTest(String configValue, ApplicationSignOnMode expectedValue) { - def internalDataStore = mock(InternalDataStore.class) - - Map data = new HashMap<>() - data.put("signOnMode", configValue) - def absResource = mock(AbstractResource.class, - withSettings().useConstructor(internalDataStore, data).defaultAnswer(CALLS_REAL_METHODS) - ) - - def res = absResource.getEnumProperty("signOnMode", ApplicationSignOnMode) - assertThat(res, is(expectedValue)) - } - - @DataProvider - Object[][] signOnModes() { - return [ - ["BOOKMARK", ApplicationSignOnMode.BOOKMARK], - ["BASIC_AUTH", ApplicationSignOnMode.BASIC_AUTH], - ["BROWSER_PLUGIN", ApplicationSignOnMode.BROWSER_PLUGIN], - ["SECURE_PASSWORD_STORE", ApplicationSignOnMode.SECURE_PASSWORD_STORE], - ["AUTO_LOGIN", ApplicationSignOnMode.AUTO_LOGIN], - ["WS_FEDERATION", ApplicationSignOnMode.WS_FEDERATION], - ["SAML_2_0", ApplicationSignOnMode.SAML_2_0], - ["OPENID_CONNECT", ApplicationSignOnMode.OPENID_CONNECT], - ["SAML_1_1", ApplicationSignOnMode.SAML_1_1], - ["RADIUS_FOR_GENERIC_APP", ApplicationSignOnMode.SDK_UNKNOWN], - ["RADIUS_FOR_CISCO_ASA", ApplicationSignOnMode.SDK_UNKNOWN], - ["AWS_FEDERATED_LOGIN", ApplicationSignOnMode.SDK_UNKNOWN], - ["UNKNOWN_VALUE", ApplicationSignOnMode.SDK_UNKNOWN], - ["", ApplicationSignOnMode.SDK_UNKNOWN] - ] - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractResourceTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractResourceTest.groovy deleted file mode 100644 index e82caf40d1f..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/AbstractResourceTest.groovy +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.impl.ds.InternalDataStore -import org.testng.annotations.Test - -import java.time.Instant -import java.time.format.DateTimeFormatter - -import static org.hamcrest.Matchers.allOf -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.hasItem -import static org.hamcrest.Matchers.hasProperty -import static org.hamcrest.Matchers.hasSize -import static org.hamcrest.Matchers.nullValue -import static org.mockito.Mockito.* - -class AbstractResourceTest { - - @Test - void matchingTemplateUrl() { - runScenario("/api/v1/users/{userId}/factors/{factorId}", - "/api/v1/users/my-userId/factors/my-factorId", - [ userId: "my-userId", - factorId: "my-factorId" ]) - } - - @Test - void fullHref() { - runScenario("/api/v1/users/{userId}/factors/{factorId}", - "https://example.com/api/v1/users/my-userId/factors/my-factorId", - [ userId: "my-userId", - factorId: "my-factorId"]) - } - - @Test - void longerTemplateThenHref() { - runScenario("/api/v1/users/{userId}/factors/{factorId}", - "https://example.com/api/v1/users/my-userId", - [ userId: "my-userId"]) - } - - @Test - void longerHrefThenTemplate() { - runScenario("/api/v1/users/{userId}/factors/{factorId}", - "https://example.com/api/v1/users/my-userId/factors/my-factorId/anotherAction", - [ userId: "my-userId", - factorId: "my-factorId"]) - } - - @Test - void oddHref() { - runScenario("/api/v1/users/{userId}/factors/{factorId}", - "foobar", - Collections.emptyMap()) - } - - @Test(expectedExceptions = URIParseException) - void invalidHref() { - runScenario("/api/v1/users/{userId}/factors/{factorId}", - " 😡 ", - null) - } - - @Test(expectedExceptions = IllegalArgumentException) - void missingHref() { - runScenario("/api/v1/users/{userId}/factors/{factorId}", - null, - null) - } - - @Test(expectedExceptions = IllegalArgumentException) - void nullTemplate() { - runScenario(null, - "https://example.com/api/v1/users/my-userId/factors/my-factorId/anotherAction", - null) - } - - private static void runScenario(String templateUrl, String href, Map expectedValues) { - - def resource = new AbstractResource(null){ - @Override - Map getPropertyDescriptors() { - return Collections.emptyMap() - } - } - - resource.setResourceHref(href) - def actualMap = resource.getParamsFromHref(templateUrl) - assertThat actualMap, equalTo(expectedValues) - } - - StubResource createSubResource() { - - List nestedResourceData = [ - [nestedStringPropKey: "item0"], - [nestedStringPropKey: "item1"]] - - Map data = [ - booleanPropKey: true, - datePropKey: "2015-08-30T18:41:35.818Z", - enumListPropKey: [ - "VALUE_3", - "VALUE_1" - ], - enumPropKey: "VALUE_2", - intPropKey: 42, - doublePropKey: 42.42d, - listPropKey: [ - "one", - "two", - "three" - ], - mapPropKey: [ - one: "1", - two: "22", - three: "333" - ], - resourceListPropKey: nestedResourceData, - stringPropKey: "string_value", - charArrayPropKey1: "valueAsString", - charArrayPropKey2: "valueAsChars".toCharArray(), - - ] - - InternalDataStore dataStore = mock(InternalDataStore) - Map item0 = nestedResourceData.get(0) - Map item1 = nestedResourceData.get(1) - def resource0 = new NestedStubResource(dataStore, item0) - def resource1 = new NestedStubResource(dataStore, item1) - when(dataStore.instantiate(NestedStubResource, item0)).thenReturn(resource0) - when(dataStore.instantiate(NestedStubResource, item1)).thenReturn(resource1) - return new StubResource(dataStore, data) - } - - @Test - void basicPropertyValuesTest() { - StubResource resource = createSubResource() - - Date expectedDate = Date.from(Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse("2015-08-30T18:41:35.818Z"))) - - assertThat resource.getBoolean(resource.booleanProp), equalTo(true) - assertThat resource.getDateProperty(resource.dateProp), equalTo(expectedDate) - assertThat resource.getEnumListProperty(resource.enumListProp), equalTo([StubEnum.VALUE_3, StubEnum.VALUE_1]) - assertThat resource.getEnumProperty(resource.enumProp), equalTo(StubEnum.VALUE_2) - assertThat resource.getInt(resource.integerProp), equalTo(42) - assertThat resource.getIntProperty(resource.integerProp), equalTo(42) - assertThat resource.getDoubleProperty(resource.doubleProp), equalTo(42.42d) - assertThat resource.getListProperty(resource.listProp), equalTo(["one", "two", "three"]) - assertThat resource.getMap(resource.mapProp), equalTo([one: "1", two: "22", three: "333"]) - assertThat resource.getString(resource.stringProp), equalTo("string_value") - assertThat resource.getResourceListProperty(resource.resourceListProp), allOf( - hasItem(hasProperty("stringProp", equalTo("item0"))), - hasItem(hasProperty("stringProp", equalTo("item1"))), - hasSize(2)) - assertThat resource.getCharArray(resource.charArrayProp1), equalTo("valueAsString".toCharArray()) - assertThat resource.getCharArray(resource.charArrayProp2), equalTo("valueAsChars".toCharArray()) - } - - @Test - void nullPropertyValueTest() { - - Map data = [ - booleanPropKey: null, - datePropKey: null, - enumListPropKey: null, - enumPropKey: null, - intPropKey: null, - doublePropKey: null, - listPropKey: null, - mapPropKey: null, - resourceListPropKey: null, - stringPropKey: null, - charArrayPropKey1: null, - charArrayPropKey2: null - ] - - StubResource resource = new StubResource(null, data) - - assertThat resource.getBoolean(resource.booleanProp), equalTo(false) - assertThat resource.getNullableBoolean(resource.booleanProp), nullValue() - assertThat resource.getDateProperty(resource.dateProp), nullValue() - assertThat resource.getEnumListProperty(resource.enumListProp), nullValue() - assertThat resource.getEnumProperty(resource.enumProp), nullValue() - assertThat resource.getInt(resource.integerProp), equalTo(-1) - assertThat resource.getIntProperty(resource.integerProp), nullValue() - assertThat resource.getDoubleProperty(resource.doubleProp), nullValue() - assertThat resource.getListProperty(resource.listProp), nullValue() - assertThat resource.getMap(resource.mapProp), nullValue() - assertThat resource.getString(resource.stringProp), nullValue() - assertThat resource.getResourceListProperty(resource.resourceListProp), nullValue() - assertThat resource.getCharArray(resource.charArrayProp1), nullValue() - assertThat resource.getCharArray(resource.charArrayProp2), nullValue() - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/ApplicationFeatureTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/ApplicationFeatureTest.groovy deleted file mode 100644 index 522ee041385..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/ApplicationFeatureTest.groovy +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2022-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.commons.http.HttpHeaders -import com.okta.commons.http.HttpMethod -import com.okta.commons.http.MediaType -import com.okta.commons.http.Request -import com.okta.commons.http.RequestExecutor -import com.okta.commons.http.Response -import com.okta.sdk.impl.api.ClientCredentialsResolver -import com.okta.sdk.impl.ds.DefaultDataStore -import com.okta.sdk.impl.resource.application.DefaultApplication -import com.okta.sdk.impl.resource.application.DefaultApplicationFeature -import com.okta.sdk.impl.resource.application.DefaultCapabilitiesObject -import com.okta.sdk.impl.resource.application.DefaultOrg2OrgApplication -import com.okta.sdk.impl.util.StringInputStream -import com.okta.sdk.resource.common.EnabledStatus -import org.hamcrest.MatcherAssert -import org.mockito.ArgumentCaptor -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.is -import static org.hamcrest.Matchers.notNullValue -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.when -/** - * Unit tests for {@code /api/v1/apps}. - * @since 2.10.0 - */ -class ApplicationFeatureTest { - - @Test - void testListFeaturesForApplication() { - def requestCapture = ArgumentCaptor.forClass(Request) - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com", apiKeyResolver) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - def responseBody = '[' + - ' {' + - ' "name": "USER_PROVISIONING",' + - ' "status": "ENABLED",' + - ' "description": "User provisioning settings from Okta to a downstream application",' + - ' "capabilities": {' + - ' "create":{"lifecycleCreate":{"status":"DISABLED"}},' + - ' "update":{"profile":{"status":"DISABLED"},"lifecycleDeactivate":{"status":"DISABLED"},"password":{"status":"DISABLED","seed":"RANDOM","change":"KEEP_EXISTING"}}' + - ' }' + - ' }' + - ']' - when(response.getBody()).thenReturn(new StringInputStream(responseBody)) - when(response.getHeaders()).thenReturn(headers) - - def application = new DefaultApplication(defaultDataStore) - application.put("id", "app-id") - - def applicationFeatureList = new DefaultApplicationFeature(defaultDataStore) - .listFeaturesForApplication(application.getId()) - - def request = requestCapture.getValue() - assertThat request.getMethod(), is(HttpMethod.GET) - MatcherAssert.assertThat request.getResourceUrl().getPath(), is("/api/v1/apps/app-id/features") - assertThat applicationFeatureList, notNullValue() - def features = applicationFeatureList.collect() - assertThat features.size(), is(1) - assertThat features.get(0).getName(), is("USER_PROVISIONING") - assertThat features.get(0).getStatus(), is(EnabledStatus.ENABLED) - } - - @Test - void testGetFeatureForApplication() { - def requestCapture = ArgumentCaptor.forClass(Request) - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com", apiKeyResolver) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - def responseBody = '{' + - ' "name": "USER_PROVISIONING",' + - ' "status": "ENABLED",' + - ' "description": "User provisioning settings from Okta to a downstream application",' + - ' "capabilities": {' + - ' "create":{"lifecycleCreate":{"status":"DISABLED"}},' + - ' "update":{"profile":{"status":"DISABLED"},"lifecycleDeactivate":{"status":"DISABLED"},"password":{"status":"DISABLED","seed":"RANDOM","change":"KEEP_EXISTING"}}' + - ' }' + - '}' - when(response.getBody()).thenReturn(new StringInputStream(responseBody)) - when(response.getHeaders()).thenReturn(headers) - - def application = new DefaultApplication(defaultDataStore) - application.put("id", "app-id") - def applicationFeature = application.getFeatureForApplication("USER_PROVISIONING") - - def request = requestCapture.getValue() - assertThat request.getMethod(), is(HttpMethod.GET) - MatcherAssert.assertThat request.getResourceUrl().getPath(), is("/api/v1/apps/app-id/features/USER_PROVISIONING") - assertThat applicationFeature, notNullValue() - assertThat applicationFeature.getName(), is("USER_PROVISIONING") - assertThat applicationFeature.getStatus(), is(EnabledStatus.ENABLED) - } - - @Test - void testUpdateFeatureForApplication() { - def requestCapture = ArgumentCaptor.forClass(Request) - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com", apiKeyResolver) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - def responseBody = '{' + - ' "name": "USER_PROVISIONING",' + - ' "status": "DISABLED",' + - ' "description": "User provisioning settings from Okta to a downstream application",' + - ' "capabilities": {' + - ' "create":{"lifecycleCreate":{"status":"DISABLED"}},' + - ' "update":{"profile":{"status":"DISABLED"},"lifecycleDeactivate":{"status":"DISABLED"},"password":{"status":"DISABLED","seed":"RANDOM","change":"KEEP_EXISTING"}}' + - ' }' + - '}' - when(response.getBody()).thenReturn(new StringInputStream(responseBody)) - when(response.getHeaders()).thenReturn(headers) - - def application = new DefaultApplication(defaultDataStore) - application.put("id", "app-id") - def applicationFeature = application.updateFeatureForApplication("USER_PROVISIONING", new DefaultCapabilitiesObject(defaultDataStore)) - - def request = requestCapture.getValue() - assertThat request.getMethod(), is(HttpMethod.PUT) - MatcherAssert.assertThat request.getResourceUrl().getPath(), is("/api/v1/apps/app-id/features/USER_PROVISIONING") - assertThat applicationFeature, notNullValue() - assertThat applicationFeature.getName(), is("USER_PROVISIONING") - assertThat applicationFeature.getStatus(), is(EnabledStatus.DISABLED) - } - - @Test - void testUploadApplicationLogo(){ - def requestCapture = ArgumentCaptor.forClass(Request) - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com", apiKeyResolver) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.getHttpStatus()).thenReturn(HttpURLConnection.HTTP_CREATED) - when(response.hasBody()).thenReturn(false) - when(response.getHeaders()).thenReturn(headers) - - def application = new DefaultOrg2OrgApplication(defaultDataStore) - application.put("id", "app-id") - - new DefaultApplication(defaultDataStore).uploadApplicationLogo(application.getId(), new File("src/test/resources/okta_logo_favicon.png")) - - def request = requestCapture.getValue() - assertThat request.getMethod(), is(HttpMethod.POST) - MatcherAssert.assertThat request.getResourceUrl().getPath(), is("/api/v1/apps/app-id/logo") - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultApplicationBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultApplicationBuilderTest.groovy deleted file mode 100644 index 8c89763af49..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultApplicationBuilderTest.groovy +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.application.* -import org.testng.annotations.Test - -import static com.okta.sdk.impl.Util.expect -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultApplicationBuilderTest { - - @Test - void basicUsage() { - def client = mock(Client) - def application = mock(Application) - def applicationAccessibility = mock(ApplicationAccessibility) - def applicationVisibilityHide = mock(ApplicationVisibilityHide) - def applicationVisibility = mock(ApplicationVisibility) - - when(client.instantiate(Application.class)).thenReturn(application) - when(client.instantiate(ApplicationAccessibility.class)).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibilityHide.class)).thenReturn(applicationVisibilityHide) - when(application.getAccessibility()).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibility.class)).thenReturn(applicationVisibility) - when(application.getVisibility())thenReturn(applicationVisibility) - - new DefaultApplicationBuilder() - .setLabel("test_app") - .setLoginRedirectUrl("http://www.myApp.com") - .setErrorRedirectUrl("http://www.myApp.com/error") - .setSelfService(false) - .setSignOnMode(ApplicationSignOnMode.AUTO_LOGIN) - .setIOS(false) - .setWeb(true) - .buildAndCreate(client) - - verify(client).createApplication(eq(application)) - verify(application).setLabel("test_app") - verify(application).setSignOnMode(ApplicationSignOnMode.AUTO_LOGIN) - verify(applicationAccessibility).setSelfService(false) - verify(applicationAccessibility).setErrorRedirectUrl("http://www.myApp.com/error") - verify(applicationAccessibility).setLoginRedirectUrl("http://www.myApp.com") - verify(applicationVisibilityHide).setWeb(true) - verify(applicationVisibilityHide).setIOS(false) - } - - @Test - void invalidApplicationSignOnMode() { - def client = mock(Client) - def application = mock(Application) - def applicationAccessibility = mock(ApplicationAccessibility) - def applicationVisibilityHide = mock(ApplicationVisibilityHide) - def applicationVisibility = mock(ApplicationVisibility) - - when(client.instantiate(Application.class)).thenReturn(application); - when(client.instantiate(ApplicationAccessibility.class)).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibilityHide.class)).thenReturn(applicationVisibilityHide) - when(application.getAccessibility()).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibility.class)).thenReturn(applicationVisibility) - when(application.getVisibility())thenReturn(applicationVisibility) - - expect IllegalArgumentException, { - new DefaultApplicationBuilder() - .setLabel("test_app") - .setLoginRedirectUrl("http://www.myApp.com") - .setErrorRedirectUrl("http://www.myApp.com/error") - .setSelfService(false) - .setSignOnMode(ApplicationSignOnMode.SDK_UNKNOWN) - .setIOS(false) - .setWeb(true) - .buildAndCreate(client) - } - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultGroupRuleBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultGroupRuleBuilderTest.groovy deleted file mode 100644 index ca14bbe514a..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultGroupRuleBuilderTest.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.group.rule.* -import org.testng.annotations.Test - -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultGroupRuleBuilderTest { - - @Test - void basicUsage(){ - def client = mock(Client) - def groupRule = mock(GroupRule) - def groupRuleAction = mock(GroupRuleAction) - def groupRuleConditions = mock(GroupRuleConditions) - def groupRuleExpression = mock(GroupRuleExpression) - def groupRulePeopleCondition = mock(GroupRulePeopleCondition) - def groupRuleGroupCondition = mock(GroupRuleGroupCondition) - def groupRuleUserCondition = mock(GroupRuleUserCondition) - def groupRuleGroupAssignment = mock(GroupRuleGroupAssignment) - - when(client.instantiate(GroupRule.class)).thenReturn(groupRule) - when(client.instantiate(GroupRuleAction.class)).thenReturn(groupRuleAction) - when(groupRule.getActions()).thenReturn(groupRuleAction) - when(client.instantiate(GroupRuleConditions.class)).thenReturn(groupRuleConditions) - when(groupRule.getConditions()).thenReturn(groupRuleConditions) - when(client.instantiate(GroupRuleExpression.class)).thenReturn(groupRuleExpression) - when(client.instantiate(GroupRulePeopleCondition.class)).thenReturn(groupRulePeopleCondition) - when(client.instantiate(GroupRuleGroupCondition.class)).thenReturn(groupRuleGroupCondition) - when(client.instantiate(GroupRuleUserCondition.class)).thenReturn(groupRuleUserCondition) - when(client.instantiate(GroupRuleGroupAssignment.class)).thenReturn(groupRuleGroupAssignment) - - new DefaultGroupRuleBuilder() - .setName("dummy rule") - .setType("group_rule") - .addGroup("ajhd1234kak") - .buildAndCreate(client) - - verify(client).createGroupRule(eq(groupRule)) - verify(groupRule).setName("dummy rule") - verify(groupRule).setType("group_rule") - verify(groupRuleGroupCondition).setInclude(Arrays.asList("ajhd1234kak")) - - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultOIDCApplicationBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultOIDCApplicationBuilderTest.groovy deleted file mode 100644 index e3ab04a5794..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultOIDCApplicationBuilderTest.groovy +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.application.* -import org.testng.annotations.Test - -import static com.okta.sdk.impl.Util.expect -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultOIDCApplicationBuilderTest { - - @Test - void basicUsage() { - def client = mock(Client) - def application = mock(OpenIdConnectApplication) - def applicationAccessibility = mock(ApplicationAccessibility) - def applicationVisibilityHide = mock(ApplicationVisibilityHide) - def applicationVisibility = mock(ApplicationVisibility) - def openIdConnectApplicationSettingsClient = mock(OpenIdConnectApplicationSettingsClient) - def applicationCredentialsOAuthClient = mock(ApplicationCredentialsOAuthClient) - def openIdConnectApplicationSettings = mock(OpenIdConnectApplicationSettings) - def oAuthApplicationCredentials = mock(OAuthApplicationCredentials) - - when(client.instantiate(OpenIdConnectApplication.class)).thenReturn(application); - when(client.instantiate(ApplicationAccessibility.class)).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibilityHide.class)).thenReturn(applicationVisibilityHide) - when(application.getAccessibility()).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibility.class)).thenReturn(applicationVisibility) - when(application.getVisibility())thenReturn(applicationVisibility) - when(client.instantiate(OpenIdConnectApplicationSettingsClient.class))thenReturn(openIdConnectApplicationSettingsClient) - when(client.instantiate(ApplicationCredentialsOAuthClient.class))thenReturn(applicationCredentialsOAuthClient) - //when(client.instantiate(OpenIdConnectApplicationSettings.class))thenReturn(applicationCredentialsOAuthClient) - when(application.getSettings()).thenReturn(openIdConnectApplicationSettings) - when(application.getCredentials())thenReturn(oAuthApplicationCredentials) - - new DefaultOIDCApplicationBuilder() - .setName("oidc_client") - .setLabel("test_app") - .addRedirectUris("http://www.google.com") - .setPostLogoutRedirectUris(Collections.singletonList("http://www.example.com/logout")) - .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setClientId("dummy_id") - .setClientSecret("dummy_shgfhsgdhfgwg") - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.NONE) - .setIOS(true) - .setWeb(false) - .setLoginRedirectUrl("http://www.myApp.com") - .setErrorRedirectUrl("http://www.myApp.com/errror") - .setSelfService(false) - .buildAndCreate(client); - - verify(client).createApplication(eq(application)) - verify(application).setLabel("test_app") - verify(applicationAccessibility).setSelfService(false) - verify(applicationAccessibility).setErrorRedirectUrl("http://www.myApp.com/errror") - verify(applicationAccessibility).setLoginRedirectUrl("http://www.myApp.com") - verify(applicationVisibilityHide).setWeb(false) - verify(applicationVisibilityHide).setIOS(true) - verify(openIdConnectApplicationSettingsClient).setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - verify(openIdConnectApplicationSettingsClient).setPostLogoutRedirectUris(Collections.singletonList("http://www.example.com/logout")) - } - - @Test - void createWithoutResponseType(){ - - def client = mock(Client) - def application = mock(OpenIdConnectApplication) - def applicationAccessibility = mock(ApplicationAccessibility) - def applicationVisibilityHide = mock(ApplicationVisibilityHide) - def applicationVisibility = mock(ApplicationVisibility) - def openIdConnectApplicationSettingsClient = mock(OpenIdConnectApplicationSettingsClient) - def applicationCredentialsOAuthClient = mock(ApplicationCredentialsOAuthClient) - def openIdConnectApplicationSettings = mock(OpenIdConnectApplicationSettings) - def oAuthApplicationCredentials = mock(OAuthApplicationCredentials) - - when(client.instantiate(OpenIdConnectApplication.class)).thenReturn(application); - when(client.instantiate(ApplicationAccessibility.class)).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibilityHide.class)).thenReturn(applicationVisibilityHide) - when(application.getAccessibility()).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibility.class)).thenReturn(applicationVisibility) - when(application.getVisibility())thenReturn(applicationVisibility) - when(client.instantiate(OpenIdConnectApplicationSettingsClient.class))thenReturn(openIdConnectApplicationSettingsClient) - when(client.instantiate(ApplicationCredentialsOAuthClient.class))thenReturn(applicationCredentialsOAuthClient) - when(application.getSettings()).thenReturn(openIdConnectApplicationSettings) - when(application.getCredentials())thenReturn(oAuthApplicationCredentials) - - expect IllegalArgumentException, { - new DefaultOIDCApplicationBuilder() - .setName("oidc_client") - .setLabel("test_app") - .addRedirectUris("http://www.google.com") - .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setClientId("dummy_id") - .setClientSecret("dummy_shgfhsgdhfgwg") - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.NONE) - .setIOS(true) - .setWeb(false) - .setLoginRedirectUrl("http://www.myApp.com") - .setErrorRedirectUrl("http://www.myApp.com/errror") - .setSelfService(false) - .buildAndCreate(client); - } - - } - - @Test - void createWithoutGrantType(){ - - def client = mock(Client) - def application = mock(OpenIdConnectApplication) - def applicationAccessibility = mock(ApplicationAccessibility) - def applicationVisibilityHide = mock(ApplicationVisibilityHide) - def applicationVisibility = mock(ApplicationVisibility) - def openIdConnectApplicationSettingsClient = mock(OpenIdConnectApplicationSettingsClient) - def applicationCredentialsOAuthClient = mock(ApplicationCredentialsOAuthClient) - def openIdConnectApplicationSettings = mock(OpenIdConnectApplicationSettings) - def oAuthApplicationCredentials = mock(OAuthApplicationCredentials) - - when(client.instantiate(OpenIdConnectApplication.class)).thenReturn(application); - when(client.instantiate(ApplicationAccessibility.class)).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibilityHide.class)).thenReturn(applicationVisibilityHide) - when(application.getAccessibility()).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibility.class)).thenReturn(applicationVisibility) - when(application.getVisibility())thenReturn(applicationVisibility) - when(client.instantiate(OpenIdConnectApplicationSettingsClient.class))thenReturn(openIdConnectApplicationSettingsClient) - when(client.instantiate(ApplicationCredentialsOAuthClient.class))thenReturn(applicationCredentialsOAuthClient) - when(application.getSettings()).thenReturn(openIdConnectApplicationSettings) - when(application.getCredentials())thenReturn(oAuthApplicationCredentials) - - expect IllegalArgumentException, { - new DefaultOIDCApplicationBuilder() - .setName("oidc_client") - .setLabel("test_app") - .addRedirectUris("http://www.google.com") - .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setClientId("dummy_id") - .setClientSecret("dummy_shgfhsgdhfgwg") - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.NONE) - .setIOS(true) - .setWeb(false) - .setLoginRedirectUrl("http://www.myApp.com") - .setErrorRedirectUrl("http://www.myApp.com/errror") - .setSelfService(false) - .buildAndCreate(client); - } - - } - - @Test - void createWithoutApplicationType(){ - - def client = mock(Client) - def application = mock(OpenIdConnectApplication) - def applicationAccessibility = mock(ApplicationAccessibility) - def applicationVisibilityHide = mock(ApplicationVisibilityHide) - def applicationVisibility = mock(ApplicationVisibility) - def openIdConnectApplicationSettingsClient = mock(OpenIdConnectApplicationSettingsClient) - def applicationCredentialsOAuthClient = mock(ApplicationCredentialsOAuthClient) - def openIdConnectApplicationSettings = mock(OpenIdConnectApplicationSettings) - def oAuthApplicationCredentials = mock(OAuthApplicationCredentials) - - when(client.instantiate(OpenIdConnectApplication.class)).thenReturn(application); - when(client.instantiate(ApplicationAccessibility.class)).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibilityHide.class)).thenReturn(applicationVisibilityHide) - when(application.getAccessibility()).thenReturn(applicationAccessibility) - when(client.instantiate(ApplicationVisibility.class)).thenReturn(applicationVisibility) - when(application.getVisibility())thenReturn(applicationVisibility) - when(client.instantiate(OpenIdConnectApplicationSettingsClient.class))thenReturn(openIdConnectApplicationSettingsClient) - when(client.instantiate(ApplicationCredentialsOAuthClient.class))thenReturn(applicationCredentialsOAuthClient) - when(application.getSettings()).thenReturn(openIdConnectApplicationSettings) - when(application.getCredentials())thenReturn(oAuthApplicationCredentials) - - expect IllegalArgumentException, { - new DefaultOIDCApplicationBuilder() - .setName("oidc_client") - .setLabel("test_app") - .addRedirectUris("http://www.google.com") - .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - .setClientId("dummy_id") - .setClientSecret("dummy_shgfhsgdhfgwg") - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.NONE) - .setIOS(true) - .setWeb(false) - .setLoginRedirectUrl("http://www.myApp.com") - .setErrorRedirectUrl("http://www.myApp.com/errror") - .setSelfService(false) - .buildAndCreate(client); - } - - } - - @Test - void createOIDCApplicationWithPrivateKeyJwtTest(){ - - def client = mock(Client) - def application = mock(OpenIdConnectApplication) - def applicationVisibilityHide = mock(ApplicationVisibilityHide) - def openIdConnectApplicationSettingsClient = mock(OpenIdConnectApplicationSettingsClient) - def applicationCredentialsOAuthClient = mock(ApplicationCredentialsOAuthClient) - def openIdConnectApplicationSettings = mock(OpenIdConnectApplicationSettings) - def clientKeys = mock(OpenIdConnectApplicationSettingsClientKeys) - def oAuthApplicationCredentials = mock(OAuthApplicationCredentials) - def jsonWebKey = mock(JsonWebKey) - - jsonWebKey.setKid("kid_value") - jsonWebKey.setKty("kty_value") - jsonWebKey.setE("e_value") - jsonWebKey.setN("n_value") - - when(client.instantiate(OpenIdConnectApplication.class)).thenReturn(application); - when(client.instantiate(ApplicationVisibilityHide.class)).thenReturn(applicationVisibilityHide) - when(client.instantiate(OpenIdConnectApplicationSettingsClient.class))thenReturn(openIdConnectApplicationSettingsClient) - when(client.instantiate(ApplicationCredentialsOAuthClient.class))thenReturn(applicationCredentialsOAuthClient) - when(application.getSettings()).thenReturn(openIdConnectApplicationSettings) - when(application.getSettings().getOAuthClient()).thenReturn(openIdConnectApplicationSettingsClient) - when(client.instantiate(OpenIdConnectApplicationSettingsClientKeys.class)).thenReturn(clientKeys) - when(application.getCredentials())thenReturn(oAuthApplicationCredentials) - - new DefaultOIDCApplicationBuilder() - .setName("oidc_client") - .setLabel("test_app") - .setSignOnMode(ApplicationSignOnMode.OPENID_CONNECT) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.PRIVATE_KEY_JWT) - .addRedirectUris("http://www.example.com") - .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setJwks(Arrays.asList(jsonWebKey)) - .buildAndCreate(client) - - verify(client).createApplication(eq(application)) - verify(application).setLabel("test_app") - verify(application).setSignOnMode(ApplicationSignOnMode.OPENID_CONNECT) - verify(applicationCredentialsOAuthClient).setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.PRIVATE_KEY_JWT) - verify(openIdConnectApplicationSettingsClient).setRedirectUris(Arrays.asList("http://www.example.com")) - verify(openIdConnectApplicationSettingsClient).setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - verify(openIdConnectApplicationSettingsClient).setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - verify(openIdConnectApplicationSettingsClient).setApplicationType(OpenIdConnectApplicationType.NATIVE) - verify(clientKeys).setKeys(Arrays.asList(jsonWebKey)) - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultOktaSignOnPolicyBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultOktaSignOnPolicyBuilderTest.groovy deleted file mode 100644 index f557a492c08..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultOktaSignOnPolicyBuilderTest.groovy +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.policy.* -import org.testng.annotations.Test - -import static com.okta.sdk.impl.Util.expect -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultOktaSignOnPolicyBuilderTest { - - @Test - void basicUsage(){ - def client = mock(Client) - def policy = mock(Policy) - def oktaSignOnPolicy = mock(OktaSignOnPolicy) - def oktaSignOnPolicyConditions = mock(OktaSignOnPolicyConditions) - def policyPeopleCondition = mock(PolicyPeopleCondition) - def groupCondition = mock(GroupCondition) - - when(client.instantiate(Policy.class)).thenReturn(policy) - when(client.instantiate(OktaSignOnPolicy.class)).thenReturn(oktaSignOnPolicy) - when(client.instantiate(OktaSignOnPolicyConditions)).thenReturn(oktaSignOnPolicyConditions) - when(client.instantiate(PolicyPeopleCondition.class)).thenReturn(policyPeopleCondition) - when(client.instantiate(GroupCondition.class)).thenReturn(groupCondition) - when(oktaSignOnPolicy.getConditions()).thenReturn(oktaSignOnPolicyConditions) - - new DefaultOktaSignOnPolicyBuilder() - .setName("dummy_policy") - .setDescription("dummy") - .setPriority(1) - .setStatus(Policy.StatusEnum.ACTIVE) - .setType(PolicyType.OKTA_SIGN_ON) - .addGroup("abcdef123456") - .buildAndCreate(client); - - verify(client).createPolicy(eq(oktaSignOnPolicy), eq(true)) - verify(oktaSignOnPolicy).setName("dummy_policy") - verify(oktaSignOnPolicy).setDescription("dummy") - verify(oktaSignOnPolicy).setPriority(1) - verify(oktaSignOnPolicy).setStatus(Policy.StatusEnum.ACTIVE) - verify(oktaSignOnPolicy).setType(PolicyType.OKTA_SIGN_ON) - verify(groupCondition).setInclude(new ArrayList(Arrays.asList("abcdef123456"))) - - } - - @Test - void createWithNonOktaSignOnPolicyType(){ - - def client = mock(Client) - def policy = mock(Policy) - def oktaSignOnPolicy = mock(OktaSignOnPolicy) - when(client.instantiate(Policy.class)).thenReturn(policy) - when(client.instantiate(OktaSignOnPolicy.class)).thenReturn(oktaSignOnPolicy) - List groupList = new ArrayList(Arrays.asList("dsfjhgsjhg")) - expect IllegalArgumentException, { - new DefaultOktaSignOnPolicyBuilder() - .setName("Test Policy") - .setDescription("dummy policy for test") - .setPriority(1) - .setGroups(groupList) - .setType(PolicyType.PASSWORD) - .setStatus(Policy.StatusEnum.ACTIVE) - .buildAndCreate(client) - } - } - -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPasswordPolicyBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPasswordPolicyBuilderTest.groovy deleted file mode 100644 index bee4ec672bc..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPasswordPolicyBuilderTest.groovy +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.policy.* -import org.testng.annotations.Test - -import static com.okta.sdk.impl.Util.expect -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultPasswordPolicyBuilderTest { - - @Test - void basicUsage(){ - def client = mock(Client) - def policy = mock(Policy) - def passwordPolicy = mock(PasswordPolicy) - def passwordPolicyAuthenticationProviderCondition = mock(PasswordPolicyAuthenticationProviderCondition) - def passwordPolicyConditions = mock(PasswordPolicyConditions) - def passwordPolicySettings = mock(PasswordPolicySettings) - def policyPeopleCondition = mock(PolicyPeopleCondition) - def groupCondition = mock(GroupCondition) - def passwordPolicyPasswordSettings = mock(PasswordPolicyPasswordSettings) - def passwordPolicyPasswordSettingsComplexity = mock(PasswordPolicyPasswordSettingsComplexity) - def passwordDictionary = mock(PasswordDictionary) - def passwordDictionaryCommon = mock(PasswordDictionaryCommon) - def passwordPolicyDelegationSettings = mock(PasswordPolicyDelegationSettings) - def passwordPolicyDelegationSettingsOptions = mock(PasswordPolicyDelegationSettingsOptions) - def passwordPolicyPasswordSettingsAge = mock(PasswordPolicyPasswordSettingsAge) - def passwordPolicyPasswordSettingsLockout = mock(PasswordPolicyPasswordSettingsLockout) - def passwordPolicyRecoverySettings = mock(PasswordPolicyRecoverySettings) - def passwordPolicyRecoveryFactors = mock(PasswordPolicyRecoveryFactors) - def passwordPolicyRecoveryFactorSettings = mock(PasswordPolicyRecoveryFactorSettings) - def passwordPolicyRecoveryEmail = mock(PasswordPolicyRecoveryEmail) - def passwordPolicyRecoveryEmailProperties = mock(PasswordPolicyRecoveryEmailProperties) - def passwordPolicyRecoveryEmailRecoveryToken = mock(PasswordPolicyRecoveryEmailRecoveryToken) - - - when(client.instantiate(Policy.class)).thenReturn(policy) - when(client.instantiate(PasswordPolicy.class)).thenReturn(passwordPolicy) - when(client.instantiate(PasswordPolicyAuthenticationProviderCondition.class)).thenReturn(passwordPolicyAuthenticationProviderCondition) - when(client.instantiate(PasswordPolicyConditions.class)).thenReturn(passwordPolicyConditions) - when(client.instantiate(PasswordPolicySettings.class)).thenReturn(passwordPolicySettings) - when(client.instantiate(PasswordPolicy.class).getConditions()).thenReturn(passwordPolicyConditions) - when(client.instantiate(PasswordPolicy.class).getSettings()).thenReturn(passwordPolicySettings) - when(client.instantiate(PolicyPeopleCondition.class)).thenReturn(policyPeopleCondition) - when(client.instantiate(GroupCondition.class)).thenReturn(groupCondition) - when(client.instantiate(PasswordPolicyPasswordSettings.class)).thenReturn(passwordPolicyPasswordSettings) - when(client.instantiate(PasswordPolicyPasswordSettingsComplexity.class)).thenReturn(passwordPolicyPasswordSettingsComplexity) - when(client.instantiate(PasswordDictionaryCommon.class)).thenReturn(passwordDictionaryCommon) - when(client.instantiate(PasswordDictionary.class)).thenReturn(passwordDictionary) - when(client.instantiate(PasswordPolicyDelegationSettings.class)).thenReturn(passwordPolicyDelegationSettings) - when(client.instantiate(PasswordPolicyDelegationSettingsOptions.class)).thenReturn(passwordPolicyDelegationSettingsOptions) - when(client.instantiate(PasswordPolicyPasswordSettingsAge.class)).thenReturn(passwordPolicyPasswordSettingsAge) - when(client.instantiate(PasswordPolicyPasswordSettingsLockout.class)).thenReturn(passwordPolicyPasswordSettingsLockout) - when(client.instantiate(PasswordPolicyRecoverySettings.class)).thenReturn(passwordPolicyRecoverySettings) - when(client.instantiate(PasswordPolicyRecoveryFactors.class)).thenReturn(passwordPolicyRecoveryFactors) - when(client.instantiate(PasswordPolicyRecoveryFactorSettings.class)).thenReturn(passwordPolicyRecoveryFactorSettings) - when(client.instantiate(PasswordPolicyRecoveryEmail.class)).thenReturn(passwordPolicyRecoveryEmail) - when(client.instantiate(PasswordPolicyRecoveryEmailProperties.class)).thenReturn(passwordPolicyRecoveryEmailProperties) - when(client.instantiate(PasswordPolicyRecoveryEmailRecoveryToken.class)).thenReturn(passwordPolicyRecoveryEmailRecoveryToken) - - new DefaultPasswordPolicyBuilder() - .setAuthProvider(PasswordPolicyAuthenticationProviderCondition.ProviderEnum.OKTA) - .setExcludePasswordDictionary(false) - .setExcludeUserNameInPassword(false) - .setMinPasswordLength(8) - .setMinLowerCase(1) - .setMinUpperCase(1) - .setMinNumbers(1) - .setMinSymbols(1) - .addGroup("shvcgfhs345sdfjhg") - .setSkipUnlock(false) - .setPasswordExpireWarnDays(85) - .setPasswordHistoryCount(5) - .setPasswordMaxAgeDays(90) - .setPasswordMinMinutes(2) - .setPasswordAutoUnlockMinutes(5) - .setPasswordMaxAttempts(3) - .setShowLockoutFailures(true) - .setPasswordRecoveryOktaSMS(PasswordPolicyRecoveryFactorSettings.StatusEnum.ACTIVE) - .setPasswordRecoveryOktaCall(PasswordPolicyRecoveryFactorSettings.StatusEnum.ACTIVE) - .setPasswordRecoveryTokenLifeMinutes(500) - .setType(PolicyType.PASSWORD) - .setStatus(Policy.StatusEnum.ACTIVE) - .setPriority(1) - .setDescription("Dummy policy for sdk test") - .setName("SDK created policy") - .buildAndCreate(client) - - - verify(client).createPolicy(eq(passwordPolicy), eq(true)) - verify(passwordPolicy).setName("SDK created policy") - verify(passwordPolicy).setDescription("Dummy policy for sdk test") - verify(passwordPolicy).setPriority(1) - verify(passwordPolicy).setStatus(Policy.StatusEnum.ACTIVE) - verify(passwordPolicy).setType(PolicyType.PASSWORD) - verify(passwordPolicyPasswordSettingsLockout).setShowLockoutFailures(true) - verify(passwordPolicyRecoveryFactors).setOktaSms(passwordPolicyRecoveryFactorSettings.setStatus(PasswordPolicyRecoveryFactorSettings.StatusEnum.ACTIVE)) - verify(passwordPolicyRecoveryFactors).setOktaCall(passwordPolicyRecoveryFactorSettings.setStatus(PasswordPolicyRecoveryFactorSettings.StatusEnum.ACTIVE)) - verify(passwordPolicyRecoveryEmailRecoveryToken).setTokenLifetimeMinutes(500) - verify(passwordPolicyPasswordSettingsLockout).setMaxAttempts(3) - verify(passwordPolicyPasswordSettingsLockout).setAutoUnlockMinutes(5) - verify(passwordPolicyPasswordSettingsAge).setMinAgeMinutes(2) - verify(passwordPolicyPasswordSettingsAge).setMinAgeMinutes(2) - verify(passwordPolicyPasswordSettingsAge).setMinAgeMinutes(2) - verify(passwordPolicyPasswordSettingsAge).setMaxAgeDays(90) - verify(passwordPolicyPasswordSettingsAge).setExpireWarnDays(85) - verify(passwordPolicyPasswordSettingsAge).setHistoryCount(5) - verify(passwordPolicyDelegationSettingsOptions).setSkipUnlock(false) - verify(groupCondition).setInclude(new ArrayList(Arrays.asList("shvcgfhs345sdfjhg"))) - verify(passwordPolicyPasswordSettingsComplexity).setMinSymbol(1) - verify(passwordPolicyPasswordSettingsComplexity).setMinNumber(1) - verify(passwordPolicyPasswordSettingsComplexity).setMinLowerCase(1) - verify(passwordPolicyPasswordSettingsComplexity).setMinUpperCase(1) - verify(passwordPolicyPasswordSettingsComplexity).setMinLength(8) - verify(passwordPolicyPasswordSettingsComplexity).setExcludeUsername(false) - verify(passwordDictionaryCommon).setExclude(false) - verify(passwordPolicyAuthenticationProviderCondition).setProvider(PasswordPolicyAuthenticationProviderCondition.ProviderEnum.OKTA) - } - - @Test - void createWithNonPasswordPolicyType(){ - - def client = mock(Client) - def policy = mock(Policy) - def passwordPolicy = mock(PasswordPolicy) - when(client.instantiate(Policy.class)).thenReturn(policy) - when(client.instantiate(PasswordPolicy.class)).thenReturn(passwordPolicy) - List groupList = new ArrayList(Arrays.asList("dsfjhgsjhg")); - expect IllegalArgumentException, { - new DefaultPasswordPolicyBuilder() - .setName("Test Password Policy") - .setDescription("dummy policy for test") - .setPriority(1) - .setGroups(groupList) - .setType(PolicyType.OKTA_SIGN_ON) - .setStatus(Policy.StatusEnum.ACTIVE) - .buildAndCreate(client) - } - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPasswordPolicyRuleBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPasswordPolicyRuleBuilderTest.groovy deleted file mode 100644 index bd413b5662c..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPasswordPolicyRuleBuilderTest.groovy +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.policy.* -import org.testng.annotations.Test - -import static com.okta.sdk.impl.Util.expect -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultPasswordPolicyRuleBuilderTest { - - @Test - void basicUsage(){ - def client = mock(Client) - def policy = mock(Policy) - def passwordPolicyRule = mock(PasswordPolicyRule) - def passwordPolicyRuleActions = mock(PasswordPolicyRuleActions) - def passwordPolicyRuleConditions = mock(PasswordPolicyRuleConditions) - def passwordPolicyRuleAction = mock(PasswordPolicyRuleAction) - def policyNetworkCondition = mock(PolicyNetworkCondition) - def policyPeopleCondition = mock(PolicyPeopleCondition) - def groupCondition = mock(GroupCondition) - def userCondition = mock(UserCondition) - - when(client.instantiate(PasswordPolicyRule.class)).thenReturn(passwordPolicyRule) - when(client.instantiate(PasswordPolicyRuleActions.class)).thenReturn(passwordPolicyRuleActions) - when(passwordPolicyRule.getActions()).thenReturn(passwordPolicyRuleActions) - when(client.instantiate(PasswordPolicyRuleConditions.class)).thenReturn(passwordPolicyRuleConditions) - when(passwordPolicyRule.getConditions()).thenReturn(passwordPolicyRuleConditions) - when(client.instantiate(PasswordPolicyRuleAction.class)).thenReturn(passwordPolicyRuleAction) - when(client.instantiate(PolicyNetworkCondition.class)).thenReturn(policyNetworkCondition) - when(client.instantiate(PolicyPeopleCondition.class)).thenReturn(policyPeopleCondition) - when(client.instantiate(GroupCondition.class))thenReturn(groupCondition) - when(client.instantiate(UserCondition.class)).thenReturn(userCondition) - - new DefaultPasswordPolicyRuleBuilder() - .setName("name here") - .setStatus(PolicyRule.StatusEnum.ACTIVE) - .setType(PolicyRule.TypeEnum.PASSWORD) - .setPriority(1) - .addGroup("sdjfsdyfjsfsj") - .setNetworkConnection(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - .setSelfServicePasswordResetAccess(PasswordPolicyRuleAction.AccessEnum.ALLOW) - .setSelfServiceUnlockAccess(PasswordPolicyRuleAction.AccessEnum.ALLOW) - .setSelfServiceUnlockAccess(PasswordPolicyRuleAction.AccessEnum.DENY) - .buildAndCreate(client, policy) - - verify(policy).createRule(eq(passwordPolicyRule)) - verify(passwordPolicyRule).setName("name here") - verify(passwordPolicyRule).setType(PolicyRule.TypeEnum.PASSWORD) - verify(passwordPolicyRuleActions).setSelfServicePasswordReset(passwordPolicyRuleAction.setAccess(PasswordPolicyRuleAction.AccessEnum.ALLOW)) - verify(passwordPolicyRuleConditions).setNetwork(policyNetworkCondition.setConnection(PolicyNetworkCondition.ConnectionEnum.ANYWHERE)) - } - - @Test - void createWithoutType(){ - def client = mock(Client) - def policy = mock(Policy) - def passwordPolicyRule = mock(PasswordPolicyRule) - - when(client.instantiate(PasswordPolicyRule.class)).thenReturn(passwordPolicyRule) - expect IllegalArgumentException, { - new DefaultPasswordPolicyRuleBuilder() - .setName("test rule") - .setStatus(PolicyRule.StatusEnum.ACTIVE) - .buildAndCreate(client, policy) - } - } - - @Test - void createWithSignOnType(){ - def client = mock(Client) - def policy = mock(Policy) - def passwordPolicyRule = mock(PasswordPolicyRule) - - when(client.instantiate(PasswordPolicyRule.class)).thenReturn(passwordPolicyRule) - expect IllegalArgumentException, { - new DefaultPasswordPolicyRuleBuilder() - .setName("test rule") - .setStatus(PolicyRule.StatusEnum.ACTIVE) - .setType(PolicyRule.TypeEnum.SIGN_ON) - .buildAndCreate(client, policy) - } - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPolicyBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPolicyBuilderTest.groovy deleted file mode 100644 index a6a59e7df6d..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPolicyBuilderTest.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.policy.Policy -import com.okta.sdk.resource.policy.PolicyType -import org.testng.annotations.Test - -import static com.okta.sdk.impl.Util.expect -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultPolicyBuilderTest { - - @Test - void basicUsage() { - - def client = mock(Client) - def policy = mock(Policy) - when(client.instantiate(Policy.class)).thenReturn(policy) - - new DefaultPolicyBuilder() - .setName("Test Policy") - .setDescription("dummy policy for test") - .setPriority(1) - .setType(PolicyType.OKTA_SIGN_ON) - .setStatus(Policy.StatusEnum.ACTIVE) - .buildAndCreate(client) - - verify(client).createPolicy(eq(policy), eq(true)) - verify(policy).setName("Test Policy") - verify(policy).setDescription("dummy policy for test") - } - - @Test - void createWithoutPolicyType() { - def client = mock(Client) - def policy = mock(Policy) - when(client.instantiate(Policy.class)).thenReturn(policy) - - expect IllegalArgumentException, { - new DefaultPolicyBuilder() - .setName("Test Policy") - .setDescription("dummy policy for test") - .setPriority(1) - .setStatus(Policy.StatusEnum.ACTIVE) - .buildAndCreate(client) - } - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPolicyRuleBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPolicyRuleBuilderTest.groovy deleted file mode 100644 index 2fec3b2e24b..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultPolicyRuleBuilderTest.groovy +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.policy.Policy -import com.okta.sdk.resource.policy.PolicyRule -import org.testng.annotations.Test - -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultPolicyRuleBuilderTest { - - @Test - void basicUsage(){ - def policy = mock(Policy) - def client = mock(Client) - def policyRule = mock(PolicyRule) - - when(client.instantiate(Policy.class)).thenReturn(policy) - when(client.instantiate(PolicyRule.class)).thenReturn(policyRule) - - new DefaultPolicyRuleBuilder() - .setStatus(PolicyRule.StatusEnum.ACTIVE) - .setPriority(1) - .buildAndCreate(client, policy) - - verify(policy).createRule(eq(policyRule)) - verify(policyRule).setPriority(1) - verify(policyRule).setStatus(PolicyRule.StatusEnum.ACTIVE) - - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultSignOnPolicyRuleBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultSignOnPolicyRuleBuilderTest.groovy deleted file mode 100644 index ae6f5d6869d..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultSignOnPolicyRuleBuilderTest.groovy +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.policy.* -import org.testng.annotations.Test - -import static com.okta.sdk.impl.Util.expect -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.* - -class DefaultSignOnPolicyRuleBuilderTest { - - @Test - void basicUsage(){ - def client = mock(Client) - def policy = mock(Policy) - def signOnPolicyRule = mock(OktaSignOnPolicyRule) - def oktaSignOnPolicyRuleActions = mock(OktaSignOnPolicyRuleActions) - def oktaSignOnPolicyRuleConditions = mock(OktaSignOnPolicyRuleConditions) - def oktaSignOnPolicyRuleSignonActions = mock(OktaSignOnPolicyRuleSignonActions) - def policyNetworkCondition = mock(PolicyNetworkCondition) - def policyPeopleCondition = mock(PolicyPeopleCondition) - def groupCondition = mock(GroupCondition) - def userCondition = mock(UserCondition) - def oktaSignOnPolicyRuleSignonSessionActions = mock(OktaSignOnPolicyRuleSignonSessionActions) - def policyRuleAuthContextCondition = mock(PolicyRuleAuthContextCondition) - - when(client.instantiate(OktaSignOnPolicyRule.class)).thenReturn(signOnPolicyRule) - when(client.instantiate(OktaSignOnPolicyRuleActions.class)).thenReturn(oktaSignOnPolicyRuleActions) - when(signOnPolicyRule.getActions()).thenReturn(oktaSignOnPolicyRuleActions) - when(client.instantiate(PasswordPolicyRuleConditions.class)).thenReturn(oktaSignOnPolicyRuleConditions) - when(signOnPolicyRule.getConditions()).thenReturn(oktaSignOnPolicyRuleConditions) - when(client.instantiate(OktaSignOnPolicyRuleSignonActions.class)).thenReturn(oktaSignOnPolicyRuleSignonActions) - when(client.instantiate(PolicyNetworkCondition.class)).thenReturn(policyNetworkCondition) - when(client.instantiate(PolicyPeopleCondition.class)).thenReturn(policyPeopleCondition) - when(client.instantiate(GroupCondition.class))thenReturn(groupCondition) - when(client.instantiate(UserCondition.class)).thenReturn(userCondition) - when(client.instantiate(OktaSignOnPolicyRuleSignonSessionActions.class)).thenReturn(oktaSignOnPolicyRuleSignonSessionActions) - when(client.instantiate(PolicyRuleAuthContextCondition.class)).thenReturn(policyRuleAuthContextCondition) - - new DefaultSignOnPolicyRuleBuilder() - .setName("name here") - .setStatus(PolicyRule.StatusEnum.ACTIVE) - .setType(PolicyRule.TypeEnum.SIGN_ON) - .setPriority(1) - .addGroup("sdjfsdyfjsfsj") - .setNetworkConnection(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - .setAuthType(PolicyRuleAuthContextCondition.AuthTypeEnum.ANY) - .setFactorLifetime(1) - .setFactorPromptMode(OktaSignOnPolicyRuleSignonActions.FactorPromptModeEnum.SESSION) - .setRequireFactor(true) - .setUsePersistentCookie(true) - .setRememberDeviceByDefault(true) - .setMaxSessionLifetimeMinutes(10) - .setMaxSessionIdleMinutes(5) - .buildAndCreate(client, policy) - - verify(policy).createRule(eq(signOnPolicyRule)) - verify(signOnPolicyRule).setName("name here") - verify(signOnPolicyRule).setType(PolicyRule.TypeEnum.SIGN_ON) - verify(oktaSignOnPolicyRuleSignonActions).setFactorLifetime(1) - verify(oktaSignOnPolicyRuleSignonActions).setRememberDeviceByDefault(true) - verify(oktaSignOnPolicyRuleSignonActions).setRequireFactor(true) - verify(oktaSignOnPolicyRuleSignonActions).setFactorPromptMode(OktaSignOnPolicyRuleSignonActions.FactorPromptModeEnum.SESSION) - verify(oktaSignOnPolicyRuleSignonSessionActions).setMaxSessionIdleMinutes(5) - verify(oktaSignOnPolicyRuleSignonSessionActions).setMaxSessionLifetimeMinutes(10) - verify(policyRuleAuthContextCondition).setAuthType(PolicyRuleAuthContextCondition.AuthTypeEnum.ANY) - verify(oktaSignOnPolicyRuleSignonActions).setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - } - - @Test - void createWithPasswordType(){ - def client = mock(Client) - def policy = mock(Policy) - def signOnPolicyRule = mock(OktaSignOnPolicyRule) - - when(client.instantiate(OktaSignOnPolicyRule.class)).thenReturn(signOnPolicyRule) - expect IllegalArgumentException, { - new DefaultSignOnPolicyRuleBuilder() - .setName("test name") - .setStatus(PolicyRule.StatusEnum.ACTIVE) - .setType(PolicyRule.TypeEnum.PASSWORD) - .buildAndCreate(client, policy) - } - - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultUserBuilderTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultUserBuilderTest.groovy deleted file mode 100644 index a19cafde330..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/DefaultUserBuilderTest.groovy +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright 2018-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.user.CreateUserRequest -import com.okta.sdk.resource.user.PasswordCredential -import com.okta.sdk.resource.user.PasswordCredentialHook -import com.okta.sdk.resource.user.UserCredentials -import com.okta.sdk.resource.user.UserNextLogin -import com.okta.sdk.resource.user.UserProfile -import org.mockito.ArgumentCaptor -import org.testng.annotations.Test - -import static com.okta.sdk.impl.Util.expect -import static org.hamcrest.Matchers.aMapWithSize -import static org.hamcrest.Matchers.allOf -import static org.hamcrest.Matchers.hasEntry -import static org.hamcrest.MatcherAssert.assertThat -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.verify -import static org.mockito.Mockito.when - -class DefaultUserBuilderTest { - - @Test - void basicUsage() { - - def client = mock(Client) - def createUserRequest = mock(CreateUserRequest) - def profile = mock(UserProfile) - when(client.instantiate(CreateUserRequest)).thenReturn(createUserRequest) - when(client.instantiate(UserProfile)).thenReturn(profile) - when(createUserRequest.getProfile()).thenReturn(profile) - - new DefaultUserBuilder() - .setFirstName("Joe") - .setLastName("Coder") - .setEmail("joe.coder@example.com") - .setNextLogin(UserNextLogin.CHANGEPASSWORD) - .buildAndCreate(client) - - verify(client).createUser(eq(createUserRequest), eq(null), eq(false), eq(UserNextLogin.CHANGEPASSWORD)) - verify(profile).setFirstName("Joe") - verify(profile).setLastName("Coder") - verify(profile).setEmail("joe.coder@example.com") - } - - @Test - void importPasswordSha256() { - def client = mock(Client) - def createUserRequest = mock(CreateUserRequest) - def profile = mock(UserProfile) - def passwordCredential = mock(PasswordCredential) - def userCredentials = mock(UserCredentials) - when(client.instantiate(CreateUserRequest)).thenReturn(createUserRequest) - when(client.instantiate(UserProfile)).thenReturn(profile) - when(client.instantiate(UserCredentials)).thenReturn(userCredentials) - when(client.instantiate(PasswordCredential)).thenReturn(passwordCredential) - when(createUserRequest.getProfile()).thenReturn(profile) - when(createUserRequest.getCredentials()).thenReturn(userCredentials) - - String salt = "some-salt" - String hashedPassword = "a-hashed-password" - - new DefaultUserBuilder() - .setFirstName("Joe") - .setLastName("Coder") - .setEmail("joe.coder@example.com") - .setSha256PasswordHash(hashedPassword, salt, "PREFIX") - .buildAndCreate(client) - - def hashCapture = ArgumentCaptor.forClass(Map.class) - - verify(userCredentials).setPassword(passwordCredential) - verify(passwordCredential).put(eq("hash"), hashCapture.capture()) - - assertThat hashCapture.value, allOf( - hasEntry("salt", salt), - hasEntry("saltOrder", "PREFIX"), - hasEntry("value", hashedPassword), - hasEntry("algorithm", "SHA-256"), - aMapWithSize(4)) - } - - @Test - void importPasswordSha512() { - def client = mock(Client) - def createUserRequest = mock(CreateUserRequest) - def profile = mock(UserProfile) - def passwordCredential = mock(PasswordCredential) - def userCredentials = mock(UserCredentials) - when(client.instantiate(CreateUserRequest)).thenReturn(createUserRequest) - when(client.instantiate(UserProfile)).thenReturn(profile) - when(client.instantiate(UserCredentials)).thenReturn(userCredentials) - when(client.instantiate(PasswordCredential)).thenReturn(passwordCredential) - when(createUserRequest.getProfile()).thenReturn(profile) - when(createUserRequest.getCredentials()).thenReturn(userCredentials) - - String salt = "some-salt" - String hashedPassword = "a-hashed-password" - - new DefaultUserBuilder() - .setFirstName("Joe") - .setLastName("Coder") - .setEmail("joe.coder@example.com") - .setSha512PasswordHash(hashedPassword, salt, "PREFIX") - .buildAndCreate(client) - - def hashCapture = ArgumentCaptor.forClass(Map.class) - - verify(userCredentials).setPassword(passwordCredential) - verify(passwordCredential).put(eq("hash"), hashCapture.capture()) - - assertThat hashCapture.value, allOf( - hasEntry("salt", salt), - hasEntry("saltOrder", "PREFIX"), - hasEntry("value", hashedPassword), - hasEntry("algorithm", "SHA-512"), - aMapWithSize(4)) - } - - @Test - void importPasswordSha1() { - def client = mock(Client) - def createUserRequest = mock(CreateUserRequest) - def profile = mock(UserProfile) - def passwordCredential = mock(PasswordCredential) - def userCredentials = mock(UserCredentials) - when(client.instantiate(CreateUserRequest)).thenReturn(createUserRequest) - when(client.instantiate(UserProfile)).thenReturn(profile) - when(client.instantiate(UserCredentials)).thenReturn(userCredentials) - when(client.instantiate(PasswordCredential)).thenReturn(passwordCredential) - when(createUserRequest.getProfile()).thenReturn(profile) - when(createUserRequest.getCredentials()).thenReturn(userCredentials) - - String salt = "some-salt" - String hashedPassword = "a-hashed-password" - - new DefaultUserBuilder() - .setFirstName("Joe") - .setLastName("Coder") - .setEmail("joe.coder@example.com") - .setSha1PasswordHash(hashedPassword, salt, "PREFIX") - .buildAndCreate(client) - - def hashCapture = ArgumentCaptor.forClass(Map.class) - - verify(userCredentials).setPassword(passwordCredential) - verify(passwordCredential).put(eq("hash"), hashCapture.capture()) - - assertThat hashCapture.value, allOf( - hasEntry("salt", salt), - hasEntry("saltOrder", "PREFIX"), - hasEntry("value", hashedPassword), - hasEntry("algorithm", "SHA-1"), - aMapWithSize(4)) - } - - @Test - void importPasswordBcrypt() { - def client = mock(Client) - def createUserRequest = mock(CreateUserRequest) - def profile = mock(UserProfile) - def passwordCredential = mock(PasswordCredential) - def userCredentials = mock(UserCredentials) - when(client.instantiate(CreateUserRequest)).thenReturn(createUserRequest) - when(client.instantiate(UserProfile)).thenReturn(profile) - when(client.instantiate(UserCredentials)).thenReturn(userCredentials) - when(client.instantiate(PasswordCredential)).thenReturn(passwordCredential) - when(createUserRequest.getProfile()).thenReturn(profile) - when(createUserRequest.getCredentials()).thenReturn(userCredentials) - - String salt = "some-salt" - String hashedPassword = "a-hashed-password" - - new DefaultUserBuilder() - .setFirstName("Joe") - .setLastName("Coder") - .setEmail("joe.coder@example.com") - .setBcryptPasswordHash(hashedPassword, salt, 10) - .buildAndCreate(client) - - def hashCapture = ArgumentCaptor.forClass(Map.class) - - verify(userCredentials).setPassword(passwordCredential) - verify(passwordCredential).put(eq("hash"), hashCapture.capture()) - - assertThat hashCapture.value, allOf( - hasEntry("salt", salt), - hasEntry("workFactor", 10), - hasEntry("value", hashedPassword), - hasEntry("algorithm", "BCRYPT"), - aMapWithSize(4)) - } - - @Test - void createUserWithClearAndImportPassword() { - - def client = mock(Client) - def createUserRequest = mock(CreateUserRequest) - def profile = mock(UserProfile) - def passwordCredential = mock(PasswordCredential) - def userCredentials = mock(UserCredentials) - when(client.instantiate(CreateUserRequest)).thenReturn(createUserRequest) - when(client.instantiate(UserProfile)).thenReturn(profile) - when(client.instantiate(UserCredentials)).thenReturn(userCredentials) - when(client.instantiate(PasswordCredential)).thenReturn(passwordCredential) - when(createUserRequest.getProfile()).thenReturn(profile) - when(createUserRequest.getCredentials()).thenReturn(userCredentials) - - String salt = "some-salt" - String hashedPassword = "a-hashed-password" - String password = "regularPassowrd" - - expect IllegalArgumentException, { - new DefaultUserBuilder() - .setFirstName("Joe") - .setLastName("Coder") - .setEmail("joe.coder@example.com") - .setPassword(password.toCharArray()) - .setSha512PasswordHash(hashedPassword, salt, "PREFIX") - .buildAndCreate(client) - } - } - - @Test - void createUserWithUsePasswordHookForImportDefaultType() { - createUserWithUsePasswordHookForImport(null) - } - - @Test - void createUserWithUsePasswordHookForImportOtherType() { - createUserWithUsePasswordHookForImport("other") - } - - void createUserWithUsePasswordHookForImport(String type) { - - def client = mock(Client) - def createUserRequest = mock(CreateUserRequest) - def profile = mock(UserProfile) - def passwordCredential = mock(PasswordCredential) - def passwordCredentialHook = mock(PasswordCredentialHook) - def userCredentials = mock(UserCredentials) - when(client.instantiate(CreateUserRequest)).thenReturn(createUserRequest) - when(client.instantiate(UserProfile)).thenReturn(profile) - when(client.instantiate(UserCredentials)).thenReturn(userCredentials) - when(client.instantiate(PasswordCredential)).thenReturn(passwordCredential) - when(client.instantiate(PasswordCredentialHook)).thenReturn(passwordCredentialHook) - when(createUserRequest.getProfile()).thenReturn(profile) - when(createUserRequest.getCredentials()).thenReturn(userCredentials) - - DefaultUserBuilder defaultUserBuilder = new DefaultUserBuilder() - .setFirstName("Joe") - .setLastName("Coder") - .setEmail("joe.coder@example.com") - - if (type == null) { - defaultUserBuilder.usePasswordHookForImport() - } else { - defaultUserBuilder.usePasswordHookForImport(type) - } - - defaultUserBuilder.buildAndCreate(client) - - verify(userCredentials).setPassword(passwordCredential) - verify(passwordCredential).setHook(passwordCredentialHook) - - if (type == null) { - verify(passwordCredentialHook).setType("default") - } else { - verify(passwordCredentialHook).setType(type) - } - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/EnumConverterTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/EnumConverterTest.groovy deleted file mode 100644 index aba1e38734d..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/EnumConverterTest.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.resource.user.factor.FactorType -import org.testng.annotations.Test - -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.MatcherAssert.assertThat - -/** - * Tests for {@link EnumConverter}. - * @since 0.8.1 - */ -class EnumConverterTest { - - @Test - void validLookup() { - EnumConverter converter = new EnumConverter() - assertThat converter.fromValue(FactorType, "token:software:totp"), equalTo(FactorType.TOKEN_SOFTWARE_TOTP) - assertThat converter.fromValue(FactorType, "TOKEN_SOFTWARE_TOTP"), equalTo(FactorType.TOKEN_SOFTWARE_TOTP) - } - - @Test(expectedExceptions = IllegalArgumentException) - void invalidLookup() { - new EnumConverter().fromValue(FactorType, "invalid") - } - - @Test(expectedExceptions = IllegalArgumentException) - void nullLookup() { - new EnumConverter().fromValue(FactorType, null) - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/GeneratedResourceTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/GeneratedResourceTest.groovy deleted file mode 100644 index ed6413f1342..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/GeneratedResourceTest.groovy +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.impl.ds.InternalDataStore -import com.okta.commons.lang.Assert -import com.okta.commons.lang.Classes -import com.okta.sdk.resource.Resource -import org.mockito.Mockito -import org.mockito.invocation.InvocationOnMock -import org.mockito.stubbing.Answer -import org.testng.annotations.Test - -import java.lang.reflect.Method -import java.text.DateFormat -import java.text.SimpleDateFormat -import java.util.regex.Matcher -import java.util.regex.Pattern -import java.util.stream.Stream - -import static org.hamcrest.MatcherAssert.* -import static org.hamcrest.Matchers.* -import static org.mockito.Mockito.* -import static org.testng.Assert.fail - - -/** - * Reflection based tests for basic getter and setter methods on generated code. These tests provide very basic - * coverage and do NOT test anything specific. - */ -class GeneratedResourceTest { - - /** - * Sets values via setter methods then validates the value was set by using the corresponding getter method. - */ - @Test - void testGetterAndSetters() { - - InternalDataStore dataStore = createMockDataStore() - - clazzStream().forEach { clazz -> - - def resource = (AbstractResource) Classes.instantiate( - clazz.getDeclaredConstructor(InternalDataStore, Map), dataStore, null) - - setViaSetter(resource) - validateViaGetter(clazz, resource, true) - } - } - - /** - * Sets values via property methods then validates the value was set by using the corresponding getter method. - */ - @Test - void testPropertySetThenGetters() { - - InternalDataStore dataStore = createMockDataStore() - - clazzStream().forEach { clazz -> - - def resource = (AbstractResource) Classes.instantiate( - clazz.getDeclaredConstructor(InternalDataStore, Map), dataStore, null) - - setViaProperty(resource) - validateViaGetter(clazz, resource, true) - } - } - - /** - * Tests calling Resource(InternalDataStore) does NOT throw an exception and the internal properties - * results in an empty map. - */ - @Test - void testConstructorsDoNotThrowException() { - InternalDataStore dataStore = createMockDataStore() - - clazzStream().forEach { clazz -> - - // just make sure this doesn't throw an exception. - def resource = (AbstractResource) Classes.instantiate(clazz.getDeclaredConstructor(InternalDataStore), dataStore) - assertThat resource.getInternalProperties(), anEmptyMap() - } - - } - - Stream clazzStream() { - return Arrays.stream(getClasses("com.okta.sdk.impl.resource")) - .filter { clazz -> clazz.superclass != null} - .filter { clazz -> AbstractInstanceResource.isAssignableFrom(clazz)} - .filter { clazz -> !clazz.name.contains("Test")} - .filter { clazz -> !clazz.name.contains("Abstract")} - } - - void validateViaGetter(Class clazz, Resource resource, boolean withSettersOnly = true) { - - DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") - - Arrays.stream(clazz.getDeclaredMethods()) - .filter { it.name.startsWith("get") } - .filter { !withSettersOnly || setterFromGetter(clazz, it) != null } - .forEach { - def result = it.invoke(resource) - if (it.returnType == String) { - assertThat it.invoke(resource), equalToObject("value for: ${it.name}".toString()) - } - else if (it.returnType == Integer){ - assertThat it.invoke(resource), equalToObject(42) - } - else if (it.returnType == Date) { - assertThat it.invoke(resource), equalToObject(df.parse("2001-07-04T12:08:56.235-0700")) - } - else if (it.returnType == Map) { - assertThat it.invoke(resource), instanceOf(Map) - } - else if (it.returnType == List && !withSettersOnly) { // TODO: Lists are only being set via property right now - assertThat it.invoke(resource), instanceOf(List) - } - else if (it.returnType.interfaces.contains(Resource)) { - assertThat "method ${it.toString()} returned null value.", result, notNullValue() - } - else if (it.returnType.isEnum()) { - assertThat "method ${it.toString()} returned null value.", result, notNullValue() - } - } - } - - static void setViaProperty(def resource) { - resource.getPropertyDescriptors() - .forEach { key, property -> - if (property instanceof StringProperty) { - resource.setProperty(property, "value for: get${camelize(key, false)}") - } - else if (property instanceof IntegerProperty) { - resource.setProperty(property, 42) - } - else if (property instanceof DateProperty) { - resource.setProperty(property, "2001-07-04T12:08:56.235-0700") - } - else if (property instanceof MapProperty) { - resource.setProperty(property, [one: "two"]) - } - else if (property instanceof ResourceReference) { - resource.setProperty(property, [one: "two"]) - } - else if (property instanceof BooleanProperty) { - resource.setProperty(property, true) - } - else if (property instanceof EnumProperty) { - def value = property.type.getEnumConstants()[0] - resource.setProperty(property, value.name()) - } - } - resource.materialize() - } - - /////////////////////// - // Test Util methods // - /////////////////////// - - static Method setterFromGetter(Class clazz, Method method) { - try { - return clazz.getMethod(method.name.replaceFirst("get", "set"), method.returnType) - } - catch (NoSuchMethodException e) { - // ignored - } - return null - } - - static Method setterFromProperty(AbstractResource resource, Property property) { - try { - def methodName = "set${camelize(property.name, false)}" - return resource.getClass().getMethod(methodName, property.getType()) - } - catch (NoSuchMethodException e) { - // ignored - } - return null - } - - static void setViaSetter(AbstractResource resource) { - resource.getPropertyDescriptors() - .forEach { key, property -> - - def method = setterFromProperty(resource, property) - if (method != null) { - def value = null - - if (property instanceof StringProperty) { - value = "value for: get${camelize(key, false)}".toString() - } else if (property instanceof IntegerProperty) { - value = 42 - } else if (property instanceof DateProperty) { - value = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") - .parse("2001-07-04T12:08:56.235-0700") - } else if (property instanceof MapProperty) { - value = [one: "two"] - } else if (property instanceof ResourceReference) { - value = mock(property.getType()) - } else if (property instanceof BooleanProperty) { - value = true - } else if (property instanceof ListProperty) { - value = new ArrayList() - } else if (property instanceof EnumProperty) { - value = property.type.getEnumConstants()[0] - } - - try { - method.invoke(resource, value) - } catch(IllegalArgumentException e) { - fail("Illegal argument for method '${method.name}', resource class: '${resource.getClass()}', attempted value type '${value.getClass()}'", e) - } - } - - } - resource.materialize() - } - - InternalDataStore createMockDataStore() { - InternalDataStore dataStore = mock(InternalDataStore) - when(dataStore.getResource(Mockito.nullable(String), Mockito.any(Class.class))) - .then(new Answer() { - @Override - Object answer(InvocationOnMock invocation) throws Throwable { - def clazz = (Class)invocation.arguments[1] - def resource = (AbstractResource) Classes.instantiate( - clazz.getDeclaredConstructor(InternalDataStore, Map), dataStore, [three: "four"]) - return resource - - } - }) - - when(dataStore.instantiate(Mockito.any(Class.class), Mockito.any(Map))) - .then(new Answer() { - @Override - Object answer(InvocationOnMock invocation) throws Throwable { - def clazz = (Class)invocation.arguments[0] - clazz = Classes.forName("${clazz.package.name.replace("sdk.resource", "sdk.impl.resource")}.Default${clazz.simpleName}") - def resource = (AbstractResource) Classes.instantiate( - clazz.getDeclaredConstructor(InternalDataStore, Map), dataStore, [three: "four"]) - return resource - } - }) - - return dataStore - } - - /** - * Camelize name (parameter, property, method, etc) - * - * @param word string to be camelize - * @param lowercaseFirstLetter lower case for first letter if set to true - * @return camelized string - */ - static String camelize(String word, boolean lowercaseFirstLetter) { - - // special cases - if (word.toLowerCase(Locale.ENGLISH).contains("oauth")) { - // set to oAuth, 'lowercaseFirstLetter' will be resolved below - word = word.replaceAll("oauth", "oAuth") - } - - // Replace all slashes with dots (package separator) - Pattern p = Pattern.compile("\\/(.?)"); - Matcher m = p.matcher(word); - while (m.find()) { - word = m.replaceFirst("." + m.group(1)/*.toUpperCase()*/); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. - m = p.matcher(word); - } - - // case out dots - String[] parts = word.split("\\."); - StringBuilder f = new StringBuilder(); - for (String z : parts) { - if (z.length() > 0) { - f.append(Character.toUpperCase(z.charAt(0))).append(z.substring(1)); - } - } - word = f.toString(); - - m = p.matcher(word); - while (m.find()) { - word = m.replaceFirst("" + Character.toUpperCase(m.group(1).charAt(0)) + m.group(1).substring(1)/*.toUpperCase()*/); - m = p.matcher(word); - } - - // Uppercase the class name. - p = Pattern.compile('''(\\.?)(\\w)([^\\.]*)$'''); - m = p.matcher(word); - if (m.find()) { - String rep = m.group(1) + m.group(2).toUpperCase() + m.group(3); - rep = rep.replaceAll('''\\$''', '''\\\\\\$'''); - word = m.replaceAll(rep); - } - - // Remove all underscores - p = Pattern.compile("(_)(.)"); - m = p.matcher(word); - while (m.find()) { - word = m.replaceFirst(m.group(2).toUpperCase()); - m = p.matcher(word); - } - - if (lowercaseFirstLetter && word.length() > 0) { - word = word.substring(0, 1).toLowerCase() + word.substring(1); - } - - word = word.replace('#', '') - word = word.replace('$', '') - - return word; - } - - - /** - * Scans all classes accessible from the context class loader which belong to the given package and subpackages. - * - * @param packageName The base package - * @return The classes - * @throws ClassNotFoundException - * @throws IOException - */ - private static Class[] getClasses(String packageName) - throws ClassNotFoundException, IOException { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader() - assert classLoader != null - String path = packageName.replace('.', '/') - Enumeration resources = classLoader.getResources(path) - List dirs = new ArrayList() - while (resources.hasMoreElements()) { - URL resource = resources.nextElement() - dirs.add(new File(resource.getFile())) - } - ArrayList classes = new ArrayList() - for (File directory : dirs) { - classes.addAll(findClasses(directory, packageName)); - } - return classes.toArray(new Class[classes.size()]) - } - -/** - * Recursive method used to find all classes in a given directory and subdirs. - * - * @param directory The base directory - * @param packageName The package name for classes found inside the base directory - * @return The classes - * @throws ClassNotFoundException - */ - private static List findClasses(File directory, String packageName) throws ClassNotFoundException { - List classes = new ArrayList() - if (!directory.exists()) { - return classes - } - File[] files = directory.listFiles() - for (File file : files) { - if (file.isDirectory()) { - Assert.isTrue(!file.getName().contains("."), "Expected directory containing '.' in path") - classes.addAll(findClasses(file, packageName + "." + file.getName())) - } else if (file.getName().endsWith(".class")) { - classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6))) - } - } - return classes; - } - -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/HalResourceHrefResolverTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/HalResourceHrefResolverTest.groovy deleted file mode 100644 index 6d5a9d667f3..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/HalResourceHrefResolverTest.groovy +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2018 Okta, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.resource.user.User -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.nullValue - -class HalResourceHrefResolverTest { - - @Test - void missingHrefReturnsNullTest() { - - ResourceHrefResolver resolver = new HalResourceHrefResolver() - - Map nullHrefProps = [ - _links: [ - self: [ - href: null - ]]] - - Map missingHrefProps = [ - _links: [ - self: [ - foo: "bar" - ]]] - - assertThat resolver.resolveHref(Collections.emptyMap(), User), nullValue() - assertThat resolver.resolveHref(nullHrefProps, User), nullValue() - assertThat resolver.resolveHref(missingHrefProps, User), nullValue() - } - - @Test - void resourceWithSelfLinkTest() { - - String selfHref = "https://okta-test.example.com/my/href" - Map props = [ - _links: [ - self: [ - href: selfHref - ]]] - - ResourceHrefResolver resolver = new HalResourceHrefResolver() - assertThat resolver.resolveHref(props, User), equalTo(selfHref) - assertThat resolver.resolveHref(props, null), equalTo(selfHref) // clazz doesn't matter when self link is set - } - - @Test - void resourceWithMultipleLinksTest() { - - String selfHref = "https://okta-test.example.com/my/href" - Map props = [ - _links: [ - other: [ - bar: "foo" - ], - self: [ - href: selfHref, - foo: "bar" - ]]] - - ResourceHrefResolver resolver = new HalResourceHrefResolver() - assertThat resolver.resolveHref(props, User), equalTo(selfHref) - assertThat resolver.resolveHref(props, null), equalTo(selfHref) // clazz doesn't matter when self link is set - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/ListPropertyTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/ListPropertyTest.groovy deleted file mode 100644 index 7b439cedbf7..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/ListPropertyTest.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* -* Copyright 2015 Okta, Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package com.okta.sdk.impl.resource - -import org.testng.annotations.Test - -import static org.testng.Assert.assertEquals -import static org.testng.Assert.assertSame - -/** - * Test for ListProperty class - * - * @since 0.5.0 - */ -class ListPropertyTest { - - @Test - void testDefault() { - def prop = new ListProperty("test") - assertSame prop.type, List.class - assertEquals prop.name, "test" - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/OktaResourceHrefResolverTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/OktaResourceHrefResolverTest.groovy deleted file mode 100644 index 51a58090670..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/OktaResourceHrefResolverTest.groovy +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2018 Okta, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.sdk.resource.application.AppUser -import com.okta.sdk.resource.application.Application -import com.okta.sdk.resource.group.Group -import com.okta.sdk.resource.group.rule.GroupRule -import com.okta.sdk.resource.user.User -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.nullValue - -class OktaResourceHrefResolverTest { - - final static String BASE_URL = "https://okta.example.com" - - @Test - void missingHrefReturnsNullTest() { - - ResourceHrefResolver resolver = new OktaResourceHrefResolver() - - Map nullHrefProps = [ - _links: [ - self: [ - href: null - ]]] - - Map missingHrefProps = [ - _links: [ - self: [ - foo: "bar" - ]]] - - assertThat resolver.resolveHref(Collections.emptyMap(), User), nullValue() - assertThat resolver.resolveHref(nullHrefProps, User), nullValue() - assertThat resolver.resolveHref(missingHrefProps, User), nullValue() - } - - @Test - void resourceWithSelfLinkTest() { - - String selfHref = "https://okta-test.example.com/my/href" - Map props = [ - _links: [ - self: [ - href: selfHref - ]]] - - ResourceHrefResolver resolver = new OktaResourceHrefResolver() - assertThat resolver.resolveHref(props, User), equalTo(selfHref) - assertThat resolver.resolveHref(props, null), equalTo(selfHref) // clazz doesn't matter when self link is set - } - - @Test - void appUserHrefTest() { - - Map props = [ - id: "this-user-id", - _links: [ - app: [ - href: "https://okta-test.example.com/api/v1/apps/an-app-id" - ], - user: [ - href: "https://okta-test.example.com/api/v1/users/a-user-id" - ], - group: [ - name: "Everyone", - href: "https://okta-test.example.com/api/v1/groups/everyone-id" - ] - ] - ] - - ResourceHrefResolver resolver = new OktaResourceHrefResolver() - assertThat resolver.resolveHref(props, AppUser), equalTo("https://okta-test.example.com/api/v1/apps/an-app-id/users/this-user-id") - assertThat resolver.resolveHref(props, User), nullValue() // wrong class, so this should return null - } - - @Test - void applicationHrefTest() { - - String appId = "this-app-id" - Map props = [ - id: appId, - _links: [ - appLinks: [ - [ - name: "oidc_client_link", - href: "https://okta-test.example.com/home/oidc_client/${appId}/aln5z7uhkbM6y7bMy0g7", - type: "text/html" - ] - ], - groups: [ - href: "https://okta-test.example.com/api/v1/apps/${appId}/groups" - ], - logo: [ - [ - name: "medium", - href: "https://op1static.oktacdn.com/assets/img/logos/default.some-image.png", - type: "image/png" - ] - ], - users: [ - href: "https://okta-test.example.com/api/v1/apps/${appId}/users" - ], - deactivate: [ - href: "https://okta-test.example.com/api/v1/apps/${appId}/lifecycle/deactivate" - ] - ] - ] - - ResourceHrefResolver resolver = new OktaResourceHrefResolver() - assertThat resolver.resolveHref(props, Application), equalTo("https://okta-test.example.com/api/v1/apps/this-app-id") - assertThat resolver.resolveHref(props, User), nullValue() // wrong class, so this should return null - } - - @Test - void groupHrefTest() { - - String groupId = "this-group-id" - Map props = [ - id: groupId, - _links: [ - logo: [ - [ - name: "medium", - href: "https://op1static.oktacdn.com/assets/img/logos/groups/okta-medium.some-image.png", - type: "image/png" - ], - [ - name: "large", - href: "https://op1static.oktacdn.com/assets/img/logos/groups/okta-large.some-image.png", - type: "image/png" - ] - ], - users: [ - href: "https://okta-test.example.com/api/v1/groups/${groupId}/users" - ], - apps: [ - href: "https://okta-test.example.com/api/v1/groups/${groupId}/apps" - ] - ] - ] - - ResourceHrefResolver resolver = new OktaResourceHrefResolver() - assertThat resolver.resolveHref(props, Group), equalTo("/api/v1/groups/this-group-id".toString()) - assertThat resolver.resolveHref(props, User), nullValue() // wrong class, so this should return null - } - - @Test - void groupRuleHrefTest() { - - String groupRuleId = "this-group-rule-id" - Map props = [ - id: groupRuleId - ] - - ResourceHrefResolver resolver = new OktaResourceHrefResolver() - assertThat resolver.resolveHref(props, GroupRule), equalTo("/api/v1/groups/rules/this-group-rule-id".toString()) - assertThat resolver.resolveHref(props, User), nullValue() // wrong class, so this should return null - } - -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/ProvisioningConnectionTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/ProvisioningConnectionTest.groovy deleted file mode 100644 index e533cb0ed19..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/ProvisioningConnectionTest.groovy +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2022-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import com.okta.commons.http.HttpHeaders -import com.okta.commons.http.HttpMethod -import com.okta.commons.http.MediaType -import com.okta.commons.http.Request -import com.okta.commons.http.RequestExecutor -import com.okta.commons.http.Response -import com.okta.sdk.impl.api.ClientCredentialsResolver -import com.okta.sdk.impl.ds.DefaultDataStore -import com.okta.sdk.impl.resource.application.DefaultApplication -import com.okta.sdk.impl.resource.application.DefaultProvisioningConnection -import com.okta.sdk.impl.resource.application.DefaultProvisioningConnectionProfile -import com.okta.sdk.impl.resource.application.DefaultProvisioningConnectionRequest -import com.okta.sdk.impl.util.StringInputStream -import com.okta.sdk.resource.application.ProvisioningConnection -import com.okta.sdk.resource.application.ProvisioningConnectionAuthScheme -import com.okta.sdk.resource.application.ProvisioningConnectionProfile -import com.okta.sdk.resource.application.ProvisioningConnectionStatus -import org.mockito.ArgumentCaptor -import org.testng.annotations.Test - -import java.util.stream.Collectors - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.is -import static org.hamcrest.Matchers.notNullValue -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.when - -/** - * Unit tests of - * @see ProvisioningConnection - * @see ProvisioningConnectionProfile - */ -class ProvisioningConnectionTest { - - @Test - void testGetDefaultProvisioningConnectionForApplication() { - def requestCapture = ArgumentCaptor.forClass(Request) - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com", apiKeyResolver) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - when(response.getBody()).thenReturn(new StringInputStream('{"authScheme": "UNKNOWN","status": "UNKNOWN"}')) - when(response.getHeaders()).thenReturn(headers) - - def application = new DefaultApplication(defaultDataStore) - application.put("id", "app-id") - - def provisioningConnection = new DefaultProvisioningConnection(defaultDataStore) - .getDefaultProvisioningConnectionForApplication(application.getId()) - - def request = requestCapture.getValue() - assertThat request.getMethod(), is(HttpMethod.GET) - assertThat request.getResourceUrl().getPath(), is("/api/v1/apps/app-id/connections/default") - assertThat provisioningConnection, notNullValue() - assertThat provisioningConnection.getAuthScheme(), is(ProvisioningConnectionAuthScheme.UNKNOWN) - assertThat provisioningConnection.getStatus(), is(ProvisioningConnectionStatus.UNKNOWN) - } - - @Test - void testSetDefaultProvisioningConnectionForApplication() { - def requestCapture = ArgumentCaptor.forClass(Request) - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com", apiKeyResolver) - def headers = new HttpHeaders() - headers.setContentType(MediaType.APPLICATION_JSON) - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(true) - when(response.getBody()).thenReturn(new StringInputStream('{"authScheme": "TOKEN","status": "ENABLED"}')) - when(response.getHeaders()).thenReturn(headers) - - def application = new DefaultApplication(defaultDataStore) - application.put("id", "app-id") - def profile = new DefaultProvisioningConnectionProfile(defaultDataStore) - .setAuthScheme(ProvisioningConnectionAuthScheme.TOKEN) - .setToken("foo") - def provisioningRequest = new DefaultProvisioningConnectionRequest(defaultDataStore).setProfile(profile) - - def provisioningConnection = profile - .setDefaultProvisioningConnectionForApplication(application.getId(), provisioningRequest, true) - - def request = requestCapture.getValue() - def requestBody = new BufferedReader(new InputStreamReader(request.getBody())).lines().collect(Collectors.joining()) - assertThat request.getMethod(), is(HttpMethod.POST) - assertThat request.getResourceUrl().getPath(), is("/api/v1/apps/app-id/connections/default") - assertThat requestBody, is('{"profile":{"authScheme":"TOKEN","token":"foo"}}') - assertThat provisioningConnection, notNullValue() - assertThat provisioningConnection.getAuthScheme(), is(ProvisioningConnectionAuthScheme.TOKEN) - assertThat provisioningConnection.getStatus(), is(ProvisioningConnectionStatus.ENABLED) - } - - - @Test - void testActivateDefaultProvisioningConnectionForApplication() { - def requestCapture = ArgumentCaptor.forClass(Request) - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com", apiKeyResolver) - def headers = new HttpHeaders() - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(false) - when(response.getHeaders()).thenReturn(headers) - when(response.getHttpStatus()).thenReturn(HttpURLConnection.HTTP_NO_CONTENT) - - def application = new DefaultApplication(defaultDataStore) - application.put("id", "app-id") - - new DefaultProvisioningConnection(defaultDataStore).activateDefaultProvisioningConnectionForApplication(application.getId()) - - assertThat requestCapture.getValue().getResourceUrl().getPath(), is("/api/v1/apps/app-id/connections/default/lifecycle/activate") - } - - @Test - void testDeactivateDefaultProvisioningConnectionForApplication() { - def requestCapture = ArgumentCaptor.forClass(Request) - def requestExecutor = mock(RequestExecutor) - def apiKeyResolver = mock(ClientCredentialsResolver) - def response = mock(Response) - def defaultDataStore = new DefaultDataStore(requestExecutor, "https://api.okta.com", apiKeyResolver) - def headers = new HttpHeaders() - - when(requestExecutor.executeRequest(requestCapture.capture())).thenReturn(response) - when(response.hasBody()).thenReturn(false) - when(response.getHeaders()).thenReturn(headers) - when(response.getHttpStatus()).thenReturn(HttpURLConnection.HTTP_NO_CONTENT) - - def application = new DefaultApplication(defaultDataStore) - application.put("id", "app-id") - - new DefaultProvisioningConnection(defaultDataStore).deactivateDefaultProvisioningConnectionForApplication(application.getId()) - - assertThat requestCapture.getValue().getResourceUrl().getPath(), is("/api/v1/apps/app-id/connections/default/lifecycle/deactivate") - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/StringPropertyTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/StringPropertyTest.groovy deleted file mode 100644 index 2d4f5c49d75..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/StringPropertyTest.groovy +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource - -import org.testng.annotations.Test - -import static org.testng.Assert.assertEquals -import static org.testng.Assert.assertSame - -/** - * - * @since 0.5.0 - */ -class StringPropertyTest { - - @Test - void testDefault() { - def prop = new StringProperty('foo') - assertSame prop.type, String.class - assertEquals prop.name, 'foo' - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/log/LogsTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/log/LogsTest.groovy deleted file mode 100644 index 48121b3008d..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/log/LogsTest.groovy +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.log - -import com.okta.sdk.impl.client.MockClient -import com.okta.commons.http.Request -import com.okta.sdk.resource.log.LogActor -import com.okta.sdk.resource.log.LogAuthenticationContext -import com.okta.sdk.resource.log.LogClient -import com.okta.sdk.resource.log.LogDebugContext -import com.okta.sdk.resource.log.LogEvent -import com.okta.sdk.resource.log.LogGeographicalContext -import com.okta.sdk.resource.log.LogGeolocation -import com.okta.sdk.resource.log.LogIpAddress -import com.okta.sdk.resource.log.LogOutcome -import com.okta.sdk.resource.log.LogRequest -import com.okta.sdk.resource.log.LogSecurityContext -import com.okta.sdk.resource.log.LogSeverity -import com.okta.sdk.resource.log.LogTransaction -import com.okta.sdk.resource.log.LogUserAgent -import org.mockito.ArgumentCaptor -import org.mockito.Mockito -import static org.mockito.Mockito.verify - -import org.testng.annotations.BeforeMethod -import org.testng.annotations.Test - -import java.time.Instant -import java.time.format.DateTimeFormatter -import java.util.stream.Collectors - -import static org.hamcrest.Matchers.* -import static org.hamcrest.MatcherAssert.* - -class LogsTest { - MockClient client - - @BeforeMethod - void setup() { - // mock the response objects in the client - client = new MockClient() - .withMockResponse(Mockito.any(Request), '/stubs/logs.json') - } - - @Test - void testGetLogs() { - - // get the list of logs - List logs = client.getLogs().stream().collect(Collectors.toList()) - assertThat logs, hasSize(100) - logs.forEach { assertThat it, instanceOf(LogEvent) } - - // grab the first Log item and validate it - LogEvent log = logs.get(0) - - Date expectedDate = Date.from(Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse("2017-11-30T21:15:16.838Z"))) - - assertThat log.getActor(), instanceOf(LogActor) - assertThat log.getActor().id, equalTo("0000222244448888000") - assertThat log.getActor().type, equalTo("User") - assertThat log.getActor().alternateId, equalTo("joe.coder@example.com") - assertThat log.getActor().displayName, equalTo("Joe Coder") - assertThat log.getActor().detail, nullValue() - assertThat log.getActor().type, equalTo("User") - assertThat log.getActor().type, equalTo("User") - - assertThat log.getClient(), instanceOf(LogClient) - assertThat log.getClient().getUserAgent(), instanceOf(LogUserAgent) - assertThat log.getClient().getUserAgent().rawUserAgent, equalTo("okta-sdk-java/0.9.0-SNAPSHOT okta-sdk-java/0.9.0-SNAPSHOT jetty/9.2.22.v20170606 java/1.8.0_121 Mac OS X/10.13.1") - assertThat log.getClient().getUserAgent().os, equalTo( "Mac OS X") - assertThat log.getClient().getUserAgent().browser, equalTo( "UNKNOWN") - - assertThat log.getClient().zone, equalTo("null") - assertThat log.getClient().device, equalTo("Computer") - assertThat log.getClient().id, nullValue() - assertThat log.getClient().ipAddress, equalTo("66.222.111.88") - assertThat log.getClient().getGeographicalContext(), instanceOf(LogGeographicalContext) - assertThat log.getClient().getGeographicalContext().city, equalTo("Concord") - assertThat log.getClient().getGeographicalContext().state, equalTo("New Hampshire") - assertThat log.getClient().getGeographicalContext().country, equalTo("United States") - assertThat log.getClient().getGeographicalContext().postalCode, equalTo("03303") - assertThat log.getClient().getGeographicalContext().getGeolocation(), instanceOf(LogGeolocation) - assertThat log.getClient().getGeographicalContext().getGeolocation().lat, equalTo(43.3091d) - assertThat log.getClient().getGeographicalContext().getGeolocation().lon, equalTo(-71.6861d) - - assertThat log.getAuthenticationContext(), instanceOf(LogAuthenticationContext) - assertThat log.getAuthenticationContext().authenticationProvider, nullValue() - assertThat log.getAuthenticationContext().credentialProvider, nullValue() - assertThat log.getAuthenticationContext().credentialType, nullValue() - assertThat log.getAuthenticationContext().issuer, nullValue() - assertThat log.getAuthenticationContext().interface, nullValue() -// assertThat log.getAuthenticationContext().authenticationStep, equalTo(0) - assertThat log.getAuthenticationContext().externalSessionId, equalTo("trs-T02AyaeRDKxyrAUXkV-yg") - - assertThat log.displayMessage, equalTo("Deactivate Okta User") - assertThat log.eventType, equalTo("user.lifecycle.deactivate") - assertThat log.getPublished(), equalTo(expectedDate) - assertThat log.getSeverity(), equalTo(LogSeverity.INFO) - assertThat log.uuid, equalTo("0626e18a-3d17-40fb-a1f3-094be1f39208") - assertThat log.version, equalTo("0") - assertThat log.legacyEventType, equalTo("core.user.config.user_deactivated") - - assertThat log.getOutcome(), instanceOf(LogOutcome) - assertThat log.getOutcome().result, equalTo("SUCCESS") - assertThat log.getOutcome().reason, nullValue() - - assertThat log.getSecurityContext(), instanceOf(LogSecurityContext) - assertThat log.getSecurityContext().asNumber, nullValue() - assertThat log.getSecurityContext().asOrg, nullValue() - assertThat log.getSecurityContext().isp, nullValue() - assertThat log.getSecurityContext().domain, nullValue() - assertThat log.getSecurityContext().getIsProxy(), equalTo(false) - - assertThat log.getDebugContext(), instanceOf(LogDebugContext) - assertThat log.getDebugContext().getDebugData().get("requestUri"), equalTo("/api/v1/users/00ud384zryL1GFAg30h7/lifecycle/deactivate") - - assertThat log.getTransaction(), instanceOf(LogTransaction) - assertThat log.getTransaction().type, equalTo("WEB") - assertThat log.getTransaction().id, equalTo("WiB04-V4MgacZHWciQq8YwAADpA") - assertThat log.getTransaction().detail, anEmptyMap() - - assertThat log.getTarget(), hasSize(1) - assertThat log.getTarget().get(0).id, equalTo("00ud384zryL1GFAg30h7") - assertThat log.getTarget().get(0).type, equalTo("User") - assertThat log.getTarget().get(0).alternateId, equalTo("john-with-group@example.com") - assertThat log.getTarget().get(0).displayName, equalTo("John With-Group") - assertThat log.getTarget().get(0).detailEntry, nullValue() - - assertThat log.getRequest(), instanceOf(LogRequest) - assertThat log.getRequest().getIpChain().get(0), instanceOf(LogIpAddress) - assertThat log.getRequest().getIpChain().get(0).ip, equalTo("66.222.111.88") - assertThat log.getRequest().getIpChain().get(0).version, equalTo("V4") - assertThat log.getRequest().getIpChain().get(0).source, nullValue() - assertThat log.getRequest().getIpChain().get(0).getGeographicalContext(), instanceOf(LogGeographicalContext) - assertThat log.getRequest().getIpChain().get(0).getGeographicalContext().city, equalTo("Concord") - assertThat log.getRequest().getIpChain().get(0).getGeographicalContext().state, equalTo("New Hampshire") - assertThat log.getRequest().getIpChain().get(0).getGeographicalContext().country, equalTo("United States") - assertThat log.getRequest().getIpChain().get(0).getGeographicalContext().postalCode, equalTo("03303") - assertThat log.getRequest().getIpChain().get(0).getGeographicalContext().getGeolocation(), instanceOf(LogGeolocation) - assertThat log.getRequest().getIpChain().get(0).getGeographicalContext().getGeolocation().lat, equalTo(43.3091d) - assertThat log.getRequest().getIpChain().get(0).getGeographicalContext().getGeolocation().lon, equalTo(-71.6861d) - } - - @Test - void testGetLogsBetweenDates() { - - Date sinceDate = Date.from(Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse("2017-11-30T21:15:16.838Z"))) - Date untilDate = Date.from(Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse("2017-11-30T21:16:00.081Z"))) - - // get log events between dates - List logs = client.getLogs(sinceDate, untilDate, null, null, null).stream().collect(Collectors.toList()) - logs.forEach { assertThat it, instanceOf(LogEvent) } - - ArgumentCaptor argument = ArgumentCaptor.forClass(Request.class) - verify(client.mockRequestExecutor).executeRequest(argument.capture()) - assertThat argument.getValue().queryString.since, equalTo("2017-11-30T21:15:16.838Z") - assertThat argument.getValue().queryString.until, equalTo("2017-11-30T21:16:00.081Z") - } - - @Test - void testGetLogsSinceDate() { - - Date sinceDate = Date.from(Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse("2017-11-30T21:15:16.838Z"))) - - // get log events since given date - List logs = client.getLogs(sinceDate, null, null, null, null).stream().collect(Collectors.toList()) - assertThat logs, hasSize(100) - logs.forEach { assertThat it, instanceOf(LogEvent) } - - ArgumentCaptor argument = ArgumentCaptor.forClass(Request.class) - verify(client.mockRequestExecutor).executeRequest(argument.capture()) - assertThat argument.getValue().queryString.since, equalTo("2017-11-30T21:15:16.838Z") - } - - @Test - void testGetLogsUntilDate() { - - Date untilDate = Date.from(Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse("2017-11-30T21:16:00.081Z"))) - - // get log events until given date - List logs = client.getLogs(null, untilDate, null, null, null).stream().collect(Collectors.toList()) - assertThat logs, hasSize(100) - logs.forEach { assertThat it, instanceOf(LogEvent) } - - ArgumentCaptor argument = ArgumentCaptor.forClass(Request.class) - verify(client.mockRequestExecutor).executeRequest(argument.capture()) - assertThat argument.getValue().queryString.until, equalTo("2017-11-30T21:16:00.081Z") - } -} diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/session/FeaturesTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/session/FeaturesTest.groovy deleted file mode 100644 index 212fdce90e4..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/session/FeaturesTest.groovy +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.session - -import com.okta.sdk.impl.ds.InternalDataStore -import com.okta.sdk.impl.resource.feature.DefaultFeature -import com.okta.sdk.resource.feature.Feature -import org.testng.annotations.Test - -import static org.mockito.ArgumentMatchers.any -import static org.mockito.ArgumentMatchers.eq -import static org.mockito.Mockito.mock -import static org.mockito.Mockito.verify - -/** - * Tests for the Features API. - * - * @since 2.0.0 - */ -class FeaturesTest { - - @Test - void toggleFeatureTest() { - - InternalDataStore dataStore = mock(InternalDataStore) - - Feature featureToEnable = new DefaultFeature(dataStore, [id: "test_feature_id", name: "test feature", status: "DISABLED"]) - - // enable - featureToEnable.updateLifecycle("enable", "force") - - verify(dataStore).create( - (String) eq("/api/v1/features/test_feature_id/enable".toString()), - any(), - any(), - (Class) eq(Feature.class), - eq(Collections.singletonMap("mode", "force")), - eq(Collections.emptyMap())) - - Feature featureToDisable = new DefaultFeature(dataStore, [id: "test_feature_id", name: "test feature", status: "ENABLED"]) - - // disable - featureToDisable.updateLifecycle("disable", "force") - - verify(dataStore).create( - (String) eq("/api/v1/features/test_feature_id/disable".toString()), - any(), - any(), - (Class) eq(Feature.class), - eq(Collections.singletonMap("mode", "force")), - eq(Collections.emptyMap())) - } -} \ No newline at end of file diff --git a/impl/src/test/groovy/com/okta/sdk/impl/resource/session/SessionsTest.groovy b/impl/src/test/groovy/com/okta/sdk/impl/resource/session/SessionsTest.groovy deleted file mode 100644 index ca2fd6107cc..00000000000 --- a/impl/src/test/groovy/com/okta/sdk/impl/resource/session/SessionsTest.groovy +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource.session - -import com.okta.sdk.authc.credentials.TokenClientCredentials -import com.okta.sdk.cache.CacheManager -import com.okta.sdk.client.AuthenticationScheme -import com.okta.sdk.client.Client -import com.okta.sdk.impl.api.ClientCredentialsResolver -import com.okta.sdk.impl.api.DefaultClientCredentialsResolver -import com.okta.sdk.impl.cache.DisabledCacheManager -import com.okta.sdk.impl.client.DefaultClient -import com.okta.sdk.impl.config.ClientConfiguration -import com.okta.sdk.impl.ds.InternalDataStore -import com.okta.sdk.impl.ds.JacksonMapMarshaller -import com.okta.commons.http.RequestExecutor -import com.okta.sdk.impl.resource.user.DefaultUser -import com.okta.commons.http.config.BaseUrlResolver -import com.okta.sdk.impl.util.DefaultBaseUrlResolver -import com.okta.sdk.resource.Resource -import com.okta.sdk.resource.session.Session -import com.okta.sdk.resource.session.SessionAuthenticationMethod -import com.okta.sdk.resource.session.SessionIdentityProvider -import com.okta.sdk.resource.session.SessionIdentityProviderType -import com.okta.sdk.resource.session.SessionStatus -import org.testng.annotations.Test - -import java.time.Instant -import java.time.format.DateTimeFormatter - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -import static org.mockito.Mockito.* - -/** - * Tests for the Sessions API. - * - * @since 0.10.0 - */ -class SessionsTest { - - private static String MOCK_SESSION_ID = "101W_juydrDRByB7fUdRyE2JQ" - - @Test - void simpleCreateSessionTest() { - - ClientConfiguration clientConfig = new ClientConfiguration() - clientConfig.setBaseUrlResolver(new DefaultBaseUrlResolver("https://example.com")) - clientConfig.setAuthenticationScheme(AuthenticationScheme.SSWS) - clientConfig.setClientCredentialsResolver(new DefaultClientCredentialsResolver(new TokenClientCredentials("foobar"))) - - Client client = new DefaultClient(clientConfig, new DisabledCacheManager()) { - protected InternalDataStore createDataStore(RequestExecutor requestExecutor, - BaseUrlResolver baseUrlResolver, - ClientCredentialsResolver clientCredentialsResolver, - CacheManager cacheManager) { - - Map data = dataFromJsonFile() - final InternalDataStore dataStore = mock(InternalDataStore) - DefaultSession session = new DefaultSession(dataStore, dataFromJsonFile()) - Map idpData = data.get("idp") - def sessionIdp = new DefaultSessionIdentityProvider(dataStore, idpData) - when(dataStore.instantiate(SessionIdentityProvider, idpData)).thenReturn(sessionIdp) - when(dataStore.create( - (String) eq("/api/v1/sessions"), - any(), - isNull(), - (Class) eq(Session.class), - eq(Collections.emptyMap()), - eq(Collections.emptyMap()))) - .thenReturn(session) - return dataStore - } - } - - Session createdSession = client.createSession(new DefaultCreateSessionRequest(null, null) - .setSessionToken(MOCK_SESSION_ID)) - assertSession(createdSession) - - createdSession.delete() - verify(client.dataStore).delete("/api/v1/sessions/${MOCK_SESSION_ID}", (Resource) createdSession, Collections.emptyMap(), Collections.emptyMap()) - } - - @Test - void simpleGetSessionTest() { - - ClientConfiguration clientConfig = new ClientConfiguration() - clientConfig.setBaseUrlResolver(new DefaultBaseUrlResolver("https://example.com")) - clientConfig.setAuthenticationScheme(AuthenticationScheme.SSWS) - clientConfig.setClientCredentialsResolver(new DefaultClientCredentialsResolver(new TokenClientCredentials("foobar"))) - - Client client = new DefaultClient(clientConfig, new DisabledCacheManager()) { - protected InternalDataStore createDataStore(RequestExecutor requestExecutor, - BaseUrlResolver baseUrlResolver, - ClientCredentialsResolver clientCredentialsResolver, - CacheManager cacheManager) { - - Map data = dataFromJsonFile() - final InternalDataStore dataStore = mock(InternalDataStore) - DefaultSession session = new DefaultSession(dataStore, data) - Map idpData = data.get("idp") - def sessionIdp = new DefaultSessionIdentityProvider(dataStore, idpData) - when(dataStore.instantiate(SessionIdentityProvider, idpData)).thenReturn(sessionIdp) - when(dataStore.getResource("/api/v1/sessions/${MOCK_SESSION_ID}", Session, Collections.emptyMap(), Collections.emptyMap())).thenReturn(session) - when(dataStore.create( - (String) eq("/api/v1/sessions/${MOCK_SESSION_ID}/lifecycle/refresh".toString()), - any(), - eq(session), - (Class) eq(Session.class), - eq(Collections.emptyMap()), - eq(Collections.emptyMap()))) - .thenReturn(session) - return dataStore - } - } - - Session session = client.getSession(MOCK_SESSION_ID) - assertSession(session) - - assertThat session.refresh(), notNullValue() - verify(client.dataStore) - .create( - (String) eq("/api/v1/sessions/${MOCK_SESSION_ID}/lifecycle/refresh".toString()), - any(), - eq(session), - (Class) eq(Session.class), - eq(Collections.emptyMap()), - eq(Collections.emptyMap())) - } - - @Test - void deleteUserSessions() { - - InternalDataStore dataStore = mock(InternalDataStore) - - new DefaultUser(dataStore, [id: "test_user_id"]).clearSessions() - verify(dataStore).delete("/api/v1/users/test_user_id/sessions", Collections.emptyMap(), Collections.emptyMap()) - } - - void assertSession(Session session) { - - assertThat session.getId(), equalTo(MOCK_SESSION_ID) - assertThat session.getLogin(), equalTo("joe.coder@example.com") - assertThat session.getUserId(), equalTo("00ubgaSARVOQDIOXMORI") - assertThat session.getCreatedAt(), equalTo(parseDate("2015-08-30T18:41:35.818Z")) - assertThat session.getExpiresAt(), equalTo(parseDate("2015-08-30T18:41:35.818Z")) - assertThat session.getStatus(), equalTo(SessionStatus.ACTIVE) - assertThat session.getLastPasswordVerification(), equalTo(parseDate("2015-08-30T18:41:35.818Z")) - assertThat session.getLastFactorVerification(), equalTo(parseDate("2015-08-30T18:41:35.818Z")) - assertThat session.getAmr(), equalTo([ - SessionAuthenticationMethod.PWD, - SessionAuthenticationMethod.OTP, - SessionAuthenticationMethod.MFA - ]) - assertThat session.getIdp(), notNullValue() - assertThat session.getIdp().getId(), equalTo("00oi5cpnylv792IcF0g3") - assertThat session.getIdp().getType(), equalTo(SessionIdentityProviderType.OKTA) - } - - private Date parseDate(String dateString) { - DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME - return Date.from(Instant.from(timeFormatter.parse(dateString))) - } - - private Map dataFromJsonFile(String resourceFile = '/stubs/sessions.json') { - - return new JacksonMapMarshaller().unmarshal( - this.getClass().getResource(resourceFile).openStream(), - Collections.emptyMap()) - } -} \ No newline at end of file diff --git a/impl/src/test/java/com/okta/sdk/impl/resource/NestedStubResource.java b/impl/src/test/java/com/okta/sdk/impl/resource/NestedStubResource.java deleted file mode 100644 index 03b7ef0c5c6..00000000000 --- a/impl/src/test/java/com/okta/sdk/impl/resource/NestedStubResource.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; - -import java.util.Map; - -public class NestedStubResource extends AbstractResource { - - public final StringProperty stringProp = new StringProperty("nestedStringPropKey"); - private final Map propertyDescriptors = AbstractResource.createPropertyDescriptorMap(stringProp); - - protected NestedStubResource(InternalDataStore dataStore) { - super(dataStore); - } - - protected NestedStubResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - public String getStringProp() { - return getString(stringProp); - } - - @Override - public Map getPropertyDescriptors() { - return propertyDescriptors; - } -} \ No newline at end of file diff --git a/impl/src/test/java/com/okta/sdk/impl/resource/StubEnum.java b/impl/src/test/java/com/okta/sdk/impl/resource/StubEnum.java deleted file mode 100644 index 5b906a867a2..00000000000 --- a/impl/src/test/java/com/okta/sdk/impl/resource/StubEnum.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -public enum StubEnum { - VALUE_1, VALUE_2, VALUE_3 -} diff --git a/impl/src/test/java/com/okta/sdk/impl/resource/StubResource.java b/impl/src/test/java/com/okta/sdk/impl/resource/StubResource.java deleted file mode 100644 index 03043029874..00000000000 --- a/impl/src/test/java/com/okta/sdk/impl/resource/StubResource.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; - -import java.util.Map; - -public class StubResource extends AbstractResource { - - public final BooleanProperty booleanProp = new BooleanProperty("booleanPropKey"); - public final DateProperty dateProp = new DateProperty("datePropKey"); - public final EnumListProperty enumListProp = new EnumListProperty<>("enumListPropKey", StubEnum.class); - public final EnumProperty enumProp = new EnumProperty<>("enumPropKey", StubEnum.class); - public final IntegerProperty integerProp = new IntegerProperty("intPropKey"); - public final DoubleProperty doubleProp = new DoubleProperty("doublePropKey"); - public final ListProperty listProp = new ListProperty("listPropKey"); - public final MapProperty mapProp = new MapProperty("mapPropKey"); - public final ResourceListProperty resourceListProp = new ResourceListProperty<>("resourceListPropKey", NestedStubResource.class); - public final StringProperty stringProp = new StringProperty("stringPropKey"); - public final CharacterArrayProperty charArrayProp1 = new CharacterArrayProperty("charArrayPropKey1"); - public final CharacterArrayProperty charArrayProp2 = new CharacterArrayProperty("charArrayPropKey2"); - - private final Map propertyDescriptors = AbstractResource.createPropertyDescriptorMap(booleanProp, dateProp, enumListProp, enumProp, integerProp, doubleProp, listProp, mapProp, resourceListProp, stringProp, charArrayProp1, charArrayProp2); - - protected StubResource(InternalDataStore dataStore) { - super(dataStore); - } - - protected StubResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - @Override - public Map getPropertyDescriptors() { - return propertyDescriptors; - } -} diff --git a/impl/src/test/java/com/okta/sdk/impl/resource/TestCollectionResource.java b/impl/src/test/java/com/okta/sdk/impl/resource/TestCollectionResource.java deleted file mode 100644 index 179492c6fcc..00000000000 --- a/impl/src/test/java/com/okta/sdk/impl/resource/TestCollectionResource.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.resource.user.User; - -import java.util.Map; - -public class TestCollectionResource extends AbstractCollectionResource { - - private static final ArrayProperty ITEMS = new ArrayProperty<>("items", User.class); - private static final Map PROPERTY_DESCRIPTORS = createPropertyDescriptorMap(ITEMS); - - protected TestCollectionResource(InternalDataStore dataStore) { - super(dataStore); - } - - protected TestCollectionResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - protected TestCollectionResource(InternalDataStore dataStore, Map properties, Map queryParams) { - super(dataStore, properties, queryParams); - } - - @Override - public Map getPropertyDescriptors() { - return PROPERTY_DESCRIPTORS; - } - - @Override - protected Class getItemType() { - return TestResource.class; - } -} diff --git a/impl/src/test/java/com/okta/sdk/impl/resource/TestResource.java b/impl/src/test/java/com/okta/sdk/impl/resource/TestResource.java deleted file mode 100644 index 7af924cd660..00000000000 --- a/impl/src/test/java/com/okta/sdk/impl/resource/TestResource.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2014 Stormpath, Inc. - * Modifications Copyright 2018 Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.impl.resource; - -import com.okta.sdk.impl.ds.InternalDataStore; - -import java.util.Collections; -import java.util.Map; - -public class TestResource extends AbstractInstanceResource implements Map { - - public TestResource(InternalDataStore dataStore) { - super(dataStore); - } - - public TestResource(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - @Override - public Map getPropertyDescriptors() { - return Collections.emptyMap(); - } - - public String getName() { - return super.getStringProperty("name"); - } - - public void setName(String name) { - super.setProperty("name", name); - } - - public String getDescription() { - return super.getStringProperty("description"); - } - - public void setDescription(String description) { - super.setProperty("description", description); - } -} \ No newline at end of file diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 8cfa08bd418..2a51526e6a1 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -20,7 +20,7 @@ com.okta.sdk okta-sdk-root - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT ../pom.xml @@ -42,6 +42,11 @@ logback-classic runtime + + org.apache.commons + commons-lang3 + 3.12.0 + org.testng testng @@ -85,36 +90,6 @@ - - okhttp - - - !httpclient - - - - - com.okta.sdk - okta-sdk-okhttp - runtime - - - - - httpclient - - - httpclient - - - - - com.okta.sdk - okta-sdk-httpclient - runtime - - - mock-server @@ -137,4 +112,4 @@ - + \ No newline at end of file diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ApplicationsIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ApplicationsIT.groovy deleted file mode 100644 index 5c58e9113cd..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ApplicationsIT.groovy +++ /dev/null @@ -1,946 +0,0 @@ -/* - * Copyright 2017-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.commons.http.MediaType -import com.okta.sdk.client.Client -import com.okta.sdk.impl.ds.DefaultDataStore -import com.okta.sdk.resource.Resource -import com.okta.sdk.resource.ResourceException -import com.okta.sdk.resource.application.* -import com.okta.sdk.resource.group.Group -import com.okta.sdk.resource.group.GroupBuilder -import com.okta.sdk.resource.inline.hook.InlineHook -import com.okta.sdk.resource.inline.hook.InlineHookBuilder -import com.okta.sdk.resource.inline.hook.InlineHookChannel -import com.okta.sdk.resource.inline.hook.InlineHookType -import com.okta.sdk.resource.user.User -import com.okta.sdk.resource.user.schema.UserSchema -import com.okta.sdk.resource.user.schema.UserSchemaDefinitions -import com.okta.sdk.resource.user.schema.UserSchemaPublic -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.Assert -import org.testng.annotations.Test - -import javax.xml.parsers.DocumentBuilderFactory - -import static com.okta.sdk.tests.it.util.Util.assertNotPresent -import static com.okta.sdk.tests.it.util.Util.assertPresent -import static com.okta.sdk.tests.it.util.Util.expect -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/apps}. - * @since 0.9.0 - */ -class ApplicationsIT extends ITSupport { - - void doCrudTest(Application app) { - - // Create a resource - def resource = create(client, app) - registerForCleanup(resource) - - // getting the resource again should result in the same object - def readResource = read(client, resource.getId()) - assertThat readResource, notNullValue() - - // OpenIdConnectApplication contains a password when created, so it will not be the same when retrieved) - if (!(app instanceof OpenIdConnectApplication)) { - // getting the resource again should result in the same object - assertThat readResource, equalTo(resource) - } - - // update the resource - updateAndValidate(client, resource) - - // delete the resource - deleteAndValidate(resource) - } - - def create(Client client, Application app) { - app.setLabel("java-sdk-it-" + UUID.randomUUID().toString()) - registerForCleanup(app) - return client.createApplication(app) - } - - def read(Client client, String id) { - return client.getApplication(id) - } - - void updateAndValidate(Client client, def resource) { - String newLabel = resource.label + "-update" - resource.label = newLabel - resource.update() - - // make sure the label was updated - assertThat read(client, resource.getId()).label, equalTo(newLabel) - } - - void deleteAndValidate(def resource) { - resource.deactivate() - resource.delete() - - try { - read(client, resource.getId()) - Assert.fail("Expected ResourceException (404)") - } catch (ResourceException e) { - assertThat e.status, equalTo(404) - } - } - - @Test (groups = "bacon") - void testClientIsReady() { - assertThat "Expected client to be ready", client.isReady({ -> client.listApplications() }) - } - - @Test (groups = "group1") - void basicListTest() { - // Create a resource - def resource = create(client, client.instantiate(AutoLoginApplication) - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com")) - .setNotes( - client.instantiate(ApplicationSettingsNotes) - .setAdmin("Notes for Admin") - .setEnduser("Notes for EndUser") - ) - )) - // search the resource collection looking for the new resource - Optional optional = client.listApplications().stream() - .filter {it.getId() == resource.getId()} - .findFirst() - - // make sure it exists - assertThat "New resource with id ${resource.getId()} was not found in list resource.", optional.isPresent() - } - - @Test (groups = "group1") - void crudOpenIdConnect() { - doCrudTest(client.instantiate(OpenIdConnectApplication) - .setSettings(client.instantiate(OpenIdConnectApplicationSettings) - .setOAuthClient(client.instantiate(OpenIdConnectApplicationSettingsClient) - .setClientUri("https://example.com/client") - .setLogoUri("https://example.com/assets/images/logo-new.png") - .setRedirectUris(["https://example.com/oauth2/callback", - "myapp://callback"]) - .setResponseTypes([OAuthResponseType.TOKEN, - OAuthResponseType.ID_TOKEN, - OAuthResponseType.CODE]) - .setGrantTypes([OAuthGrantType.IMPLICIT, - OAuthGrantType.AUTHORIZATION_CODE]) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setTosUri("https://example.com/client/tos") - .setPolicyUri("https://example.com/client/policy"))) - .setCredentials(client.instantiate(OAuthApplicationCredentials) - .setOAuthClient(client.instantiate(ApplicationCredentialsOAuthClient) - .setClientId(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.CLIENT_SECRET_POST)))) - } - - @Test - void crudAutoLogin() { - doCrudTest(client.instantiate(AutoLoginApplication) - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com")))) - } - - @Test - void crudWsFed() { - doCrudTest(client.instantiate(WsFederationApplication) - .setSettings(client.instantiate(WsFederationApplicationSettings) - .setApp(client.instantiate(WsFederationApplicationSettingsApplication) - .setAudienceRestriction( "urn:example:app") - .setGroupName(null) - .setGroupValueFormat("windowsDomainQualifiedName") - .setRealm("urn:example:app") - .setWReplyURL("https://example.com/") - .setAttributeStatements(null) - .setNameIDFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified") - .setAuthnContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport") - .setSiteURL("https://example.com") - .setWReplyOverride(false) - .setGroupFilter(null) - .setUsernameAttribute("username")))) - } - - @Test - void crudSaml20() { - - String name = "java-sdk-it-" + UUID.randomUUID().toString() - InlineHook createdInlineHook = InlineHookBuilder.instance() - .setName(name) - .setHookType(InlineHookType.SAML_TOKENS_TRANSFORM) - .setChannelType(InlineHookChannel.TypeEnum.HTTP) - .setUrl("https://www.example.com/inlineHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdInlineHook) - - doCrudTest(client.instantiate(SamlApplication) - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(SamlApplicationSettings) - .setSignOn(client.instantiate(SamlApplicationSettingsSignOn) - .setDefaultRelayState("") - .setSsoAcsUrl("http://testorgone.okta") - .setIdpIssuer('http://www.okta.com/${org.externalKey}') - .setAudience("asdqwe123") - .setRecipient("http://testorgone.okta") - .setDestination("http://testorgone.okta") - .setSubjectNameIdTemplate('${user.userName}') - .setSubjectNameIdFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified") - .setResponseSigned(true) - .setAssertionSigned(true) - .setSignatureAlgorithm("RSA_SHA256") - .setDigestAlgorithm("SHA256") - .setHonorForceAuthn(true) - .setAuthnContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport") - .setSpIssuer(null) - .setRequestCompressed(false) - .setInlineHooks(Arrays.asList( - client - .instantiate(SignOnInlineHook) - .setId(createdInlineHook.getId()) - )) - .setAttributeStatements(new ArrayList([ - client.instantiate(SamlAttributeStatement) - .setType("EXPRESSION") - .setName("Attribute") - .setNamespace("urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified") - .setValues(["Value"])]))))) - } - - @Test - void crudSecurePasswordStore() { - doCrudTest(client.instantiate(SecurePasswordStoreApplication) - .setSettings(client.instantiate(SecurePasswordStoreApplicationSettings) - .setApp(client.instantiate(SecurePasswordStoreApplicationSettingsApplication) - .setUrl("https://example.com/login.html") - .setPasswordField("#txtbox-password") - .setUsernameField("#txtbox-username") - .setOptionalField1("param1") - .setOptionalField1Value("somevalue") - .setOptionalField2("param2") - .setOptionalField2Value("yetanothervalue") - .setOptionalField3("param3") - .setOptionalField3Value("finalvalue")))) - } - - @Test - void crudBrowserPlugin() { - doCrudTest(client.instantiate(SwaApplication) - .setLabel(uniqueTestName) - .setSettings(client.instantiate(SwaApplicationSettings) - .setApp(client.instantiate(SwaApplicationSettingsApplication) - .setButtonField("btn-login") - .setPasswordField("txtbox-password") - .setUsernameField("txtbox-username") - .setUrl("https://example.com/login.html")))) -// .setLoginUrlRegex("REGEX_EXPRESSION")) - } - - @Test - void crudBasicAuth() { - doCrudTest(client.instantiate(BasicAuthApplication) - .setSettings(client.instantiate(BasicApplicationSettings) - .setApp(client.instantiate(BasicApplicationSettingsApplication) - .setAuthURL("https://example.com/auth.html") - .setUrl("https://example.com/login.html")))) - } - - @Test - void crudBasicAuth_editUsernameAndPassword() { - doCrudTest(client.instantiate(BasicAuthApplication) - .setCredentials(client.instantiate(SchemeApplicationCredentials) - .setScheme(ApplicationCredentialsScheme.EDIT_USERNAME_AND_PASSWORD)) - .setSettings(client.instantiate(BasicApplicationSettings) - .setApp(client.instantiate(BasicApplicationSettingsApplication) - .setAuthURL("https://example.com/auth.html") - .setUrl("https://example.com/login.html")))) - } - - @Test - void crudBasicAuth_adminSetsCredentials() { - doCrudTest(client.instantiate(BasicAuthApplication) - .setCredentials(client.instantiate(SchemeApplicationCredentials) - .setScheme(ApplicationCredentialsScheme.ADMIN_SETS_CREDENTIALS) - .setRevealPassword(true)) - .setSettings(client.instantiate(BasicApplicationSettings) - .setApp(client.instantiate(BasicApplicationSettingsApplication) - .setAuthURL("https://example.com/auth.html") - .setUrl("https://example.com/login.html")))) - } - - @Test - void invalidApplicationCredentialsSchemeTest() { - expect(IllegalArgumentException, { - client.instantiate(BasicAuthApplication) - .setCredentials(client.instantiate(SchemeApplicationCredentials) - .setScheme(ApplicationCredentialsScheme.SDK_UNKNOWN) - .setRevealPassword(true)) - .setSettings(client.instantiate(BasicApplicationSettings) - .setApp(client.instantiate(BasicApplicationSettingsApplication) - .setAuthURL("https://example.com/auth.html") - .setUrl("https://example.com/login.html"))) - }) - } - - @Test - void invalidOAuthEndpointAuthenticationMethodTest() { - expect(IllegalArgumentException ,{client.instantiate(OpenIdConnectApplication) - .setSettings(client.instantiate(OpenIdConnectApplicationSettings) - .setOAuthClient(client.instantiate(OpenIdConnectApplicationSettingsClient) - .setClientUri("https://example.com/client") - .setLogoUri("https://example.com/assets/images/logo-new.png") - .setRedirectUris(["https://example.com/oauth2/callback", - "myapp://callback"]) - .setResponseTypes([OAuthResponseType.TOKEN, - OAuthResponseType.ID_TOKEN, - OAuthResponseType.CODE]) - .setGrantTypes([OAuthGrantType.IMPLICIT, - OAuthGrantType.AUTHORIZATION_CODE]) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setTosUri("https://example.com/client/tos") - .setPolicyUri("https://example.com/client/policy"))) - .setCredentials(client.instantiate(OAuthApplicationCredentials) - .setOAuthClient(client.instantiate(ApplicationCredentialsOAuthClient) - .setClientId(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.SDK_UNKNOWN)))}) - } - - @Test - void invalidOAuthResponseTypeTest() { - expect(IllegalArgumentException ,{client.instantiate(OpenIdConnectApplication) - .setSettings(client.instantiate(OpenIdConnectApplicationSettings) - .setOAuthClient(client.instantiate(OpenIdConnectApplicationSettingsClient) - .setClientUri("https://example.com/client") - .setLogoUri("https://example.com/assets/images/logo-new.png") - .setRedirectUris(["https://example.com/oauth2/callback", - "myapp://callback"]) - .setResponseTypes([OAuthResponseType.TOKEN, - OAuthResponseType.ID_TOKEN, - OAuthResponseType.CODE, - OAuthResponseType.SDK_UNKNOWN]) - .setGrantTypes([OAuthGrantType.IMPLICIT, - OAuthGrantType.AUTHORIZATION_CODE]) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setTosUri("https://example.com/client/tos") - .setPolicyUri("https://example.com/client/policy"))) - .setCredentials(client.instantiate(OAuthApplicationCredentials) - .setOAuthClient(client.instantiate(ApplicationCredentialsOAuthClient) - .setClientId(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.CLIENT_SECRET_POST)))}) - } - - @Test - void invalidOAuthGrantTypeTest() { - expect(IllegalArgumentException, {client.instantiate(OpenIdConnectApplication) - .setSettings(client.instantiate(OpenIdConnectApplicationSettings) - .setOAuthClient(client.instantiate(OpenIdConnectApplicationSettingsClient) - .setClientUri("https://example.com/client") - .setLogoUri("https://example.com/assets/images/logo-new.png") - .setRedirectUris(["https://example.com/oauth2/callback", - "myapp://callback"]) - .setResponseTypes([OAuthResponseType.TOKEN, - OAuthResponseType.ID_TOKEN, - OAuthResponseType.CODE]) - .setGrantTypes([OAuthGrantType.IMPLICIT, - OAuthGrantType.AUTHORIZATION_CODE, - OAuthGrantType.SDK_UNKNOWN]) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setTosUri("https://example.com/client/tos") - .setPolicyUri("https://example.com/client/policy"))) - .setCredentials(client.instantiate(OAuthApplicationCredentials) - .setOAuthClient(client.instantiate(ApplicationCredentialsOAuthClient) - .setClientId(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.CLIENT_SECRET_POST))) - }) - } - - @Test - void invalidOpenIdConnectApplicationTypeTest() { - expect(IllegalArgumentException ,{ - client.instantiate(OpenIdConnectApplication) - .setSettings(client.instantiate(OpenIdConnectApplicationSettings) - .setOAuthClient(client.instantiate(OpenIdConnectApplicationSettingsClient) - .setClientUri("https://example.com/client") - .setLogoUri("https://example.com/assets/images/logo-new.png") - .setRedirectUris(["https://example.com/oauth2/callback", - "myapp://callback"]) - .setResponseTypes([OAuthResponseType.TOKEN, - OAuthResponseType.ID_TOKEN, - OAuthResponseType.CODE]) - .setGrantTypes([OAuthGrantType.IMPLICIT, - OAuthGrantType.AUTHORIZATION_CODE]) - .setApplicationType(OpenIdConnectApplicationType.SDK_UNKNOWN) - .setTosUri("https://example.com/client/tos") - .setPolicyUri("https://example.com/client/policy"))) - .setCredentials(client.instantiate(OAuthApplicationCredentials) - .setOAuthClient(client.instantiate(ApplicationCredentialsOAuthClient) - .setClientId(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.CLIENT_SECRET_POST))) - }) - } - - @Test - void crudBookmark() { - doCrudTest(client.instantiate(BookmarkApplication) - .setSettings(client.instantiate(BookmarkApplicationSettings) - .setApp(client.instantiate(BookmarkApplicationSettingsApplication) - .setRequestIntegration(false) - .setUrl("https://example.com/bookmark.htm")))) - } - - @Test(enabled = false) // OKTA-75280 - void applicationKeysTest() { - - Client client = getClient() - - Application app1 = client.instantiate(AutoLoginApplication) - .setLabel("app-${uniqueTestName}") - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com"))) - - Application app2 = client.instantiate(AutoLoginApplication) - .setLabel("app-${uniqueTestName}") - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com"))) - client.createApplication(app1) - registerForCleanup(app1) - client.createApplication(app2) - registerForCleanup(app2) - - JsonWebKeyList app1Keys = app1.listKeys() - assertThat(app1Keys.size(), equalTo(1)) - - JsonWebKey webKey = app1.generateApplicationKey(5) - assertThat(webKey, notNullValue()) - assertThat(app1.listKeys().size(), equalTo(2)) - - JsonWebKey readWebKey = app1.getApplicationKey(webKey.getKid()) - assertThat(webKey, equalTo(readWebKey)) - - JsonWebKey clonedWebKey = app1.cloneApplicationKey(webKey.getKid(), app2.getId()) - assertThat(clonedWebKey, notNullValue()) - - JsonWebKeyList app2Keys = app2.listKeys() - assertThat(app2Keys.size(), equalTo(2)) - } - - @Test (groups = "group1") - void deactivateActivateTest() { - Application app = client.createApplication(client.instantiate(AutoLoginApplication) - .setLabel("app-${uniqueTestName}") - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com")))) - - registerForCleanup(app) - - assertThat(app.getStatus(), equalTo(Application.StatusEnum.ACTIVE)) - - app.deactivate() - assertThat(client.getApplication(app.getId()).getStatus(), equalTo(Application.StatusEnum.INACTIVE)) - - app.activate() - assertThat(client.getApplication(app.getId()).getStatus(), equalTo(Application.StatusEnum.ACTIVE)) - } - - // Quarantining this till OKTA-421154 is fixed - @Test (groups = "bacon") - void groupAssignmentWithNullBodyTest() { - - Application app = client.createApplication(client.instantiate(AutoLoginApplication) - .setLabel("app-${uniqueTestName}") - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com")))) - - Group group = GroupBuilder.instance() - .setName("app-test-group-${uniqueTestName}") - .setDescription("IT created Group") - .buildAndCreate(client) - - registerForCleanup(app) - registerForCleanup(group) - - ApplicationGroupAssignment groupAssignment = app.createApplicationGroupAssignment(group.getId()) - assertThat(groupAssignment, notNullValue()) - } - - @Test (groups = "group1") - void groupAssignmentTest() { - - Application app = client.createApplication(client.instantiate(AutoLoginApplication) - .setLabel("app-${uniqueTestName}") - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com")))) - - Group group = GroupBuilder.instance() - .setName("app-test-group-${uniqueTestName}") - .setDescription("IT created Group") - .buildAndCreate(client) - - registerForCleanup(app) - registerForCleanup(group) - - assertThat(app.listGroupAssignments().iterator().size(), equalTo(0)) - - ApplicationGroupAssignment aga = client.instantiate(ApplicationGroupAssignment) - .setPriority(2) - - ApplicationGroupAssignment groupAssignment = app.createApplicationGroupAssignment(group.getId(), aga) - assertThat(groupAssignment, notNullValue()) - assertThat(groupAssignment.priority, equalTo(2)) - assertThat(app.listGroupAssignments().iterator().size(), equalTo(1)) - - ApplicationGroupAssignment receivedGroupAssignment = app.getApplicationGroupAssignment(group.getId()) - assertThat(groupAssignment.getId(), equalTo(receivedGroupAssignment.getId())) - assertThat(groupAssignment.getPriority(), equalTo(receivedGroupAssignment.getPriority())) - - // delete the assignment - groupAssignment.delete() - assertThat(app.listGroupAssignments().iterator().size(), equalTo(0)) - } - - // Remove this groups tag after OKTA-337342 is resolved (Adding this tag disables the test in bacon PDV) - @Test (groups = "bacon") - void associateUserWithApplication() { - - Client client = getClient() - User user1 = randomUser() - User user2 = randomUser() - - String label = "app-${uniqueTestName}" - Application app = client.instantiate(AutoLoginApplication) - .setLabel(label) - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com"))) - client.createApplication(app) - registerForCleanup(app) - - // issue: listApplicationUsers() occasionally throws HTTP 404, Okta E0000007 - Resource not found error. - // adding a sleep after createApplication() helps resolve the above issue. - sleep(getTestOperationDelay()) - - AppUserList appUserList = app.listApplicationUsers() - assertThat appUserList.iterator().size(), equalTo(0) - - AppUser appUser1 = client.instantiate(AppUser) - .setScope("USER") - .setId(user1.getId()) - .setCredentials(client.instantiate(AppUserCredentials) - .setUserName(user1.getProfile().getEmail()) - .setPassword(client.instantiate(AppUserPasswordCredential) - .setValue("super-secret1".toCharArray()))) - app.assignUserToApplication(appUser1) - - AppUser appUser2 = client.instantiate(AppUser) - .setScope("USER") - .setId(user2.getId()) - .setCredentials(client.instantiate(AppUserCredentials) - .setUserName(user2.getProfile().getEmail()) - .setPassword(client.instantiate(AppUserPasswordCredential) - .setValue("super-secret2".toCharArray()))) - - assertThat(app.assignUserToApplication(appUser1), sameInstance(appUser1)) - assertThat(app.assignUserToApplication(appUser2), sameInstance(appUser2)) - - // fix flakiness seen in PDV tests - Thread.sleep(getTestOperationDelay()) - - // now we should have 2 - assertThat appUserList.iterator().size(), equalTo(2) - - // delete just one - appUser1.delete() - - // fix flakiness seen in PDV tests - Thread.sleep(getTestOperationDelay()) - - // now we should have 1 - assertThat appUserList.iterator().size(), equalTo(1) - - appUser2.getCredentials().setUserName("updated-"+user2.getProfile().getEmail()) - appUser2.update() - - AppUser readAppUser = app.getApplicationUser(appUser2.getId()) - assertThat readAppUser.getCredentials().getUserName(), equalTo("updated-"+user2.getProfile().getEmail()) - } - - @Test - void csrTest() { - Client client = getClient() - - String label = "app-${uniqueTestName}" - Application app = client.instantiate(OpenIdConnectApplication) - .setLabel(label) - .setSettings(client.instantiate(OpenIdConnectApplicationSettings) - .setOAuthClient(client.instantiate(OpenIdConnectApplicationSettingsClient) - .setClientUri("https://example.com/client") - .setLogoUri("https://example.com/assets/images/logo-new.png") - .setRedirectUris(["https://example.com/oauth2/callback", - "myapp://callback"]) - .setResponseTypes([OAuthResponseType.TOKEN, - OAuthResponseType.ID_TOKEN, - OAuthResponseType.CODE]) - .setGrantTypes([OAuthGrantType.IMPLICIT, - OAuthGrantType.AUTHORIZATION_CODE]) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setTosUri("https://example.com/client/tos") - .setPolicyUri("https://example.com/client/policy"))) - .setCredentials(client.instantiate(OAuthApplicationCredentials) - .setOAuthClient(client.instantiate(ApplicationCredentialsOAuthClient) - .setClientId(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.CLIENT_SECRET_POST))) - client.createApplication(app) - registerForCleanup(app) - - assertThat(app.getStatus(), equalTo(Application.StatusEnum.ACTIVE)) - - // create csr metadata - CsrMetadata csrMetadata = client.instantiate(CsrMetadata) - .setSubject(client.instantiate(CsrMetadataSubject) - .setCountryName("US") - .setStateOrProvinceName("California") - .setLocalityName("San Francisco") - .setOrganizationName("Okta, Inc.") - .setOrganizationalUnitName("Dev") - .setCommonName("SP Issuer")) - .setSubjectAltNames(client.instantiate(CsrMetadataSubjectAltNames) - .setDnsNames(["dev.okta.com"])) - - // generate csr with metadata - Csr csr = app.generateCsr(csrMetadata) - - // verify - assertPresent(app.listCsrs(), csr) - - // revoke csr - app.revokeCsr(csr.getId()) - - // verify - assertNotPresent(app.listCsrs(), csr) - } - - // Quarantining this till OKTA-421154 is fixed - @Test (groups = "bacon") - void oAuth2ScopeConsentGrantTest() { - Client client = getClient() - - String label = "app-${uniqueTestName}" - Application app = client.instantiate(OpenIdConnectApplication) - .setLabel(label) - .setSettings(client.instantiate(OpenIdConnectApplicationSettings) - .setOAuthClient(client.instantiate(OpenIdConnectApplicationSettingsClient) - .setClientUri("https://example.com/client") - .setLogoUri("https://example.com/assets/images/logo-new.png") - .setRedirectUris(["https://example.com/oauth2/callback", - "myapp://callback"]) - .setResponseTypes([OAuthResponseType.TOKEN, - OAuthResponseType.ID_TOKEN, - OAuthResponseType.CODE]) - .setGrantTypes([OAuthGrantType.IMPLICIT, - OAuthGrantType.AUTHORIZATION_CODE]) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setTosUri("https://example.com/client/tos") - .setPolicyUri("https://example.com/client/policy"))) - .setCredentials(client.instantiate(OAuthApplicationCredentials) - .setOAuthClient(client.instantiate(ApplicationCredentialsOAuthClient) - .setClientId(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.CLIENT_SECRET_POST))) - client.createApplication(app) - registerForCleanup(app) - - assertThat(app.getStatus(), equalTo(Application.StatusEnum.ACTIVE)) - - // grant consent - OAuth2ScopeConsentGrant oAuth2ScopeConsentGrant = app.grantConsentToScope(client.instantiate(OAuth2ScopeConsentGrant) - .setIssuer(client.dataStore.baseUrlResolver.baseUrl) - .setScopeId("okta.apps.manage")) - - // verify - assertPresent(app.listScopeConsentGrants(), app.getScopeConsentGrant(oAuth2ScopeConsentGrant.getId())) - - // revoke consent - app.revokeScopeConsentGrant(oAuth2ScopeConsentGrant.getId()) - - // verify - assertNotPresent(app.listScopeConsentGrants(), app.getScopeConsentGrant(oAuth2ScopeConsentGrant.getId())) - } - - // Quarantining this till OKTA-421154 is fixed - @Test (groups = "bacon") - void testExecuteWithoutAcceptHeader() { - def app = client.instantiate(SamlApplication) - .setVisibility(client.instantiate(ApplicationVisibility)) - .setSettings(client.instantiate(SamlApplicationSettings) - .setSignOn(client.instantiate(SamlApplicationSettingsSignOn) - .setSsoAcsUrl("http://testorgone.okta") - .setAudience("asdqwe123") - .setRecipient("http://testorgone.okta") - .setDestination("http://testorgone.okta") - .setAssertionSigned(true) - .setSignatureAlgorithm("RSA_SHA256") - .setDigestAlgorithm("SHA256") - ) - ) - def dataStore = (DefaultDataStore) client.getDataStore() - def resource = create(client, app) - def url = resource.getLinks().get("users")["href"] - registerForCleanup(resource) - - // issue: testExecuteWithoutAcceptHeader() occasionally throws HTTP 404, Okta E0000007 - Resource not found error. - // adding a sleep after create() helps resolve the above issue. - sleep(getTestOperationDelay()) - - Resource response = dataStore.getResource(url as String, Application.class) - - assertThat(response.isEmpty(), is(false)) - assertThat(response.size(), is(3)) - } - - @Test (groups = "bacon") - void testExecuteAcceptIonPlusJson() { - def app = client.instantiate(SamlApplication) - .setVisibility(client.instantiate(ApplicationVisibility)) - .setSettings(client.instantiate(SamlApplicationSettings) - .setSignOn(client.instantiate(SamlApplicationSettingsSignOn) - .setSsoAcsUrl("http://testorgone.okta") - .setAudience("asdqwe123") - .setRecipient("http://testorgone.okta") - .setDestination("http://testorgone.okta") - .setAssertionSigned(true) - .setSignatureAlgorithm("RSA_SHA256") - .setDigestAlgorithm("SHA256") - ) - ) - def dataStore = (DefaultDataStore) client.getDataStore() - def resource = create(client, app) - def url = resource.getLinks().get("users")["href"] - def headers = Collections.singletonMap("Accept", Collections.singletonList("application/ion+json")) - registerForCleanup(resource) - - Resource response = dataStore.getResource(url as String, Application.class, null, headers) - - assertThat(response.isEmpty(), is(false)) - assertThat(response.size(), is(3)) - } - - @Test - void testGetRawResponse() { - def app = client.instantiate(SamlApplication) - .setVisibility(client.instantiate(ApplicationVisibility)) - .setSettings(client.instantiate(SamlApplicationSettings) - .setSignOn(client.instantiate(SamlApplicationSettingsSignOn) - .setSsoAcsUrl("http://testorgone.okta") - .setAudience("asdqwe123") - .setRecipient("http://testorgone.okta") - .setDestination("http://testorgone.okta") - .setAssertionSigned(true) - .setSignatureAlgorithm("RSA_SHA256") - .setDigestAlgorithm("SHA256") - ) - ) - def dataStore = (DefaultDataStore) client.getDataStore() - def resource = create(client, app) - def url = resource.getLinks().get("metadata")["href"] - def headers = Collections.singletonMap("Accept", Collections.singletonList(MediaType.APPLICATION_XML as String)) - registerForCleanup(resource) - - InputStream response = dataStore.getRawResponse(url as String, null, headers) - - assertThat(resource.isEmpty(), is(false)) - String x509Certificate = DocumentBuilderFactory.newInstance() - .newDocumentBuilder() - .parse(response) - .getElementsByTagName("ds:X509Certificate") - .item(0) - .getFirstChild() - .getNodeValue() - assertThat(x509Certificate.isBlank(), is(false)) - } - - @Test (groups = "group1") - void getApplicationUserSchemaTest() { - - Application createdApp = client.instantiate(AutoLoginApplication) - .setLabel("app-${uniqueTestName}") - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com"))) - client.createApplication(createdApp) - registerForCleanup(createdApp) - - def userSchema = client.getApplicationUserSchema(createdApp.getId()) - assertThat(userSchema, notNullValue()) - assertThat(userSchema.getName(), notNullValue()) - assertThat(userSchema.getTitle(), notNullValue()) - assertThat(userSchema.getType(), notNullValue()) - assertThat(userSchema.getDefinitions(), notNullValue()) - - def userSchemaBase = userSchema.getDefinitions().getBase() - assertThat(userSchemaBase, notNullValue()) - userSchemaBase.getRequired().forEach({ requiredItem -> - assertThat(userSchemaBase.getProperties().containsKey(requiredItem), equalTo(true)) - }) - } - - @Test (groups = "bacon") - void updateApplicationUserProfileTest() { - - Application createdApp = client.instantiate(AutoLoginApplication) - .setLabel("app-${uniqueTestName}") - .setVisibility(client.instantiate(ApplicationVisibility) - .setAutoSubmitToolbar(false) - .setHide(client.instantiate(ApplicationVisibilityHide) - .setIOS(false) - .setWeb(false))) - .setSettings(client.instantiate(AutoLoginApplicationSettings) - .setSignOn(client.instantiate(AutoLoginApplicationSettingsSignOn) - .setRedirectUrl("http://swasecondaryredirecturl.okta.com") - .setLoginUrl("http://swaprimaryloginurl.okta.com"))) - client.createApplication(createdApp) - registerForCleanup(createdApp) - - def userSchema = client.getApplicationUserSchema(createdApp.getId()) - assertThat(userSchema, notNullValue()) - assertThat(userSchema.getDefinitions(), notNullValue()) - - def app = client.instantiate(UserSchema) - app.setDefinitions(client.instantiate(UserSchemaDefinitions)) - app.getDefinitions().setCustom(client.instantiate(UserSchemaPublic)) - app.getDefinitions().getCustom().setProperties(new LinkedHashMap() { - { - put("twitterUserName", - new LinkedHashMap() { - { - put("title", "Twitter username") - put("description", "Username for twitter.com") - put("type", "string") - put("minLength", 1) - put("maxLength", 20) - } - }) - } - }) - - def updatedUserSchema = client.updateApplicationUserProfile(createdApp.getId(), app) - assertThat(updatedUserSchema, notNullValue()) - assertThat(updatedUserSchema.getDefinitions().getCustom(), notNullValue()) - - def userSchemaPublic = updatedUserSchema.getDefinitions().getCustom() - assertThat(userSchemaPublic.getProperties().containsKey("twitterUserName"), equalTo(true)) - - def customPropertyMap = userSchemaPublic.getProperties().get("twitterUserName") - assertThat(customPropertyMap["title"], equalTo("Twitter username")) - assertThat(customPropertyMap["description"], equalTo("Username for twitter.com")) - assertThat(customPropertyMap["type"], equalTo("string")) - assertThat(customPropertyMap["minLength"], equalTo(1)) - assertThat(customPropertyMap["maxLength"], equalTo(20)) - } - - @Test - /** - * Currently is no way to check the logo. - * Just make sure that no exception was thrown during the upload. - */ - void testUploadApplicationLogo() { - Application application = create(client, client.instantiate(Org2OrgApplication) - .setSettings(client.instantiate(Org2OrgApplicationSettings) - .setApp(client.instantiate(Org2OrgApplicationSettingsApp) - .setAcsUrl("https://example.com/acs.html") - .setAudRestriction("https://example.com/login.html") - .setBaseUrl("https://example.com/home.html"))) - ) - - client.instantiate(Application.class) - .uploadApplicationLogo(application.getId(), new File("src/test/resources/okta_logo_favicon.png")) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AppsIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AppsIT.groovy new file mode 100644 index 00000000000..437efaa92ba --- /dev/null +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AppsIT.groovy @@ -0,0 +1,358 @@ +/* + * Copyright 2017-Present Okta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.okta.sdk.tests.it + +import com.google.common.net.HttpHeaders +import com.okta.sdk.tests.it.util.ITSupport +import org.openapitools.client.api.ApplicationApi +import org.openapitools.client.api.InlineHookApi +import org.openapitools.client.model.* +import org.testng.annotations.Test + +import static org.hamcrest.MatcherAssert.assertThat +import static org.hamcrest.Matchers.equalTo +import static org.hamcrest.Matchers.notNullValue + +/** + * Tests for {@code /api/v1/apps}. + * @since 0.5.0 + */ +class AppsIT extends ITSupport { + + String prefix = "java-sdk-it-" + + @Test + void basicAuthAppTest() { + + ApplicationApi applicationApi = new ApplicationApi(getClient()) + BasicAuthApplication basicAuthApplication = new BasicAuthApplication() + basicAuthApplication.name("template_basic_auth") + .label(prefix + UUID.randomUUID().toString()) + .signOnMode(ApplicationSignOnMode.BASIC_AUTH) + BasicApplicationSettingsApplication basicApplicationSettingsApplication = + new BasicApplicationSettingsApplication() + basicApplicationSettingsApplication.url("https://example.com/login.html") + .authURL("https://example.com/auth.html") + BasicApplicationSettings basicApplicationSettings = new BasicApplicationSettings() + basicApplicationSettings.app(basicApplicationSettingsApplication) + basicAuthApplication.settings(basicApplicationSettings) + + BasicAuthApplication createdApp = + applicationApi.createApplication(BasicAuthApplication.class, basicAuthApplication, true, null) + registerForCleanup(createdApp) + + assertThat(createdApp, notNullValue()) + assertThat(createdApp.getId(), notNullValue()) + assertThat(createdApp.getLabel(), equalTo(basicAuthApplication.getLabel())) + assertThat(createdApp.getSignOnMode(), equalTo(ApplicationSignOnMode.BASIC_AUTH)) + assertThat(createdApp.getStatus().name(), equalTo("ACTIVE")) + } + + @Test + void bookmarkAppTest() { + + ApplicationApi applicationApi = new ApplicationApi(getClient()) + BookmarkApplication bookmarkApplication = new BookmarkApplication() + bookmarkApplication.name("bookmark") + .label(prefix + UUID.randomUUID().toString()) + .signOnMode(ApplicationSignOnMode.BOOKMARK) + BookmarkApplicationSettingsApplication bookmarkApplicationSettingsApplication = + new BookmarkApplicationSettingsApplication() + bookmarkApplicationSettingsApplication.url("https://example.com/bookmark.htm") + .requestIntegration(false) + BookmarkApplicationSettings bookmarkApplicationSettings = new BookmarkApplicationSettings() + bookmarkApplicationSettings.app(bookmarkApplicationSettingsApplication) + bookmarkApplication.settings(bookmarkApplicationSettings) + + // create + BookmarkApplication createdApp = + applicationApi.createApplication(BookmarkApplication.class, bookmarkApplication, true, null) + registerForCleanup(createdApp) + + assertThat(createdApp, notNullValue()) + assertThat(createdApp.getId(), notNullValue()) + assertThat(createdApp.getLabel(), equalTo(bookmarkApplication.getLabel())) + assertThat(createdApp.getSignOnMode(), equalTo(ApplicationSignOnMode.BOOKMARK)) + assertThat(createdApp.getStatus().name(), equalTo("ACTIVE")) + + // update + Application toBeUpdatedApp = bookmarkApplication.label("updated-" + bookmarkApplication.getLabel()) + BookmarkApplication updatedApp = applicationApi.replaceApplication(BookmarkApplication.class, createdApp.getId(), toBeUpdatedApp) + + assertThat(updatedApp.getId(), equalTo(createdApp.getId())) + + // retrieve + Application retrievedApp = applicationApi.getApplication(createdApp.getId(), null) + + assertThat(retrievedApp, notNullValue()) + assertThat(retrievedApp.getId(), equalTo(updatedApp.getId())) + assertThat(retrievedApp.getLabel(), equalTo(updatedApp.getLabel())) + assertThat(retrievedApp.getSignOnMode(), equalTo(ApplicationSignOnMode.BOOKMARK)) + assertThat(retrievedApp.getStatus().name(), equalTo("ACTIVE")) + } + + @Test + void browserPluginAppTest() { + + ApplicationApi applicationApi = new ApplicationApi(getClient()) + + SwaApplicationSettingsApplication swaApplicationSettingsApplication = new SwaApplicationSettingsApplication() + swaApplicationSettingsApplication.buttonField("btn-login") + .passwordField("txtbox-password") + .usernameField("txtbox-username") + .url("https://example.com/login.html") + SwaApplicationSettings swaApplicationSettings = new SwaApplicationSettings() + swaApplicationSettings.app(swaApplicationSettingsApplication) + BrowserPluginApplication browserPluginApplication = new BrowserPluginApplication() + browserPluginApplication.name("template_swa") + browserPluginApplication.label(prefix + UUID.randomUUID().toString()) + browserPluginApplication.settings(swaApplicationSettings) + + // create + BrowserPluginApplication createdApp = + applicationApi.createApplication(BrowserPluginApplication.class, browserPluginApplication, true, null) + registerForCleanup(createdApp) + + assertThat(createdApp, notNullValue()) + assertThat(createdApp.getId(), notNullValue()) + assertThat(createdApp.getLabel(), equalTo(browserPluginApplication.getLabel())) + assertThat(createdApp.getSignOnMode(), equalTo(ApplicationSignOnMode.BROWSER_PLUGIN)) + assertThat(createdApp.getStatus().name(), equalTo("ACTIVE")) + + // update + Application toBeUpdatedApp = browserPluginApplication.label("updated-" + browserPluginApplication.getLabel()) + BrowserPluginApplication updatedApp = applicationApi.replaceApplication(BrowserPluginApplication.class, createdApp.getId(), toBeUpdatedApp) + + assertThat(updatedApp.getId(), equalTo(createdApp.getId())) + + // retrieve + Application retrievedApp = applicationApi.getApplication(createdApp.getId(), null) + + assertThat(retrievedApp, notNullValue()) + assertThat(retrievedApp.getId(), equalTo(updatedApp.getId())) + assertThat(retrievedApp.getLabel(), equalTo(updatedApp.getLabel())) + assertThat(retrievedApp.getSignOnMode(), equalTo(ApplicationSignOnMode.BROWSER_PLUGIN)) + assertThat(retrievedApp.getStatus().name(), equalTo("ACTIVE")) + } + + @Test + void oidcAppTest() { + + ApplicationApi applicationApi = new ApplicationApi(getClient()) + + OpenIdConnectApplication openIdConnectApplication = new OpenIdConnectApplication() + openIdConnectApplication.label(prefix + UUID.randomUUID().toString()) + openIdConnectApplication.name("oidc_client") + OpenIdConnectApplicationSettingsClient openIdConnectApplicationSettingsClient = + new OpenIdConnectApplicationSettingsClient() + openIdConnectApplicationSettingsClient.applicationType(OpenIdConnectApplicationType.WEB) + openIdConnectApplicationSettingsClient.consentMethod(OpenIdConnectApplicationConsentMethod.REQUIRED) + openIdConnectApplicationSettingsClient.clientUri("https://example.com/client") + openIdConnectApplicationSettingsClient.logoUri("https://example.com/assets/images/logo-new.png") + openIdConnectApplicationSettingsClient.redirectUris(["https://example.com/oauth2/callback", + "myapp://callback"]) + openIdConnectApplicationSettingsClient.responseTypes([OAuthResponseType.TOKEN, OAuthResponseType.ID_TOKEN, OAuthResponseType.CODE]) + openIdConnectApplicationSettingsClient.issuerMode(OpenIdConnectApplicationIssuerMode.ORG_URL) + openIdConnectApplicationSettingsClient.grantTypes([OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE]) + openIdConnectApplicationSettingsClient.applicationType(OpenIdConnectApplicationType.NATIVE) + openIdConnectApplicationSettingsClient.tosUri("https://example.com/client/tos") + openIdConnectApplicationSettingsClient.policyUri("https://example.com/client/policy") + OpenIdConnectApplicationSettings openIdConnectApplicationSettings = + new OpenIdConnectApplicationSettings() + openIdConnectApplicationSettings.oauthClient(openIdConnectApplicationSettingsClient) + openIdConnectApplication.settings(openIdConnectApplicationSettings) + + ApplicationCredentialsOAuthClient applicationCredentialsOAuthClient = new ApplicationCredentialsOAuthClient() + applicationCredentialsOAuthClient.clientId(UUID.randomUUID().toString()) + applicationCredentialsOAuthClient.autoKeyRotation(true) + applicationCredentialsOAuthClient.tokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.CLIENT_SECRET_BASIC) + OAuthApplicationCredentials oAuthApplicationCredentials = + new OAuthApplicationCredentials() + oAuthApplicationCredentials.oauthClient(applicationCredentialsOAuthClient) + openIdConnectApplication.credentials(oAuthApplicationCredentials) + openIdConnectApplication.signOnMode(ApplicationSignOnMode.OPENID_CONNECT) + + // create + OpenIdConnectApplication createdApp = + applicationApi.createApplication(OpenIdConnectApplication.class, openIdConnectApplication, true, null) + registerForCleanup(createdApp) + + assertThat(createdApp, notNullValue()) + assertThat(createdApp.getId(), notNullValue()) + assertThat(createdApp.getLabel(), equalTo(openIdConnectApplication.getLabel())) + assertThat(createdApp.getSignOnMode(), equalTo(ApplicationSignOnMode.OPENID_CONNECT)) + assertThat(createdApp.getStatus().name(), equalTo("ACTIVE")) + + // update + Application toBeUpdatedApp = openIdConnectApplication.label("updated-" + openIdConnectApplication.getLabel()) + OpenIdConnectApplication updatedApp = applicationApi.replaceApplication(OpenIdConnectApplication.class, createdApp.getId(), toBeUpdatedApp) + + assertThat(updatedApp.getId(), equalTo(createdApp.getId())) + + // retrieve + Application retrievedApp = applicationApi.getApplication(createdApp.getId(), null) + + assertThat(retrievedApp, notNullValue()) + assertThat(retrievedApp.getId(), equalTo(updatedApp.getId())) + assertThat(retrievedApp.getLabel(), equalTo(updatedApp.getLabel())) + assertThat(retrievedApp.getSignOnMode(), equalTo(ApplicationSignOnMode.OPENID_CONNECT)) + assertThat(retrievedApp.getStatus().name(), equalTo("ACTIVE")) + } + + @Test + void samlAppTest() { + + ApplicationApi applicationApi = new ApplicationApi(getClient()) + + String name = "java-sdk-it-" + UUID.randomUUID().toString() + String version = "1.0.0" + + InlineHookChannelConfigAuthScheme inlineHookChannelConfigAuthScheme = new InlineHookChannelConfigAuthScheme() + inlineHookChannelConfigAuthScheme.type("HEADER") + inlineHookChannelConfigAuthScheme.key(HttpHeaders.AUTHORIZATION) + inlineHookChannelConfigAuthScheme.value("Test-Api-Key") + + InlineHookChannelConfigHeaders inlineHookChannelConfigHeaders = new InlineHookChannelConfigHeaders() + inlineHookChannelConfigHeaders.key("X-Test-Header") + .value("Test header value") + + List headers = new ArrayList() + headers.add(inlineHookChannelConfigHeaders) + + InlineHookChannelConfig inlineHookChannelConfig = new InlineHookChannelConfig() + .uri("https://www.example.com/inlineHooks") + .headers(headers) + .authScheme(inlineHookChannelConfigAuthScheme) + + InlineHookChannel inlineHookChannel = new InlineHookChannel() + inlineHookChannel.type(InlineHookChannelType.HTTP) + inlineHookChannel.version(version) + inlineHookChannel.config(inlineHookChannelConfig) + + InlineHookApi inlineHookApi = new InlineHookApi(getClient()) + InlineHook inlineHook = new InlineHook() + inlineHook.name(name) + inlineHook.type(InlineHookType.SAML_TOKENS_TRANSFORM) + inlineHook.version(version) + inlineHook.channel(inlineHookChannel) + + InlineHook createdInlineHook = inlineHookApi.createInlineHook(inlineHook) + registerForCleanup(createdInlineHook) + + SamlApplication samlApplication = new SamlApplication() + samlApplication.label(prefix + UUID.randomUUID().toString()) + + ApplicationVisibility applicationVisibility = new ApplicationVisibility() + applicationVisibility.autoSubmitToolbar(false) + ApplicationVisibilityHide applicationVisibilityHide = new ApplicationVisibilityHide() + applicationVisibilityHide.iOS(false) + .web(false) + applicationVisibility.hide(applicationVisibilityHide) + + SamlAttributeStatement samlAttributeStatement = new SamlAttributeStatement() + samlAttributeStatement.type("EXPRESSION") + .name("Attribute") + .namespace("urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified") + .values(["Value"]) + + List samlAttributeStatementList = new ArrayList<>() + samlAttributeStatementList.add(samlAttributeStatement) + + SamlApplicationSettings samlApplicationSettings = new SamlApplicationSettings() + SamlApplicationSettingsSignOn samlApplicationSettingsSignOn = new SamlApplicationSettingsSignOn() + samlApplicationSettingsSignOn.defaultRelayState("") + .ssoAcsUrl("http://testorgone.okta") + .idpIssuer('https://www.okta.com/${org.externalKey}') + .audience("asdqwe123") + .recipient("http://testorgone.okta") + .destination("http://testorgone.okta") + .subjectNameIdTemplate('${user.userName}') + .subjectNameIdFormat("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified") + .responseSigned(true) + .assertionSigned(true) + .signatureAlgorithm("RSA_SHA256") + .digestAlgorithm("SHA256") + .honorForceAuthn(true) + .authnContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport") + .spIssuer(null) + .requestCompressed(false) + .attributeStatements(samlAttributeStatementList) + + SignOnInlineHook signOnInlineHook = new SignOnInlineHook() + signOnInlineHook.id(createdInlineHook.getId()) + + samlApplicationSettings.signOn(samlApplicationSettingsSignOn) + samlApplication.visibility(applicationVisibility) + samlApplication.settings(samlApplicationSettings) + samlApplication.signOnMode(ApplicationSignOnMode.SAML_2_0) + + // create + SamlApplication createdApp = applicationApi.createApplication(SamlApplication.class, samlApplication, true, null) + registerForCleanup(createdApp) + + assertThat(createdApp, notNullValue()) + assertThat(createdApp.getId(), notNullValue()) + assertThat(createdApp.getLabel(), equalTo(samlApplication.getLabel())) + assertThat(createdApp.getSignOnMode(), equalTo(ApplicationSignOnMode.SAML_2_0)) + assertThat(createdApp.getStatus().name(), equalTo("ACTIVE")) + + // update + Application toBeUpdatedApp = samlApplication.label("updated-" + samlApplication.getLabel()) + SamlApplication updatedApp = applicationApi.replaceApplication(SamlApplication.class, createdApp.getId(), toBeUpdatedApp) + + assertThat(updatedApp.getId(), equalTo(createdApp.getId())) + + // retrieve + Application retrievedApp = applicationApi.getApplication(createdApp.getId(), null) + + assertThat(retrievedApp, notNullValue()) + assertThat(retrievedApp.getId(), equalTo(updatedApp.getId())) + assertThat(retrievedApp.getLabel(), equalTo(updatedApp.getLabel())) + assertThat(retrievedApp.getSignOnMode(), equalTo(ApplicationSignOnMode.SAML_2_0)) + assertThat(retrievedApp.getStatus().name(), equalTo("ACTIVE")) + } + + //TODO: fix me + @Test + void testUploadApplicationLogo() { + /** + * Currently is no way to check the logo. + * Just make sure that no exception was thrown during the upload. + */ + ApplicationApi applicationApi = new ApplicationApi(getClient()) + + SamlApplication org2OrgApplication = new SamlApplication() + org2OrgApplication.name("okta_org2org") + .label(prefix + UUID.randomUUID().toString()) + .signOnMode(ApplicationSignOnMode.SAML_2_0) + + SamlApplicationSettingsApplication samlApplicationSettingsApplication = new SamlApplicationSettingsApplication() + samlApplicationSettingsApplication.setAcsUrl("https://example.com/acs.html") + samlApplicationSettingsApplication.setAudRestriction("https://example.com/login.html") + samlApplicationSettingsApplication.setBaseUrl("https://example.com/home.html") + SamlApplicationSettings samlApplicationSettings = new SamlApplicationSettings() + samlApplicationSettings.app(samlApplicationSettingsApplication) + org2OrgApplication.settings(samlApplicationSettings) + + SamlApplication createdApp = applicationApi.createApplication(SamlApplication.class, org2OrgApplication, true, null) + registerForCleanup(createdApp) + +// File file = new File("/tmp/okta_logo_favicon.png") +// println("Uploading logo file " + file.getName() + " of size: " + file.size()) +// +// applicationApi.uploadApplicationLogo(createdApp.getId(), file) + } +} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AuthenticatorsIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AuthenticatorsIT.groovy deleted file mode 100644 index 3e29e9e25a3..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AuthenticatorsIT.groovy +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2021-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.authenticator.Authenticator -import com.okta.sdk.resource.authenticator.AuthenticatorList -import com.okta.sdk.resource.authenticator.AuthenticatorStatus -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import java.util.stream.Collectors - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/authenticators}. - * These tests requires the Org to be OIE enabled. - * @since 6.x.x - */ -class AuthenticatorsIT extends ITSupport { - - // temporarily disabled until we figure out if its safe to toggle authenticator status on an Org - // where several other management ITs run in parallel. - // https://oktainc.atlassian.net/browse/OKTA-433369 - @Test (groups = "bacon", enabled = false) - void listAndGetAuthenticatorsTest() { - - AuthenticatorList authenticators = client.listAuthenticators() - assertThat(authenticators, notNullValue()) - assertThat(authenticators.size(), greaterThan(0)) - - List authenticatorIds = authenticators.stream() - .map(Authenticator::getId).collect(Collectors.toList()) - - authenticatorIds.stream() - .forEach({ - authenticatorId -> - Authenticator authenticator = client.getAuthenticator(authenticatorId) - assertThat(authenticator, notNullValue()) - assertThat(authenticator.getName(), notNullValue()) - assertThat(authenticator.getStatus(), notNullValue()) - assertThat(authenticator.getKey(), notNullValue()) - }) - } - - // temporarily disabled until we figure out if its safe to toggle authenticator status on an Org - // where several other management ITs run in parallel. - // https://oktainc.atlassian.net/browse/OKTA-433369 - @Test (groups = "bacon", enabled = false) - void deactivateAndActivateAuthenticatorTest() { - - AuthenticatorList authenticators = client.listAuthenticators() - assertThat(authenticators, notNullValue()) - assertThat(authenticators.size(), greaterThan(0)) - - // get okta verify authenticator - String oktaVerifyAuthenticatorId = authenticators.stream() - .filter(authenticator -> authenticator.getName() == "Okta Verify") - .map(Authenticator::getId).collect(Collectors.toList()) - assertThat(oktaVerifyAuthenticatorId, notNullValue()) - - oktaVerifyAuthenticatorId = oktaVerifyAuthenticatorId.substring(1, oktaVerifyAuthenticatorId.length() - 1) - - // deactivate okta verify authenticator - Authenticator oktaVerifyAuthenticator = client.getAuthenticator(oktaVerifyAuthenticatorId) - Authenticator deactivatedOktaVerifyAuthenticator = oktaVerifyAuthenticator.deactivate() - - // check authenticator status - assertThat(deactivatedOktaVerifyAuthenticator.getStatus(), equalTo(AuthenticatorStatus.INACTIVE)) - - // activate it back - Authenticator activatedOktaVerifyAuthenticator = deactivatedOktaVerifyAuthenticator.activate() - - // check authenticator status - assertThat(activatedOktaVerifyAuthenticator.getStatus(), equalTo(AuthenticatorStatus.ACTIVE)) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AuthorizationServerIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AuthorizationServerIT.groovy deleted file mode 100644 index adc60b487a9..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/AuthorizationServerIT.groovy +++ /dev/null @@ -1,947 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.application.OAuth2Claim -import com.okta.sdk.resource.application.OAuth2Scope -import com.okta.sdk.resource.application.OAuth2ScopesMediationPolicyRuleCondition -import com.okta.sdk.resource.authorization.server.AuthorizationServer -import com.okta.sdk.resource.authorization.server.AuthorizationServerList -import com.okta.sdk.resource.authorization.server.AuthorizationServerPolicy -import com.okta.sdk.resource.authorization.server.policy.AuthorizationServerPolicyRule -import com.okta.sdk.resource.authorization.server.policy.AuthorizationServerPolicyRuleActions -import com.okta.sdk.resource.authorization.server.policy.AuthorizationServerPolicyRuleConditions -import com.okta.sdk.resource.authorization.server.policy.TokenAuthorizationServerPolicyRuleAction -import com.okta.sdk.resource.authorization.server.policy.TokenAuthorizationServerPolicyRuleActionInlineHook -import com.okta.sdk.resource.inline.hook.InlineHook -import com.okta.sdk.resource.inline.hook.InlineHookBuilder -import com.okta.sdk.resource.inline.hook.InlineHookChannel -import com.okta.sdk.resource.inline.hook.InlineHookType -import com.okta.sdk.resource.policy.* -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test -import wiremock.org.apache.commons.lang3.RandomStringUtils - -import static com.okta.sdk.tests.it.util.Util.assertNotPresent -import static com.okta.sdk.tests.it.util.Util.assertPresent -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/authorizationServers}. - * @since 2.0.0 - */ -class AuthorizationServerIT extends ITSupport { - - // Authorization server operations - - @Test - void createAuthorizationServerTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"]) - ) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - assertThat(createdAuthorizationServer.getId(), notNullValue()) - assertThat(createdAuthorizationServer.getName(), equalTo(name)) - assertThat(createdAuthorizationServer.getDescription(), equalTo("Test Authorization Server")) - assertThat(createdAuthorizationServer.getAudiences(), hasSize(1)) - assertThat(createdAuthorizationServer.getAudiences(), contains("api://example")) - } - - @Test (groups = "group3") - void listCreatedAuthorizationServerTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - // create operation may not take effect immediately in the backend - sleep(getTestOperationDelay()) - - assertThat(createdAuthorizationServer, notNullValue()) - assertPresent(client.listAuthorizationServers(), createdAuthorizationServer) - } - - @Test - void getAuthorizationServerTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"]) - ) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServer retrievedAuthorizationServer = client.getAuthorizationServer(createdAuthorizationServer.getId()) - assertThat(retrievedAuthorizationServer.getId(), equalTo(createdAuthorizationServer.getId())) - assertThat(retrievedAuthorizationServer.getName(), equalTo(createdAuthorizationServer.getName())) - assertThat(retrievedAuthorizationServer.getDescription(), equalTo(createdAuthorizationServer.getDescription())) - } - - @Test - void updateAuthorizationServerTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"]) - ) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - createdAuthorizationServer.setDescription("Updated Test Authorization Server") - - AuthorizationServer updatedAuthorizationServer = createdAuthorizationServer.update() - assertThat(updatedAuthorizationServer.getId(), equalTo(createdAuthorizationServer.getId())) - assertThat(updatedAuthorizationServer.getDescription(), equalTo("Updated Test Authorization Server")) - } - - @Test - void deleteAuthorizationServerTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - assertThat(client.getAuthorizationServer(createdAuthorizationServer.getId()), notNullValue()) - - createdAuthorizationServer.deactivate() - createdAuthorizationServer.delete() - - // delete operation may not effect immediately in the backend - sleep(getTestOperationDelay()) - - assertNotPresent(client.listAuthorizationServers(), createdAuthorizationServer) - } - - @Test - void deactivateAuthorizationServerTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"]) - ) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - assertThat(createdAuthorizationServer.getStatus(), equalTo(AuthorizationServer.StatusEnum.ACTIVE)) - - createdAuthorizationServer.deactivate() - - // delete operation may not effect immediately in the backend - sleep(getTestOperationDelay()) - - AuthorizationServer retrievedAuthorizationServer = client.getAuthorizationServer(createdAuthorizationServer.getId()) - assertThat(retrievedAuthorizationServer, notNullValue()) - assertThat(retrievedAuthorizationServer.getId(), equalTo(createdAuthorizationServer.getId())) - assertThat(retrievedAuthorizationServer.getStatus(), equalTo(AuthorizationServer.StatusEnum.INACTIVE)) - } - - @Test - void activateAuthorizationServerTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"]) - ) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - assertThat(createdAuthorizationServer.getStatus(), equalTo(AuthorizationServer.StatusEnum.ACTIVE)) - - createdAuthorizationServer.deactivate() - - // delete operation may not effect immediately in the backend - sleep(getTestOperationDelay()) - - AuthorizationServer retrievedAuthorizationServer = client.getAuthorizationServer(createdAuthorizationServer.getId()) - assertThat(retrievedAuthorizationServer, notNullValue()) - assertThat(retrievedAuthorizationServer.getId(), equalTo(createdAuthorizationServer.getId())) - assertThat(retrievedAuthorizationServer.getStatus(), equalTo(AuthorizationServer.StatusEnum.INACTIVE)) - - createdAuthorizationServer.activate() - - // delete operation may not effect immediately in the backend - sleep(getTestOperationDelay()) - - retrievedAuthorizationServer = client.getAuthorizationServer(createdAuthorizationServer.getId()) - assertThat(retrievedAuthorizationServer, notNullValue()) - assertThat(retrievedAuthorizationServer.getId(), equalTo(createdAuthorizationServer.getId())) - assertThat(retrievedAuthorizationServer.getStatus(), equalTo(AuthorizationServer.StatusEnum.ACTIVE)) - } - - // Policy operations - @Test (groups = "group3") - void listAuthorizationServerPoliciesTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"]) - ) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - // create may not effect immediately in the backend - sleep(getTestOperationDelay()) - - AuthorizationServerList authorizationServerList = client.listAuthorizationServers() - assertThat(authorizationServerList, notNullValue()) - assertThat(authorizationServerList.size(), greaterThan(0)) - assertPresent(authorizationServerList, createdAuthorizationServer) - - authorizationServerList.stream() - .filter({ - authServer -> authServer.getId() == createdAuthorizationServer.getId() - }) - .forEach({ - authServer -> - assertThat(authServer.listPolicies(), notNullValue()) - authServer.listPolicies().forEach({ - authPolicy -> assertThat(authPolicy.getId(), notNullValue()) - }) - }) - } - - @Test - void createAuthorizationServerPolicyTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerPolicy authorizationServerPolicy = client.instantiate(AuthorizationServerPolicy) - .setType(PolicyType.OAUTH_AUTHORIZATION_POLICY) - .setName("Test Policy") - .setDescription("Test Policy") - .setPriority(1) - .setConditions(client.instantiate(PolicyRuleConditions) - .setClients(client.instantiate(ClientPolicyCondition) - .setInclude( - [OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS.name()] - ) - ) - ) - AuthorizationServerPolicy createdPolicy = createdAuthorizationServer.createPolicy(authorizationServerPolicy) - assertThat(createdPolicy, notNullValue()) - - AuthorizationServerPolicy retrievedPolicy = createdAuthorizationServer.getPolicy(createdPolicy.getId()) - assertThat(retrievedPolicy, notNullValue()) - assertThat(retrievedPolicy.getId(), equalTo(createdPolicy.getId())) - assertThat(retrievedPolicy.getDescription(), equalTo(createdPolicy.getDescription())) - assertThat(retrievedPolicy.getName(), equalTo(createdPolicy.getName())) - } - - @Test - void updateAuthorizationServerPolicyTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerPolicy authorizationServerPolicy = client.instantiate(AuthorizationServerPolicy) - .setType(PolicyType.OAUTH_AUTHORIZATION_POLICY) - .setName("Test Policy") - .setDescription("Test Policy") - .setPriority(1) - .setConditions(client.instantiate(PolicyRuleConditions) - .setClients(client.instantiate(ClientPolicyCondition) - .setInclude( - [OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS.name()] - ) - ) - ) - AuthorizationServerPolicy createdPolicy = createdAuthorizationServer.createPolicy(authorizationServerPolicy) - assertThat(createdPolicy, notNullValue()) - - createdPolicy.setName("Test Policy Updated") - createdPolicy.setDescription("Test Policy Updated") - - AuthorizationServerPolicy updatedPolicy = createdAuthorizationServer.updatePolicy(createdPolicy.getId(), createdPolicy) - assertThat(updatedPolicy, notNullValue()) - assertThat(updatedPolicy.getId(), equalTo(createdPolicy.getId())) - assertThat(updatedPolicy.getName(), equalTo("Test Policy Updated")) - assertThat(updatedPolicy.getDescription(), equalTo("Test Policy Updated")) - } - - @Test - void deleteAuthorizationServerPolicyTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerPolicy authorizationServerPolicy = client.instantiate(AuthorizationServerPolicy) - .setType(PolicyType.OAUTH_AUTHORIZATION_POLICY) - .setName("Test Policy") - .setDescription("Test Policy") - .setPriority(1) - .setConditions(client.instantiate(PolicyRuleConditions) - .setClients(client.instantiate(ClientPolicyCondition) - .setInclude( - [OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS.name()] - ) - ) - ) - AuthorizationServerPolicy createdPolicy = createdAuthorizationServer.createPolicy(authorizationServerPolicy) - assertThat(createdPolicy, notNullValue()) - - createdAuthorizationServer.deletePolicy(createdPolicy.getId()) - - // delete may not effect immediately in the backend - sleep(getTestOperationDelay()) - - assertNotPresent(createdAuthorizationServer.listPolicies(), createdPolicy) - } - - @Test - void activateDeactivateAuthorizationServerPolicyTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerPolicy authorizationServerPolicy = client.instantiate(AuthorizationServerPolicy) - .setType(PolicyType.OAUTH_AUTHORIZATION_POLICY) - .setName("Test Policy") - .setDescription("Test Policy") - .setPriority(1) - .setConditions(client.instantiate(PolicyRuleConditions) - .setClients(client.instantiate(ClientPolicyCondition) - .setInclude( - [OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS.name()] - ) - ) - ) - AuthorizationServerPolicy createdPolicy = createdAuthorizationServer.createPolicy(authorizationServerPolicy) - assertThat(createdPolicy, notNullValue()) - - createdPolicy.deactivate(createdAuthorizationServer.getId()) - def deactivatedPolicy = createdAuthorizationServer.getPolicy(createdPolicy.getId()) - assertThat(deactivatedPolicy, notNullValue()) - assertThat(deactivatedPolicy.getStatus(), equalTo(AuthorizationServerPolicy.StatusEnum.INACTIVE)) - - deactivatedPolicy.activate(createdAuthorizationServer.getId()) - def activatedPolicy = createdAuthorizationServer.getPolicy(deactivatedPolicy.getId()) - assertThat(activatedPolicy, notNullValue()) - assertThat(activatedPolicy.getStatus(), equalTo(AuthorizationServerPolicy.StatusEnum.ACTIVE)) - - createdAuthorizationServer.deletePolicy(activatedPolicy.getId()) - - // delete may not effect immediately in the backend - sleep(getTestOperationDelay()) - - assertNotPresent(createdAuthorizationServer.listPolicies(), activatedPolicy) - } - - @Test - void listAuthorizationServerPolicyRulesTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerList authorizationServerList = client.listAuthorizationServers() - - assertThat(authorizationServerList, notNullValue()) - assertThat(authorizationServerList.size(), greaterThan(0)) - - authorizationServerList.stream() - .filter({ - authServer -> authServer.getId() == createdAuthorizationServer.getId() - }) - .forEach({ - authServer -> - assertThat(authServer.listPolicies(), notNullValue()) - authServer.listPolicies().forEach({ authPolicy -> - assertThat(authPolicy, notNullValue()) - assertThat(authPolicy.getId(), notNullValue()) - assertThat(authPolicy.listPolicyRules(authServer.getId()), notNullValue()) - }) - }) - } - - @Test - void createAuthorizationServerPolicyRuleTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerPolicy authorizationServerPolicy = client.instantiate(AuthorizationServerPolicy) - .setType(PolicyType.OAUTH_AUTHORIZATION_POLICY) - .setName("Test Policy") - .setDescription("Test Policy") - .setPriority(1) - .setConditions(client.instantiate(PolicyRuleConditions) - .setClients(client.instantiate(ClientPolicyCondition) - .setInclude( - [OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS.name()] - ) - ) - ) - AuthorizationServerPolicy createdPolicy = createdAuthorizationServer.createPolicy(authorizationServerPolicy) - assertThat(createdPolicy, notNullValue()) - - AuthorizationServerPolicy retrievedPolicy = createdAuthorizationServer.getPolicy(createdPolicy.getId()) - assertThat(retrievedPolicy, notNullValue()) - assertThat(retrievedPolicy.getId(), equalTo(createdPolicy.getId())) - - String hookName = "java-sdk-it-" + UUID.randomUUID().toString() - InlineHook createdInlineHook = InlineHookBuilder.instance() - .setName(hookName) - .setHookType(InlineHookType.OAUTH2_TOKENS_TRANSFORM) - .setChannelType(InlineHookChannel.TypeEnum.HTTP) - .setUrl("https://www.example.com/inlineHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdInlineHook) - - AuthorizationServerPolicyRule createdPolicyRule = retrievedPolicy.createPolicyRule(createdAuthorizationServer.getId(), - client.instantiate(AuthorizationServerPolicyRule) - .setName(name) - .setType(AuthorizationServerPolicyRule.TypeEnum.ACCESS) - .setPriority(1) - .setConditions(client.instantiate(AuthorizationServerPolicyRuleConditions) - .setPeople(client.instantiate(PolicyPeopleCondition) - .setGroups(client.instantiate(GroupCondition) - .setInclude(["EVERYONE"]))) - .setGrantTypes(client.instantiate(GrantTypePolicyRuleCondition) - .setInclude(["implicit", "client_credentials", "authorization_code", "password"])) - .setScopes(client.instantiate(OAuth2ScopesMediationPolicyRuleCondition).setInclude(["openid", "email", "address"])) - ) - .setActions(client.instantiate(AuthorizationServerPolicyRuleActions) - .setToken( - client.instantiate(TokenAuthorizationServerPolicyRuleAction) - .setAccessTokenLifetimeMinutes(60) - .setRefreshTokenLifetimeMinutes(0) - .setRefreshTokenWindowMinutes(10080) - .setInlineHook( - client.instantiate(TokenAuthorizationServerPolicyRuleActionInlineHook) - .setId(createdInlineHook.getId()) - ) - ) - ) - ) - - assertThat(createdPolicyRule, notNullValue()) - assertThat(createdPolicyRule.getType(), equalTo(AuthorizationServerPolicyRule.TypeEnum.ACCESS)) - assertThat(createdPolicyRule.getPriority(), equalTo(1)) - assertThat(createdPolicyRule.getConditions().getPeople().getGroups().getInclude(), contains("EVERYONE")) - assertThat(createdPolicyRule.getConditions().getGrantTypes().getInclude(), - containsInAnyOrder("implicit", "client_credentials", "authorization_code", "password")) - assertThat(createdPolicyRule.getConditions().getScopes().getInclude(), - containsInAnyOrder("openid", "email", "address")) - assertThat(createdPolicyRule.getActions().getToken().getAccessTokenLifetimeMinutes(), equalTo(60)) - assertThat(createdPolicyRule.getActions().getToken().getRefreshTokenLifetimeMinutes(), equalTo(0)) - assertThat(createdPolicyRule.getActions().getToken().getRefreshTokenWindowMinutes(), equalTo(10080)) - } - - @Test (groups = "group3") - void updateAuthorizationServerPolicyRuleTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerPolicy authorizationServerPolicy = client.instantiate(AuthorizationServerPolicy) - .setType(PolicyType.OAUTH_AUTHORIZATION_POLICY) - .setName("Test Policy") - .setDescription("Test Policy") - .setPriority(1) - .setConditions(client.instantiate(PolicyRuleConditions) - .setClients(client.instantiate(ClientPolicyCondition) - .setInclude( - [OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS.name()] - ) - ) - ) - - AuthorizationServerPolicy createdPolicy = createdAuthorizationServer.createPolicy(authorizationServerPolicy) - assertThat(createdPolicy, notNullValue()) - - AuthorizationServerPolicy retrievedPolicy = createdAuthorizationServer.getPolicy(createdPolicy.getId()) - assertThat(retrievedPolicy, notNullValue()) - assertThat(retrievedPolicy.getId(), equalTo(createdPolicy.getId())) - - AuthorizationServerPolicyRule createdPolicyRule = retrievedPolicy.createPolicyRule(createdAuthorizationServer.getId(), - client.instantiate(AuthorizationServerPolicyRule) - .setName(name) - .setType(AuthorizationServerPolicyRule.TypeEnum.ACCESS) - .setPriority(1) - .setConditions(client.instantiate(AuthorizationServerPolicyRuleConditions) - .setPeople(client.instantiate(PolicyPeopleCondition) - .setGroups(client.instantiate(GroupCondition) - .setInclude(["EVERYONE"]))) - .setGrantTypes(client.instantiate(GrantTypePolicyRuleCondition) - .setInclude(["implicit", "client_credentials", "authorization_code", "password"])) - .setScopes(client.instantiate(OAuth2ScopesMediationPolicyRuleCondition).setInclude(["openid", "email", "address"])) - ) - .setActions(client.instantiate(AuthorizationServerPolicyRuleActions) - .setToken( - client.instantiate(TokenAuthorizationServerPolicyRuleAction) - .setAccessTokenLifetimeMinutes(60) - .setRefreshTokenLifetimeMinutes(0) - .setRefreshTokenWindowMinutes(10080) - ) - ) - ) - - assertThat(createdPolicyRule, notNullValue()) - assertThat(createdPolicyRule.getType(), equalTo(AuthorizationServerPolicyRule.TypeEnum.ACCESS)) - assertThat(createdPolicyRule.getPriority(), equalTo(1)) - assertThat(createdPolicyRule.getConditions().getPeople().getGroups().getInclude(), contains("EVERYONE")) - assertThat(createdPolicyRule.getConditions().getGrantTypes().getInclude(), - containsInAnyOrder("implicit", "client_credentials", "authorization_code", "password")) - assertThat(createdPolicyRule.getConditions().getScopes().getInclude(), - containsInAnyOrder("openid", "email", "address")) - assertThat(createdPolicyRule.getActions().getToken().getAccessTokenLifetimeMinutes(), equalTo(60)) - assertThat(createdPolicyRule.getActions().getToken().getRefreshTokenLifetimeMinutes(), equalTo(0)) - assertThat(createdPolicyRule.getActions().getToken().getRefreshTokenWindowMinutes(), equalTo(10080)) - - createdPolicyRule - .setActions(client.instantiate(AuthorizationServerPolicyRuleActions) - .setToken( - client.instantiate(TokenAuthorizationServerPolicyRuleAction) - .setAccessTokenLifetimeMinutes(55) - .setRefreshTokenLifetimeMinutes(55) - .setRefreshTokenWindowMinutes(55) - ) - ) - - AuthorizationServerPolicyRule retrievedPolicyRule = createdPolicyRule.update(createdAuthorizationServer.getId()) - - assertThat(retrievedPolicyRule, notNullValue()) - assertThat(retrievedPolicyRule.getActions().getToken().getAccessTokenLifetimeMinutes(), equalTo(55)) - assertThat(retrievedPolicyRule.getActions().getToken().getRefreshTokenLifetimeMinutes(), equalTo(55)) - assertThat(retrievedPolicyRule.getActions().getToken().getRefreshTokenWindowMinutes(), equalTo(55)) - } - - @Test - void deleteAuthorizationServerPolicyRuleTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerPolicy authorizationServerPolicy = client.instantiate(AuthorizationServerPolicy) - .setType(PolicyType.OAUTH_AUTHORIZATION_POLICY) - .setName("Test Policy") - .setDescription("Test Policy") - .setPriority(1) - .setConditions(client.instantiate(PolicyRuleConditions) - .setClients(client.instantiate(ClientPolicyCondition) - .setInclude( - [OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS.name()] - ) - ) - ) - AuthorizationServerPolicy createdPolicy = createdAuthorizationServer.createPolicy(authorizationServerPolicy) - assertThat(createdPolicy, notNullValue()) - - AuthorizationServerPolicy retrievedPolicy = createdAuthorizationServer.getPolicy(createdPolicy.getId()) - assertThat(retrievedPolicy, notNullValue()) - assertThat(retrievedPolicy.getId(), equalTo(createdPolicy.getId())) - - AuthorizationServerPolicyRule createdPolicyRule = retrievedPolicy.createPolicyRule(createdAuthorizationServer.getId(), - client.instantiate(AuthorizationServerPolicyRule) - .setName(name) - .setType(AuthorizationServerPolicyRule.TypeEnum.ACCESS) - .setPriority(1) - .setConditions(client.instantiate(AuthorizationServerPolicyRuleConditions) - .setPeople(client.instantiate(PolicyPeopleCondition) - .setGroups(client.instantiate(GroupCondition) - .setInclude(["EVERYONE"]))) - .setGrantTypes(client.instantiate(GrantTypePolicyRuleCondition) - .setInclude(["implicit", "client_credentials", "authorization_code", "password"])) - .setScopes(client.instantiate(OAuth2ScopesMediationPolicyRuleCondition).setInclude(["openid", "email", "address"])) - ) - ) - - assertThat(createdPolicyRule, notNullValue()) - assertThat(createdPolicyRule.getType(), equalTo(AuthorizationServerPolicyRule.TypeEnum.ACCESS)) - - createdPolicyRule.delete(createdAuthorizationServer.getId()) - - // delete may not effect immediately in the backend - sleep(getTestOperationDelay()) - - assertNotPresent(createdPolicy.listPolicyRules(createdAuthorizationServer.getId()), createdPolicyRule) - } - - @Test - void activateDeactivateAuthorizationServerPolicyRuleTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - assertThat(createdAuthorizationServer, notNullValue()) - - AuthorizationServerPolicy authorizationServerPolicy = client.instantiate(AuthorizationServerPolicy) - .setType(PolicyType.OAUTH_AUTHORIZATION_POLICY) - .setName("Test Policy") - .setDescription("Test Policy") - .setPriority(1) - .setConditions(client.instantiate(PolicyRuleConditions) - .setClients(client.instantiate(ClientPolicyCondition) - .setInclude( - [OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS.name()] - ) - ) - ) - AuthorizationServerPolicy createdPolicy = createdAuthorizationServer.createPolicy(authorizationServerPolicy) - assertThat(createdPolicy, notNullValue()) - - AuthorizationServerPolicyRule createdPolicyRule = createdPolicy.createPolicyRule(createdAuthorizationServer.getId(), - client.instantiate(AuthorizationServerPolicyRule) - .setName(name) - .setType(AuthorizationServerPolicyRule.TypeEnum.ACCESS) - .setPriority(1) - .setConditions(client.instantiate(AuthorizationServerPolicyRuleConditions) - .setPeople(client.instantiate(PolicyPeopleCondition) - .setGroups(client.instantiate(GroupCondition) - .setInclude(["EVERYONE"]))) - .setGrantTypes(client.instantiate(GrantTypePolicyRuleCondition) - .setInclude(["implicit", "client_credentials", "authorization_code", "password"])) - .setScopes(client.instantiate(OAuth2ScopesMediationPolicyRuleCondition).setInclude(["openid", "email", "address"])) - ) - ) - assertThat(createdPolicyRule, notNullValue()) - - createdPolicyRule.deactivate(createdAuthorizationServer.getId()) - def deactivatedPolicyRule = createdPolicy.getPolicyRule(createdAuthorizationServer.getId(), createdPolicyRule.getId()) - assertThat(deactivatedPolicyRule, notNullValue()) - assertThat(deactivatedPolicyRule.getStatus(), equalTo(AuthorizationServerPolicyRule.StatusEnum.INACTIVE)) - - deactivatedPolicyRule.activate(createdAuthorizationServer.getId()) - def activatedPolicyRule = createdPolicy.getPolicyRule(createdAuthorizationServer.getId(), createdPolicyRule.getId()) - assertThat(activatedPolicyRule, notNullValue()) - assertThat(activatedPolicyRule.getStatus(), equalTo(AuthorizationServerPolicyRule.StatusEnum.ACTIVE)) - - activatedPolicyRule.delete(createdAuthorizationServer.getId()) - - // delete may not effect immediately in the backend - sleep(getTestOperationDelay()) - - assertNotPresent(createdPolicy.listPolicyRules(createdAuthorizationServer.getId()), activatedPolicyRule) - } - - // Scope operations - - @Test - void listOAuth2ScopesTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - - OAuth2Scope oAuth2Scope = client.instantiate(OAuth2Scope) - .setName("java-sdk-it-" + RandomStringUtils.randomAlphanumeric(10)) - - OAuth2Scope createdOAuth2Scope = createdAuthorizationServer.createOAuth2Scope(oAuth2Scope) - - assertThat(createdOAuth2Scope, notNullValue()) - assertPresent(createdAuthorizationServer.listOAuth2Scopes(), createdOAuth2Scope) - } - - @Test (groups = "group3") - void getOAuth2ScopesTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - - OAuth2Scope oAuth2Scope = client.instantiate(OAuth2Scope) - .setName("java-sdk-it-" + RandomStringUtils.randomAlphanumeric(10)) - - OAuth2Scope createdOAuth2Scope = createdAuthorizationServer.createOAuth2Scope(oAuth2Scope) - - assertThat(createdOAuth2Scope, notNullValue()) - - OAuth2Scope retrievedOAuth2Scope = createdAuthorizationServer.getOAuth2Scope(createdOAuth2Scope.getId()) - - assertThat(retrievedOAuth2Scope.getId(), equalTo(createdOAuth2Scope.getId())) - } - - @Test (groups = "group3") - void updateOAuth2ScopesTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - - OAuth2Scope oAuth2Scope = client.instantiate(OAuth2Scope) - .setName("java-sdk-it-" + RandomStringUtils.randomAlphanumeric(10)) - .setConsent(OAuth2Scope.ConsentEnum.REQUIRED) - .setMetadataPublish(OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS) - - OAuth2Scope createdOAuth2Scope = createdAuthorizationServer.createOAuth2Scope(oAuth2Scope) - - assertThat(createdOAuth2Scope, notNullValue()) - - OAuth2Scope tobeUpdatedOAuth2Scope = client.instantiate(OAuth2Scope) - .setName("java-sdk-it-" + RandomStringUtils.randomAlphanumeric(10) + "-updated") - .setConsent(OAuth2Scope.ConsentEnum.REQUIRED) - .setMetadataPublish(OAuth2Scope.MetadataPublishEnum.ALL_CLIENTS) - - OAuth2Scope updatedOAuth2Scope = createdAuthorizationServer.updateOAuth2Scope(createdOAuth2Scope.getId(), tobeUpdatedOAuth2Scope) - - assertThat(updatedOAuth2Scope.getId(), equalTo(tobeUpdatedOAuth2Scope.getId())) - assertThat(updatedOAuth2Scope.getName(), equalTo(tobeUpdatedOAuth2Scope.getName())) - } - - @Test - void deleteOAuth2ScopesTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - - OAuth2Scope oAuth2Scope = client.instantiate(OAuth2Scope) - .setName("java-sdk-it-" + RandomStringUtils.randomAlphanumeric(10)) - - OAuth2Scope createdOAuth2Scope = createdAuthorizationServer.createOAuth2Scope(oAuth2Scope) - - assertThat(createdOAuth2Scope, notNullValue()) - - createdAuthorizationServer.deleteOAuth2Scope(createdOAuth2Scope.getId()) - - // delete may not effect immediately in the backend - sleep(getTestOperationDelay()) - - assertNotPresent(createdAuthorizationServer.listOAuth2Scopes(), createdOAuth2Scope) - } - - // Claim operations - - @Test - void listOAuth2ClaimsTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - - OAuth2Claim oAuth2Claim = client.instantiate(OAuth2Claim) - .setName("java-sdk-it-claims" + RandomStringUtils.randomAlphanumeric(10)) - .setStatus(OAuth2Claim.StatusEnum.INACTIVE) - .setClaimType(OAuth2Claim.ClaimTypeEnum.RESOURCE) - .setValueType(OAuth2Claim.ValueTypeEnum.EXPRESSION) - .setValue("\"driving!\"") // value must be an Okta EL expression if valueType is EXPRESSION - - OAuth2Claim createdOAuth2Claim = createdAuthorizationServer.createOAuth2Claim(oAuth2Claim) - assertThat(createdOAuth2Claim, notNullValue()) - - assertPresent(createdAuthorizationServer.listOAuth2Claims(), createdOAuth2Claim) - } - - @Test - void getOAuth2ClaimTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - - OAuth2Claim oAuth2Claim = client.instantiate(OAuth2Claim) - .setName("java-sdk-it-claims" + RandomStringUtils.randomAlphanumeric(10)) - .setStatus(OAuth2Claim.StatusEnum.INACTIVE) - .setClaimType(OAuth2Claim.ClaimTypeEnum.RESOURCE) - .setValueType(OAuth2Claim.ValueTypeEnum.EXPRESSION) - .setValue("\"driving!\"") - - OAuth2Claim createdOAuth2Claim = createdAuthorizationServer.createOAuth2Claim(oAuth2Claim) - assertThat(createdOAuth2Claim, notNullValue()) - - OAuth2Claim retrievedOAuth2Claim = createdAuthorizationServer.getOAuth2Claim(createdOAuth2Claim.getId()) - assertThat(retrievedOAuth2Claim, notNullValue()) - assertThat(retrievedOAuth2Claim.getId(), equalTo(createdOAuth2Claim.getId())) - } - - @Test - void updateOAuth2ClaimTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - - OAuth2Claim oAuth2Claim = client.instantiate(OAuth2Claim) - .setName("java-sdk-it-claims" + RandomStringUtils.randomAlphanumeric(10)) - .setStatus(OAuth2Claim.StatusEnum.INACTIVE) - .setClaimType(OAuth2Claim.ClaimTypeEnum.RESOURCE) - .setValueType(OAuth2Claim.ValueTypeEnum.EXPRESSION) - .setValue("\"driving!\"") - - OAuth2Claim createdOAuth2Claim = createdAuthorizationServer.createOAuth2Claim(oAuth2Claim) - assertThat(createdOAuth2Claim, notNullValue()) - - OAuth2Claim tobeUpdatedOAuth2Claim = client.instantiate(OAuth2Claim) - .setName("java-sdk-it-claims" + RandomStringUtils.randomAlphanumeric(10) + "-updated") - .setStatus(OAuth2Claim.StatusEnum.INACTIVE) - .setClaimType(OAuth2Claim.ClaimTypeEnum.RESOURCE) - .setValueType(OAuth2Claim.ValueTypeEnum.EXPRESSION) - .setValue("\"driving!\"") - - OAuth2Claim updatedOAuth2Claim = createdAuthorizationServer.updateOAuth2Claim(createdOAuth2Claim.getId(), tobeUpdatedOAuth2Claim) - - assertThat(updatedOAuth2Claim.getId(), equalTo(tobeUpdatedOAuth2Claim.getId())) - assertThat(updatedOAuth2Claim.getName(), equalTo(tobeUpdatedOAuth2Claim.getName())) - } - - @Test (groups = "group3") - void deleteOAuth2ClaimTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - AuthorizationServer createdAuthorizationServer = client.createAuthorizationServer( - client.instantiate(AuthorizationServer) - .setName(name) - .setDescription("Test Authorization Server") - .setAudiences(["api://example"])) - registerForCleanup(createdAuthorizationServer) - - assertThat(createdAuthorizationServer, notNullValue()) - - OAuth2Claim oAuth2Claim = client.instantiate(OAuth2Claim) - .setName("java-sdk-it-claims" + RandomStringUtils.randomAlphanumeric(10)) - .setStatus(OAuth2Claim.StatusEnum.INACTIVE) - .setClaimType(OAuth2Claim.ClaimTypeEnum.RESOURCE) - .setValueType(OAuth2Claim.ValueTypeEnum.EXPRESSION) - .setValue("\"driving!\"") - - OAuth2Claim createdOAuth2Claim = createdAuthorizationServer.createOAuth2Claim(oAuth2Claim) - assertThat(createdOAuth2Claim, notNullValue()) - - createdAuthorizationServer.deleteOAuth2Claim(createdOAuth2Claim.getId()) - - // delete may not effect immediately in the backend - sleep(getTestOperationDelay()) - - assertNotPresent(createdAuthorizationServer.listOAuth2Claims(), createdOAuth2Claim) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/BrandsIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/BrandsIT.groovy deleted file mode 100644 index 5b783d35d3d..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/BrandsIT.groovy +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright 2021-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.brand.Brand -import com.okta.sdk.resource.brand.BrandList -import com.okta.sdk.resource.brand.EmailTemplateTouchPointVariant -import com.okta.sdk.resource.brand.EndUserDashboardTouchPointVariant -import com.okta.sdk.resource.brand.ErrorPageTouchPointVariant -import com.okta.sdk.resource.brand.ImageUploadResponse -import com.okta.sdk.resource.brand.SignInPageTouchPointVariant -import com.okta.sdk.resource.brand.Theme -import com.okta.sdk.resource.brand.ThemeResponse -import com.okta.sdk.resource.brands.EmailTemplate -import com.okta.sdk.resource.brands.EmailTemplateContent -import com.okta.sdk.resource.brands.EmailTemplateCustomization -import com.okta.sdk.resource.brands.EmailTemplateCustomizationList -import com.okta.sdk.resource.brands.EmailTemplateCustomizationRequest -import com.okta.sdk.resource.brands.EmailTemplateList -import com.okta.sdk.tests.Scenario -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test -import org.testng.util.Strings - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/brands}. - * @since 7.x.x - */ -class BrandsIT extends ITSupport { - - private final String pathToImage = "src/test/resources/okta_logo_white.png" - private final String pathToFavicon = "src/test/resources/okta_logo_favicon.png" - - @Test (groups = "bacon") - @Scenario("basic-brand") - void basicBrandTest() { - - Brand brand = client.getBrand(getBrandId()) - //remember original values - String customPrivacyPolicyUrl = brand.getCustomPrivacyPolicyUrl() - Boolean removePoweredByOkta = brand.getRemovePoweredByOkta() - - brand.setAgreeToCustomPrivacyPolicy(true) - brand.setCustomPrivacyPolicyUrl("https://custom-privacy-policy@example.com") - brand.setRemovePoweredByOkta(!removePoweredByOkta) - brand.update() - assertThat(brand.getCustomPrivacyPolicyUrl(), equalTo("https://custom-privacy-policy@example.com")) - assertThat(brand.getRemovePoweredByOkta(), equalTo(!removePoweredByOkta)) - - //restore previous values - if(!Strings.isNullOrEmpty(customPrivacyPolicyUrl)) { - brand.setAgreeToCustomPrivacyPolicy(true) - } - brand.setCustomPrivacyPolicyUrl(customPrivacyPolicyUrl) - brand.setRemovePoweredByOkta(removePoweredByOkta) - brand.update() - - assertThat(brand.getCustomPrivacyPolicyUrl(), equalTo(customPrivacyPolicyUrl)) - assertThat(brand.getRemovePoweredByOkta(), equalTo(removePoweredByOkta)) - } - - @Test (groups = "bacon") - @Scenario("basic-brand-theme") - void basicBrandThemeTest() { - - String brandId = getBrandId() - String themeId = getThemeId(brandId) - - ThemeResponse themeResponse = client.getBrandTheme(brandId, themeId) - String primaryColorHex = themeResponse.getPrimaryColorHex() - String secondaryColorHex = themeResponse.getSecondaryColorHex() - SignInPageTouchPointVariant signInPageTPV = themeResponse.getSignInPageTouchPointVariant() - EndUserDashboardTouchPointVariant endUserDashboardTPV = themeResponse.getEndUserDashboardTouchPointVariant() - ErrorPageTouchPointVariant errorPageTPV = themeResponse.getErrorPageTouchPointVariant() - EmailTemplateTouchPointVariant emailTemplateTPV = themeResponse.getEmailTemplateTouchPointVariant() - - Theme themeToUpdate = client.instantiate(Theme) - .setPrimaryColorHex("#1662dd") - .setSecondaryColorHex("#ebebed") - .setSignInPageTouchPointVariant(SignInPageTouchPointVariant.BACKGROUND_IMAGE) - .setEndUserDashboardTouchPointVariant(EndUserDashboardTouchPointVariant.FULL_THEME) - .setErrorPageTouchPointVariant(ErrorPageTouchPointVariant.BACKGROUND_IMAGE) - .setEmailTemplateTouchPointVariant(EmailTemplateTouchPointVariant.FULL_THEME) - ThemeResponse updatedThemeResponse = themeToUpdate.update(brandId, themeId, themeToUpdate) - - assertThat(updatedThemeResponse, notNullValue()) - assertThat(updatedThemeResponse.getPrimaryColorHex(), equalTo("#1662dd")) - assertThat(updatedThemeResponse.getSecondaryColorHex(), equalTo("#ebebed")) - assertThat(updatedThemeResponse.getSignInPageTouchPointVariant(), equalTo(SignInPageTouchPointVariant.BACKGROUND_IMAGE)) - assertThat(updatedThemeResponse.getEndUserDashboardTouchPointVariant(), equalTo(EndUserDashboardTouchPointVariant.FULL_THEME)) - assertThat(updatedThemeResponse.getErrorPageTouchPointVariant(), equalTo(ErrorPageTouchPointVariant.BACKGROUND_IMAGE)) - assertThat(updatedThemeResponse.getEmailTemplateTouchPointVariant(), equalTo(EmailTemplateTouchPointVariant.FULL_THEME)) - - //restore previous state - Theme themeToRestore = client.instantiate(Theme) - .setPrimaryColorHex(primaryColorHex) - .setSecondaryColorHex(secondaryColorHex) - .setSignInPageTouchPointVariant(signInPageTPV) - .setEndUserDashboardTouchPointVariant(endUserDashboardTPV) - .setErrorPageTouchPointVariant(errorPageTPV) - .setEmailTemplateTouchPointVariant(emailTemplateTPV) - themeToRestore.update(brandId, themeId, themeToRestore) - } - - @Test (groups = "bacon") - @Scenario("brand-theme-logo") - void brandThemeLogoTest() { - - String brandId = getBrandId() - String themeId = getThemeId(brandId) - File file = new File(pathToImage) - - ImageUploadResponse resp = client.instantiate(Theme).uploadBrandThemeLogo(brandId, themeId, file) - assertThat(resp, notNullValue()) - assertThat(resp.getUrl(), notNullValue()) - - client.instantiate(Theme).deleteBrandThemeLogo(brandId, themeId) - } - - @Test (groups = "bacon") - @Scenario("brand-theme-background-image") - void brandThemeBackgroundImageTest() { - - String brandId = getBrandId() - String themeId = getThemeId(brandId) - File file = new File(pathToImage) - - ImageUploadResponse resp = client.instantiate(Theme).updateBrandThemeBackgroundImage(brandId, themeId, file) - assertThat(resp, notNullValue()) - assertThat(resp.getUrl(), notNullValue()) - - client.instantiate(Theme).deleteBrandThemeBackgroundImage(brandId, themeId) - } - - @Test (groups = "bacon") - @Scenario("brand-theme-favicon") - void brandThemeFaviconTest() { - - String brandId = getBrandId() - String themeId = getThemeId(brandId) - File file = new File(pathToFavicon) - - ImageUploadResponse resp = client.instantiate(Theme).updateBrandThemeFavicon(brandId, themeId, file) - assertThat(resp, notNullValue()) - assertThat(resp.getUrl(), notNullValue()) - - client.instantiate(Theme).deleteBrandThemeFavicon(brandId, themeId) - } - - @Test (groups = "bacon") - void listEmailTemplatesTest() { - - BrandList brandList = client.listBrands() - assertThat(brandList, notNullValue()) - - Brand brand = brandList.first() - assertThat(brand, notNullValue()) - - EmailTemplateList emailTemplateList = client.listEmailTemplates(brand.getId()) - assertThat(emailTemplateList, notNullValue()) - - EmailTemplate emailTemplate = emailTemplateList.first() - assertThat(emailTemplate.getName(), notNullValue()) - } - - @Test (groups = "bacon") - void listEmailTemplateCustomizationsTest() { - - BrandList brandList = client.listBrands() - assertThat(brandList, notNullValue()) - - Brand brand = brandList.first() - assertThat(brand, notNullValue()) - - EmailTemplateList emailTemplateList = client.listEmailTemplates(brand.getId()) - assertThat(emailTemplateList, notNullValue()) - - EmailTemplate emailTemplate = emailTemplateList.first() - assertThat(emailTemplate, notNullValue()) - - EmailTemplateCustomizationList emailTemplateCustomizationList = - emailTemplate.listEmailTemplateCustomizations(brand.getId(), emailTemplate.getName()) - assertThat(emailTemplateCustomizationList, notNullValue()) - } - - @Test (groups = "bacon") - void getEmailTemplateCustomizationTest() { - - BrandList brandList = client.listBrands() - assertThat(brandList, notNullValue()) - - Brand brand = brandList.first() - assertThat(brand, notNullValue()) - - EmailTemplateList emailTemplateList = client.listEmailTemplates(brand.getId()) - assertThat(emailTemplateList, notNullValue()) - - EmailTemplate emailTemplate = emailTemplateList.first() - assertThat(emailTemplate, notNullValue()) - - EmailTemplateCustomizationList emailTemplateCustomizationList = - emailTemplate.listEmailTemplateCustomizations(brand.getId(), emailTemplate.getName()) - assertThat(emailTemplateCustomizationList, notNullValue()) - - EmailTemplateCustomization emailTemplateCustomization = - emailTemplate.getEmailTemplateCustomization(brand.getId(), emailTemplate.getName(), emailTemplateCustomizationList.first().getId()) - assertThat(emailTemplateCustomization, notNullValue()) - assertThat(emailTemplateCustomization.getSubject(), notNullValue()) - assertThat(emailTemplateCustomization.getBody(), notNullValue()) - } - - @Test (groups = "bacon") - void createUpdateAndDeleteEmailTemplateCustomizationTest() { - - String language = "uk" - - BrandList brandList = client.listBrands() - assertThat(brandList, notNullValue()) - - Brand brand = brandList.first() - assertThat(brand, notNullValue()) - - EmailTemplateList emailTemplateList = client.listEmailTemplates(brand.getId()) - assertThat(emailTemplateList, notNullValue()) - - EmailTemplate emailTemplate = emailTemplateList.first() - assertThat(emailTemplate, notNullValue()) - - EmailTemplateCustomizationRequest emailTemplateCustomizationRequest = client.instantiate(EmailTemplateCustomizationRequest) - .setBody("Test Customization - \${activationLink} \${activationToken}") - .setSubject("Test Subject - Java SDK IT") - .setLanguage(language) - .setIsDefault(false) - - EmailTemplateCustomization emailTemplateCustomization = - emailTemplate.createEmailTemplateCustomization(brand.getId(), emailTemplate.getName(), emailTemplateCustomizationRequest) - - assertThat(emailTemplateCustomization, notNullValue()) - assertThat(emailTemplateCustomization.getSubject(), is("Test Subject - Java SDK IT")) - assertThat(emailTemplateCustomization.getBody(), is("Test Customization - \${activationLink} \${activationToken}")) - assertThat(emailTemplateCustomization.getLanguage(), is(language)) - - EmailTemplateCustomizationRequest updateEmailTemplateCustomizationRequest = client.instantiate(EmailTemplateCustomizationRequest) - .setBody("Updated - Test Customization - \${activationLink} \${activationToken}") - .setSubject("Updated - Test Subject - Java SDK IT") - .setLanguage(language) - .setIsDefault(false) - - EmailTemplateCustomization updatedEmailTemplateCustomization = - emailTemplate.updateEmailTemplateCustomization(brand.getId(), emailTemplate.getName(), emailTemplateCustomization.getId(), updateEmailTemplateCustomizationRequest) - - assertThat(updatedEmailTemplateCustomization, notNullValue()) - assertThat(updatedEmailTemplateCustomization.getSubject(), is("Updated - Test Subject - Java SDK IT")) - assertThat(updatedEmailTemplateCustomization.getBody(), is("Updated - Test Customization - \${activationLink} \${activationToken}")) - assertThat(updatedEmailTemplateCustomization.getLanguage(), is(language)) - - EmailTemplateCustomization retrievedEmailTemplateCustomization = - emailTemplate.getEmailTemplateCustomization(brand.getId(), emailTemplate.getName(), updatedEmailTemplateCustomization.getId()) - - // delete if it is not the default one (Orgs consider the first created email template customization as a default one even if setIsDefault is set to true in create request) - // therefore, to prevent deletion errors we check for non-default before deletion. Note that only non-default template customizations can be deleted. - if (!retrievedEmailTemplateCustomization.getIsDefault()) { - emailTemplate.deleteEmailTemplateCustomization(brand.getId(), emailTemplate.getName(), updatedEmailTemplateCustomization.getId()) - } - } - - @Test (groups = "bacon") - void getEmailTemplateCustomizationPreviewTest() { - - BrandList brandList = client.listBrands() - assertThat(brandList, notNullValue()) - - Brand brand = brandList.first() - assertThat(brand, notNullValue()) - - EmailTemplateList emailTemplateList = client.listEmailTemplates(brand.getId()) - assertThat(emailTemplateList, notNullValue()) - - EmailTemplate emailTemplate = emailTemplateList.first() - assertThat(emailTemplate, notNullValue()) - - EmailTemplateCustomizationList emailTemplateCustomizationList = - emailTemplate.listEmailTemplateCustomizations(brand.getId(), emailTemplate.getName()) - assertThat(emailTemplateCustomizationList, notNullValue()) - - EmailTemplateContent emailTemplateCustomizationPreview = - emailTemplate.getEmailTemplateCustomizationPreview(brand.getId(), emailTemplate.getName(), emailTemplateCustomizationList.first().getId()) - assertThat(emailTemplateCustomizationPreview, notNullValue()) - assertThat(emailTemplateCustomizationPreview.getBody(), notNullValue()) - assertThat(emailTemplateCustomizationPreview.getSubject(), notNullValue()) - } - - @Test (groups = "bacon") - void getEmailTemplateDefaultContentTest() { - - BrandList brandList = client.listBrands() - assertThat(brandList, notNullValue()) - - Brand brand = brandList.first() - assertThat(brand, notNullValue()) - - EmailTemplateList emailTemplateList = client.listEmailTemplates(brand.getId()) - assertThat(emailTemplateList, notNullValue()) - - EmailTemplate emailTemplate = emailTemplateList.first() - assertThat(emailTemplate, notNullValue()) - - EmailTemplateCustomizationList emailTemplateCustomizationList = - emailTemplate.listEmailTemplateCustomizations(brand.getId(), emailTemplate.getName()) - assertThat(emailTemplateCustomizationList, notNullValue()) - - EmailTemplateContent emailTemplateDefaultContent = - emailTemplate.getEmailTemplateDefaultContent(brand.getId(), emailTemplate.getName()) - assertThat(emailTemplateDefaultContent, notNullValue()) - assertThat(emailTemplateDefaultContent.getBody(), notNullValue()) - assertThat(emailTemplateDefaultContent.getSubject(), notNullValue()) - } - - /** - * https://developer.okta.com/docs/reference/api/brands/#use-examples - * Currently, only one Brand per org is supported. - */ - String getBrandId() { - - BrandList brandList = client.listBrands() - assertThat(brandList, notNullValue()) - - assertThat(brandList.asList().size(), equalTo(1)) - Brand brandFromList = brandList[0] - return brandFromList.getId() - } - - /** - * https://developer.okta.com/docs/reference/api/brands/#use-examples-4 - * Currently, only one Theme per Brand is supported. - */ - String getThemeId(String brandId) { - - def themeList = client.listBrandThemes(brandId) - assertThat(themeList, notNullValue()) - - assertThat(themeList.asList().size(), equalTo(1)) - ThemeResponse themeFromList = themeList[0] - return themeFromList.getId() - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/CrudTestSupport.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/CrudTestSupport.groovy deleted file mode 100644 index 1a35bae664e..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/CrudTestSupport.groovy +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2017-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.ResourceException -import com.okta.sdk.tests.it.util.ClientProvider -import org.testng.Assert -import org.testng.annotations.Test - -import java.util.stream.Stream -import java.util.stream.StreamSupport - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Support for basic CRUD tests - */ -trait CrudTestSupport implements ClientProvider { - - @Test (groups = ["group1"]) - void basicCrudTest() { - - Client client = getClient() - preTestSetup(client) - - // Create a resource - def resource = create(client) - - // getting the resource again should result in the same object - def readResource = read(client, resource.id) - assertThat readResource, notNullValue() - assertThat readResource, equalTo(resource) - - // update the resource - update(client, resource) - assertUpdate(client, read(client, resource.id)) - - // delete the resource - delete(client, resource) - assertDelete(client, resource) - } - - @Test (groups = ["group1"]) - void basicListTest() { - - // Create a resource - def resource = create(client) - registerForCleanup(resource) - - // search the resource collection looking for the new resource - Optional optional = getResourceListStream(client) - .filter {it.id == resource.id} - .findFirst() - - // make sure it exists - assertThat "New resource with id ${resource.id} was not found in list resource.", optional.isPresent() - } - - void preTestSetup(Client client) {} - - abstract def create(Client client) - - abstract def read(Client client, String id) - - abstract Iterator getResourceCollectionIterator(Client client) - - abstract void update(Client client, def resource) - - abstract void assertUpdate(Client client, def resource) - - Stream getResourceListStream(Client client) { - return StreamSupport.stream(Spliterators.spliteratorUnknownSize(getResourceCollectionIterator(client), Spliterator.ORDERED),false) - } - - // delete - void delete(Client client, def resource) { - if (resource.getMetaClass().respondsTo(resource, "deactivate")) { - resource.deactivate() - } - resource.delete() - } - - void assertDelete(Client client, def resource) { - try { - read(client, resource.id) - Assert.fail("Expected ResourceException (404)") - } catch (ResourceException e) { - assertThat e.status, equalTo(404) - } - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/DomainIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/DomainIT.groovy deleted file mode 100644 index 22fb5bef879..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/DomainIT.groovy +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.ResourceException -import com.okta.sdk.resource.domain.Domain -import com.okta.sdk.resource.domain.DomainCertificateSourceType -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.Assert -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/domains}. - */ -class DomainIT extends ITSupport { - - @Test(groups = "group1", enabled = false) - void customTemplatesCrudTest() { - - String domain = "java-sdk-it-${UUID.randomUUID().toString()}.example.com" - - def domainCreated = client.createDomain( - client.instantiate(Domain) - .setDomain(domain) - .setCertificateSourceType(DomainCertificateSourceType.MANUAL) - ) - - assertThat(domainCreated, notNullValue()) - assertThat(domainCreated.getId(), notNullValue()) - assertThat(domainCreated.getDomain(), equalTo(domain)) - assertThat(domainCreated.getCertificateSourceType(), equalTo(DomainCertificateSourceType.MANUAL)) - - def domainFetched = client.getDomain(domainCreated.getId()) - - assertThat(domainFetched, notNullValue()) - assertThat(domainFetched.getId(), equalTo(domainCreated.getId())) - - client.deleteDomain(domainCreated.getId()) - - try { - client.verifyDomain(domainCreated.getId()) - Assert.fail("Expected ResourceException (404)") - } catch (ResourceException e) { - assertThat(e.status, equalTo(404)) - } - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/EventHooksIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/EventHooksIT.groovy deleted file mode 100644 index 9ae8c732643..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/EventHooksIT.groovy +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.ResourceException -import com.okta.sdk.resource.event.hook.EventHook -import com.okta.sdk.resource.event.hook.EventHookBuilder -import com.okta.sdk.resource.event.hook.EventHookChannelConfigAuthScheme -import com.okta.sdk.resource.event.hook.EventHookChannelConfigAuthSchemeType - -import com.okta.sdk.tests.it.util.ITSupport - -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.iterableWithSize -import static org.hamcrest.Matchers.notNullValue - -import static com.okta.sdk.tests.it.util.Util.assertPresent - -/** - * Tests for {@code /api/v1/eventHooks}. - * @since 2.0.0 - */ -class EventHooksIT extends ITSupport { - - @Test (groups = "group1") - void createEventHookTest() { - String name = "java-sdk-it-${UUID.randomUUID().toString()}" - - EventHook createdEventHook = EventHookBuilder.instance() - .setName(name) - .setUrl("https://www.example.com/eventHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdEventHook) - - assertThat(createdEventHook.getId(), notNullValue()) - assertThat(createdEventHook.getName(), equalTo(name)) - assertThat(createdEventHook.getStatus(), equalTo(EventHook.StatusEnum.ACTIVE)) - assertThat(createdEventHook.getEvents().getItems(), iterableWithSize(2)) - assertThat(createdEventHook.getChannel().getConfig().getUri(), equalTo("https://www.example.com/eventHooks")) - - createdEventHook.deactivate() - } - - @Test - void getEventHookTest() { - String name = "java-sdk-it-${UUID.randomUUID().toString()}" - - EventHook createdEventHook = EventHookBuilder.instance() - .setName(name) - .setUrl("https://www.example.com/eventHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdEventHook) - - assertThat(createdEventHook.getId(), notNullValue()) - - EventHook retrievedEventHook = client.getEventHook(createdEventHook.getId()) - - assertThat(retrievedEventHook.getId(), notNullValue()) - assertThat(retrievedEventHook.getName(), equalTo(name)) - assertThat(createdEventHook.getStatus(), equalTo(EventHook.StatusEnum.ACTIVE)) - assertThat(retrievedEventHook.getEvents().getItems(), iterableWithSize(2)) - assertThat(retrievedEventHook.getChannel().getConfig().getUri(), equalTo("https://www.example.com/eventHooks")) - - createdEventHook.deactivate() - } - - @Test - void updateEventHookTest() { - String name = "java-sdk-it-${UUID.randomUUID().toString()}" - - EventHook createdEventHook = EventHookBuilder.instance() - .setName(name) - .setUrl("https://www.example.com/eventHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdEventHook) - - assertThat(createdEventHook.getId(), notNullValue()) - - EventHook toBeUpdatedEventHook = createdEventHook.setName("updated-" + name) - createdEventHook.getEvents().getItems().add("user.lifecycle.deactivate") - createdEventHook.getChannel().getConfig().setAuthScheme(client.instantiate(EventHookChannelConfigAuthScheme) - .setType(EventHookChannelConfigAuthSchemeType.HEADER) - .setKey("Authorization") - .setValue("Test-Api-Key-Updated")) - .setUri("https://www.example.com/eventHooksUpdated") - - EventHook updatedEventHook = toBeUpdatedEventHook.update() - - assertThat(updatedEventHook.getId(), notNullValue()) - assertThat(updatedEventHook.getId(), equalTo(createdEventHook.getId())) - assertThat(createdEventHook.getStatus(), equalTo(EventHook.StatusEnum.ACTIVE)) - assertThat(updatedEventHook.getName(), equalTo("updated-" + name)) - assertThat(updatedEventHook.getEvents().getItems(), iterableWithSize(3)) - assertThat(updatedEventHook.getChannel().getConfig().getUri(), equalTo("https://www.example.com/eventHooksUpdated")) - - createdEventHook.deactivate() - } - - @Test - void deleteEventHookTest() { - String name = "java-sdk-it-${UUID.randomUUID().toString()}" - - EventHook createdEventHook = EventHookBuilder.instance() - .setName(name) - .setUrl("https://www.example.com/eventHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdEventHook) - - assertThat(createdEventHook.getId(), notNullValue()) - - EventHook retrievedEventHook = client.getEventHook(createdEventHook.getId()) - assertThat(retrievedEventHook.getId(), equalTo(createdEventHook.getId())) - assertThat(retrievedEventHook.getStatus(), equalTo(EventHook.StatusEnum.ACTIVE)) - - createdEventHook.deactivate() - createdEventHook.delete() - - try { - client.getEventHook(createdEventHook.getId()) - } - catch (ResourceException e) { - assertThat(e.status, equalTo(404)) - } - } - - @Test (groups = "group1") - void listAllEventHooksTest() { - String name = "java-sdk-it-${UUID.randomUUID().toString()}" - - EventHook createdEventHook = EventHookBuilder.instance() - .setName(name) - .setUrl("https://www.example.com/eventHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdEventHook) - - assertThat(createdEventHook.getId(), notNullValue()) - - assertPresent(client.listEventHooks(), createdEventHook) - - createdEventHook.deactivate() - } - - @Test - void activateDeactivateEventHookTest() { - String name = "java-sdk-it-${UUID.randomUUID().toString()}" - - EventHook createdEventHook = EventHookBuilder.instance() - .setName(name) - .setUrl("https://www.example.com/eventHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdEventHook) - - assertThat(createdEventHook.getId(), notNullValue()) - assertThat(createdEventHook.getStatus(), equalTo(EventHook.StatusEnum.ACTIVE)) - - createdEventHook.deactivate() - - EventHook retrievedEventHook = client.getEventHook(createdEventHook.getId()) - - assertThat(retrievedEventHook.getStatus(), equalTo(EventHook.StatusEnum.INACTIVE)) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/FactorsIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/FactorsIT.groovy deleted file mode 100644 index fc264e75e6a..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/FactorsIT.groovy +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2017-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.google.common.collect.Lists - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.user.User -import com.okta.sdk.resource.user.factor.ActivateFactorRequest -import com.okta.sdk.resource.user.factor.CallUserFactor -import com.okta.sdk.resource.user.factor.EmailUserFactor -import com.okta.sdk.resource.user.factor.EmailUserFactorProfile -import com.okta.sdk.resource.user.factor.FactorProvider -import com.okta.sdk.resource.user.factor.FactorStatus -import com.okta.sdk.resource.user.factor.FactorType -import com.okta.sdk.resource.user.factor.PushUserFactor -import com.okta.sdk.resource.user.factor.SecurityQuestionUserFactor -import com.okta.sdk.resource.user.factor.SecurityQuestionList -import com.okta.sdk.resource.user.factor.SmsUserFactor -import com.okta.sdk.resource.user.factor.TokenUserFactor -import com.okta.sdk.resource.user.factor.TotpUserFactor -import com.okta.sdk.resource.user.factor.UserFactor -import com.okta.sdk.resource.user.factor.UserFactorList -import com.okta.sdk.resource.user.factor.VerifyFactorRequest -import com.okta.sdk.resource.user.factor.VerifyUserFactorResponse -import com.okta.sdk.tests.NonOIEEnvironmentOnly -import com.okta.sdk.tests.it.util.ITSupport -import org.jboss.aerogear.security.otp.Totp -import org.testng.annotations.Test - -import static org.hamcrest.Matchers.* -import static org.hamcrest.MatcherAssert.assertThat - -class FactorsIT extends ITSupport { - - private String smsTestNumber = "185 635 15491" - - @Test - void factorListTest() { - - Client client = getClient() - User user = randomUser() - assertListFactors(user) - - SmsUserFactor smsUserFactor = client.instantiate(SmsUserFactor) - smsUserFactor.getProfile().setPhoneNumber(smsTestNumber) - user.enrollFactor(smsUserFactor) - - SecurityQuestionUserFactor securityQuestionUserFactor = client.instantiate(SecurityQuestionUserFactor) - securityQuestionUserFactor.getProfile() - .setQuestion("disliked_food") - .setAnswer("pizza") - user.enrollFactor(securityQuestionUserFactor) - - UserFactorList factorsList = user.listFactors() - List factorsArrayList = Lists.newArrayList(factorsList) - assertThat factorsArrayList, hasItems( - allOf( - instanceOf(SmsUserFactor), - hasProperty("id", is(smsUserFactor.getId())) - ), - allOf( - instanceOf(SecurityQuestionUserFactor), - hasProperty("id", is(securityQuestionUserFactor.getId())) - ) - ) - } - - @Test - void testSecurityQuestionFactorCreation() { - Client client = getClient() - User user = randomUser() - assertListFactors(user) - - SecurityQuestionUserFactor securityQuestionUserFactor = client.instantiate(SecurityQuestionUserFactor) - securityQuestionUserFactor.getProfile() - .setQuestion("disliked_food") - .setAnswer("pizza") - - assertThat securityQuestionUserFactor.id, nullValue() - assertThat securityQuestionUserFactor, sameInstance(user.enrollFactor(securityQuestionUserFactor)) - assertThat securityQuestionUserFactor.id, notNullValue() - } - - @Test - void testCallFactorCreation() { - Client client = getClient() - User user = randomUser() - assertListFactors(user) - - CallUserFactor callUserFactor = client.instantiate(CallUserFactor) - callUserFactor.getProfile().setPhoneNumber(smsTestNumber) - - assertThat callUserFactor.id, nullValue() - assertThat callUserFactor, sameInstance(user.enrollFactor(callUserFactor)) - assertThat callUserFactor.id, notNullValue() - } - - @Test - void testSmsFactorCreation() { - Client client = getClient() - User user = randomUser() - assertListFactors(user) - - SmsUserFactor smsUserFactor = client.instantiate(SmsUserFactor) - smsUserFactor.getProfile().setPhoneNumber(smsTestNumber) - - assertThat smsUserFactor.id, nullValue() - assertThat smsUserFactor, sameInstance(user.enrollFactor(smsUserFactor)) - assertThat smsUserFactor.id, notNullValue() - } - - @Test - void testPushFactorCreation() { - Client client = getClient() - User user = randomUser() - assertListFactors(user) - - PushUserFactor pushUserFactor = client.instantiate(PushUserFactor) - assertThat pushUserFactor.id, nullValue() - assertThat pushUserFactor, sameInstance(user.enrollFactor(pushUserFactor)) - assertThat pushUserFactor.id, notNullValue() - } - - @Test - void testListSecurityQuestionsNotEmpty() { - User user = randomUser() - SecurityQuestionList securityQuestions = user.listSupportedSecurityQuestions() - assertThat securityQuestions, iterableWithSize(greaterThan(1)) - } - - @Test (groups = "group3") - void testAvailableFactorsNotEmpty() { - User user = randomUser() - UserFactorList factors = user.listSupportedFactors() - assertThat factors, iterableWithSize(greaterThan(1)) - } - - @Test - void activateTotpFactor() { - User user = randomUser() - assertListFactors(user) - - TotpUserFactor totpUserFactor = client.instantiate(TotpUserFactor) - user.enrollFactor(totpUserFactor) - - assertThat totpUserFactor.getStatus(), is(FactorStatus.PENDING_ACTIVATION) - Totp totp = new Totp(totpUserFactor.getEmbedded().get("activation").get("sharedSecret")) - - ActivateFactorRequest activateFactorRequest = client.instantiate(ActivateFactorRequest) - activateFactorRequest.setPassCode(totp.now()) - UserFactor factorResult = totpUserFactor.activate(activateFactorRequest) - assertThat factorResult.getStatus(), is(FactorStatus.ACTIVE) - assertThat factorResult, instanceOf(TotpUserFactor) - } - - @Test - void verifyQuestionFactor() { - User user = randomUser() - - SecurityQuestionUserFactor securityQuestionUserFactor = client.instantiate(SecurityQuestionUserFactor) - securityQuestionUserFactor.getProfile() - .setQuestion("disliked_food") - .setAnswer("pizza") - user.enrollFactor(securityQuestionUserFactor) - - VerifyFactorRequest request = client.instantiate(VerifyFactorRequest) - request.setAnswer("pizza") - VerifyUserFactorResponse response = - securityQuestionUserFactor.verify(request, null, null, null, null, null) - assertThat response.getFactorResult(), is(VerifyUserFactorResponse.FactorResultEnum.SUCCESS) - } - - @Test - void verifyQuestionFactor_withoutBody() { - User user = randomUser() - - SecurityQuestionUserFactor securityQuestionUserFactor = client.instantiate(SecurityQuestionUserFactor) - securityQuestionUserFactor.getProfile() - .setQuestion("disliked_food") - .setAnswer("pizza") - user.enrollFactor(securityQuestionUserFactor) - - VerifyFactorRequest request = client.instantiate(VerifyFactorRequest).setAnswer("pizza") - VerifyUserFactorResponse response = securityQuestionUserFactor.setVerify(request).verify() - assertThat response.getFactorResult(), is(VerifyUserFactorResponse.FactorResultEnum.SUCCESS) - } - - @NonOIEEnvironmentOnly - @Test (groups = "group3") - void testEmailUserFactor() { - User user = randomUser() - assertThat user.listFactors(), emptyIterable() - - EmailUserFactor emailUserFactor = client.instantiate(EmailUserFactor) - .setFactorType(FactorType.EMAIL) - .setProvider(FactorProvider.OKTA) - .setProfile(client.instantiate(EmailUserFactorProfile) - .setEmail(user.getProfile().getEmail())) - - assertThat emailUserFactor.id, nullValue() - // enroll and activate - assertThat emailUserFactor, sameInstance(user.enrollFactor(emailUserFactor, false, null, null, true)) - assertThat emailUserFactor.getStatus(), is(FactorStatus.ACTIVE) - assertThat emailUserFactor.id, notNullValue() - - VerifyFactorRequest request = client.instantiate(VerifyFactorRequest) - VerifyUserFactorResponse response = - emailUserFactor.verify(request, null, null, null, null, null) - assertThat response.getFactorResult(), is(VerifyUserFactorResponse.FactorResultEnum.CHALLENGE) - } - - @Test (groups = "group3") - void testGoogleTotpUserFactorCreation() { - User user = randomUser() - assertListFactors(user) - - TokenUserFactor tokenUserFactor = client.instantiate(TokenUserFactor) - .setFactorType(FactorType.TOKEN_SOFTWARE_TOTP) - .setProvider(FactorProvider.GOOGLE) - - assertThat tokenUserFactor.id, nullValue() - assertThat tokenUserFactor, sameInstance(user.enrollFactor(tokenUserFactor)) - assertThat tokenUserFactor.id, notNullValue() - assertThat tokenUserFactor.getStatus(), is(FactorStatus.PENDING_ACTIVATION) - } - - @Test - void deleteFactorTest() { - - User user = randomUser() - assertListFactors(user) - TotpUserFactor totpUserFactor = client.instantiate(TotpUserFactor) - totpUserFactor.setProvider(FactorProvider.OKTA) - user.enrollFactor(totpUserFactor) - totpUserFactor.delete() - } - - void assertListFactors(User user) { - if(!isOIEEnvironment) { - assertThat user.listFactors(), emptyIterable() - } else { - assertThat user.listFactors(), hasItem( - allOf( - instanceOf(EmailUserFactor), - hasProperty("id", is(notNullValue())) - ) - ) - } - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/FeaturesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/FeaturesIT.groovy deleted file mode 100644 index 6a1a8912965..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/FeaturesIT.groovy +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.feature.Feature -import com.okta.sdk.resource.feature.FeatureList -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/features}. - * @since 2.0.0 - */ -class FeaturesIT extends ITSupport { - - @Test - void featureOperationsTest() { - // list features - FeatureList featureList = client.listFeatures() - assertThat(featureList, iterableWithSize(greaterThan(0))) - - // pick first one from the list - Feature feature = featureList.getAt(0) - assertThat(feature, notNullValue()) - - // get feature by id - Feature retrievedFeature = client.getFeature(feature.getId()) - assertThat(retrievedFeature, notNullValue()) - assertThat(retrievedFeature.getId(), equalTo(feature.getId())) - assertThat(retrievedFeature.getName(), equalTo(feature.getName())) - assertThat(retrievedFeature.getDescription(), equalTo(feature.getDescription())) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupRolesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupRolesIT.groovy deleted file mode 100644 index 027d32c73c6..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupRolesIT.groovy +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.group.GroupBuilder -import com.okta.sdk.resource.group.Group -import com.okta.sdk.resource.role.AssignRoleRequest -import com.okta.sdk.resource.role.RoleType -import com.okta.sdk.resource.user.Role -import com.okta.sdk.resource.user.RoleList -import com.okta.sdk.tests.Scenario -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test -import wiremock.org.apache.commons.lang3.RandomStringUtils - -import static com.okta.sdk.tests.it.util.Util.assertGroupPresent -import static com.okta.sdk.tests.it.util.Util.assertGroupAbsent -import static com.okta.sdk.tests.it.util.Util.assertRolePresent -import static com.okta.sdk.tests.it.util.Util.assertRoleAbsent -import static com.okta.sdk.tests.it.util.Util.validateGroup - -/** - * Tests for {@code /api/v1/groups/roles}. - * @since 2.0.0 - */ -class GroupRolesIT extends ITSupport { - - @Test (groups = "group1") - @Scenario("list-roles-assigned-to-group") - void listRolesAssignedToGroupTest() { - - String groupName = "java-sdk-it-" + RandomStringUtils.randomAlphanumeric(15) - - // 1. Create a new group - Group createdGroup = GroupBuilder.instance() - .setName(groupName) - .buildAndCreate(client) - registerForCleanup(createdGroup) - - validateGroup(createdGroup, groupName) - - // 2. List all groups and find the group created - assertGroupPresent(client.listGroups(), createdGroup) - - // 3. Create assign role requests - AssignRoleRequest userAdminRoleRequest = client.instantiate(AssignRoleRequest) - userAdminRoleRequest.setType(RoleType.USER_ADMIN) - - AssignRoleRequest appAdminRoleRequest = client.instantiate(AssignRoleRequest) - appAdminRoleRequest.setType(RoleType.APP_ADMIN) - - // 4. Assign USER_ADMIN & APP_ADMIN roles - Role userAdminRole = createdGroup.assignRole(userAdminRoleRequest) - Role appAdminRole = createdGroup.assignRole(appAdminRoleRequest) - - // fix flakiness seen in PDV tests - Thread.sleep(getTestOperationDelay()) - - // 5. List assigned group roles and check the assignments - RoleList roles = client.listGroupAssignedRoles(createdGroup.getId()) - - assertRolePresent(roles, userAdminRole) - assertRolePresent(roles, appAdminRole) - } - - @Test - @Scenario("unassigned-roles-for-group") - void unassignRoleForGroupTest() { - - String groupName = "java-sdk-it-" + RandomStringUtils.randomAlphanumeric(15) - - // 1. Create a new group - Group createdGroup = GroupBuilder.instance() - .setName(groupName) - .buildAndCreate(client) - registerForCleanup(createdGroup) - - validateGroup(createdGroup, groupName) - - // 2. List all groups and find the group created - assertGroupPresent(client.listGroups(), createdGroup) - - // 3. Create a USER_ADMIN role request - AssignRoleRequest userAdminRoleRequest = client.instantiate(AssignRoleRequest) - userAdminRoleRequest.setType(RoleType.USER_ADMIN) - - // 4. Assign the above role - Role userAdminRole = createdGroup.assignRole(userAdminRoleRequest) - - // 5. List assigned group roles and check the assignments - assertRolePresent(client.listGroupAssignedRoles(createdGroup.getId()), userAdminRole) - - // 6. Remove the role from group - client.removeRoleFromGroup(createdGroup.getId(), userAdminRole.getId()) - - // 7. List assigned group roles and check the assignments - assertRoleAbsent(client.listGroupAssignedRoles(createdGroup.getId()), userAdminRole) - } - - @Test - @Scenario("list-group-targets-for-group") - void listGroupTargetsForGroupTest() { - - String groupName1 = "java-sdk-it-" + RandomStringUtils.randomAlphanumeric(15) - String groupName2 = "java-sdk-it-" + RandomStringUtils.randomAlphanumeric(15) - - // 1. Create two groups - Group createdGroup1 = GroupBuilder.instance() - .setName(groupName1) - .buildAndCreate(client) - Group createdGroup2 = GroupBuilder.instance() - .setName(groupName2) - .buildAndCreate(client) - registerForCleanup(createdGroup1) - registerForCleanup(createdGroup2) - - validateGroup(createdGroup1, groupName1) - validateGroup(createdGroup2, groupName2) - - // 2. List all groups and find the groups created - assertGroupPresent(client.listGroups(), createdGroup1) - assertGroupPresent(client.listGroups(), createdGroup2) - - // 3. Create a USER_ADMIN role & assign it to the first group - Role userAdminRole = createdGroup1.assignRole(client.instantiate(AssignRoleRequest) - .setType(RoleType.USER_ADMIN)) - - // 4. Add second group as the admin target for the user admin role - userAdminRole.addAdminGroupTarget(createdGroup2.getId()) - - // 5. Verify the same - assertGroupPresent(client.listGroupTargetsForGroupRole(createdGroup1.getId(), userAdminRole.getId()), createdGroup2) - } - - @Test - @Scenario("list-group-targets-for-group") - void removeGroupTargetFromGroupAdministratorRoleGivenToGroupTest() { - - String groupName1 = "java-sdk-it-" + RandomStringUtils.randomAlphanumeric(15) - String groupName2 = "java-sdk-it-" + RandomStringUtils.randomAlphanumeric(15) - String groupName3 = "java-sdk-it-" + RandomStringUtils.randomAlphanumeric(15) - - // 1. Create three groups - Group createdGroup1 = GroupBuilder.instance() - .setName(groupName1) - .buildAndCreate(client) - Group createdGroup2 = GroupBuilder.instance() - .setName(groupName2) - .buildAndCreate(client) - Group createdGroup3 = GroupBuilder.instance() - .setName(groupName3) - .buildAndCreate(client) - registerForCleanup(createdGroup1) - registerForCleanup(createdGroup2) - registerForCleanup(createdGroup3) - - validateGroup(createdGroup1, groupName1) - validateGroup(createdGroup2, groupName2) - validateGroup(createdGroup3, groupName3) - - // 2. List all groups and find the groups created - assertGroupPresent(client.listGroups(), createdGroup1) - assertGroupPresent(client.listGroups(), createdGroup2) - assertGroupPresent(client.listGroups(), createdGroup3) - - // 3. Create a USER_ADMIN role & assign it to the first group - Role userAdminRole = createdGroup1.assignRole(client.instantiate(AssignRoleRequest) - .setType(RoleType.USER_ADMIN)) - - // 4. Add second group as the admin target for the user admin role - userAdminRole.addAdminGroupTarget(createdGroup2.getId()) - - // 5. Add third group as the admin target for the user admin role - userAdminRole.addAdminGroupTarget(createdGroup3.getId()) - - // 6. Verify if both the above targets (group 2 & group 3) are added - assertGroupPresent(client.listGroupTargetsForGroupRole(createdGroup1.getId(), userAdminRole.getId()), createdGroup2) - assertGroupPresent(client.listGroupTargetsForGroupRole(createdGroup1.getId(), userAdminRole.getId()), createdGroup3) - - // 7. Remove group 2 from the target - client.removeGroupTargetFromGroupAdministratorRoleGivenToGroup(createdGroup1.getId(), userAdminRole.getId(), createdGroup2.getId()) - - // 8. Verify that group 2 is removed from the target - assertGroupAbsent(client.listGroupTargetsForGroupRole(createdGroup1.getId(), userAdminRole.getId()), createdGroup2) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupRulesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupRulesIT.groovy deleted file mode 100644 index 336cd0190ae..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupRulesIT.groovy +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.group.Group -import com.okta.sdk.resource.group.GroupBuilder -import com.okta.sdk.resource.group.rule.* -import com.okta.sdk.resource.user.User -import com.okta.sdk.resource.user.UserBuilder -import com.okta.sdk.tests.Scenario -import com.okta.sdk.tests.TestResources -import org.testng.annotations.Test - -import static com.okta.sdk.tests.it.util.Util.assertPresent -import static com.okta.sdk.tests.it.util.Util.validateUser -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.matchesPattern - -/** - * Tests for {@code /api/v1/groups/rules}. - * @since 0.5.0 - */ -class GroupRulesIT implements CrudTestSupport { - - Group group - - void preTestSetup(Client client) { - group = GroupBuilder.instance() - .setName("java-sdk-it-" + UUID.randomUUID().toString()) - .setDescription("IT created Group") - .buildAndCreate(client) - } - - @Override - def create(Client client) { - - GroupRule rule = client.instantiate(GroupRule) - rule.setName("java-sdk-it-" + UUID.randomUUID().toString() ) - rule.setType("group_rule") - - rule.setConditions(client.instantiate(GroupRuleConditions)) - rule.getConditions().setExpression(client.instantiate(GroupRuleExpression)) - rule.getConditions().getExpression().setValue("user.firstName==\"Joe\"") - - rule.setActions(client.instantiate(GroupRuleAction)) - rule.getActions().setAssignUserToGroups(client.instantiate(GroupRuleGroupAssignment)) - rule.getActions().getAssignUserToGroups().setGroupIds(Collections.singletonList(group.getId())) - - rule = client.createGroupRule(rule) - registerForCleanup(rule) - - return rule - } - - @Override - def read(Client client, String id) { - return client.getGroupRule(id) - } - - @Override - void update(Client client, def rule) { - rule.setName(rule.name +"-2") - rule.update() - } - - @Override - void assertUpdate(Client client, def resource) { - assertThat resource.name, matchesPattern('^java-sdk-it-.*-2$') - } - - @Override - Iterator getResourceCollectionIterator(Client client) { - return client.listGroupRules().iterator() - } - - @Test (groups = "group1") - @Scenario("group-rule-operations") - @TestResources(rules = ["Test group rule", "Test group rule updated"]) - void groupRuleCrudTest() { - - def password = 'Passw0rd!2@3#' - def firstName = 'John' - def lastName = 'With-Group-Rule' - def email = "john-${uniqueTestName}@example.com" - def groupName = "java-sdk-it-" + UUID.randomUUID().toString() - def groupRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - - // 1. Create a user and a group - User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) - registerForCleanup(user) - validateUser(user, firstName, lastName, email) - - registerForCleanup(group) - - // 2. Create a group rule and verify rule executes - GroupRule rule = GroupRuleBuilder.instance() - .setType("group_rule") - .setName(groupRuleName) - .setGroupRuleExpressionType("urn:okta:expression:1.0") - .setGroupRuleExpressionValue("user.lastName==\"${user.getProfile().lastName}\"".toString()) - .setAssignUserToGroups(Collections.singletonList(group.getId())) - .buildAndCreate(client) - registerForCleanup(rule) - rule.activate() - - GroupRule readRule = client.getGroupRule(rule.getId()) - assertThat readRule.getStatus(), equalTo(GroupRuleStatus.ACTIVE) - - // 3. List group rules - assertPresent(client.listGroupRules(), rule) - - // 4. Deactivate the rule and update it - rule.deactivate() - - rule.name = ("updated-" + groupRuleName).subSequence(0, 50) //Trim the name to 50 chars (server limit) - rule.getConditions().getExpression().value = 'user.lastName==\"incorrect\"' - rule.update() - rule.activate() - - readRule = client.getGroupRule(rule.getId()) - assertThat readRule.getStatus(), equalTo(GroupRuleStatus.ACTIVE) - - // 5. delete rule - rule.deactivate() - rule.delete() - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupSchemaIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupSchemaIT.groovy deleted file mode 100644 index 064f135e74f..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupSchemaIT.groovy +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2021-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.group.schema.GroupSchema -import com.okta.sdk.resource.group.schema.GroupSchemaAttribute -import com.okta.sdk.resource.user.schema.UserSchemaAttributeMaster -import com.okta.sdk.resource.user.schema.UserSchemaAttributeMasterType -import com.okta.sdk.resource.user.schema.UserSchemaAttributePermission -import com.okta.sdk.resource.user.schema.UserSchemaAttributeScope -import com.okta.sdk.resource.user.schema.UserSchemaAttributeType -import com.okta.sdk.tests.Scenario -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test -import org.testng.collections.Lists -import wiremock.org.apache.commons.lang3.RandomStringUtils - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/meta/schemas/group/default}. - * @since 6.x.x - */ -class GroupSchemaIT extends ITSupport { - - @Test - @Scenario("get-group-schema") - void getGroupSchemaTest() { - - GroupSchema schema = client.getGroupSchema() - assertThat(schema, notNullValue()) - assertThat(schema.getId(), notNullValue()) - assertThat(schema.getDescription(), notNullValue()) - assertThat(schema.getName(), notNullValue()) - assertThat(schema.getSchema(), notNullValue()) - assertThat(schema.getTitle(), notNullValue()) - assertThat(schema.getType(), notNullValue()) - assertThat(schema.getType(), equalTo("object")) - assertThat(schema.getDefinitions(), notNullValue()) - assertThat(schema.getDefinitions().getBase(), notNullValue()) - assertThat(schema.getDefinitions().getBase().getId(), notNullValue()) - assertThat(schema.getDefinitions().getBase().getType(), notNullValue()) - assertThat(schema.getDefinitions().getBase().getType(), equalTo("object")) - } - - @Test (groups = "group2") - @Scenario("update-group-schema") - void updateGroupSchemaTest() { - - String customPropertyKey = "java_sdk_it_custom_property_" + RandomStringUtils.randomAlphanumeric(10) - GroupSchema schema = client.getGroupSchema() - schema.getDefinitions().getCustom().getProperties().put(customPropertyKey, - client.instantiate(GroupSchemaAttribute) - .setDescription("exampleCustomPropertyDescription") - .setMaxLength(20) - .setMinLength(1) - .setMutability("READ_WRITE") - .setPermissions(Lists.newArrayList( - client.instantiate(UserSchemaAttributePermission) - .setAction("READ_WRITE") - .setPrincipal("SELF")) - ) - .setRequired(false) - .setScope(UserSchemaAttributeScope.NONE) - .setTitle("exampleCustomPropertyTitle") - .setType(UserSchemaAttributeType.STRING) - .setUnique("UNIQUE_VALIDATED") - ) - - GroupSchema updatedSchema = client.updateGroupSchema(schema) - assertThat(updatedSchema.getId(), equalTo(schema.getId())) - def groupSchemaAttribute = updatedSchema.getDefinitions().getCustom().getProperties().get(customPropertyKey) - assertThat(groupSchemaAttribute, notNullValue()) - assertThat(groupSchemaAttribute["description"], equalTo("exampleCustomPropertyDescription")) - assertThat(groupSchemaAttribute["maxLength"], equalTo(20)) - assertThat(groupSchemaAttribute["minLength"], equalTo(1)) - assertThat(groupSchemaAttribute["mutability"], equalTo("READ_WRITE")) - assertThat(groupSchemaAttribute["permissions"], containsInAnyOrder(allOf( - hasEntry("action", "READ_WRITE"), - hasEntry("principal", "SELF"), - ))) - assertThat(groupSchemaAttribute["scope"], equalTo(UserSchemaAttributeScope.NONE.toString())) - assertThat(groupSchemaAttribute["title"], equalTo("exampleCustomPropertyTitle")) - assertThat(groupSchemaAttribute["type"], equalTo(UserSchemaAttributeType.STRING.toString())) - assertThat(groupSchemaAttribute["unique"], equalTo("UNIQUE_VALIDATED")) - - updatedSchema.getDefinitions().getCustom().getProperties().put(customPropertyKey, null) - GroupSchema restoredSchema = client.updateGroupSchema(updatedSchema) - assertThat(restoredSchema.getId(), equalTo(updatedSchema.getId())) - assertThat(restoredSchema.getDefinitions().getCustom().getProperties().get(customPropertyKey), nullValue()) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupsIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupsIT.groovy index 0217e885f4f..e0e78166397 100644 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupsIT.groovy +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/GroupsIT.groovy @@ -1,7 +1,7 @@ /* * Copyright 2017-Present Okta, Inc. * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the "License") * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * @@ -15,57 +15,28 @@ */ package com.okta.sdk.tests.it -import com.okta.sdk.client.Client -import com.okta.sdk.resource.group.Group -import com.okta.sdk.resource.group.GroupBuilder -import com.okta.sdk.resource.user.UserBuilder import com.okta.sdk.tests.Scenario import com.okta.sdk.tests.it.util.ITSupport +import com.okta.sdk.resource.group.GroupBuilder +import com.okta.sdk.resource.user.UserBuilder +import org.openapitools.client.api.GroupApi +import org.openapitools.client.api.UserApi +import org.openapitools.client.model.Group import org.testng.annotations.Test +import java.nio.charset.StandardCharsets + import static com.okta.sdk.tests.it.util.Util.assertGroupPresent -import static com.okta.sdk.tests.it.util.Util.assertPresent import static com.okta.sdk.tests.it.util.Util.assertUserInGroup import static com.okta.sdk.tests.it.util.Util.assertUserNotInGroup import static com.okta.sdk.tests.it.util.Util.validateGroup import static com.okta.sdk.tests.it.util.Util.validateUser -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* /** - * Tests for {@code /api/v1/groups}. + * Tests for {@code /api/v1/apps}. * @since 0.5.0 */ -class GroupsIT extends ITSupport implements CrudTestSupport { - - @Override - def create(Client client) { - return GroupBuilder.instance() - .setName("java-sdk-it-" + UUID.randomUUID().toString()) - .setDescription("IT created Group") - .buildAndCreate(client) - } - - @Override - def read(Client client, String id) { - return client.getGroup(id) - } - - @Override - void update(Client client, def group) { - group.getProfile().description = "IT created Group - Updated" - group.update() - } - - @Override - void assertUpdate(Client client, def resource) { - assertThat resource.getProfile().description, equalTo("IT created Group - Updated") - } - - @Override - Iterator getResourceCollectionIterator(Client client) { - return client.listGroups().iterator() - } +class GroupsIT extends ITSupport { @Test (groups = "group1") @Scenario("list-groups") @@ -73,16 +44,18 @@ class GroupsIT extends ITSupport implements CrudTestSupport { String groupName = "sdk-java List Test Group ${uniqueTestName}" + GroupApi groupApi = new GroupApi(getClient()) + // 1. Create a new group Group createdGroup = GroupBuilder.instance() .setName(groupName) - .buildAndCreate(client) + .buildAndCreate(groupApi) registerForCleanup(createdGroup) validateGroup(createdGroup, groupName) // 2. List all groups and find the group created - assertGroupPresent(client.listGroups(), createdGroup) + assertGroupPresent(groupApi.listGroups(null, null, null, null, null, null), createdGroup) } @Test (groups = "group1") @@ -91,33 +64,39 @@ class GroupsIT extends ITSupport implements CrudTestSupport { String groupName = "Search Test Group ${uniqueTestName}" + GroupApi groupApi = new GroupApi(getClient()) + // 1. Create a new group Group group = GroupBuilder.instance() .setName(groupName) - .buildAndCreate(client) + .buildAndCreate(groupApi) registerForCleanup(group) validateGroup(group, groupName) // 2. Search the group by name - assertPresent(client.listGroups(groupName, null, null), group) + assertGroupPresent(groupApi.listGroups(groupName, null, null, null, null, null), group) } - @Test (groups = "bacon") + // disabled due to an issue in backend infrastructure at the moment + @Test (enabled = false, groups = "bacon") @Scenario("search-groups-by-search-parameter") void searchGroupsBySearchParameterTest() { String groupName = "Search Test Group ${uniqueTestName}" + GroupApi groupApi = new GroupApi(getClient()) + // 1. Create a new group Group group = GroupBuilder.instance() .setName(groupName) - .buildAndCreate(client) + .buildAndCreate(groupApi) registerForCleanup(group) validateGroup(group, groupName) // 2. Search the group by search parameter Thread.sleep(getTestOperationDelay()) - assertPresent(client.listGroups(null, "profile.name eq \"" + groupName + "\"", null), group) + + assertGroupPresent(groupApi.listGroups(null, null, null, null, null, "profile.name eq \"" + groupName + "\""), group) } @Test @@ -127,17 +106,20 @@ class GroupsIT extends ITSupport implements CrudTestSupport { String groupName = "Update Test Group ${uniqueTestName}" String groupNameUpdated = "${groupName} - Updated" + GroupApi groupApi = new GroupApi(getClient()) + // 1. Create a new group Group group = GroupBuilder.instance() - .setName(groupName) - .buildAndCreate(client) + .setName(groupName) + .buildAndCreate(groupApi) registerForCleanup(group) validateGroup(group, groupName) // 2. Update the group name and description group.getProfile().name = groupNameUpdated group.getProfile().description = 'Description updated' - group.update() + + groupApi.replaceGroup(group.getId(), group) validateGroup(group, groupNameUpdated, 'Description updated') } @@ -151,33 +133,36 @@ class GroupsIT extends ITSupport implements CrudTestSupport { def lastName = 'With-Group' def email = "john-with-group-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + GroupApi groupApi = new GroupApi(getClient()) + // 1. Create a user and a group def user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(false) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(false) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) String groupName = "Group-Member API Test Group ${uniqueTestName}" Group group = GroupBuilder.instance() - .setName(groupName) - .buildAndCreate(client) + .setName(groupName) + .buildAndCreate(groupApi) registerForCleanup(group) validateGroup(group, groupName) // 2. Add user to the group and validate user present in group - user.addToGroup(group.getId()) + groupApi.assignUserToGroup(group.getId(), user.getId()) - assertUserInGroup(user, group, 5, getTestOperationDelay()) + assertUserInGroup(user, group, groupApi, 5, getTestOperationDelay()) // 3. Remove user from group and validate user removed - group.removeUser(user.getId()) + groupApi.unassignUserFromGroup(group.getId(), user.getId()) - assertUserNotInGroup(user, group, 5, getTestOperationDelay()) + assertUserNotInGroup(user, group, groupApi,5, getTestOperationDelay()) } -} +} \ No newline at end of file diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/IdpIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/IdpIT.groovy index f17fe5a133c..4d37b1864a7 100644 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/IdpIT.groovy +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/IdpIT.groovy @@ -1,7 +1,7 @@ /* * Copyright 2020-Present Okta, Inc. * - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the "License") * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * @@ -15,14 +15,11 @@ */ package com.okta.sdk.tests.it -import com.okta.sdk.resource.identity.provider.* -import com.okta.sdk.resource.policy.* -import com.okta.sdk.resource.user.User -import com.okta.sdk.resource.user.UserBuilder import com.okta.sdk.tests.it.util.ITSupport +import org.openapitools.client.api.IdentityProviderApi +import org.openapitools.client.model.* import org.testng.annotations.Test -import static com.okta.sdk.tests.it.util.Util.* import static org.hamcrest.MatcherAssert.assertThat import static org.hamcrest.Matchers.* @@ -37,105 +34,211 @@ class IdpIT extends ITSupport { String name = "java-sdk-it-" + UUID.randomUUID().toString() - // create idp - IdentityProvider createdIdp = IdentityProviderBuilders.oidc() - .setName(name) - .setIssuerMode(IdentityProvider.IssuerModeEnum.ORG_URL) - .setRequestSignatureAlgorithm("SHA-256") - .setRequestSignatureScope(ProtocolAlgorithmTypeSignature.ScopeEnum.REQUEST) - .setResponseSignatureAlgorithm("SHA-256") - .setResponseSignatureScope(ProtocolAlgorithmTypeSignature.ScopeEnum.ANY) - .setAcsEndpointBinding(ProtocolEndpoint.BindingEnum.POST) - .setAcsEndpointType(ProtocolEndpoint.TypeEnum.INSTANCE) - .setAuthorizationEndpointBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setAuthorizationEndpointUrl("https://idp.example.com/authorize") - .setTokenEndpointBinding(ProtocolEndpoint.BindingEnum.POST) - .setTokenEndpointUrl("https://idp.example.com/token") - .setUserInfoEndpointBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setUserInfoEndpointUrl("https://idp.example.com/userinfo") - .setJwksEndpointBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setJwksEndpointUrl("https://idp.example.com/keys") - .setScopes(["openid", "profile", "email"]) - .setClientId("your-client-id") - .setClientSecret("your-client-secret") - .setIssuerUrl("https://idp.example.com") - .setMaxClockSkew(120000) - .setUserName("idpuser.email") - .setMatchType(PolicySubjectMatchType.USERNAME) - .buildAndCreate(client) + // create oidc idp + IdentityProviderApi identityProviderApi = new IdentityProviderApi(getClient()) + IdentityProvider idp = new IdentityProvider() + idp.setName(name) + idp.setType(IdentityProviderType.OIDC) + idp.setIssuerMode(IssuerMode.ORG_URL) + Protocol protocol = new Protocol() + + ProtocolAlgorithmType protocolAlgorithmTypeReq = new ProtocolAlgorithmType() + ProtocolAlgorithmType protocolAlgorithmTypeRes = new ProtocolAlgorithmType() + ProtocolAlgorithmTypeSignature protocolAlgorithmTypeSignature_Req = new ProtocolAlgorithmTypeSignature() + protocolAlgorithmTypeSignature_Req.setScope(ProtocolAlgorithmTypeSignatureScope.REQUEST) + protocolAlgorithmTypeSignature_Req.setAlgorithm("SHA-256") + protocolAlgorithmTypeReq.setSignature(protocolAlgorithmTypeSignature_Req) + ProtocolAlgorithmTypeSignature protocolAlgorithmTypeSignature_Res = new ProtocolAlgorithmTypeSignature() + protocolAlgorithmTypeSignature_Res.setScope(ProtocolAlgorithmTypeSignatureScope.RESPONSE) + protocolAlgorithmTypeSignature_Res.setAlgorithm("SHA-256") + protocolAlgorithmTypeRes.setSignature(protocolAlgorithmTypeSignature_Res) + + ProtocolAlgorithms protocolAlgorithms = new ProtocolAlgorithms() + protocolAlgorithms.setRequest(protocolAlgorithmTypeReq) + protocolAlgorithms.setResponse(protocolAlgorithmTypeRes) + protocol.setAlgorithms(protocolAlgorithms) + List scopes = Arrays.asList("openid", "profile", "email") + protocol.setScopes(scopes) + protocol.setType(ProtocolType.OIDC) + + ProtocolEndpoint protocolEndpointIssuer = new ProtocolEndpoint() + protocolEndpointIssuer.setUrl("https://idp.example.com") + protocol.setIssuer(protocolEndpointIssuer) + IdentityProviderCredentials identityProviderCredentials = new IdentityProviderCredentials() + IdentityProviderCredentialsClient identityProviderCredentialsClient = new IdentityProviderCredentialsClient() + identityProviderCredentialsClient.setClientId("your-client-id") + identityProviderCredentialsClient.setClientSecret("your-client-secret") + identityProviderCredentials.setClient(identityProviderCredentialsClient) + protocol.setCredentials(identityProviderCredentials) + + ProtocolEndpoints protocolEndpoints = new ProtocolEndpoints() + ProtocolEndpoint protocolEndpointAcs = new ProtocolEndpoint() + protocolEndpointAcs.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointAcs.setType(ProtocolEndpointType.INSTANCE) + + ProtocolEndpoint protocolEndpointAuthorization = new ProtocolEndpoint() + protocolEndpointAuthorization.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointAuthorization.setUrl("https://idp.example.com/authorize") + + ProtocolEndpoint protocolEndpointToken = new ProtocolEndpoint() + protocolEndpointToken.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointToken.setUrl("https://idp.example.com/token") + + ProtocolEndpoint protocolEndpointUserInfo = new ProtocolEndpoint() + protocolEndpointUserInfo.setBinding(ProtocolEndpointBinding.REDIRECT) + protocolEndpointUserInfo.setUrl("https://idp.example.com/userinfo") + + ProtocolEndpoint protocolEndpointJwks = new ProtocolEndpoint() + protocolEndpointJwks.setBinding(ProtocolEndpointBinding.REDIRECT) + protocolEndpointJwks.setUrl("https://idp.example.com/keys") + + protocolEndpoints.setAcs(protocolEndpointAcs) + protocolEndpoints.setAuthorization(protocolEndpointAuthorization) + protocolEndpoints.setToken(protocolEndpointToken) + protocolEndpoints.setUserInfo(protocolEndpointUserInfo) + protocolEndpoints.setJwks(protocolEndpointJwks) + protocol.setEndpoints(protocolEndpoints) + idp.setProtocol(protocol) + + IdentityProviderPolicy identityProviderPolicy = new IdentityProviderPolicy() + PolicyAccountLink policyAccountLink = new PolicyAccountLink() + policyAccountLink.setAction(PolicyAccountLinkAction.AUTO) + identityProviderPolicy.setAccountLink(policyAccountLink) + Provisioning provisioning = new Provisioning() + provisioning.setAction(ProvisioningAction.AUTO) + ProvisioningConditions provisioningConditions = new ProvisioningConditions() + ProvisioningDeprovisionedCondition provisioningDeprovisionedConditionDeprov = new ProvisioningDeprovisionedCondition() + provisioningDeprovisionedConditionDeprov.setAction(ProvisioningDeprovisionedAction.NONE) + provisioningConditions.setDeprovisioned(provisioningDeprovisionedConditionDeprov) + ProvisioningSuspendedCondition provisioningDeprovisionedConditionSusp = new ProvisioningSuspendedCondition() + provisioningDeprovisionedConditionSusp.setAction(ProvisioningSuspendedAction.NONE) + provisioningConditions.setSuspended(provisioningDeprovisionedConditionSusp) + provisioning.setConditions(provisioningConditions) + identityProviderPolicy.setProvisioning(provisioning) + identityProviderPolicy.setMaxClockSkew(1000) + ProvisioningGroups provisioningGroups = new ProvisioningGroups() + provisioningGroups.setAction(ProvisioningGroupsAction.NONE) + provisioning.setGroups(provisioningGroups) + identityProviderPolicy.setProvisioning(provisioning) + PolicySubject policySubject = new PolicySubject() + PolicyUserNameTemplate policyUserNameTemplate = new PolicyUserNameTemplate() + policyUserNameTemplate.setTemplate("idpuser.email") + policySubject.setUserNameTemplate(policyUserNameTemplate) + policySubject.setMatchType(PolicySubjectMatchType.USERNAME) + identityProviderPolicy.setSubject(policySubject) + idp.setPolicy(identityProviderPolicy) + + IdentityProvider createdIdp = identityProviderApi.createIdentityProvider(idp) registerForCleanup(createdIdp) assertThat(createdIdp, notNullValue()) assertThat(createdIdp.getId(), notNullValue()) assertThat(createdIdp.getName(), equalTo(name)) - assertThat(createdIdp.getStatus(), equalTo(IdentityProvider.StatusEnum.ACTIVE)) + assertThat(createdIdp.getStatus(), equalTo(LifecycleStatus.ACTIVE)) - // get - IdentityProvider retrievedIdp = client.getIdentityProvider(createdIdp.getId()) + // retrieve + IdentityProvider retrievedIdp = identityProviderApi.getIdentityProvider(createdIdp.getId()) assertThat(retrievedIdp.getId(), equalTo(createdIdp.getId())) // update String newName = "java-sdk-it-" + UUID.randomUUID().toString() - IdentityProvider updatedIdp = createdIdp.update(client.instantiate(IdentityProvider) - .setType(IdentityProvider.TypeValues.OIDC) - .setName(newName) - .setIssuerMode(IdentityProvider.IssuerModeEnum.ORG_URL) - .setProtocol(client.instantiate(Protocol) - .setAlgorithms(client.instantiate(ProtocolAlgorithms) - .setRequest(client.instantiate(ProtocolAlgorithmType) - .setSignature(client.instantiate(ProtocolAlgorithmTypeSignature) - .setAlgorithm("SHA-256") - .setScope(ProtocolAlgorithmTypeSignature.ScopeEnum.REQUEST))) - .setResponse(client.instantiate(ProtocolAlgorithmType) - .setSignature(client.instantiate(ProtocolAlgorithmTypeSignature) - .setAlgorithm("SHA-256") - .setScope(ProtocolAlgorithmTypeSignature.ScopeEnum.ANY)))) - .setEndpoints(client.instantiate(ProtocolEndpoints) - .setAcs(client.instantiate(ProtocolEndpoint) - .setBinding(ProtocolEndpoint.BindingEnum.POST) - .setType(ProtocolEndpoint.TypeEnum.INSTANCE)) - .setAuthorization(client.instantiate(ProtocolEndpoint) - .setBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setUrl("https://idp.example.com/authorize_new")) - .setToken(client.instantiate(ProtocolEndpoint) - .setBinding(ProtocolEndpoint.BindingEnum.POST) - .setUrl("https://idp.example.com/token_new")) - .setUserInfo(client.instantiate(ProtocolEndpoint) - .setBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setUrl("https://idp.example.com/userinfo_new")) - .setJwks(client.instantiate(ProtocolEndpoint) - .setBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setUrl("https://idp.example.com/keys_new"))) - .setScopes(["openid", "profile", "email"]) - .setType(Protocol.TypeEnum.OIDC) - .setCredentials(client.instantiate(IdentityProviderCredentials) - .setClient(client.instantiate(IdentityProviderCredentialsClient) - .setClientId("your-new-client-id") - .setClientSecret("your-new-client-secret"))) - .setIssuer(client.instantiate(ProtocolEndpoint) - .setUrl("https://idp.example.com/new"))) - .setPolicy(client.instantiate(IdentityProviderPolicy) - .setAccountLink(client.instantiate(PolicyAccountLink) - .setAction(PolicyAccountLink.ActionEnum.AUTO) - .setFilter(null)) - .setProvisioning(client.instantiate(Provisioning) - .setAction(Provisioning.ActionEnum.AUTO) - .setConditions(client.instantiate(ProvisioningConditions) - .setDeprovisioned(client.instantiate(ProvisioningDeprovisionedCondition) - .setAction(ProvisioningDeprovisionedCondition.ActionEnum.NONE)) - .setSuspended(client.instantiate(ProvisioningSuspendedCondition) - .setAction(ProvisioningSuspendedCondition.ActionEnum.NONE))) - .setGroups(client.instantiate(ProvisioningGroups) - .setAction(ProvisioningGroups.ActionEnum.NONE))) - .setMaxClockSkew(120000) - .setSubject(client.instantiate(PolicySubject) - .setUserNameTemplate(client.instantiate(PolicyUserNameTemplate) - .setTemplate("idpuser.email")) - .setMatchType(PolicySubjectMatchType.USERNAME)))) - registerForCleanup(updatedIdp) - - IdentityProvider retrievedUpdatedIdp = client.getIdentityProvider(updatedIdp.getId()) + IdentityProvider newIdp = new IdentityProvider() + newIdp.setName(newName) + newIdp.setType(IdentityProviderType.OIDC) + newIdp.setIssuerMode(IssuerMode.ORG_URL) + protocol = new Protocol() + + protocolAlgorithmTypeReq = new ProtocolAlgorithmType() + protocolAlgorithmTypeRes = new ProtocolAlgorithmType() + protocolAlgorithmTypeSignature_Req = new ProtocolAlgorithmTypeSignature() + protocolAlgorithmTypeSignature_Req.setScope(ProtocolAlgorithmTypeSignatureScope.REQUEST) + protocolAlgorithmTypeSignature_Req.setAlgorithm("SHA-256") + protocolAlgorithmTypeReq.setSignature(protocolAlgorithmTypeSignature_Req) + protocolAlgorithmTypeSignature_Res = new ProtocolAlgorithmTypeSignature() + protocolAlgorithmTypeSignature_Res.setScope(ProtocolAlgorithmTypeSignatureScope.RESPONSE) + protocolAlgorithmTypeSignature_Res.setAlgorithm("SHA-256") + protocolAlgorithmTypeRes.setSignature(protocolAlgorithmTypeSignature_Res) + + protocolAlgorithms = new ProtocolAlgorithms() + protocolAlgorithms.setRequest(protocolAlgorithmTypeReq) + protocolAlgorithms.setResponse(protocolAlgorithmTypeRes) + protocol.setAlgorithms(protocolAlgorithms) + protocol.setScopes(scopes) + protocol.setType(ProtocolType.OIDC) + + protocolEndpointIssuer = new ProtocolEndpoint() + protocolEndpointIssuer.setUrl("https://idp.example.com/new") + protocol.setIssuer(protocolEndpointIssuer) + identityProviderCredentials = new IdentityProviderCredentials() + identityProviderCredentialsClient = new IdentityProviderCredentialsClient() + identityProviderCredentialsClient.setClientId("your-new-client-id") + identityProviderCredentialsClient.setClientSecret("your-new-client-secret") + identityProviderCredentials.setClient(identityProviderCredentialsClient) + protocol.setCredentials(identityProviderCredentials) + + protocolEndpoints = new ProtocolEndpoints() + protocolEndpointAcs = new ProtocolEndpoint() + protocolEndpointAcs.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointAcs.setType(ProtocolEndpointType.INSTANCE) + + protocolEndpointAuthorization = new ProtocolEndpoint() + protocolEndpointAuthorization.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointAuthorization.setUrl("https://idp.example.com/authorize_new") + + protocolEndpointToken = new ProtocolEndpoint() + protocolEndpointToken.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointToken.setUrl("https://idp.example.com/token_new") + + protocolEndpointUserInfo = new ProtocolEndpoint() + protocolEndpointUserInfo.setBinding(ProtocolEndpointBinding.REDIRECT) + protocolEndpointUserInfo.setUrl("https://idp.example.com/userinfo_new") + + protocolEndpointJwks = new ProtocolEndpoint() + protocolEndpointJwks.setBinding(ProtocolEndpointBinding.REDIRECT) + protocolEndpointJwks.setUrl("https://idp.example.com/keys_new") + + protocolEndpoints.setAcs(protocolEndpointAcs) + protocolEndpoints.setAuthorization(protocolEndpointAuthorization) + protocolEndpoints.setToken(protocolEndpointToken) + protocolEndpoints.setUserInfo(protocolEndpointUserInfo) + protocolEndpoints.setJwks(protocolEndpointJwks) + protocol.setEndpoints(protocolEndpoints) + newIdp.setProtocol(protocol) + + identityProviderPolicy = new IdentityProviderPolicy() + policyAccountLink = new PolicyAccountLink() + policyAccountLink.setAction(PolicyAccountLinkAction.AUTO) + identityProviderPolicy.setAccountLink(policyAccountLink) + provisioning = new Provisioning() + provisioning.setAction(ProvisioningAction.AUTO) + provisioningConditions = new ProvisioningConditions() + provisioningDeprovisionedConditionDeprov = new ProvisioningDeprovisionedCondition() + provisioningDeprovisionedConditionDeprov.setAction(ProvisioningDeprovisionedAction.NONE) + provisioningConditions.setDeprovisioned(provisioningDeprovisionedConditionDeprov) + provisioningDeprovisionedConditionSusp = new ProvisioningSuspendedCondition() + provisioningDeprovisionedConditionSusp.setAction(ProvisioningSuspendedAction.NONE) + provisioningConditions.setSuspended(provisioningDeprovisionedConditionSusp) + provisioning.setConditions(provisioningConditions) + identityProviderPolicy.setProvisioning(provisioning) + identityProviderPolicy.setMaxClockSkew(1000) + provisioningGroups = new ProvisioningGroups() + provisioningGroups.setAction(ProvisioningGroupsAction.NONE) + provisioning.setGroups(provisioningGroups) + identityProviderPolicy.setProvisioning(provisioning) + policySubject = new PolicySubject() + policyUserNameTemplate = new PolicyUserNameTemplate() + policyUserNameTemplate.setTemplate("idpuser.email") + policySubject.setUserNameTemplate(policyUserNameTemplate) + policySubject.setMatchType(PolicySubjectMatchType.USERNAME) + identityProviderPolicy.setSubject(policySubject) + newIdp.setPolicy(identityProviderPolicy) + + IdentityProvider updatedIdp = identityProviderApi.replaceIdentityProvider(createdIdp.getId(), newIdp) + + // retrieve + IdentityProvider retrievedUpdatedIdp = identityProviderApi.getIdentityProvider(updatedIdp.getId()) + assertThat(retrievedUpdatedIdp.getId(), equalTo(createdIdp.getId())) assertThat(retrievedUpdatedIdp.getName(), equalTo(newName)) assertThat(retrievedUpdatedIdp.getProtocol().getEndpoints().getAuthorization().getUrl(), @@ -153,359 +256,480 @@ class IdpIT extends ITSupport { assertThat(retrievedUpdatedIdp.getProtocol().getIssuer().getUrl(), equalTo("https://idp.example.com/new")) - assertPresent(client.listIdentityProviders(), updatedIdp) - // deactivate - createdIdp.deactivate() + identityProviderApi.deactivateIdentityProvider(createdIdp.getId()) // delete - createdIdp.delete() - - // earlier operation may not complete immediately - sleep(getTestOperationDelay()) - - assertNotPresent(client.listIdentityProviders(), createdIdp) + identityProviderApi.deleteIdentityProvider(createdIdp.getId()) } - @Test + @Test (groups = "group2") void oidcIdpUserTest() { // create user - def email = "joe.coder+${uniqueTestName}@example.com" - User createdUser = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .buildAndCreate(client) + User createdUser = randomUser() registerForCleanup(createdUser) - // create idp + // create oidc idp String name = "java-sdk-it-" + UUID.randomUUID().toString() - IdentityProvider createdIdp = IdentityProviderBuilders.oidc() - .setName(name) - .setIssuerMode(IdentityProvider.IssuerModeEnum.ORG_URL) - .setRequestSignatureAlgorithm("SHA-256") - .setRequestSignatureScope(ProtocolAlgorithmTypeSignature.ScopeEnum.REQUEST) - .setResponseSignatureAlgorithm("SHA-256") - .setResponseSignatureScope(ProtocolAlgorithmTypeSignature.ScopeEnum.ANY) - .setAcsEndpointBinding(ProtocolEndpoint.BindingEnum.POST) - .setAcsEndpointType(ProtocolEndpoint.TypeEnum.INSTANCE) - .setAuthorizationEndpointBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setAuthorizationEndpointUrl("https://idp.example.com/authorize") - .setTokenEndpointBinding(ProtocolEndpoint.BindingEnum.POST) - .setTokenEndpointUrl("https://idp.example.com/token") - .setUserInfoEndpointBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setUserInfoEndpointUrl("https://idp.example.com/userinfo") - .setJwksEndpointBinding(ProtocolEndpoint.BindingEnum.REDIRECT) - .setJwksEndpointUrl("https://idp.example.com/keys") - .setScopes(["openid", "profile", "email"]) - .setClientId("your-client-id") - .setClientSecret("your-client-secret") - .setIssuerUrl("https://idp.example.com") - .setMaxClockSkew(120000) - .setUserName("idpuser.email") - .setMatchType(PolicySubjectMatchType.USERNAME) - .buildAndCreate(client) + IdentityProviderApi identityProviderApi = new IdentityProviderApi(getClient()) + IdentityProvider idp = new IdentityProvider() + idp.setName(name) + idp.setType(IdentityProviderType.OIDC) + idp.setIssuerMode(IssuerMode.ORG_URL) + Protocol protocol = new Protocol() + + ProtocolAlgorithmType protocolAlgorithmTypeReq = new ProtocolAlgorithmType() + ProtocolAlgorithmType protocolAlgorithmTypeRes = new ProtocolAlgorithmType() + ProtocolAlgorithmTypeSignature protocolAlgorithmTypeSignature_Req = new ProtocolAlgorithmTypeSignature() + protocolAlgorithmTypeSignature_Req.setScope(ProtocolAlgorithmTypeSignatureScope.REQUEST) + protocolAlgorithmTypeSignature_Req.setAlgorithm("SHA-256") + protocolAlgorithmTypeReq.setSignature(protocolAlgorithmTypeSignature_Req) + ProtocolAlgorithmTypeSignature protocolAlgorithmTypeSignature_Res = new ProtocolAlgorithmTypeSignature() + protocolAlgorithmTypeSignature_Res.setScope(ProtocolAlgorithmTypeSignatureScope.RESPONSE) + protocolAlgorithmTypeSignature_Res.setAlgorithm("SHA-256") + protocolAlgorithmTypeRes.setSignature(protocolAlgorithmTypeSignature_Res) + + ProtocolAlgorithms protocolAlgorithms = new ProtocolAlgorithms() + protocolAlgorithms.setRequest(protocolAlgorithmTypeReq) + protocolAlgorithms.setResponse(protocolAlgorithmTypeRes) + protocol.setAlgorithms(protocolAlgorithms) + List scopes = Arrays.asList("openid", "profile", "email") + protocol.setScopes(scopes) + protocol.setType(ProtocolType.OIDC) + + ProtocolEndpoint protocolEndpointIssuer = new ProtocolEndpoint() + protocolEndpointIssuer.setUrl("https://idp.example.com") + protocol.setIssuer(protocolEndpointIssuer) + IdentityProviderCredentials identityProviderCredentials = new IdentityProviderCredentials() + IdentityProviderCredentialsClient identityProviderCredentialsClient = new IdentityProviderCredentialsClient() + identityProviderCredentialsClient.setClientId("your-client-id") + identityProviderCredentialsClient.setClientSecret("your-client-secret") + identityProviderCredentials.setClient(identityProviderCredentialsClient) + protocol.setCredentials(identityProviderCredentials) + + ProtocolEndpoints protocolEndpoints = new ProtocolEndpoints() + ProtocolEndpoint protocolEndpointAcs = new ProtocolEndpoint() + protocolEndpointAcs.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointAcs.setType(ProtocolEndpointType.INSTANCE) + + ProtocolEndpoint protocolEndpointAuthorization = new ProtocolEndpoint() + protocolEndpointAuthorization.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointAuthorization.setUrl("https://idp.example.com/authorize") + + ProtocolEndpoint protocolEndpointToken = new ProtocolEndpoint() + protocolEndpointToken.setBinding(ProtocolEndpointBinding.POST) + protocolEndpointToken.setUrl("https://idp.example.com/token") + + ProtocolEndpoint protocolEndpointUserInfo = new ProtocolEndpoint() + protocolEndpointUserInfo.setBinding(ProtocolEndpointBinding.REDIRECT) + protocolEndpointUserInfo.setUrl("https://idp.example.com/userinfo") + + ProtocolEndpoint protocolEndpointJwks = new ProtocolEndpoint() + protocolEndpointJwks.setBinding(ProtocolEndpointBinding.REDIRECT) + protocolEndpointJwks.setUrl("https://idp.example.com/keys") + + protocolEndpoints.setAcs(protocolEndpointAcs) + protocolEndpoints.setAuthorization(protocolEndpointAuthorization) + protocolEndpoints.setToken(protocolEndpointToken) + protocolEndpoints.setUserInfo(protocolEndpointUserInfo) + protocolEndpoints.setJwks(protocolEndpointJwks) + protocol.setEndpoints(protocolEndpoints) + idp.setProtocol(protocol) + + IdentityProviderPolicy identityProviderPolicy = new IdentityProviderPolicy() + PolicyAccountLink policyAccountLink = new PolicyAccountLink() + policyAccountLink.setAction(PolicyAccountLinkAction.AUTO) + identityProviderPolicy.setAccountLink(policyAccountLink) + Provisioning provisioning = new Provisioning() + provisioning.setAction(ProvisioningAction.AUTO) + ProvisioningConditions provisioningConditions = new ProvisioningConditions() + ProvisioningDeprovisionedCondition provisioningDeprovisionedConditionDeprov = new ProvisioningDeprovisionedCondition() + provisioningDeprovisionedConditionDeprov.setAction(ProvisioningDeprovisionedAction.NONE) + provisioningConditions.setDeprovisioned(provisioningDeprovisionedConditionDeprov) + ProvisioningSuspendedCondition provisioningDeprovisionedConditionSusp = new ProvisioningSuspendedCondition() + provisioningDeprovisionedConditionSusp.setAction(ProvisioningSuspendedAction.NONE) + provisioningConditions.setSuspended(provisioningDeprovisionedConditionSusp) + provisioning.setConditions(provisioningConditions) + identityProviderPolicy.setProvisioning(provisioning) + identityProviderPolicy.setMaxClockSkew(1000) + ProvisioningGroups provisioningGroups = new ProvisioningGroups() + provisioningGroups.setAction(ProvisioningGroupsAction.NONE) + provisioning.setGroups(provisioningGroups) + identityProviderPolicy.setProvisioning(provisioning) + PolicySubject policySubject = new PolicySubject() + PolicyUserNameTemplate policyUserNameTemplate = new PolicyUserNameTemplate() + policyUserNameTemplate.setTemplate("idpuser.email") + policySubject.setUserNameTemplate(policyUserNameTemplate) + policySubject.setMatchType(PolicySubjectMatchType.USERNAME) + identityProviderPolicy.setSubject(policySubject) + idp.setPolicy(identityProviderPolicy) + + IdentityProvider createdIdp = identityProviderApi.createIdentityProvider(idp) registerForCleanup(createdIdp) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), hasSize(0)) // link user - IdentityProviderApplicationUser idpAppUser = createdIdp.linkUser(createdUser.getId(), - client.instantiate(UserIdentityProviderLinkRequest) - .setExternalId("externalId")) + UserIdentityProviderLinkRequest userIdentityProviderLinkRequest = new UserIdentityProviderLinkRequest() + userIdentityProviderLinkRequest.setExternalId("external-id") + identityProviderApi.linkUserToIdentityProvider(createdIdp.getId(), createdUser.getId(), userIdentityProviderLinkRequest) - assertThat(createdIdp.listUsers(), iterableWithSize(1)) - assertPresent(createdIdp.listUsers(), idpAppUser) + // list linked idp users + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), hasSize(1)) // unlink user - createdIdp.unlinkUser(createdUser.getId()) + identityProviderApi.unlinkUserFromIdentityProvider(createdIdp.getId(), createdUser.getId()) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), hasSize(0)) // list social auth tokens - SocialAuthTokenList socialAuthTokenList = createdIdp.listSocialAuthTokens(createdUser.getId()) + List socialAuthTokenList = identityProviderApi.listSocialAuthTokens(createdIdp.getId(), createdUser.getId()) assertThat(socialAuthTokenList, iterableWithSize(0)) // deactivate - createdIdp.deactivate() + identityProviderApi.deactivateIdentityProvider(createdIdp.getId()) // delete - createdIdp.delete() + identityProviderApi.deleteIdentityProvider(createdIdp.getId()) } @Test (groups = "group2") void googleIdpTest() { // create user - def email = "joe.coder+${uniqueTestName}@example.com" - User createdUser = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .buildAndCreate(client) + User createdUser = randomUser() registerForCleanup(createdUser) // create Google idp String name = "java-sdk-it-" + UUID.randomUUID().toString() - IdentityProvider createdIdp = IdentityProviderBuilders.google() - .setName(name) - .setScopes(["openid", "profile", "email"]) - .setClientId("your-client-id") - .setClientSecret("your-client-secret") - .isProfileMaster(true) - .setMaxClockSkew(120000) - .setUserName("idpuser.email") - .setMatchType(PolicySubjectMatchType.USERNAME) - .buildAndCreate(client) + IdentityProviderApi identityProviderApi = new IdentityProviderApi(getClient()) + IdentityProvider idp = new IdentityProvider() + idp.setName(name) + idp.setType(IdentityProviderType.GOOGLE) + Protocol protocol = new Protocol() + + List scopes = Arrays.asList("openid", "profile", "email") + protocol.setScopes(scopes) + protocol.setType(ProtocolType.OAUTH2) + + IdentityProviderCredentials identityProviderCredentials = new IdentityProviderCredentials() + IdentityProviderCredentialsClient identityProviderCredentialsClient = new IdentityProviderCredentialsClient() + identityProviderCredentialsClient.setClientId("your-client-id") + identityProviderCredentialsClient.setClientSecret("your-client-secret") + identityProviderCredentials.setClient(identityProviderCredentialsClient) + protocol.setCredentials(identityProviderCredentials) + idp.setProtocol(protocol) + + IdentityProviderPolicy identityProviderPolicy = new IdentityProviderPolicy() + PolicyAccountLink policyAccountLink = new PolicyAccountLink() + policyAccountLink.setAction(PolicyAccountLinkAction.AUTO) + identityProviderPolicy.setAccountLink(policyAccountLink) + Provisioning provisioning = new Provisioning() + provisioning.setAction(ProvisioningAction.AUTO) + provisioning.setProfileMaster(Boolean.TRUE) + ProvisioningConditions provisioningConditions = new ProvisioningConditions() + ProvisioningDeprovisionedCondition provisioningDeprovisionedConditionDeprov = new ProvisioningDeprovisionedCondition() + provisioningDeprovisionedConditionDeprov.setAction(ProvisioningDeprovisionedAction.NONE) + provisioningConditions.setDeprovisioned(provisioningDeprovisionedConditionDeprov) + ProvisioningSuspendedCondition provisioningDeprovisionedConditionSusp = new ProvisioningSuspendedCondition() + provisioningDeprovisionedConditionSusp.setAction(ProvisioningSuspendedAction.NONE) + provisioningConditions.setSuspended(provisioningDeprovisionedConditionSusp) + provisioning.setConditions(provisioningConditions) + identityProviderPolicy.setProvisioning(provisioning) + identityProviderPolicy.setMaxClockSkew(120000) + ProvisioningGroups provisioningGroups = new ProvisioningGroups() + provisioningGroups.setAction(ProvisioningGroupsAction.NONE) + provisioning.setGroups(provisioningGroups) + identityProviderPolicy.setProvisioning(provisioning) + PolicySubject policySubject = new PolicySubject() + PolicyUserNameTemplate policyUserNameTemplate = new PolicyUserNameTemplate() + policyUserNameTemplate.setTemplate("idpuser.email") + policySubject.setUserNameTemplate(policyUserNameTemplate) + policySubject.setMatchType(PolicySubjectMatchType.USERNAME) + identityProviderPolicy.setSubject(policySubject) + idp.setPolicy(identityProviderPolicy) + + IdentityProvider createdIdp = identityProviderApi.createIdentityProvider(idp) registerForCleanup(createdIdp) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(0)) // link user - IdentityProviderApplicationUser idpAppUser = createdIdp.linkUser(createdUser.getId(), - client.instantiate(UserIdentityProviderLinkRequest) - .setExternalId("externalId")) + UserIdentityProviderLinkRequest userIdentityProviderLinkRequest = new UserIdentityProviderLinkRequest() + userIdentityProviderLinkRequest.setExternalId("external-id") + identityProviderApi.linkUserToIdentityProvider(createdIdp.getId(), createdUser.getId(), userIdentityProviderLinkRequest) - assertThat(createdIdp.listUsers(), iterableWithSize(1)) - assertPresent(createdIdp.listUsers(), idpAppUser) + // list linked idp users + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(1)) // unlink user - createdIdp.unlinkUser(createdUser.getId()) + identityProviderApi.unlinkUserFromIdentityProvider(createdIdp.getId(), createdUser.getId()) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(0)) // deactivate - createdIdp.deactivate() + identityProviderApi.deactivateIdentityProvider(createdIdp.getId()) // delete - createdIdp.delete() - - assertNotPresent(client.listIdentityProviders(), createdIdp) + identityProviderApi.deleteIdentityProvider(createdIdp.getId()) } - @Test + @Test (groups = "group2") void facebookIdpTest() { // create user - def email = "joe.coder+${uniqueTestName}@example.com" - User createdUser = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .buildAndCreate(client) + User createdUser = randomUser() registerForCleanup(createdUser) // create Facebook idp String name = "java-sdk-it-" + UUID.randomUUID().toString() - IdentityProvider createdIdp = IdentityProviderBuilders.facebook() - .setName(name) - .setScopes(["public_profile", "email"]) - .setClientId("your-client-id") - .setClientSecret("your-client-secret") - .isProfileMaster(true) - .setMaxClockSkew(120000) - .setUserName("idpuser.email") - .setMatchType(PolicySubjectMatchType.USERNAME) - .buildAndCreate(client) + IdentityProviderApi identityProviderApi = new IdentityProviderApi(getClient()) + IdentityProvider idp = new IdentityProvider() + idp.setName(name) + idp.setType(IdentityProviderType.FACEBOOK) + Protocol protocol = new Protocol() + + List scopes = Arrays.asList("public_profile", "email") + protocol.setScopes(scopes) + protocol.setType(ProtocolType.OAUTH2) + + IdentityProviderCredentials identityProviderCredentials = new IdentityProviderCredentials() + IdentityProviderCredentialsClient identityProviderCredentialsClient = new IdentityProviderCredentialsClient() + identityProviderCredentialsClient.setClientId("your-client-id") + identityProviderCredentialsClient.setClientSecret("your-client-secret") + identityProviderCredentials.setClient(identityProviderCredentialsClient) + protocol.setCredentials(identityProviderCredentials) + idp.setProtocol(protocol) + + IdentityProviderPolicy identityProviderPolicy = new IdentityProviderPolicy() + PolicyAccountLink policyAccountLink = new PolicyAccountLink() + policyAccountLink.setAction(PolicyAccountLinkAction.AUTO) + identityProviderPolicy.setAccountLink(policyAccountLink) + Provisioning provisioning = new Provisioning() + provisioning.setAction(ProvisioningAction.AUTO) + provisioning.setProfileMaster(Boolean.TRUE) + ProvisioningConditions provisioningConditions = new ProvisioningConditions() + ProvisioningDeprovisionedCondition provisioningDeprovisionedConditionDeprov = new ProvisioningDeprovisionedCondition() + provisioningDeprovisionedConditionDeprov.setAction(ProvisioningDeprovisionedAction.NONE) + provisioningConditions.setDeprovisioned(provisioningDeprovisionedConditionDeprov) + ProvisioningSuspendedCondition provisioningDeprovisionedConditionSusp = new ProvisioningSuspendedCondition() + provisioningDeprovisionedConditionSusp.setAction(ProvisioningSuspendedAction.NONE) + provisioningConditions.setSuspended(provisioningDeprovisionedConditionSusp) + provisioning.setConditions(provisioningConditions) + identityProviderPolicy.setProvisioning(provisioning) + identityProviderPolicy.setMaxClockSkew(0) + ProvisioningGroups provisioningGroups = new ProvisioningGroups() + provisioningGroups.setAction(ProvisioningGroupsAction.NONE) + provisioning.setGroups(provisioningGroups) + identityProviderPolicy.setProvisioning(provisioning) + PolicySubject policySubject = new PolicySubject() + PolicyUserNameTemplate policyUserNameTemplate = new PolicyUserNameTemplate() + policyUserNameTemplate.setTemplate("idpuser.email") + policySubject.setUserNameTemplate(policyUserNameTemplate) + policySubject.setMatchType(PolicySubjectMatchType.USERNAME) + identityProviderPolicy.setSubject(policySubject) + idp.setPolicy(identityProviderPolicy) + + IdentityProvider createdIdp = identityProviderApi.createIdentityProvider(idp) registerForCleanup(createdIdp) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(0)) // link user - IdentityProviderApplicationUser idpAppUser = createdIdp.linkUser(createdUser.getId(), - client.instantiate(UserIdentityProviderLinkRequest) - .setExternalId("externalId")) + UserIdentityProviderLinkRequest userIdentityProviderLinkRequest = new UserIdentityProviderLinkRequest() + userIdentityProviderLinkRequest.setExternalId("external-id") + identityProviderApi.linkUserToIdentityProvider(createdIdp.getId(), createdUser.getId(), userIdentityProviderLinkRequest) - assertThat(createdIdp.listUsers(), iterableWithSize(1)) - assertPresent(createdIdp.listUsers(), idpAppUser) + // list linked idp users + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(1)) // unlink user - createdIdp.unlinkUser(createdUser.getId()) + identityProviderApi.unlinkUserFromIdentityProvider(createdIdp.getId(), createdUser.getId()) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(0)) // deactivate - createdIdp.deactivate() + identityProviderApi.deactivateIdentityProvider(createdIdp.getId()) // delete - createdIdp.delete() - - assertNotPresent(client.listIdentityProviders(), createdIdp) + identityProviderApi.deleteIdentityProvider(createdIdp.getId()) } - // Remove this groups tag after OKTA-329987 is resolved (Adding this tag disables the test in bacon PDV) - @Test (groups = "bacon") + @Test (groups = "group2") void microsoftIdpTest() { // create user - def email = "joe.coder+${uniqueTestName}@example.com" - User createdUser = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .buildAndCreate(client) + User createdUser = randomUser() registerForCleanup(createdUser) // create Microsoft idp String name = "java-sdk-it-" + UUID.randomUUID().toString() - IdentityProvider createdIdp = IdentityProviderBuilders.microsoft() - .setName(name) - .setScopes(["openid", "email", "profile", "https://graph.microsoft.com/User.Read"]) - .setClientId("your-client-id") - .setClientSecret("your-client-secret") - .isProfileMaster(true) - .setMaxClockSkew(120000) - .setUserName("idpuser.userPrincipalName") - .setMatchType(PolicySubjectMatchType.USERNAME) - .buildAndCreate(client) + IdentityProviderApi identityProviderApi = new IdentityProviderApi(getClient()) + IdentityProvider idp = new IdentityProvider() + idp.setName(name) + idp.setType(IdentityProviderType.MICROSOFT) + Protocol protocol = new Protocol() + + List scopes = Arrays.asList("openid", "email", "profile", "https://graph.microsoft.com/User.Read") + protocol.setScopes(scopes) + protocol.setType(ProtocolType.OAUTH2) + + IdentityProviderCredentials identityProviderCredentials = new IdentityProviderCredentials() + IdentityProviderCredentialsClient identityProviderCredentialsClient = new IdentityProviderCredentialsClient() + identityProviderCredentialsClient.setClientId("your-client-id") + identityProviderCredentialsClient.setClientSecret("your-client-secret") + identityProviderCredentials.setClient(identityProviderCredentialsClient) + protocol.setCredentials(identityProviderCredentials) + idp.setProtocol(protocol) + + IdentityProviderPolicy identityProviderPolicy = new IdentityProviderPolicy() + PolicyAccountLink policyAccountLink = new PolicyAccountLink() + policyAccountLink.setAction(PolicyAccountLinkAction.AUTO) + identityProviderPolicy.setAccountLink(policyAccountLink) + Provisioning provisioning = new Provisioning() + provisioning.setAction(ProvisioningAction.AUTO) + provisioning.setProfileMaster(Boolean.TRUE) + ProvisioningConditions provisioningConditions = new ProvisioningConditions() + ProvisioningDeprovisionedCondition provisioningDeprovisionedConditionDeprov = new ProvisioningDeprovisionedCondition() + provisioningDeprovisionedConditionDeprov.setAction(ProvisioningDeprovisionedAction.NONE) + provisioningConditions.setDeprovisioned(provisioningDeprovisionedConditionDeprov) + ProvisioningSuspendedCondition provisioningDeprovisionedConditionSusp = new ProvisioningSuspendedCondition() + provisioningDeprovisionedConditionSusp.setAction(ProvisioningSuspendedAction.NONE) + provisioningConditions.setSuspended(provisioningDeprovisionedConditionSusp) + provisioning.setConditions(provisioningConditions) + identityProviderPolicy.setProvisioning(provisioning) + identityProviderPolicy.setMaxClockSkew(0) + ProvisioningGroups provisioningGroups = new ProvisioningGroups() + provisioningGroups.setAction(ProvisioningGroupsAction.NONE) + provisioning.setGroups(provisioningGroups) + identityProviderPolicy.setProvisioning(provisioning) + PolicySubject policySubject = new PolicySubject() + PolicyUserNameTemplate policyUserNameTemplate = new PolicyUserNameTemplate() + policyUserNameTemplate.setTemplate("idpuser.userPrincipalName") + policySubject.setUserNameTemplate(policyUserNameTemplate) + policySubject.setMatchType(PolicySubjectMatchType.USERNAME) + identityProviderPolicy.setSubject(policySubject) + idp.setPolicy(identityProviderPolicy) + + IdentityProvider createdIdp = identityProviderApi.createIdentityProvider(idp) registerForCleanup(createdIdp) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(0)) // link user - IdentityProviderApplicationUser idpAppUser = createdIdp.linkUser(createdUser.getId(), - client.instantiate(UserIdentityProviderLinkRequest) - .setExternalId("externalId")) + UserIdentityProviderLinkRequest userIdentityProviderLinkRequest = new UserIdentityProviderLinkRequest() + userIdentityProviderLinkRequest.setExternalId("external-id") + identityProviderApi.linkUserToIdentityProvider(createdIdp.getId(), createdUser.getId(), userIdentityProviderLinkRequest) - assertThat(createdIdp.listUsers(), iterableWithSize(1)) - assertPresent(createdIdp.listUsers(), idpAppUser) + // list linked idp users + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(1)) // unlink user - createdIdp.unlinkUser(createdUser.getId()) + identityProviderApi.unlinkUserFromIdentityProvider(createdIdp.getId(), createdUser.getId()) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(0)) // deactivate - createdIdp.deactivate() + identityProviderApi.deactivateIdentityProvider(createdIdp.getId()) // delete - createdIdp.delete() - - assertNotPresent(client.listIdentityProviders(), createdIdp) + identityProviderApi.deleteIdentityProvider(createdIdp.getId()) } - @Test + @Test (groups = "group2") void linkedInIdpTest() { // create user - def email = "joe.coder+${uniqueTestName}@example.com" - User createdUser = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .buildAndCreate(client) + User createdUser = randomUser() registerForCleanup(createdUser) - // create Linkedin idp + // create LinkedIn idp String name = "java-sdk-it-" + UUID.randomUUID().toString() - IdentityProvider createdIdp = IdentityProviderBuilders.linkedin() - .setName(name) - .setScopes(["r_basicprofile", "r_emailaddress"]) - .setClientId("your-client-id") - .setClientSecret("your-client-secret") - .isProfileMaster(true) - .setMaxClockSkew(120000) - .setUserName("idpuser.email") - .setMatchType(PolicySubjectMatchType.EMAIL) - .buildAndCreate(client) + IdentityProviderApi identityProviderApi = new IdentityProviderApi(getClient()) + IdentityProvider idp = new IdentityProvider() + idp.setName(name) + idp.setType(IdentityProviderType.LINKEDIN) + Protocol protocol = new Protocol() + + List scopes = Arrays.asList("r_basicprofile", "r_emailaddress") + protocol.setScopes(scopes) + protocol.setType(ProtocolType.OAUTH2) + + IdentityProviderCredentials identityProviderCredentials = new IdentityProviderCredentials() + IdentityProviderCredentialsClient identityProviderCredentialsClient = new IdentityProviderCredentialsClient() + identityProviderCredentialsClient.setClientId("your-client-id") + identityProviderCredentialsClient.setClientSecret("your-client-secret") + identityProviderCredentials.setClient(identityProviderCredentialsClient) + protocol.setCredentials(identityProviderCredentials) + idp.setProtocol(protocol) + + IdentityProviderPolicy identityProviderPolicy = new IdentityProviderPolicy() + PolicyAccountLink policyAccountLink = new PolicyAccountLink() + policyAccountLink.setAction(PolicyAccountLinkAction.AUTO) + identityProviderPolicy.setAccountLink(policyAccountLink) + Provisioning provisioning = new Provisioning() + provisioning.setAction(ProvisioningAction.AUTO) + provisioning.setProfileMaster(Boolean.TRUE) + ProvisioningConditions provisioningConditions = new ProvisioningConditions() + ProvisioningDeprovisionedCondition provisioningDeprovisionedConditionDeprov = new ProvisioningDeprovisionedCondition() + provisioningDeprovisionedConditionDeprov.setAction(ProvisioningDeprovisionedAction.NONE) + provisioningConditions.setDeprovisioned(provisioningDeprovisionedConditionDeprov) + ProvisioningSuspendedCondition provisioningDeprovisionedConditionSusp = new ProvisioningSuspendedCondition() + provisioningDeprovisionedConditionSusp.setAction(ProvisioningSuspendedAction.NONE) + provisioningConditions.setSuspended(provisioningDeprovisionedConditionSusp) + provisioning.setConditions(provisioningConditions) + identityProviderPolicy.setProvisioning(provisioning) + identityProviderPolicy.setMaxClockSkew(0) + ProvisioningGroups provisioningGroups = new ProvisioningGroups() + provisioningGroups.setAction(ProvisioningGroupsAction.NONE) + provisioning.setGroups(provisioningGroups) + identityProviderPolicy.setProvisioning(provisioning) + PolicySubject policySubject = new PolicySubject() + PolicyUserNameTemplate policyUserNameTemplate = new PolicyUserNameTemplate() + policyUserNameTemplate.setTemplate("idpuser.email") + policySubject.setUserNameTemplate(policyUserNameTemplate) + policySubject.setMatchType(PolicySubjectMatchType.EMAIL) + identityProviderPolicy.setSubject(policySubject) + idp.setPolicy(identityProviderPolicy) + + IdentityProvider createdIdp = identityProviderApi.createIdentityProvider(idp) registerForCleanup(createdIdp) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(0)) // link user - IdentityProviderApplicationUser idpAppUser = createdIdp.linkUser(createdUser.getId(), - client.instantiate(UserIdentityProviderLinkRequest) - .setExternalId("externalId")) - - assertThat(createdIdp.listUsers(), iterableWithSize(1)) - assertPresent(createdIdp.listUsers(), idpAppUser) - - // unlink user - createdIdp.unlinkUser(createdUser.getId()) - - // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) - - // deactivate - createdIdp.deactivate() - - // delete - createdIdp.delete() - - assertNotPresent(client.listIdentityProviders(), createdIdp) - } - - @Test - void idpWithStringTypeTest() { - - // create user - def email = "joe.coder+${uniqueTestName}@example.com" - User createdUser = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .buildAndCreate(client) - registerForCleanup(createdUser) - - // create Linkedin idp - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - IdentityProvider createdIdp = IdentityProviderBuilders.ofType("GOOGLE") - .setName(name) - .setScopes(["r_basicprofile", "r_emailaddress"]) - .setClientId("your-client-id") - .setClientSecret("your-client-secret") - .isProfileMaster(true) - .setMaxClockSkew(120000) - .setUserName("idpuser.email") - .setMatchType(PolicySubjectMatchType.EMAIL) - .buildAndCreate(client) - registerForCleanup(createdIdp) + UserIdentityProviderLinkRequest userIdentityProviderLinkRequest = new UserIdentityProviderLinkRequest() + userIdentityProviderLinkRequest.setExternalId("external-id") + identityProviderApi.linkUserToIdentityProvider(createdIdp.getId(), createdUser.getId(), userIdentityProviderLinkRequest) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) - - // link user - IdentityProviderApplicationUser idpAppUser = createdIdp.linkUser(createdUser.getId(), - client.instantiate(UserIdentityProviderLinkRequest) - .setExternalId("externalId")) - - assertThat(createdIdp.listUsers(), iterableWithSize(1)) - assertPresent(createdIdp.listUsers(), idpAppUser) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(1)) // unlink user - createdIdp.unlinkUser(createdUser.getId()) + identityProviderApi.unlinkUserFromIdentityProvider(createdIdp.getId(), createdUser.getId()) // list linked idp users - assertThat(createdIdp.listUsers(), iterableWithSize(0)) + assertThat(identityProviderApi.listIdentityProviderApplicationUsers(createdIdp.getId()), iterableWithSize(0)) // deactivate - createdIdp.deactivate() + identityProviderApi.deactivateIdentityProvider(createdIdp.getId()) // delete - createdIdp.delete() - - assertNotPresent(client.listIdentityProviders(), createdIdp) + identityProviderApi.deleteIdentityProvider(createdIdp.getId()) } -} +} \ No newline at end of file diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/InlineHooksIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/InlineHooksIT.groovy deleted file mode 100644 index b8893b5f6c0..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/InlineHooksIT.groovy +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.inline.hook.InlineHook -import com.okta.sdk.resource.inline.hook.InlineHookBuilder -import com.okta.sdk.resource.inline.hook.InlineHookChannelConfigAuthScheme -import com.okta.sdk.resource.inline.hook.InlineHookChannelConfigHeaders -import com.okta.sdk.resource.inline.hook.InlineHookChannel -import com.okta.sdk.resource.inline.hook.InlineHookStatus -import com.okta.sdk.resource.inline.hook.InlineHookType -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.notNullValue - -import static com.okta.sdk.tests.it.util.Util.assertPresent -import static com.okta.sdk.tests.it.util.Util.assertNotPresent - -/** - * Tests for {@code /api/v1/inlineHooks}. - * @since 2.0.0 - */ -class InlineHooksIT extends ITSupport { - - @Test (groups = "group2") - void createInlineHookTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - InlineHook createdInlineHook = InlineHookBuilder.instance() - .setName(name) - .setHookType(InlineHookType.OAUTH2_TOKENS_TRANSFORM) - .setChannelType(InlineHookChannel.TypeEnum.HTTP) - .setUrl("https://www.example.com/inlineHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdInlineHook) - - assertThat(createdInlineHook.getId(), notNullValue()) - assertThat(createdInlineHook.getName(), equalTo(name)) - assertThat(createdInlineHook.getChannel().getConfig().getUri(), equalTo("https://www.example.com/inlineHooks")) - - createdInlineHook.deactivate() - } - - @Test - void getInlineHookTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - InlineHook createdInlineHook = InlineHookBuilder.instance() - .setName(name) - .setHookType(InlineHookType.OAUTH2_TOKENS_TRANSFORM) - .setChannelType(InlineHookChannel.TypeEnum.HTTP) - .setUrl("https://www.example.com/inlineHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdInlineHook) - - assertThat(createdInlineHook.getId(), notNullValue()) - - InlineHook retrievedInlineHook = client.getInlineHook(createdInlineHook.getId()) - - assertThat(retrievedInlineHook.getId(), notNullValue()) - assertThat(retrievedInlineHook.getName(), equalTo(name)) - assertThat(retrievedInlineHook.getChannel().getConfig().getUri(), equalTo("https://www.example.com/inlineHooks")) - - createdInlineHook.deactivate() - } - - @Test - void updateInlineHookTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - InlineHook createdInlineHook = InlineHookBuilder.instance() - .setName(name) - .setHookType(InlineHookType.OAUTH2_TOKENS_TRANSFORM) - .setChannelType(InlineHookChannel.TypeEnum.HTTP) - .setUrl("https://www.example.com/inlineHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdInlineHook) - - assertThat(createdInlineHook.getId(), notNullValue()) - - String newName = "java-sdk-it-" + UUID.randomUUID().toString() - - InlineHook toBeUpdatedInlineHook = createdInlineHook.setName(newName) - toBeUpdatedInlineHook.getChannel().getConfig().setHeaders([ - client.instantiate(InlineHookChannelConfigHeaders) - .setKey("X-Test-Header") - .setValue("Test header value updated")]) - toBeUpdatedInlineHook.getChannel().getConfig().setAuthScheme(client.instantiate(InlineHookChannelConfigAuthScheme) - .setType("HEADER") - .setKey("Authorization") - .setValue("Test-Api-Key-Updated")) - .setUri("https://www.example.com/inlineHooksUpdated") - - InlineHook updatedInlineHook = toBeUpdatedInlineHook.update() - - assertThat(updatedInlineHook.getId(), notNullValue()) - assertThat(updatedInlineHook.getId(), equalTo(createdInlineHook.getId())) - assertThat(updatedInlineHook.getName(), equalTo(newName)) - assertThat(updatedInlineHook.getType(), equalTo(InlineHookType.OAUTH2_TOKENS_TRANSFORM)) - assertThat(updatedInlineHook.getChannel().getConfig().getUri(), equalTo("https://www.example.com/inlineHooksUpdated")) - - updatedInlineHook.deactivate() - } - - @Test - void deleteInlineHookTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - InlineHook createdInlineHook = InlineHookBuilder.instance() - .setName(name) - .setHookType(InlineHookType.OAUTH2_TOKENS_TRANSFORM) - .setChannelType(InlineHookChannel.TypeEnum.HTTP) - .setUrl("https://www.example.com/inlineHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdInlineHook) - - assertThat(createdInlineHook.getId(), notNullValue()) - - InlineHook retrievedInlineHook = client.getInlineHook(createdInlineHook.getId()) - assertThat(retrievedInlineHook.getId(), equalTo(createdInlineHook.getId())) - assertThat(retrievedInlineHook.getName(), equalTo(name)) - - createdInlineHook.deactivate() - createdInlineHook.delete() - - assertNotPresent(client.listInlineHooks(), createdInlineHook) - } - - @Test - void listAllInlineHooksTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - InlineHook createdInlineHook = InlineHookBuilder.instance() - .setName(name) - .setHookType(InlineHookType.OAUTH2_TOKENS_TRANSFORM) - .setChannelType(InlineHookChannel.TypeEnum.HTTP) - .setUrl("https://www.example.com/inlineHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdInlineHook) - - assertThat(createdInlineHook.getId(), notNullValue()) - assertThat(createdInlineHook.getName(), equalTo(name)) - assertPresent(client.listInlineHooks(), createdInlineHook) - - createdInlineHook.deactivate() - } - - @Test (groups = "group2") - void activateDeactivateInlineHookTest() { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - InlineHook createdInlineHook = InlineHookBuilder.instance() - .setName(name) - .setHookType(InlineHookType.OAUTH2_TOKENS_TRANSFORM) - .setChannelType(InlineHookChannel.TypeEnum.HTTP) - .setUrl("https://www.example.com/inlineHooks") - .setAuthorizationHeaderValue("Test-Api-Key") - .addHeader("X-Test-Header", "Test header value") - .buildAndCreate(client) - registerForCleanup(createdInlineHook) - - assertThat(createdInlineHook.getId(), notNullValue()) - assertThat(createdInlineHook.getName(), equalTo(name)) - assertThat(createdInlineHook.getStatus(), equalTo(InlineHookStatus.ACTIVE)) - - createdInlineHook.deactivate() - - InlineHook retrievedInlineHook = client.getInlineHook(createdInlineHook.getId()) - - assertThat(retrievedInlineHook.getStatus(), equalTo(InlineHookStatus.INACTIVE)) - - retrievedInlineHook.delete() - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/LinkedObjectsIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/LinkedObjectsIT.groovy deleted file mode 100644 index 16d00d7bcb8..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/LinkedObjectsIT.groovy +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.linked.object.LinkedObject -import com.okta.sdk.resource.linked.object.LinkedObjectDetailsType -import com.okta.sdk.resource.linked.object.LinkedObjectDetails -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test -import wiremock.org.apache.commons.lang3.RandomStringUtils - -import static com.okta.sdk.tests.it.util.Util.assertLinkedObjectPresent -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.notNullValue - -/** - * Tests for {@code /api/v1/meta/schemas/user/linkedObjects}. - * @since 2.0.0 - */ -class LinkedObjectsIT extends ITSupport { - - @Test(groups = "group3") - void addLinkedObjectDefinitionTest() { - String primaryName = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - String associatedName = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - - LinkedObjectDetails primary = client.instantiate(LinkedObjectDetails) - .setName(primaryName) - .setTitle("Manager") - .setDescription("Manager link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObjectDetails associated = client.instantiate(LinkedObjectDetails) - .setName(associatedName) - .setTitle("Subordinate") - .setDescription("Subordinate link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObject linkedObject = client.instantiate(LinkedObject) - .setPrimary(primary) - .setAssociated(associated) - registerForCleanup(linkedObject) - - LinkedObject createdLinkedObjectDefinition = client.addLinkedObjectDefinition(linkedObject) - - assertThat(createdLinkedObjectDefinition.getPrimary(), notNullValue()) - assertThat(createdLinkedObjectDefinition.getPrimary().getName(), equalTo(primaryName)) - assertThat(createdLinkedObjectDefinition.getPrimary().getTitle(), equalTo("Manager")) - assertThat(createdLinkedObjectDefinition.getPrimary().getDescription(), equalTo("Manager link property")) - assertThat(createdLinkedObjectDefinition.getPrimary().getType(), equalTo(LinkedObjectDetailsType.USER)) - assertThat(createdLinkedObjectDefinition.getAssociated(), notNullValue()) - assertThat(createdLinkedObjectDefinition.getAssociated().getName(), equalTo(associatedName)) - assertThat(createdLinkedObjectDefinition.getAssociated().getTitle(), equalTo("Subordinate")) - assertThat(createdLinkedObjectDefinition.getAssociated().getDescription(), equalTo("Subordinate link property")) - assertThat(createdLinkedObjectDefinition.getAssociated().getType(), equalTo(LinkedObjectDetailsType.USER)) - } - - @Test - void getLinkedObjectDefinitionByPrimaryNameTest() { - String primaryName = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - String associatedName = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - - LinkedObjectDetails primary = client.instantiate(LinkedObjectDetails) - .setName(primaryName) - .setTitle("Primary") - .setDescription("Primary link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObjectDetails associated = client.instantiate(LinkedObjectDetails) - .setName(associatedName) - .setTitle("Associated") - .setDescription("Associated link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObject linkedObject = client.instantiate(LinkedObject) - .setPrimary(primary) - .setAssociated(associated) - registerForCleanup(linkedObject) - - client.addLinkedObjectDefinition(linkedObject) - - LinkedObject retrievedLinkedObject = client.getLinkedObjectDefinition(primaryName) - - assertThat(retrievedLinkedObject.getPrimary(), notNullValue()) - assertThat(retrievedLinkedObject.getPrimary().getName(), equalTo(primaryName)) - assertThat(retrievedLinkedObject.getPrimary().getTitle(), equalTo("Primary")) - assertThat(retrievedLinkedObject.getPrimary().getDescription(), equalTo("Primary link property")) - assertThat(retrievedLinkedObject.getPrimary().getType(), equalTo(LinkedObjectDetailsType.USER)) - assertThat(retrievedLinkedObject.getAssociated(), notNullValue()) - assertThat(retrievedLinkedObject.getAssociated().getName(), equalTo(associatedName)) - assertThat(retrievedLinkedObject.getAssociated().getTitle(), equalTo("Associated")) - assertThat(retrievedLinkedObject.getAssociated().getDescription(), equalTo("Associated link property")) - assertThat(retrievedLinkedObject.getAssociated().getType(), equalTo(LinkedObjectDetailsType.USER)) - } - - @Test - void getLinkedObjectDefinitionByAssociatedNameTest() { - String primaryName = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - String associatedName = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - - LinkedObjectDetails primary = client.instantiate(LinkedObjectDetails) - .setName(primaryName) - .setTitle("Primary") - .setDescription("Primary link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObjectDetails associated = client.instantiate(LinkedObjectDetails) - .setName(associatedName) - .setTitle("Associated") - .setDescription("Associated link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObject linkedObject = client.instantiate(LinkedObject) - .setPrimary(primary) - .setAssociated(associated) - registerForCleanup(linkedObject) - - client.addLinkedObjectDefinition(linkedObject) - - LinkedObject retrievedLinkedObject = client.getLinkedObjectDefinition(associatedName) - - assertThat(retrievedLinkedObject.getPrimary(), notNullValue()) - assertThat(retrievedLinkedObject.getPrimary().getName(), equalTo(primaryName)) - assertThat(retrievedLinkedObject.getPrimary().getTitle(), equalTo("Primary")) - assertThat(retrievedLinkedObject.getPrimary().getDescription(), equalTo("Primary link property")) - assertThat(retrievedLinkedObject.getPrimary().getType(), equalTo(LinkedObjectDetailsType.USER)) - assertThat(retrievedLinkedObject.getAssociated(), notNullValue()) - assertThat(retrievedLinkedObject.getAssociated().getName(), equalTo(associatedName)) - assertThat(retrievedLinkedObject.getAssociated().getTitle(), equalTo("Associated")) - assertThat(retrievedLinkedObject.getAssociated().getDescription(), equalTo("Associated link property")) - assertThat(retrievedLinkedObject.getAssociated().getType(), equalTo(LinkedObjectDetailsType.USER)) - } - - @Test - void getAllLinkedObjectDefinitionsTest() { - // create first linked object definition - - String primaryName1 = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - String associatedName1 = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - - LinkedObjectDetails primary1 = client.instantiate(LinkedObjectDetails) - .setName(primaryName1) - .setTitle("Primary") - .setDescription("Primary link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObjectDetails associated1 = client.instantiate(LinkedObjectDetails) - .setName(associatedName1) - .setTitle("Associated") - .setDescription("Associated link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObject linkedObject1 = client.instantiate(LinkedObject) - .setPrimary(primary1) - .setAssociated(associated1) - registerForCleanup(linkedObject1) - - LinkedObject createdLinkedObjectDefinition1 = client.addLinkedObjectDefinition(linkedObject1) - - // create second linked object definition - - String primaryName2 = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - String associatedName2 = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(25) - - LinkedObjectDetails primary2 = client.instantiate(LinkedObjectDetails) - .setName(primaryName2) - .setTitle("Primary") - .setDescription("Primary link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObjectDetails associated2 = client.instantiate(LinkedObjectDetails) - .setName(associatedName2) - .setTitle("Associated") - .setDescription("Associated link property") - .setType(LinkedObjectDetailsType.USER) - - LinkedObject linkedObject2 = client.instantiate(LinkedObject) - .setPrimary(primary2) - .setAssociated(associated2) - registerForCleanup(linkedObject2) - - LinkedObject createdLinkedObjectDefinition2 = client.addLinkedObjectDefinition(linkedObject2) - - assertLinkedObjectPresent(client.listLinkedObjectDefinitions(), createdLinkedObjectDefinition1) - assertLinkedObjectPresent(client.listLinkedObjectDefinitions(), createdLinkedObjectDefinition2) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/NetworkZoneIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/NetworkZoneIT.groovy deleted file mode 100644 index 2001d3fb55b..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/NetworkZoneIT.groovy +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.network.zone.* -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static com.okta.sdk.tests.it.util.Util.assertNotPresent -import static com.okta.sdk.tests.it.util.Util.assertPresent -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/zones}. - * @since 4.1.0 - */ -class NetworkZoneIT extends ITSupport { - - @Test - void listNetworkZonesTest() { - - getClient().listNetworkZones() - .forEach({ networkZone -> - assertThat(networkZone.getId(), notNullValue()) - assertThat(networkZone.getName(), notNullValue()) - assertThat(networkZone.getType(), notNullValue()) - assertThat(networkZone.getType() instanceof NetworkZoneType, equalTo(true)) - assertThat(networkZone.getStatus(), notNullValue()) - assertThat(networkZone.getStatus() instanceof NetworkZoneStatus, equalTo(true)) - assertThat(networkZone.getUsage(), notNullValue()) - assertThat(networkZone.getUsage() instanceof NetworkZoneUsage, equalTo(true)) - assertThat(networkZone.getSystem(), notNullValue()) - }) - } - - @Test (groups = "group2") - void createAndDeleteNetworkZoneTest() { - - String networkZoneName = "network-zone-it-${uniqueTestName}" - - NetworkZone networkZone = getClient().instantiate(NetworkZone) - .setType(NetworkZoneType.IP) - .setName(networkZoneName) - .setStatus(NetworkZoneStatus.ACTIVE) - .setGateways(Arrays.asList( - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("1.2.3.4/24"), - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("2.3.4.5/24") - )) - .setProxies(Arrays.asList( - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("2.2.3.4/24"), - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("3.3.4.5/24") - )) - - def createdNetworkZone = getClient().createNetworkZone(networkZone) - assertThat(createdNetworkZone, notNullValue()) - registerForCleanup(createdNetworkZone) - - assertThat(createdNetworkZone.getType(), equalTo(NetworkZoneType.IP)) - assertThat(createdNetworkZone.getName(), equalTo(networkZoneName)) - assertThat(createdNetworkZone.getStatus(), equalTo(NetworkZoneStatus.ACTIVE)) - assertThat(createdNetworkZone.getGateways(), iterableWithSize(networkZone.getGateways().size())) - assertThat(createdNetworkZone.getProxies(), iterableWithSize(networkZone.getProxies().size())) - assertPresent(getClient().listNetworkZones(), createdNetworkZone) - - createdNetworkZone.delete() - assertNotPresent(getClient().listNetworkZones(), createdNetworkZone) - } - - @Test - void updateNetworkZoneTest() { - - String networkZoneName = "network-zone-it-${uniqueTestName}" - - NetworkZone networkZone = getClient().instantiate(NetworkZone) - .setType(NetworkZoneType.IP) - .setName(networkZoneName) - .setStatus(NetworkZoneStatus.ACTIVE) - .setGateways(Arrays.asList( - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("1.2.3.4/24"), - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("2.3.4.5/24") - )) - .setProxies(Arrays.asList( - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("2.2.3.4/24"), - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("3.3.4.5/24") - )) - - def createdNetworkZone = getClient().createNetworkZone(networkZone) - assertThat(createdNetworkZone, notNullValue()) - registerForCleanup(createdNetworkZone) - - createdNetworkZone.setGateways( - networkZone.getGateways().stream() - .filter({ x -> x.getValue().equals("2.3.4.5/24") }) - .collect().asList() - ) - createdNetworkZone.setProxies( - networkZone.getProxies().stream() - .filter({ x -> x.getValue().equals("3.3.4.5/24") }) - .collect().asList() - ) - createdNetworkZone.update() - - def updatedNetworkZone = getClient().getNetworkZone(createdNetworkZone.getId()) - assertThat(updatedNetworkZone, notNullValue()) - assertThat(updatedNetworkZone.getId(), equalTo(createdNetworkZone.getId())) - assertThat(updatedNetworkZone.getGateways(), iterableWithSize(1)) - assertThat( - updatedNetworkZone.getGateways().find { nz -> nz.getValue().equals("2.3.4.5/24") } - , notNullValue() - ) - assertThat(updatedNetworkZone.getProxies(), iterableWithSize(1)) - assertThat( - updatedNetworkZone.getProxies().find { nz -> nz.getValue().equals("3.3.4.5/24") } - , notNullValue() - ) - } - - @Test (groups = "group2") - void activateDeactivateNetworkZoneTest() { - - String networkZoneName = "network-zone-it-${uniqueTestName}" - - NetworkZone networkZone = getClient().instantiate(NetworkZone) - .setType(NetworkZoneType.IP) - .setName(networkZoneName) - .setStatus(NetworkZoneStatus.ACTIVE) - .setGateways(Arrays.asList( - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("1.2.3.4/24") - )) - .setProxies(Arrays.asList( - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("2.2.3.4/24") - )) - - def createdNetworkZone = getClient().createNetworkZone(networkZone) - assertThat(createdNetworkZone, notNullValue()) - registerForCleanup(createdNetworkZone) - - createdNetworkZone.deactivate() - - def deactivatedNetworkZone = getClient().getNetworkZone(createdNetworkZone.getId()) - assertThat(deactivatedNetworkZone.getStatus(), equalTo(NetworkZoneStatus.INACTIVE)) - - deactivatedNetworkZone.activate() - def activatedNetworkZone = getClient().getNetworkZone(deactivatedNetworkZone.getId()) - assertThat(activatedNetworkZone.getStatus(), equalTo(NetworkZoneStatus.ACTIVE)) - } -} - - diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/OIDCApplicationIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/OIDCApplicationIT.groovy deleted file mode 100644 index b1765270517..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/OIDCApplicationIT.groovy +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.application.* -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.hasSize -import static org.hamcrest.Matchers.instanceOf -import static org.hamcrest.Matchers.is -import static org.hamcrest.Matchers.matchesPattern - -class OIDCApplicationIT extends ITSupport implements CrudTestSupport { - - @Override - def create(Client client) { - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - Application app = OIDCApplicationBuilder.instance() - .setName(name) - .setLabel(name) - .addRedirectUris("http://www.example.com") - .setPostLogoutRedirectUris(Collections.singletonList("http://www.example.com/logout")) - .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setClientId(UUID.randomUUID().toString()) - .setClientSecret(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.NONE) - .setIOS(false) - .setWeb(true) - .setLoginRedirectUrl("http://www.myapp.com") - .setErrorRedirectUrl("http://www.myapp.com/error") - .buildAndCreate(client) - registerForCleanup(app) - - return (OpenIdConnectApplication) app - } - - @Test (groups = "group2") - void createOIDCApplicationWithPrivateKeyJwtTest() { - - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - def createdKey = client.instantiate(JsonWebKey) - .setKty("RSA") - .setKid("SIGNING_KEY") - .setE("AQAB") - .setN("MIIBIzANBgkqhkiG9w0BAQEFAAOCARAAMIIBCwKCAQIAnFo/4e91na8x/BsPkNS5QkwankewxJ1uZU6p827W/gkRcNHtNi/cE644W5OVdB4UaXV6koT+TsC1prhUEhRR3g5ggE0B/lwYqBaLq/Ejy19Crc4XYU3Aah67Y6HiHWcHGZ+BbpebtTixJv/UYW/Gw+k8M+zj4O001mOeBPpwlEiZZLIo33m/Xkfn28jaCFqTQBJHr67IQh4zEUFs4e5D5D6UE8ee93yeSUJyhbifeIgYh3tS/+ZW4Uo1KLIc0rcLRrnEMsS3aOQbrv/SEKij+Syx4KXI0Gi2xMdXctnFOVT6NM6/EkLxFp2POEdv9SNBtTvXcxIGRwK51W4Jdgh/xZcCAwEAAQ==") - - Application app = OIDCApplicationBuilder.instance() - .setName(name) - .setLabel(name) - .setSignOnMode(ApplicationSignOnMode.OPENID_CONNECT) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.PRIVATE_KEY_JWT) - .addRedirectUris("http://www.example.com") - .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setJwks(Arrays.asList(createdKey)) - .buildAndCreate(client) - registerForCleanup(app) - - assertThat(app, instanceOf(OpenIdConnectApplication)) - assertThat(app.getSettings().getOAuthClient().getJwks() , instanceOf(OpenIdConnectApplicationSettingsClientKeys)) - - OpenIdConnectApplicationSettingsClientKeys keys = app.getSettings().getOAuthClient().getJwks() - assertThat(keys.getKeys(), hasSize(1)) - assertThat(keys.getKeys().get(0), instanceOf(JsonWebKey)) - - JsonWebKey receivedKey = keys.getKeys().get(0) - assertThat(receivedKey.getKty(), equalTo(createdKey.getKty())) - assertThat(receivedKey.getKid(), equalTo(createdKey.getKid())) - assertThat(receivedKey.getE(), equalTo(createdKey.getE())) - assertThat(receivedKey.getN(), equalTo(createdKey.getN())) - } - - @Override - def read(Client client, String id) { - return client.getApplication(id) - } - - @Override - Iterator getResourceCollectionIterator(Client client) { - return client.listApplications().iterator() - } - - @Override - void update(Client client, def application) { - application.setLabel(application.label +"-2") - application.visibility.hide.iOS = true - application.update() - } - - @Override - void assertUpdate(Client client, def app) { - assertThat app.label, matchesPattern('^java-sdk-it-.*-2$') - assertThat app.visibility.hide.iOS, is(true) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/OrgSettingsIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/OrgSettingsIT.groovy deleted file mode 100644 index 76dbca7d0ee..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/OrgSettingsIT.groovy +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 2021-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.org.OrgContactType -import com.okta.sdk.resource.org.OrgContactTypeObj -import com.okta.sdk.resource.org.OrgContactUser -import com.okta.sdk.resource.org.OrgOktaSupportSetting -import com.okta.sdk.resource.org.OrgSetting -import com.okta.sdk.resource.user.User -import com.okta.sdk.resource.user.UserBuilder -import com.okta.sdk.tests.Scenario -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test -import org.testng.util.Strings -import wiremock.org.apache.commons.lang3.RandomStringUtils - -import java.util.concurrent.TimeUnit - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/org}. - * @since 6.x.x - */ -class OrgSettingsIT extends ITSupport { - - @Test (groups = "group3") - @Scenario("get-partial-update-org-settings") - void getPartialUpdateOrgSettingsTest() { - - OrgSetting orgSetting = client.getOrgSettings() - assertThat(orgSetting, notNullValue()) - assertThat(orgSetting.getId(), notNullValue()) - assertThat(orgSetting.getSubdomain(), notNullValue()) - assertThat(orgSetting.getCompanyName(), notNullValue()) - assertThat(orgSetting.getStatus(), notNullValue()) - assertThat(orgSetting.getCreated(), notNullValue()) - assertThat(orgSetting.getWebsite(), notNullValue()) - - String companyName = orgSetting.getCompanyName() - String website = orgSetting.getWebsite() - String phoneNumber = Strings.getValueOrEmpty(orgSetting.getPhoneNumber()) - String endUserSupportHelpURL = Strings.getValueOrEmpty(orgSetting.getEndUserSupportHelpURL()) - String supportPhoneNumber = Strings.getValueOrEmpty(orgSetting.getSupportPhoneNumber()) - String address1 = Strings.getValueOrEmpty(orgSetting.getAddress1()) - String address2 = Strings.getValueOrEmpty(orgSetting.getAddress2()) - String city = Strings.getValueOrEmpty(orgSetting.getCity()) - String state = orgSetting.getState() - String country = orgSetting.getCountry() - String postalCode = Strings.getValueOrEmpty(orgSetting.getPostalCode()) - - String customCompanyName = "Java SDK IT " + RandomStringUtils.randomAlphanumeric(5) - - orgSetting.setCompanyName(customCompanyName) - orgSetting.setWebsite("https://okta.com") - orgSetting.setPhoneNumber("+1-555-415-1337") - orgSetting.setEndUserSupportHelpURL("https://support.okta.com") - orgSetting.setSupportPhoneNumber("+1-555-514-1337") - orgSetting.setAddress1("301 Brannan St.") - orgSetting.setAddress2("Unit 100") - orgSetting.setCity("San Francisco") - orgSetting.setState("California") - orgSetting.setCountry("United States of America") - orgSetting.setPostalCode("94107") - - OrgSetting updatedOrgSetting = orgSetting.partialUpdate() - assertThat(updatedOrgSetting.getCompanyName(), equalTo(customCompanyName)) - assertThat(updatedOrgSetting.getWebsite(), equalTo("https://okta.com")) - assertThat(updatedOrgSetting.getPhoneNumber(), equalTo("+1-555-415-1337")) - assertThat(updatedOrgSetting.getEndUserSupportHelpURL(), equalTo("https://support.okta.com")) - assertThat(updatedOrgSetting.getSupportPhoneNumber(), equalTo("+1-555-514-1337")) - assertThat(updatedOrgSetting.getAddress1(), equalTo("301 Brannan St.")) - assertThat(updatedOrgSetting.getAddress2(), equalTo("Unit 100")) - assertThat(updatedOrgSetting.getCity(), equalTo("San Francisco")) - assertThat(updatedOrgSetting.getState(), equalTo("California")) - assertThat(updatedOrgSetting.getCountry(), equalTo("United States of America")) - assertThat(updatedOrgSetting.getPostalCode(), equalTo("94107")) - - //revert settings to previous state - orgSetting.setCompanyName(companyName) - orgSetting.setWebsite(website) - orgSetting.setPhoneNumber(phoneNumber) - orgSetting.setEndUserSupportHelpURL(endUserSupportHelpURL) - orgSetting.setSupportPhoneNumber(supportPhoneNumber) - orgSetting.setAddress1(address1) - orgSetting.setAddress2(address2) - orgSetting.setCity(city) - orgSetting.setState(state) - orgSetting.setCountry(country) - orgSetting.setPostalCode(postalCode) - orgSetting.partialUpdate() - } - - @Test - @Scenario("get-org-contacts") - void getOrgContactsTest() { - def contactTypes = client.getOrgSettings().getContactTypes() - - contactTypes.asList().stream().forEach(contact -> { - assertThat(contact, instanceOf(OrgContactTypeObj)) - assertThat(contact.getContactType(), instanceOf(OrgContactType)) - assertThat(contact.getContactType(), oneOf(OrgContactType.BILLING, OrgContactType.TECHNICAL)) - }) - } - - @Test - @Scenario("get-user-of-contact-type-test") - void getUserOfContactTypeTest() { - def orgContactUser = client.getOrgSettings().getOrgContactUser(OrgContactType.BILLING.toString()) - assertThat(orgContactUser, notNullValue()) - assertThat(orgContactUser.getUserId(), notNullValue()) - - User billingUser = client.getUser(orgContactUser.getUserId()) - assertThat(billingUser, notNullValue()) - assertThat(billingUser.getId(), equalTo(orgContactUser.getUserId())) - - String newBillingUserEmail = "joe.coder.billing.user.${RandomStringUtils.randomAlphanumeric(5)}@example.com" - User newBillingUser = UserBuilder.instance() - .setEmail(newBillingUserEmail) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .setSecurityQuestion("Favorite security question?") - .setSecurityQuestionAnswer("None of them!") - .buildAndCreate(client) - registerForCleanup(newBillingUser) - - def updatedOrgContactUser = client.instantiate(OrgContactUser) - .setUserId(newBillingUser.getId()).updateContactUser(OrgContactType.BILLING.toString()) - assertThat(updatedOrgContactUser, notNullValue()) - assertThat(updatedOrgContactUser.getUserId(), equalTo(newBillingUser.getId())) - - //restore previous value - updatedOrgContactUser = client.instantiate(OrgContactUser) - .setUserId(billingUser.getId()).updateContactUser(OrgContactType.BILLING.toString()) - assertThat(updatedOrgContactUser, notNullValue()) - assertThat(updatedOrgContactUser.getUserId(), equalTo(billingUser.getId())) - } - - @Test - @Scenario("get-org-preferences-test") - void getOrgPreferencesTest() { - def orgPreferences = client.getOrgSettings().orgPreferences() - assertThat(orgPreferences, notNullValue()) - assertThat(orgPreferences.getShowEndUserFooter(), notNullValue()) - assertThat(orgPreferences.getShowEndUserFooter(), oneOf(true, false)) - - boolean showEndUserFooter = orgPreferences.getShowEndUserFooter() - if(showEndUserFooter) { - client.getOrgSettings().orgPreferences().hideEndUserFooter() - assertThat(client.getOrgSettings().orgPreferences().getShowEndUserFooter(), is(false)) - //revert to previous state - client.getOrgSettings().orgPreferences().showEndUserFooter() - assertThat(client.getOrgSettings().orgPreferences().getShowEndUserFooter(), is(true)) - } else { - client.getOrgSettings().orgPreferences().showEndUserFooter() - assertThat(client.getOrgSettings().orgPreferences().getShowEndUserFooter(), is(true)) - //revert to previous state - client.getOrgSettings().orgPreferences().hideEndUserFooter() - assertThat(client.getOrgSettings().orgPreferences().getShowEndUserFooter(), is(false)) - } - } - - @Test - @Scenario("get-okta-communication-settings-test") - void getOktaCommunicationSettingsTest() { - def commSettings = client.getOrgSettings().communicationSettings() - assertThat(commSettings, notNullValue()) - assertThat(commSettings.getOptOutEmailUsers(), notNullValue()) - assertThat(commSettings.getOptOutEmailUsers(), oneOf(true, false)) - - boolean optOutEmailUsers = commSettings.getOptOutEmailUsers() - if(optOutEmailUsers) { - client.getOrgSettings().communicationSettings().optInUsersToOktaCommunicationEmails() - assertThat(client.getOrgSettings().communicationSettings().getOptOutEmailUsers(), is(false)) - //revert to previous state - client.getOrgSettings().communicationSettings().optOutUsersFromOktaCommunicationEmails() - assertThat(client.getOrgSettings().communicationSettings().getOptOutEmailUsers(), is(true)) - } else { - client.getOrgSettings().communicationSettings().optOutUsersFromOktaCommunicationEmails() - assertThat(client.getOrgSettings().communicationSettings().getOptOutEmailUsers(), is(true)) - //revert to previous state - client.getOrgSettings().communicationSettings().optInUsersToOktaCommunicationEmails() - assertThat(client.getOrgSettings().communicationSettings().getOptOutEmailUsers(), is(false)) - } - } - - @Test - @Scenario("get-org-okta-support-settings-test") - void getOrgOktaSupportSettingsTest() { - def supportSettings = client.getOrgSettings().getSupportSettings() - assertThat(supportSettings, notNullValue()) - assertThat(supportSettings.getSupport(), notNullValue()) - assertThat(supportSettings.getSupport(), oneOf(OrgOktaSupportSetting.ENABLED, OrgOktaSupportSetting.DISABLED)) - - def orgOktaSupportSettings = supportSettings.getSupport() - if(orgOktaSupportSettings == OrgOktaSupportSetting.DISABLED) { - assertThat(supportSettings.getExpiration(), nullValue()) - - client.getOrgSettings().getSupportSettings().grantOktaSupport() - assertThat(client.getOrgSettings().getSupportSettings().getSupport(), is(OrgOktaSupportSetting.ENABLED)) - assertThat(client.getOrgSettings().getSupportSettings().getExpiration(), notNullValue()) - Date expiration = client.getOrgSettings().getSupportSettings().getExpiration() - - client.getOrgSettings().getSupportSettings().extendOktaSupport() - assertThat(client.getOrgSettings().getSupportSettings().getSupport(), is(OrgOktaSupportSetting.ENABLED)) - assertThat(client.getOrgSettings().getSupportSettings().getExpiration(), notNullValue()) - Date extendedExpiration = client.getOrgSettings().getSupportSettings().getExpiration() - def hoursExtended = (int)TimeUnit.HOURS - .convert(extendedExpiration.getTime() - expiration.getTime(), TimeUnit.MILLISECONDS) - assertThat(hoursExtended, is(greaterThanOrEqualTo(24))) - - //revert to previous state - client.getOrgSettings().getSupportSettings().revokeOktaSupport() - assertThat(client.getOrgSettings().getSupportSettings().getSupport(), is(OrgOktaSupportSetting.DISABLED)) - } else { - assertThat(supportSettings.getExpiration(), notNullValue()) - } - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PasswordPoliciesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PasswordPoliciesIT.groovy deleted file mode 100644 index 452d60404e4..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PasswordPoliciesIT.groovy +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.group.Group -import com.okta.sdk.resource.policy.* -import com.okta.sdk.tests.it.util.ITSupport - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.is - -class PasswordPoliciesIT extends ITSupport implements CrudTestSupport { - @Override - def create(Client client) { - Group group = randomGroup() - Policy passwordPolicy = PasswordPolicyBuilder.instance() - .setAuthProvider(PasswordPolicyAuthenticationProviderCondition.ProviderEnum.OKTA) - .setExcludePasswordDictionary(false) - .setExcludeUserNameInPassword(false) - .setMinPasswordLength(8) - .setMinLowerCase(1) - .setMinUpperCase(1) - .setMinNumbers(1) - .setMinSymbols(1) - .addGroup(group.getId()) - .setSkipUnlock(false) - .setPasswordExpireWarnDays(85) - .setPasswordHistoryCount(5) - .setPasswordMaxAgeDays(90) - .setPasswordMinMinutes(2) - .setPasswordAutoUnlockMinutes(5) - .setPasswordMaxAttempts(3) - .setShowLockoutFailures(true) - .setPasswordRecoveryOktaSMS(PasswordPolicyRecoveryFactorSettings.StatusEnum.ACTIVE) - .setType(PolicyType.PASSWORD) - .setStatus(Policy.StatusEnum.ACTIVE) - .setPriority(1) - .setDescription("Dummy policy for sdk test") - .setName("SDK policy "+ UUID.randomUUID().toString()) - .buildAndCreate(client) ; - return (PasswordPolicy) passwordPolicy; - - } - - @Override - def read(Client client, String id) { - return client.getPolicy(id) - } - - @Override - Iterator getResourceCollectionIterator(Client client) { - return client.listPolicies(PolicyType.PASSWORD.toString()).iterator() - } - - @Override - void update(Client client, def policy) { - policy.setDescription("Dummy policy for sdk test - Updated") - policy.settings.password.lockout.maxAttempts = 5 - policy.update() - - } - - @Override - void assertUpdate(Client client, def policy) { - assertThat policy.description, is("Dummy policy for sdk test - Updated") - assertThat policy.settings.password.lockout.maxAttempts, is(5) - assertThat policy.settings.password.complexity.minLength, is(8) - assertThat policy.settings.recovery.factors.okta_email.status, is("ACTIVE") - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PoliciesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PoliciesIT.groovy new file mode 100644 index 00000000000..1bbbf875e3c --- /dev/null +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PoliciesIT.groovy @@ -0,0 +1,293 @@ +/* + * Copyright 2017-Present Okta, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.okta.sdk.tests.it + +import com.okta.sdk.resource.application.OIDCApplicationBuilder +import com.okta.sdk.resource.group.GroupBuilder +import com.okta.sdk.resource.policy.OktaSignOnPolicyBuilder +import com.okta.sdk.tests.NonOIEEnvironmentOnly +import com.okta.sdk.tests.it.util.ITSupport +import org.openapitools.client.api.ApplicationApi +import org.openapitools.client.api.GroupApi +import org.openapitools.client.api.PolicyApi +import org.openapitools.client.model.* +import org.testng.annotations.Test + +import static org.hamcrest.MatcherAssert.assertThat +import static org.hamcrest.Matchers.* +/** + * Tests for {@code /api/v1/policies}. + * @since 0.5.0 + */ +class PoliciesIT extends ITSupport { + + @Test (groups = "group2") + void signOnPolicyWithGroupConditions() { + + GroupApi groupApi = new GroupApi(getClient()) + PolicyApi policyApi = new PolicyApi(getClient()) + + def group = GroupBuilder.instance() + .setName("group-" + UUID.randomUUID().toString()) + .buildAndCreate(groupApi) + registerForCleanup(group) + + OktaSignOnPolicy policy = OktaSignOnPolicyBuilder.instance() + .setName("policy+" + UUID.randomUUID().toString()) + .setStatus(LifecycleStatus.ACTIVE) + .setDescription("IT created Policy - signOnPolicyWithGroupConditions") + .setType(PolicyType.OKTA_SIGN_ON) + .addGroup(group.getId()) + .buildAndCreate(policyApi) + + registerForCleanup(policy) + + assertThat policy.getId(), notNullValue() + assertThat policy.getConditions().getPeople().getGroups().getInclude(), is(Collections.singletonList(group.getId())) + assertThat policy.getConditions().getPeople().getGroups().getExclude(), nullValue() + } + + // disable running them in bacon + @Test (groups = "bacon") + void createProfileEnrollmentPolicy() { + + PolicyApi policyApi = new PolicyApi(getClient()) + + ProfileEnrollmentPolicy profileEnrollmentPolicy = new ProfileEnrollmentPolicy() + profileEnrollmentPolicy.name("policy+" + UUID.randomUUID().toString()) + .type(PolicyType.PROFILE_ENROLLMENT) + .status(LifecycleStatus.ACTIVE) + .description("IT created Policy - createProfileEnrollmentPolicy") + + Policy createdProfileEnrollmentPolicy = + policyApi.createPolicy(ProfileEnrollmentPolicy.class, profileEnrollmentPolicy, false) + + registerForCleanup(createdProfileEnrollmentPolicy) + + assertThat createdProfileEnrollmentPolicy, notNullValue() + assertThat createdProfileEnrollmentPolicy.getName(), notNullValue() + assertThat createdProfileEnrollmentPolicy.getType(), equalTo(PolicyType.PROFILE_ENROLLMENT) + assertThat createdProfileEnrollmentPolicy.getStatus(), equalTo(LifecycleStatus.ACTIVE) + } + + // disable running them in bacon + @Test (groups = "bacon") + void createAccessPolicyRule() { + + String name = "java-sdk-it-" + UUID.randomUUID().toString() + + ApplicationApi applicationApi = new ApplicationApi(getClient()) + PolicyApi policyApi = new PolicyApi(getClient()) + + Application oidcApp = OIDCApplicationBuilder.instance() + .setName(name) + .setLabel(name) + .addRedirectUris("http://www.example.com") + .setPostLogoutRedirectUris(Collections.singletonList("http://www.example.com/logout")) + .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) + .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) + .setApplicationType(OpenIdConnectApplicationType.NATIVE) + .setClientId(UUID.randomUUID().toString()) + .setClientSecret(UUID.randomUUID().toString()) + .setAutoKeyRotation(true) + .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.NONE) + .setIOS(false) + .setWeb(true) + .setLoginRedirectUrl("http://www.myapp.com") + .setErrorRedirectUrl("http://www.myapp.com/error") + .buildAndCreate(applicationApi) + registerForCleanup(oidcApp) + + assertThat(oidcApp, notNullValue()) + assertThat(oidcApp.getLinks(), notNullValue()) + assertThat(oidcApp.getLinks().getAccessPolicy(), notNullValue()) + + // accessPolicy:[href:https://example.com/api/v1/policies/rst412ay22NkOdJJr0g7] + String accessPolicyId = oidcApp.getLinks().getAccessPolicy().getHref().replaceAll("]", "").tokenize("/")[-1] + + Policy accessPolicy = policyApi.getPolicy(accessPolicyId, null) + assertThat(accessPolicy, notNullValue()) + + AccessPolicyRule accessPolicyRule = new AccessPolicyRule() + accessPolicyRule.name(name) + accessPolicyRule.setType(PolicyRuleType.ACCESS_POLICY) + + AccessPolicyRuleActions accessPolicyRuleActions = new AccessPolicyRuleActions() + AccessPolicyRuleApplicationSignOn accessPolicyRuleApplicationSignOn = new AccessPolicyRuleApplicationSignOn() + accessPolicyRuleApplicationSignOn.access("DENY") + VerificationMethod verificationMethod = new VerificationMethod() + verificationMethod.type("ASSURANCE") + .factorMode("1FA") + .reauthenticateIn("PT43800H") + accessPolicyRuleApplicationSignOn.verificationMethod(verificationMethod) + accessPolicyRuleActions.appSignOn(accessPolicyRuleApplicationSignOn) + accessPolicyRule.actions(accessPolicyRuleActions) + + AccessPolicyRule createdAccessPolicyRule = policyApi.createPolicyRule(AccessPolicyRule.class, accessPolicy.getId(), accessPolicyRule) + //registerForCleanup(createdAccessPolicyRule) + + assertThat(createdAccessPolicyRule, notNullValue()) + assertThat(createdAccessPolicyRule.getName(), is(name)) + + AccessPolicyRuleActions createdAccessPolicyRuleActions = createdAccessPolicyRule.getActions() + + assertThat(createdAccessPolicyRuleActions.getAppSignOn().getAccess(), is("DENY")) + assertThat(createdAccessPolicyRuleActions.getAppSignOn().getVerificationMethod().getType(), is("ASSURANCE")) + assertThat(createdAccessPolicyRuleActions.getAppSignOn().getVerificationMethod().getFactorMode(), is("1FA")) + assertThat(createdAccessPolicyRuleActions.getAppSignOn().getVerificationMethod().getReauthenticateIn(), is("PT43800H")) + + policyApi.deactivatePolicyRule(accessPolicy.getId(), createdAccessPolicyRule.getId()) + policyApi.deletePolicyRule(accessPolicy.getId(), createdAccessPolicyRule.getId()) + } + + @Test + void signOnActionsTest() { + + PolicyApi policyApi = new PolicyApi(getClient()) + + OktaSignOnPolicy policy = OktaSignOnPolicyBuilder.instance() + .setName("policy+" + UUID.randomUUID().toString()) + .setDescription("IT created Policy - signOnActionsTest") + .setType(PolicyType.OKTA_SIGN_ON) + .setStatus(LifecycleStatus.ACTIVE) + .buildAndCreate(policyApi) + registerForCleanup(policy) + + def policyRuleName = "policyRule+" + UUID.randomUUID().toString() + + OktaSignOnPolicyRule oktaSignOnPolicyRule = new OktaSignOnPolicyRule() + oktaSignOnPolicyRule.name(policyRuleName) + oktaSignOnPolicyRule.type(PolicyRuleType.SIGN_ON) + OktaSignOnPolicyRuleActions oktaSignOnPolicyRuleActions = new OktaSignOnPolicyRuleActions() + OktaSignOnPolicyRuleSignonActions oktaSignOnPolicyRuleSignonActions = new OktaSignOnPolicyRuleSignonActions() + oktaSignOnPolicyRuleSignonActions.setAccess(PolicyAccess.DENY) + oktaSignOnPolicyRuleSignonActions.setRequireFactor(false) + oktaSignOnPolicyRuleActions.setSignon(oktaSignOnPolicyRuleSignonActions) + oktaSignOnPolicyRule.actions(oktaSignOnPolicyRuleActions) + //registerForCleanup(policyRule) + + OktaSignOnPolicyRule createdPolicyRule = policyApi.createPolicyRule(OktaSignOnPolicyRule, policy.getId(), oktaSignOnPolicyRule) + + assertThat(createdPolicyRule.getId(), notNullValue()) + assertThat(createdPolicyRule.name, is(policyRuleName)) + + policyApi.deactivatePolicyRule(policy.getId(), createdPolicyRule.getId()) + policyApi.deletePolicyRule(policy.getId(), createdPolicyRule.getId()) + } + + @Test + void activateDeactivateTest() { + + PolicyApi policyApi = new PolicyApi(getClient()) + + Policy policy = OktaSignOnPolicyBuilder.instance() + .setName("policy+" + UUID.randomUUID().toString()) + .setDescription("IT created Policy - activateDeactivateTest") + .setType(PolicyType.OKTA_SIGN_ON) + .setStatus(LifecycleStatus.INACTIVE) + .buildAndCreate(policyApi) + registerForCleanup(policy) + + assertThat(policy.getStatus(), is(LifecycleStatus.INACTIVE)) + + // activate + policyApi.activatePolicy(policy.getId()) + + policy = policyApi.getPolicy(policy.getId(), null) + + assertThat(policy.getStatus(), is(LifecycleStatus.ACTIVE)) + + // deactivate + policyApi.deactivatePolicy(policy.getId()) + + policy = policyApi.getPolicy(policy.getId(), null) + + assertThat(policy.getStatus(), is(LifecycleStatus.INACTIVE)) + } + + @Test + @NonOIEEnvironmentOnly + void expandTest() { + + PolicyApi policyApi = new PolicyApi(getClient()) + + Policy policy = OktaSignOnPolicyBuilder.instance() + .setName("policy+" + UUID.randomUUID().toString()) + .setDescription("IT created Policy - expandTest") + .setType(PolicyType.OKTA_SIGN_ON) + .setStatus(LifecycleStatus.INACTIVE) + .buildAndCreate(policyApi) + registerForCleanup(policy) + + // verify a regular get does NOT return the embedded map with "rules" + assertRulesNotExpanded(policyApi.getPolicy(policy.getId(), null)) + + // verify a regular get DOES return the embedded map with "rules" + assertRulesExpanded(policyApi.getPolicy(policy.getId(), "rules")) + } + + @Test + @NonOIEEnvironmentOnly + void listPoliciesWithParams() { + + PolicyApi policyApi = new PolicyApi(getClient()) + + Policy policy = OktaSignOnPolicyBuilder.instance() + .setName("policy+" + UUID.randomUUID().toString()) + .setDescription("IT created Policy - listPoliciesWithParams") + .setType(PolicyType.OKTA_SIGN_ON) + .setStatus(LifecycleStatus.INACTIVE) + .buildAndCreate(policyApi) + registerForCleanup(policy) + + def policies= policyApi.listPolicies(PolicyType.OKTA_SIGN_ON.name(), LifecycleStatus.INACTIVE.name(), null) + + assertThat policies, not(empty()) + policies.stream() + .limit(5) + .forEach { assertRulesNotExpanded(it) } + + policies = policyApi.listPolicies(PolicyType.OKTA_SIGN_ON.name(), LifecycleStatus.ACTIVE.name(), "rules") + + assertThat policies, not(empty()) + policies.stream() + .limit(5) + .forEach { assertRulesExpanded(it) } + } + + static void assertRulesNotExpanded(Policy policy) { + assertThat policy.getEmbedded(), anyOf(nullValue(), not(hasKey("rules"))) + } + + static void assertRulesExpanded(Policy policy) { + assertThat policy.getEmbedded(), allOf(notNullValue(), hasKey("rules")) + } + + @Test (groups = "group2") + void listPolicyRulesTest() { + + Group group = randomGroup() + Policy policy = randomSignOnPolicy(group.getId()) + + PolicyApi policyApi = new PolicyApi(getClient()) + + policyApi.listPolicyRules(policy.getId()).forEach({policyItem -> + assertThat(policyItem, notNullValue()) + assertThat(policyItem.getId(), notNullValue()) + assertThat(policyItem, instanceOf(Policy.class)) + }) + } +} \ No newline at end of file diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PolicyRulesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PolicyRulesIT.groovy deleted file mode 100644 index 947c6f660f3..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/PolicyRulesIT.groovy +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.policy.OktaSignOnPolicy -import com.okta.sdk.resource.policy.OktaSignOnPolicyRule -import com.okta.sdk.resource.policy.OktaSignOnPolicyRuleSignonActions -import com.okta.sdk.resource.policy.PasswordPolicyRule -import com.okta.sdk.resource.policy.PasswordPolicyRuleAction -import com.okta.sdk.resource.policy.Policy -import com.okta.sdk.resource.policy.PolicyNetworkCondition -import com.okta.sdk.resource.policy.PolicyRule -import com.okta.sdk.resource.policy.PolicyRuleAuthContextCondition -import com.okta.sdk.resource.policy.rule.PasswordPolicyRuleBuilder -import com.okta.sdk.resource.policy.rule.SignOnPolicyRuleBuilder -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.hasSize -import static org.hamcrest.Matchers.instanceOf -import static org.hamcrest.Matchers.is -import static org.hamcrest.Matchers.matchesPattern -import static org.hamcrest.Matchers.notNullValue -import static org.hamcrest.Matchers.nullValue - -class PolicyRulesIT extends ITSupport implements CrudTestSupport { - - private OktaSignOnPolicy crudTestPolicy - - @Override - def create(Client client) { - - def group = randomGroup() - crudTestPolicy = randomSignOnPolicy(group.getId()) - - def policyRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - OktaSignOnPolicyRule policyRule = SignOnPolicyRuleBuilder.instance() - .setName(policyRuleName) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - .setRequireFactor(false) - .buildAndCreate(client, crudTestPolicy); - - assertThat(policyRule.getStatus(), is(PolicyRule.StatusEnum.ACTIVE)) - - return policyRule - } - - @Override - def read(Client client, String id) { - return crudTestPolicy.getPolicyRule(id) - } - - @Override - void update(Client client, def policyRule) { - policyRule.setName(policyRule.name +"-2") - policyRule.update() - } - - @Override - void assertUpdate(Client client, def policyRule) { - assertThat policyRule.name, matchesPattern('^java-sdk-it-.*-2$') - } - - @Override - Iterator getResourceCollectionIterator(Client client) { - return crudTestPolicy.listPolicyRules().iterator() - } - - @Test - void deactivateTest() { - - def group = randomGroup() - def policy = randomSignOnPolicy(group.getId()) - - def policyRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - OktaSignOnPolicyRule policyRule = SignOnPolicyRuleBuilder.instance() - .setName(policyRuleName) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - .setRequireFactor(false) - .setStatus(PolicyRule.StatusEnum.INACTIVE) - .buildAndCreate(client, policy); - registerForCleanup(policyRule) - - // policy rule is ACTIVE by default - assertThat(policyRule.getStatus(), is(PolicyRule.StatusEnum.ACTIVE)) - - // deactivate - policyRule.deactivate() - policyRule = policy.getPolicyRule(policyRule.getId()) - assertThat(policyRule.getStatus(), is(PolicyRule.StatusEnum.INACTIVE)) - } - - @Test - void listPolicyRulesTest() { - def group = randomGroup() - def policy = randomSignOnPolicy(group.getId()) - - policy.listPolicyRules().forEach({policyItem -> - assertThat(policyItem, notNullValue()) - assertThat(policyItem.getId(), notNullValue()) - assertThat(policyItem, instanceOf(Policy.class)) - }) - } - - @Test (groups = "group2") - void createPasswordPolicyRule() { - - def group = randomGroup() - def policy = randomPasswordPolicy(group.getId()) - - def policyRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - PasswordPolicyRule policyRule = PasswordPolicyRuleBuilder.instance() - .setName(policyRuleName) - .setType(PolicyRule.TypeEnum.PASSWORD) - .setSelfServiceUnlockAccess(PasswordPolicyRuleAction.AccessEnum.DENY) - .setSelfServicePasswordResetAccess(PasswordPolicyRuleAction.AccessEnum.ALLOW) - .setPasswordChangeAccess(PasswordPolicyRuleAction.AccessEnum.ALLOW) - .setNetworkConnection(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - .buildAndCreate(client, policy) - registerForCleanup(policyRule) - - assertThat policyRule.getName(), is(policyRuleName) - assertThat policyRule.getActions().getPasswordChange().getAccess(), is(PasswordPolicyRuleAction.AccessEnum.ALLOW) - assertThat policyRule.getActions().getSelfServicePasswordReset().getAccess(), is(PasswordPolicyRuleAction.AccessEnum.ALLOW) - assertThat policyRule.getActions().getSelfServiceUnlock().getAccess(), is(PasswordPolicyRuleAction.AccessEnum.DENY) - assertThat policyRule.getConditions().getPeople().getUsers().getExclude(), hasSize(0) - assertThat policyRule.getConditions().getNetwork().getConnection(), is(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - } - - @Test (groups = "group2") - void createOktaSignOnOnPremPolicyRule() { - - def group = randomGroup() - def policy = randomSignOnPolicy(group.getId()) - - def policyRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - OktaSignOnPolicyRule policyRule = SignOnPolicyRuleBuilder.instance() - .setName(policyRuleName) - .setType(PolicyRule.TypeEnum.SIGN_ON) - .setAuthType(PolicyRuleAuthContextCondition.AuthTypeEnum.ANY) - .setMaxSessionLifetimeMinutes(0) - .setMaxSessionIdleMinutes(720) - .setUsePersistentCookie(false) - .setRememberDeviceByDefault(false) - .setRequireFactor(false) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - .buildAndCreate(client, policy) - registerForCleanup(policyRule) - - assertThat policyRule.getActions().getSignon().getAccess(), is(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - assertThat policyRule.getActions().getSignon().getRequireFactor(), is(false) - assertThat policyRule.getActions().getSignon().getRememberDeviceByDefault(), is(false) - assertThat policyRule.getActions().getSignon().getSession().getMaxSessionIdleMinutes(), is(720) - assertThat policyRule.getActions().getSignon().getSession().getMaxSessionLifetimeMinutes(), is(0) - assertThat policyRule.getConditions().getAuthContext().getAuthType(), is(PolicyRuleAuthContextCondition.AuthTypeEnum.ANY) - } - - // We do not support RADIUS rules in the Okta SoP anymore. - // “Authenticates via RADIUS” has been deprecated for a long time and we have removed it completely in OIE. - // https://oktainc.atlassian.net/browse/OKTA-431665?focusedCommentId=2166278 - @Test (groups = "group2", enabled = false) - void createOktaSignOnRadiusPolicyRule() { - - def group = randomGroup() - def policy = randomSignOnPolicy(group.getId()) - - def policyRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - OktaSignOnPolicyRule policyRule = SignOnPolicyRuleBuilder.instance() - .setName(policyRuleName) - .setAuthType(PolicyRuleAuthContextCondition.AuthTypeEnum.RADIUS) - .setNetworkConnection(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - .setMaxSessionIdleMinutes(720) - .setMaxSessionLifetimeMinutes(0) - .setUsePersistentCookie(false) - .setRememberDeviceByDefault(false) - .setRequireFactor(false) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - .buildAndCreate(client, policy) - - registerForCleanup(policyRule) - - assertThat policyRule.getConditions().getAuthContext().getAuthType(), is(PolicyRuleAuthContextCondition.AuthTypeEnum.RADIUS) - assertThat policyRule.getConditions().getNetwork().getConnection(), is(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - } - - @Test (groups = "group2") - void createOktaSignOnCloudPolicyRule() { - - def group = randomGroup() - def policy = randomSignOnPolicy(group.getId()) - - def policyRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - OktaSignOnPolicyRule policyRule = SignOnPolicyRuleBuilder.instance() - .setName(policyRuleName) - .setAuthType(PolicyRuleAuthContextCondition.AuthTypeEnum.ANY) - .setNetworkConnection(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - .setUsePersistentCookie(false) - .setMaxSessionIdleMinutes(720) - .setMaxSessionLifetimeMinutes(0) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - .setRequireFactor(true) - .setFactorPromptMode(OktaSignOnPolicyRuleSignonActions.FactorPromptModeEnum.ALWAYS) - .setRememberDeviceByDefault(false) - .buildAndCreate(client, policy) - registerForCleanup(policyRule) - - assertThat policyRule.getConditions().getAuthContext().getAuthType(), is(PolicyRuleAuthContextCondition.AuthTypeEnum.ANY) - assertThat policyRule.getConditions().getNetwork().getConnection(), is(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - assertThat policyRule.getConditions().getPeople().getUsers().getInclude(), nullValue() - assertThat policyRule.getConditions().getPeople().getUsers().getExclude(), is(Collections.emptyList()) - assertThat policyRule.getConditions().getPeople().getGroups(), nullValue() - assertThat policyRule.getActions().getSignon().getAccess(), is(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - assertThat policyRule.getActions().getSignon().getRequireFactor(), is(true) - assertThat policyRule.getActions().getSignon().getRememberDeviceByDefault(), is(false) - assertThat policyRule.getConditions().getNetwork().getConnection(), is(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - assertThat policyRule.getActions().getSignon().getSession().getUsePersistentCookie(), is(false) - assertThat policyRule.getActions().getSignon().getSession().getMaxSessionLifetimeMinutes(), is(0) - assertThat policyRule.getActions().getSignon().getSession().getMaxSessionIdleMinutes(), is(720) - } - - @Test (groups = "bacon") - void createOktaSignOnDenyPolicyRule() { - - def group = randomGroup() - def policy = randomSignOnPolicy(group.getId()) - - def policyRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - OktaSignOnPolicyRule policyRule = SignOnPolicyRuleBuilder.instance() - .setName(policyRuleName) - .setAuthType(PolicyRuleAuthContextCondition.AuthTypeEnum.ANY) - .setNetworkConnection(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - .setRequireFactor(false) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.DENY) - .buildAndCreate(client, policy) - - registerForCleanup(policyRule) - - assertThat policyRule.getType(), is(PolicyRule.TypeEnum.SIGN_ON) - assertThat policyRule.getActions().getSignon().getAccess(), is(OktaSignOnPolicyRuleSignonActions.AccessEnum.DENY) - assertThat policyRule.getActions().getSignon().getRequireFactor(), is(false) - assertThat policyRule.getConditions().getAuthContext().getAuthType(), is(PolicyRuleAuthContextCondition.AuthTypeEnum.ANY) - assertThat policyRule.getConditions().getNetwork().getConnection(), is(PolicyNetworkCondition.ConnectionEnum.ANYWHERE) - } - - @Test - void testActivate(){ - def group = randomGroup() - def policy = randomSignOnPolicy(group.getId()) - - def policyRuleName = "java-sdk-it-" + UUID.randomUUID().toString() - def policyRule = SignOnPolicyRuleBuilder.instance() - .setName(policyRuleName) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.ALLOW) - .setRequireFactor(false) - .setStatus(PolicyRule.StatusEnum.INACTIVE) - .buildAndCreate(client, policy) - registerForCleanup(policyRule) - - // policy rule is ACTIVE by default - assertThat(policyRule.getStatus(), is(PolicyRule.StatusEnum.ACTIVE)) - - // deactivate - policyRule.deactivate() - policyRule = policy.getPolicyRule(policyRule.getId()) - assertThat(policyRule.getStatus(), is(PolicyRule.StatusEnum.INACTIVE)) - - policyRule.activate() - policyRule = policy.getPolicyRule(policyRule.getId()) - assertThat(policyRule.getStatus(), is(PolicyRule.StatusEnum.ACTIVE)) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ProvisioningConnectionIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ProvisioningConnectionIT.groovy deleted file mode 100644 index cf7c683ff47..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ProvisioningConnectionIT.groovy +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.application.Application -import com.okta.sdk.resource.application.Org2OrgApplication -import com.okta.sdk.resource.application.Org2OrgApplicationSettings -import com.okta.sdk.resource.application.Org2OrgApplicationSettingsApp -import com.okta.sdk.resource.application.ProvisioningConnection -import com.okta.sdk.resource.application.ProvisioningConnectionAuthScheme -import com.okta.sdk.resource.application.ProvisioningConnectionProfile -import com.okta.sdk.resource.application.ProvisioningConnectionRequest -import com.okta.sdk.resource.application.ProvisioningConnectionStatus -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.is -import static org.hamcrest.Matchers.notNullValue - -/** - * Integration tests of - * @see ProvisioningConnection - */ -class ProvisioningConnectionIT extends ITSupport { - - private Application createApp() { - Application application = client.createApplication( - client.instantiate(Org2OrgApplication) - .setLabel("java-sdk-it-" + UUID.randomUUID().toString()) - .setSettings(client.instantiate(Org2OrgApplicationSettings) - .setApp(client.instantiate(Org2OrgApplicationSettingsApp) - .setAcsUrl("https://example.com/acs.html") - .setAudRestriction("https://example.com/login.html") - .setBaseUrl("https://example.com/home.html"))) - ) - registerForCleanup(application) - application - } - - @Test - void testGetDefaultProvisioningConnectionForApplication() { - Application application = createApp() - - ProvisioningConnection provisioningConnection = client.instantiate(ProvisioningConnection) - .getDefaultProvisioningConnectionForApplication(application.getId()) - - assertThat provisioningConnection, notNullValue() - assertThat provisioningConnection.getAuthScheme(), is(ProvisioningConnectionAuthScheme.TOKEN) - assertThat provisioningConnection.getStatus(), is(ProvisioningConnectionStatus.DISABLED) - } - - @Test - void testSetDefaultProvisioningConnectionForApplication() { - Application application = createApp() - - def profile = client.instantiate(ProvisioningConnectionProfile) - .setAuthScheme(ProvisioningConnectionAuthScheme.TOKEN) - .setToken("foo") - def provisioningRequest = client.instantiate(ProvisioningConnectionRequest).setProfile(profile) - def provisioningConnection = profile.setDefaultProvisioningConnectionForApplication(application.getId(), provisioningRequest) - - assertThat provisioningConnection, notNullValue() - assertThat provisioningConnection.getAuthScheme(), is(ProvisioningConnectionAuthScheme.TOKEN) - assertThat provisioningConnection.getStatus(), is(ProvisioningConnectionStatus.DISABLED) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SignOnPoliciesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SignOnPoliciesIT.groovy deleted file mode 100644 index 04ce71d265d..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SignOnPoliciesIT.groovy +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.client.Client -import com.okta.sdk.resource.application.Application -import com.okta.sdk.resource.application.OAuthEndpointAuthenticationMethod -import com.okta.sdk.resource.application.OAuthGrantType -import com.okta.sdk.resource.application.OAuthResponseType -import com.okta.sdk.resource.application.OIDCApplicationBuilder -import com.okta.sdk.resource.application.OpenIdConnectApplication -import com.okta.sdk.resource.application.OpenIdConnectApplicationType -import com.okta.sdk.resource.authorization.server.AuthorizationServerPolicy -import com.okta.sdk.resource.group.GroupBuilder -import com.okta.sdk.resource.policy.* -import com.okta.sdk.tests.NonOIEEnvironmentOnly -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -class SignOnPoliciesIT implements CrudTestSupport { - - @Override - def create(Client client) { - Policy policy = client.createPolicy(client.instantiate(OktaSignOnPolicy) - .setName("policy+" + UUID.randomUUID().toString()) - .setDescription("IT created Policy - signOn CRUD")) - - assertThat policy.getStatus(), is(Policy.StatusEnum.ACTIVE) - return policy - } - - @Override - def read(Client client, String id) { - return client.getPolicy(id) - } - - @Override - void update(Client client, def policy) { - policy.setDescription("IT created Policy - Updated") - policy.update() - } - - @Override - void assertUpdate(Client client, def policy) { - assertThat policy.description, is("IT created Policy - Updated") - } - - @Override - Iterator getResourceCollectionIterator(Client client) { - return client.listPolicies(PolicyType.OKTA_SIGN_ON.toString()).iterator() - } - - @Test (groups = "group2") - void signOnPolicyWithGroupConditions() { - - def group = GroupBuilder.instance() - .setName("group-" + UUID.randomUUID().toString()) - .buildAndCreate(client) - registerForCleanup(group) - - OktaSignOnPolicy policy = OktaSignOnPolicyBuilder.instance() - .setName("policy+" + UUID.randomUUID().toString()) - .setStatus(Policy.StatusEnum.ACTIVE) - .setDescription("IT created Policy - signOnPolicyWithGroupConditions") - .setType(PolicyType.OKTA_SIGN_ON) - .addGroup(group.getId()) - .buildAndCreate(client) - - registerForCleanup(policy) - - assertThat policy.getId(), notNullValue() - assertThat policy.getConditions().getPeople().getGroups().getInclude(), is(Collections.singletonList(group.getId())) - assertThat policy.getConditions().getPeople().getGroups().getExclude(), nullValue() - } - - // disable running them in bacon - @Test (groups = "bacon") - void createProfileEnrollmentPolicy() { - - Policy profileEnrollmentPolicy = client.createPolicy(client.instantiate(ProfileEnrollmentPolicy) - .setName("policy+" + UUID.randomUUID().toString()) - .setType(PolicyType.PROFILE_ENROLLMENT) - .setStatus(Policy.StatusEnum.ACTIVE) - .setDescription("IT created Policy - createProfileEnrollmentPolicy")) - registerForCleanup(profileEnrollmentPolicy) - - assertThat profileEnrollmentPolicy, notNullValue() - assertThat profileEnrollmentPolicy.getName(), notNullValue() - assertThat profileEnrollmentPolicy.getType(), is(PolicyType.PROFILE_ENROLLMENT) - assertThat profileEnrollmentPolicy.getStatus(), is(Policy.StatusEnum.ACTIVE) - } - - // disable running them in bacon - @Test (groups = "bacon") - void createAccessPolicyRule() { - - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - Application oidcApp = OIDCApplicationBuilder.instance() - .setName(name) - .setLabel(name) - .addRedirectUris("http://www.example.com") - .setPostLogoutRedirectUris(Collections.singletonList("http://www.example.com/logout")) - .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - .setApplicationType(OpenIdConnectApplicationType.NATIVE) - .setClientId(UUID.randomUUID().toString()) - .setClientSecret(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.NONE) - .setIOS(false) - .setWeb(true) - .setLoginRedirectUrl("http://www.myapp.com") - .setErrorRedirectUrl("http://www.myapp.com/error") - .buildAndCreate(client) - registerForCleanup(oidcApp) - - assertThat(oidcApp, notNullValue()) - assertThat(oidcApp.getLinks(), notNullValue()) - assertThat(oidcApp.getLinks().get("accessPolicy"), notNullValue()) - - // accessPolicy:[href:https://example.com/api/v1/policies/rst412ay22NkOdJJr0g7] - String accessPolicyId = oidcApp.getLinks().get("accessPolicy").toString().replaceAll("]", "").tokenize("/")[-1] - - Policy accessPolicy = client.getPolicy(accessPolicyId) - assertThat(accessPolicy, notNullValue()) - - AccessPolicyRule accessPolicyRule = client.instantiate(AccessPolicyRule) - .setName(name) - .setActions(client.instantiate(AccessPolicyRuleActions) - .setAppSignOn(client.instantiate(AccessPolicyRuleApplicationSignOn) - .setAccess("DENY") - .setVerificationMethod(client.instantiate(VerificationMethod) - .setType("ASSURANCE") - .setFactorMode("1FA") - .setReauthenticateIn("PT43800H")))) - - PolicyRule createdAccessPolicyRule = accessPolicy.createRule(accessPolicyRule) - registerForCleanup(createdAccessPolicyRule) - - assertThat(createdAccessPolicyRule, notNullValue()) - assertThat(createdAccessPolicyRule.getName(), is(name)) - - AccessPolicyRuleActions accessPolicyRuleActions = createdAccessPolicyRule.getActions() as AccessPolicyRuleActions - - assertThat(accessPolicyRuleActions.getAppSignOn().getAccess(), is("DENY")) - assertThat(accessPolicyRuleActions.getAppSignOn().getVerificationMethod().getType(), is("ASSURANCE")) - assertThat(accessPolicyRuleActions.getAppSignOn().getVerificationMethod().getFactorMode(), is("1FA")) - assertThat(accessPolicyRuleActions.getAppSignOn().getVerificationMethod().getReauthenticateIn(), is("PT43800H")) - } - - // disable running them in bacon - @Test (groups = "bacon") - void createProfileEnrollmentPolicyRule() { - - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - Policy profileEnrollmentPolicy = client.instantiate(Policy) - .setName(name) - .setType(PolicyType.PROFILE_ENROLLMENT) - .setStatus(Policy.StatusEnum.ACTIVE) - .setDescription("IT created Policy - createProfileEnrollmentPolicyRule") - - Policy createdProfileEnrollmentPolicy = client.createPolicy(profileEnrollmentPolicy) - assertThat(createdProfileEnrollmentPolicy, notNullValue()) - - PolicyRuleList defaultPolicyRuleList = createdProfileEnrollmentPolicy.listPolicyRules() - assertThat(defaultPolicyRuleList.size(), greaterThanOrEqualTo(1)) - - PolicyRule defaultPolicyRule = defaultPolicyRuleList.first() - - ProfileEnrollmentPolicyRuleProfileAttribute policyRuleProfileAttribute = - client.instantiate(ProfileEnrollmentPolicyRuleProfileAttribute) - .setName("email") - .setLabel("Email") - .setRequired(true) - - ProfileEnrollmentPolicyRuleActions profileEnrollmentPolicyRuleActions = - defaultPolicyRule.getActions() as ProfileEnrollmentPolicyRuleActions - profileEnrollmentPolicyRuleActions.getProfileEnrollment().setAccess("ALLOW") - profileEnrollmentPolicyRuleActions.getProfileEnrollment().setPreRegistrationInlineHooks(null) - profileEnrollmentPolicyRuleActions.getProfileEnrollment().setUnknownUserAction("DENY") - profileEnrollmentPolicyRuleActions.getProfileEnrollment().setTargetGroupIds(null) - profileEnrollmentPolicyRuleActions.getProfileEnrollment().setProfileAttributes([policyRuleProfileAttribute]) - profileEnrollmentPolicyRuleActions.getProfileEnrollment().setActivationRequirements( - client.instantiate(ProfileEnrollmentPolicyRuleActivationRequirement) - .setEmailVerification(true)) - - defaultPolicyRule.setActions(profileEnrollmentPolicyRuleActions) - - PolicyRule updatePolicyRule = defaultPolicyRule.update() - assertThat(updatePolicyRule, notNullValue()) - assertThat(updatePolicyRule.getName(), is(defaultPolicyRule.getName())) - ProfileEnrollmentPolicyRuleActions updateProfileEnrollmentPolicyRuleActions = - updatePolicyRule.getActions() as ProfileEnrollmentPolicyRuleActions - assertThat(updateProfileEnrollmentPolicyRuleActions, notNullValue()) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment(), notNullValue()) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getAccess(), is("ALLOW")) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getPreRegistrationInlineHooks(), nullValue()) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getUnknownUserAction(), is("DENY")) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getTargetGroupIds(), nullValue()) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getActivationRequirements().getEmailVerification(), is(true)) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getProfileAttributes(), hasSize(1)) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getProfileAttributes().first().getName(), is("email")) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getProfileAttributes().first().getLabel(), is("Email")) - assertThat(updateProfileEnrollmentPolicyRuleActions.getProfileEnrollment().getProfileAttributes().first().getRequired(), is(true)) - } - - @Test (groups = "bacon") - void applyPolicyToApplicationTest() { - - String name = "java-sdk-it-" + UUID.randomUUID().toString() - - Application oidcApp = OIDCApplicationBuilder.instance() - .setName(name) - .setLabel(name) - .addRedirectUris("https://www.example.com") - .setPostLogoutRedirectUris(Collections.singletonList("https://www.example.com/logout")) - .setResponseTypes(Arrays.asList(OAuthResponseType.TOKEN, OAuthResponseType.CODE)) - .setGrantTypes(Arrays.asList(OAuthGrantType.IMPLICIT, OAuthGrantType.AUTHORIZATION_CODE)) - .setApplicationType(OpenIdConnectApplicationType.WEB) - .setClientId(UUID.randomUUID().toString()) - .setClientSecret(UUID.randomUUID().toString()) - .setAutoKeyRotation(true) - .setTokenEndpointAuthMethod(OAuthEndpointAuthenticationMethod.CLIENT_SECRET_BASIC) - .setIOS(false) - .setWeb(true) - .setLoginRedirectUrl("https://www.myapp.com") - .setErrorRedirectUrl("https://www.myapp.com/error") - .buildAndCreate(client) - registerForCleanup(oidcApp) - - Policy policy1 = client.instantiate(Policy) - .setName(name + "-1") - .setType(PolicyType.ACCESS_POLICY) - .setStatus(Policy.StatusEnum.ACTIVE) - .setDescription("IT created Policy - applyPolicyToApplicationTest") - - Policy createdPolicy1 = client.createPolicy(policy1) - registerForCleanup(createdPolicy1) - - assertThat(createdPolicy1, notNullValue()) - - Policy policy2 = client.instantiate(Policy) - .setName(name + "-2") - .setType(PolicyType.ACCESS_POLICY) - .setStatus(Policy.StatusEnum.ACTIVE) - .setDescription("IT created Policy - applyPolicyToApplicationTest") - - Policy createdPolicy2 = client.createPolicy(policy2) - registerForCleanup(createdPolicy2) - - assertThat(createdPolicy2, notNullValue()) - - // update app policy to createdPolicy1 - oidcApp.updateApplicationPolicy(createdPolicy1.getId()) - - Application updatedApp = client.getApplication(oidcApp.getId()) - assertThat(updatedApp, notNullValue()) - - // assert if the app access policy resource id matches createdPolicy1 resource id - String policyResourceId = extractAccessPolicyResourceIdFromApplication(updatedApp) - assertThat(policyResourceId, equalTo(createdPolicy1.getId())) - - // Now, update app policy to createdPolicy2 - oidcApp.updateApplicationPolicy(createdPolicy2.getId()) - - updatedApp = client.getApplication(oidcApp.getId()) - assertThat(updatedApp, notNullValue()) - - // assert if the app app policy resource id matches createdPolicy2 resource id - policyResourceId = extractAccessPolicyResourceIdFromApplication(updatedApp) - assertThat(policyResourceId, equalTo(createdPolicy2.getId())) - } - - @Test - void signOnActionsTest() { - - OktaSignOnPolicy policy = OktaSignOnPolicyBuilder.instance() - .setName("policy+" + UUID.randomUUID().toString()) - .setDescription("IT created Policy - signOnActionsTest") - .setType(PolicyType.OKTA_SIGN_ON) - .setStatus(Policy.StatusEnum.ACTIVE) - .buildAndCreate(client); - - registerForCleanup(policy) - - def policyRuleName = "policyRule+" + UUID.randomUUID().toString() - OktaSignOnPolicyRule policyRule = policy.createRule(client.instantiate(OktaSignOnPolicyRule) - .setName(policyRuleName) - .setActions(client.instantiate(OktaSignOnPolicyRuleActions) - .setSignon(client.instantiate(OktaSignOnPolicyRuleSignonActions) - .setAccess(OktaSignOnPolicyRuleSignonActions.AccessEnum.DENY) - .setRequireFactor(false)))) - registerForCleanup(policyRule) - - assertThat(policyRule.getId(), notNullValue()) - assertThat(policyRule.name, is(policyRuleName)) - } - - @Test - void activateDeactivateTest() { - - def policy = OktaSignOnPolicyBuilder.instance() - .setName("policy+" + UUID.randomUUID().toString()) - .setDescription("IT created Policy - activateDeactivateTest") - .setType(PolicyType.OKTA_SIGN_ON) - .setStatus(Policy.StatusEnum.INACTIVE) - .buildAndCreate(client) - - registerForCleanup(policy) - - assertThat(policy.getStatus(), is(Policy.StatusEnum.INACTIVE)) - - // activate - policy.activate() - policy = client.getPolicy(policy.getId()) - assertThat(policy.getStatus(), is(Policy.StatusEnum.ACTIVE)) - - // deactivate - policy.deactivate() - policy = client.getPolicy(policy.getId()) - assertThat(policy.getStatus(), is(Policy.StatusEnum.INACTIVE)) - } - - @Test - @NonOIEEnvironmentOnly - void expandTest() { - def resource = create(client) - registerForCleanup(resource) - - // verify a regular get does NOT return the embedded map with "rules" - assertRulesNotExpanded(client.getPolicy(resource.getId())) - - // verify a regular get DOES return the embedded map with "rules" - assertRulesExpanded(client.getPolicy(resource.getId(), "rules")) - } - - @Test - @NonOIEEnvironmentOnly - void listPoliciesWithParams() { - def resource = create(client) - registerForCleanup(resource) - - def policies = client.listPolicies(PolicyType.OKTA_SIGN_ON.toString()) - assertThat policies, not(empty()) - policies.stream() - .limit(5) - .forEach { assertRulesNotExpanded(it) } - - policies = client.listPolicies(PolicyType.OKTA_SIGN_ON.toString(), Policy.StatusEnum.ACTIVE.toString(), "rules") - assertThat policies, not(empty()) - policies.stream() - .limit(5) - .forEach { assertRulesExpanded(it) } - } - - static void assertRulesNotExpanded(Policy policy) { - assertThat policy.getEmbedded(), anyOf(nullValue(), not(hasKey("rules"))) - } - - static void assertRulesNotExpanded(AuthorizationServerPolicy policy) { - assertThat policy.getEmbedded(), anyOf(nullValue(), not(hasKey("rules"))) - } - - static void assertRulesExpanded(Policy policy) { - assertThat policy.getEmbedded(), allOf(notNullValue(), hasKey("rules")) - } - - static void assertRulesExpanded(AuthorizationServerPolicy policy) { - assertThat policy.getEmbedded(), allOf(notNullValue(), hasKey("rules")) - } - - static String extractAccessPolicyResourceIdFromApplication(Application application) { - assertThat(application, notNullValue()) - assertThat(application.getLinks(), notNullValue()) - assertThat(application.getLinks().get("accessPolicy"), notNullValue()) - String accessPolicyHref = application.getLinks().get("accessPolicy").toString() - String accessPolicyResourceId = accessPolicyHref.substring(accessPolicyHref.lastIndexOf("/") + 1).replaceAll("]", "") - return accessPolicyResourceId - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SmsTemplateIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SmsTemplateIT.groovy deleted file mode 100644 index 09e03e4af32..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SmsTemplateIT.groovy +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.template.SmsTemplateTranslations -import com.okta.sdk.resource.template.SmsTemplate -import com.okta.sdk.resource.template.SmsTemplateType -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static com.okta.sdk.tests.it.util.Util.assertPresent -import static com.okta.sdk.tests.it.util.Util.assertNotPresent -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.* - -/** - * Tests for {@code /api/v1/templates/sms}. - * @since 2.0.0 - */ -class SmsTemplateIT extends ITSupport { - - @Test (groups = "group2") - void customTemplatesCrudTest() { - def templateName = "sdk-it-" + UUID.randomUUID().toString() - def retryCount = 5 - - // create translations - SmsTemplateTranslations smsTemplateTranslations = client.instantiate(SmsTemplateTranslations) - smsTemplateTranslations.put("de", "\${org.name}: ihre bestätigungscode ist \${code}") - smsTemplateTranslations.put("it", "\${org.name}: il codice di verifica è \${code}") - - while(isSmsTemplateAlreadyCreated() && retryCount > 0) { - //Looks like another Travis CI build has created an SMS Template already. Need to wait - sleep(getTestOperationDelay()) - retryCount-- - } - - // create template - SmsTemplate smsTemplate = client.createSmsTemplate(client.instantiate(SmsTemplate) - .setName(templateName) - .setType(SmsTemplateType.CODE) - .setTemplate("\${org.name}: your verification code is \${code}") - .setTranslations(smsTemplateTranslations)) - registerForCleanup(smsTemplate) - - assertThat(smsTemplate.getId(), notNullValue()) - - // list templates - assertPresent(client.listSmsTemplates(), smsTemplate) - - // retrieve template - SmsTemplate retrievedSmsTemplate = client.getSmsTemplate(smsTemplate.getId()) - assertThat(retrievedSmsTemplate, notNullValue()) - assertThat(retrievedSmsTemplate.getTranslations().keySet(), hasSize(2)) - - // partial update template with 1 empty translation - SmsTemplateTranslations partialUpdateTranslations = client.instantiate(SmsTemplateTranslations) - partialUpdateTranslations.put("de", "") // supplying empty value here so it gets removed by partial update operation (by design) - - smsTemplate.setTranslations(partialUpdateTranslations) - - smsTemplate.partialUpdate() - assertThat(smsTemplate.getTranslations().keySet(), hasSize(1)) - - // partial update again with 2 new translations - smsTemplate.getTranslations().put("es", "\${org.name}: su código de inscripción es \${code}") - smsTemplate.getTranslations().put("fr", "\${org.name}: votre code d'inscription est \${code}",) - - smsTemplate.partialUpdate() - assertThat(smsTemplate.getTranslations().keySet(), hasSize(3)) - - // full update template - SmsTemplateTranslations fullUpdateTranslations = client.instantiate(SmsTemplateTranslations) - fullUpdateTranslations.put("de", "\${org.name}: Hier ist Ihr Registrierungscode: \${code}") - - smsTemplate.setName("new-" + templateName) - smsTemplate.setType(SmsTemplateType.CODE) - smsTemplate.setTemplate("\${org.name}: Here is your enrollment code: \${code}") - smsTemplate.setTranslations(fullUpdateTranslations) - - smsTemplate.update() - assertThat(smsTemplate.getName(), is("new-" + templateName)) - assertThat(smsTemplate.getTranslations().keySet(), hasSize(1)) - - // list templates - assertPresent(client.listSmsTemplates(), smsTemplate) - - // delete template - smsTemplate.delete() - assertNotPresent(client.listSmsTemplates(), smsTemplate) - } - - boolean isSmsTemplateAlreadyCreated() { - Optional smsTemplate = client.listSmsTemplates(SmsTemplateType.CODE) - .stream() - .filter({ it.getName().startsWith("sdk-it-") }) - .findFirst() - - return smsTemplate.isPresent() - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SubscriptionIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SubscriptionIT.groovy deleted file mode 100644 index 98e5fb4fbea..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/SubscriptionIT.groovy +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2022-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.role.RoleType -import com.okta.sdk.resource.role.Subscription -import com.okta.sdk.resource.role.SubscriptionStatus -import com.okta.sdk.resource.subscription.NotificationType -import com.okta.sdk.resource.user.User -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.greaterThan -import static org.hamcrest.Matchers.hasSize -import static org.hamcrest.Matchers.is -import static org.hamcrest.Matchers.notNullValue - -/** - * Integration tests of - * @see Subscription - */ -class SubscriptionIT extends ITSupport { - - @Test - void testListRoleSubscriptions() { - def subscriptionList = client.instantiate(Subscription).listRoleSubscriptions(RoleType.SUPER_ADMIN.toString()) - assertThat subscriptionList, notNullValue() - assertThat subscriptionList.collect(), hasSize(greaterThan(0)) - assertThat subscriptionList[0].getNotificationType(), notNullValue() - assertThat subscriptionList[0].getChannels(), notNullValue() - assertThat subscriptionList[0].getStatus(), notNullValue() - } - - @Test - void testGetRoleSubscriptionByNotificationType() { - def subscription = client.instantiate(Subscription) - .getRoleSubscriptionByNotificationType(RoleType.SUPER_ADMIN.toString(), NotificationType.IWA_AGENT.toString()) - assertThat subscription, notNullValue() - assertThat subscription.getNotificationType(), notNullValue() - assertThat subscription.getChannels(), notNullValue() - assertThat subscription.getStatus(), notNullValue() - } - - @Test - void testSubscribeRoleSubscriptionByNotificationType() { - client.instantiate(Subscription) - .unsubscribeRoleSubscriptionByNotificationType(RoleType.SUPER_ADMIN.toString(), NotificationType.IWA_AGENT.toString()) - - def unsubscribed = client.instantiate(Subscription).listRoleSubscriptions(RoleType.SUPER_ADMIN.toString()) - .stream() - .filter(subscription -> subscription.getNotificationType() == NotificationType.IWA_AGENT) - .findFirst() - .orElseThrow(() -> new RuntimeException("Subscription not found")) - .getStatus() - - assertThat(unsubscribed, is(SubscriptionStatus.UNSUBSCRIBED)) - - client.instantiate(Subscription) - .subscribeRoleSubscriptionByNotificationType(RoleType.SUPER_ADMIN.toString(), NotificationType.IWA_AGENT.toString()) - - def subscribed = client.instantiate(Subscription).listRoleSubscriptions(RoleType.SUPER_ADMIN.toString()) - .stream() - .filter(subscription -> subscription.getNotificationType() == NotificationType.IWA_AGENT) - .findFirst() - .orElseThrow(() -> new RuntimeException("Subscription not found")) - .getStatus() - - assertThat(subscribed, is(SubscriptionStatus.SUBSCRIBED)) - } - - @Test - void testListUserSubscriptions() { - def currentUser = client.http().get("/api/v1/users/me", User.class) - def subscriptionList = client.instantiate(Subscription).listUserSubscriptions(currentUser.getId()) - assertThat subscriptionList, notNullValue() - assertThat subscriptionList.collect(), hasSize(greaterThan(0)) - assertThat subscriptionList[0].getNotificationType(), notNullValue() - assertThat subscriptionList[0].getChannels(), notNullValue() - assertThat subscriptionList[0].getStatus(), notNullValue() - } - - @Test - void testGetUserSubscriptionByNotificationType() { - def currentUser = client.http().get("/api/v1/users/me", User.class) - def subscription = client.instantiate(Subscription) - .getUserSubscriptionByNotificationType(currentUser.getId(), NotificationType.IWA_AGENT.toString()) - assertThat subscription, notNullValue() - assertThat subscription.getNotificationType(), notNullValue() - assertThat subscription.getChannels(), notNullValue() - assertThat subscription.getStatus(), notNullValue() - } - - @Test - void testSubscribeUserSubscriptionByNotificationType() { - def currentUser = client.http().get("/api/v1/users/me", User.class) - client.instantiate(Subscription) - .unsubscribeUserSubscriptionByNotificationType(currentUser.getId(), NotificationType.IWA_AGENT.toString()) - - def unsubscribed = client.instantiate(Subscription).listUserSubscriptions(currentUser.getId()) - .stream() - .filter(subscription -> subscription.getNotificationType() == NotificationType.IWA_AGENT) - .findFirst() - .orElseThrow(() -> new RuntimeException("Subscription not found")) - .getStatus() - - assertThat(unsubscribed, is(SubscriptionStatus.UNSUBSCRIBED)) - - client.instantiate(Subscription) - .subscribeUserSubscriptionByNotificationType(currentUser.getId(), NotificationType.IWA_AGENT.toString()) - - def subscribed = client.instantiate(Subscription).listUserSubscriptions(currentUser.getId()) - .stream() - .filter(subscription -> subscription.getNotificationType() == NotificationType.IWA_AGENT) - .findFirst() - .orElseThrow(() -> new RuntimeException("Subscription not found")) - .getStatus() - - assertThat(subscribed, is(SubscriptionStatus.SUBSCRIBED)) - } -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ThreatInsightConfigurationIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ThreatInsightConfigurationIT.groovy deleted file mode 100644 index 372e9df3024..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/ThreatInsightConfigurationIT.groovy +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.network.zone.NetworkZone -import com.okta.sdk.resource.network.zone.NetworkZoneAddress -import com.okta.sdk.resource.network.zone.NetworkZoneAddressType -import com.okta.sdk.resource.network.zone.NetworkZoneStatus -import com.okta.sdk.resource.network.zone.NetworkZoneType -import com.okta.sdk.resource.threat.insight.ThreatInsightConfiguration -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.anyOf -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.is -import static org.hamcrest.Matchers.iterableWithSize -import static org.hamcrest.Matchers.notNullValue - -/** - * Tests for {@code /api/v1/threats/configuration}. - * @since 4.1.0 - */ -class ThreatInsightConfigurationIT extends ITSupport { - - @Test - void getThreatInsightConfigurationTest() { - - ThreatInsightConfiguration currentConfiguration = getClient().getCurrentConfiguration() - assertThat(currentConfiguration, notNullValue()) - assertThat(currentConfiguration.getAction(), anyOf(is("none"), is("audit"), is("block"))) - assertThat(currentConfiguration.getLinks(), notNullValue()) - assertThat(currentConfiguration.getLinks().containsKey("self"), equalTo(true)) - assertThat(currentConfiguration.getLinks().get("self").get("href"), notNullValue()) - assertThat(currentConfiguration.getLinks().get("self").get("hints"), notNullValue()) - assertThat(currentConfiguration.getExcludeZones(), notNullValue()) - } - - @Test (groups = "group3") - void updateThreatInsightConfigurationWithNetworkZoneTest() { - - def networkZoneName = "network-zone-it-${uniqueTestName}" - - NetworkZone networkZone = getClient().instantiate(NetworkZone) - .setType(NetworkZoneType.IP) - .setName(networkZoneName) - .setStatus(NetworkZoneStatus.ACTIVE) - .setGateways(Arrays.asList( - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("1.2.3.4/24") - )) - .setProxies(Arrays.asList( - getClient().instantiate(NetworkZoneAddress) - .setType(NetworkZoneAddressType.CIDR) - .setValue("3.3.4.5/24") - )) - - def createdNetworkZone = getClient().createNetworkZone(networkZone) - assertThat(createdNetworkZone, notNullValue()) - assertThat(createdNetworkZone.getId(), notNullValue()) - registerForCleanup(createdNetworkZone) - - ThreatInsightConfiguration currentConfiguration = getClient().getCurrentConfiguration() - def prevActionValue = currentConfiguration.getAction() - String newActionValue - if(prevActionValue.equals("audit")) { - newActionValue = "none" - } else if(prevActionValue.equals("none")) { - newActionValue = "audit" - } else { - newActionValue = prevActionValue - } - currentConfiguration.setAction(newActionValue) - currentConfiguration.setExcludeZones(Arrays.asList(createdNetworkZone.getId())) - - ThreatInsightConfiguration updatedConfiguration = currentConfiguration.update() - assertThat(updatedConfiguration, notNullValue()) - assertThat(updatedConfiguration.getAction(), equalTo(newActionValue)) - assertThat(updatedConfiguration.getExcludeZones(), iterableWithSize(1)) - assertThat(updatedConfiguration.getExcludeZones().get(0), equalTo(createdNetworkZone.getId())) - - //restore ThreatInsightConfiguration's action - updatedConfiguration.setAction(prevActionValue) - updatedConfiguration.setExcludeZones(Arrays.asList()) - ThreatInsightConfiguration restoredConfiguration = updatedConfiguration.update() - assertThat(restoredConfiguration, notNullValue()) - assertThat(restoredConfiguration.getAction(), equalTo(prevActionValue)) - assertThat(restoredConfiguration.getExcludeZones(), iterableWithSize(0)) - } -} - - diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UserRolesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UserRolesIT.groovy deleted file mode 100644 index 503c5093c2c..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UserRolesIT.groovy +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.group.GroupBuilder -import com.okta.sdk.resource.group.Group -import com.okta.sdk.resource.role.AssignRoleRequest -import com.okta.sdk.resource.role.RoleType -import com.okta.sdk.resource.user.Role -import com.okta.sdk.resource.user.User -import com.okta.sdk.resource.user.UserBuilder -import com.okta.sdk.tests.Scenario -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test - -import static com.okta.sdk.tests.it.util.Util.assertGroupPresent -import static com.okta.sdk.tests.it.util.Util.assertGroupAbsent -import static com.okta.sdk.tests.it.util.Util.validateGroup -import static com.okta.sdk.tests.it.util.Util.validateUser -import static org.hamcrest.MatcherAssert.assertThat - -/** - * Tests for {@code /api/v1/users/roles}. - * @since 2.0.0 - */ -class UserRolesIT extends ITSupport { - - // Remove this groups tag after OKTA-337497 is resolved (Adding this tag disables the test in bacon PDV) - @Test (groups = "bacon", enabled = false) - @Scenario("assign-super-admin-role-to-user") - void assignSuperAdminRoleToUserTest() { - - def password = 'Passw0rd!2@3#' - def firstName = 'John' - def lastName = 'Role' - def email = "john-${uniqueTestName}@example.com" - - // 1. Create a user - User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) - registerForCleanup(user) - validateUser(user, firstName, lastName, email) - - // 2. Assign SUPER_ADMIN role - AssignRoleRequest assignRoleRequest = client.instantiate(AssignRoleRequest) - assignRoleRequest.setType(RoleType.SUPER_ADMIN) - - // fix flakiness seen in PDV tests - Thread.sleep(getTestOperationDelay()) - - Role assignedRole = user.assignRole(assignRoleRequest) - assertThat("Incorrect RoleType", assignedRole.getType() == RoleType.SUPER_ADMIN) - } - - @Test (groups = "group3") - @Scenario("group-targets-for-role") - void groupTargetsForRoleTest() { - - def password = 'Passw0rd!2@3#' - def firstName = 'John' - def lastName = 'Role' - def email = "john-${uniqueTestName}@example.com" - - // 1. Create a user - User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) - registerForCleanup(user) - validateUser(user, firstName, lastName, email) - - // 2. Create two groups - String groupName1 = "Group-Member API Test Group ${uniqueTestName}-1" - String groupName2 = "Group-Member API Test Group ${uniqueTestName}-2" - - Group group1 = GroupBuilder.instance() - .setName(groupName1) - .buildAndCreate(client) - Group group2 = GroupBuilder.instance() - .setName(groupName2) - .buildAndCreate(client) - registerForCleanup(group1) - registerForCleanup(group2) - - validateGroup(group1, groupName1) - validateGroup(group2, groupName2) - - // 3. Assign a role - AssignRoleRequest assignRoleRequest = client.instantiate(AssignRoleRequest) - assignRoleRequest.setType(RoleType.USER_ADMIN) - - Role superAdminRole = user.assignRole(assignRoleRequest) - - // 4. Add the created groups as role targets - // Need 2 groups, because if you remove the last one it throws an (expected) exception. - user.addGroupTarget(superAdminRole.getId(), group1.getId()) - user.addGroupTarget(superAdminRole.getId(), group2.getId()) - - assertGroupPresent(user.listGroupTargets(superAdminRole.getId()), group1) - assertGroupPresent(user.listGroupTargets(superAdminRole.getId()), group2) - - // 5. Remove the target - user.removeGroupTarget(superAdminRole.getId(), group1.getId()) - - assertGroupAbsent(user.listGroupTargets(superAdminRole.getId()), group1) - } -} - - diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UserTypesIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UserTypesIT.groovy deleted file mode 100644 index 94599bb231f..00000000000 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UserTypesIT.groovy +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2020-Present Okta, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.sdk.tests.it - -import com.okta.sdk.resource.user.schema.UserSchema -import com.okta.sdk.resource.user.type.UserType -import com.okta.sdk.tests.it.util.ITSupport -import org.testng.annotations.Test -import wiremock.org.apache.commons.lang3.RandomStringUtils - -import static com.okta.sdk.tests.it.util.Util.assertNotPresent -import static com.okta.sdk.tests.it.util.Util.assertPresent -import static org.hamcrest.MatcherAssert.assertThat -import static org.hamcrest.Matchers.equalTo -import static org.hamcrest.Matchers.notNullValue - -/** - * Tests for {@code /api/v1/meta/types/user}. - * @since 2.0.0 - */ -class UserTypesIT extends ITSupport { - - @Test - void createUserTypeTest() { - String name = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(15) - - UserType createdUserType = client.createUserType(client.instantiate(UserType) - .setName(name) - .setDisplayName(name) - .setDescription(name + "_test_description")) - registerForCleanup(createdUserType) - - assertThat(createdUserType.getId(), notNullValue()) - assertThat(createdUserType.getName(), equalTo(name)) - - def schemaId = getSchemaIdForUserType(createdUserType) - assertThat(schemaId, notNullValue()) - - def userSchema = client.getUserSchema(schemaId) - assertThat(userSchema, notNullValue()) - assertThat(userSchema.getLinks(), notNullValue()) - - def userTypeId = getTypeIdFromUserSchema(userSchema) - assertThat(userTypeId, equalTo(createdUserType.getId())) - assertThat(userSchema.getDefinitions(), notNullValue()) - - def userSchemaBase = userSchema.getDefinitions().getBase() - assertThat(userSchemaBase, notNullValue()) - userSchemaBase.getRequired().forEach({ requiredItem -> - assertThat(userSchemaBase.getProperties().containsKey(requiredItem), equalTo(true)) - }) - } - - @Test - void getUserTypeTest() { - String name = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(15) - - UserType createdUserType = client.createUserType(client.instantiate(UserType) - .setName(name) - .setDisplayName(name) - .setDescription(name + "_test_description")) - registerForCleanup(createdUserType) - - assertThat(createdUserType.getId(), notNullValue()) - - UserType retrievedUserType = client.getUserType(createdUserType.getId()) - assertThat(retrievedUserType.getId(), equalTo(createdUserType.getId())) - assertThat(retrievedUserType.getName(), equalTo(createdUserType.getName())) - } - - @Test - void updateUserTypeTest() { - String name = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(15) - - UserType createdUserType = client.createUserType(client.instantiate(UserType) - .setName(name) - .setDisplayName(name) - .setDescription(name + "_test_description")) - registerForCleanup(createdUserType) - - assertThat(createdUserType.getId(), notNullValue()) - - createdUserType.setDisplayName(name + "_updated").setDescription(name + "_test_description_updated") - .update() - - assertThat(createdUserType.getId(), notNullValue()) - assertThat(createdUserType.getDisplayName(), equalTo(name + "_updated")) - assertThat(createdUserType.getDescription(), equalTo(name + "_test_description_updated")) - - def schemaId = getSchemaIdForUserType(createdUserType) - assertThat(schemaId, notNullValue()) - - def userSchema = client.getUserSchema(schemaId) - assertThat(userSchema, notNullValue()) - - userSchema.getDefinitions().getCustom().getProperties().put("customPropertyName", - new LinkedHashMap() { - { - put("title", "Title of custom property") - put("description", "Description of custom property") - put("type", "string") - put("permissions", new ArrayList() { - { - add( - new LinkedHashMap() { - { - put("principal", "SELF") - put("action", "READ_ONLY") - } - } - ) - } - }) - } - }) - - def updatedUserSchema = client.updateUserProfile(schemaId, userSchema) - assertThat(updatedUserSchema, notNullValue()) - assertThat(updatedUserSchema.getDefinitions().getCustom(), notNullValue()) - - def userSchemaPublic = updatedUserSchema.getDefinitions().getCustom() - assertThat(userSchemaPublic.getProperties().containsKey("customPropertyName"), equalTo(true)) - - def customPropertyMap = userSchemaPublic.getProperties().get("customPropertyName") - assertThat(customPropertyMap["title"], equalTo("Title of custom property")) - assertThat(customPropertyMap["description"], equalTo("Description of custom property")) - assertThat(customPropertyMap["type"], equalTo("string")) - assertThat(customPropertyMap["permissions"][0]["principal"], equalTo("SELF")) - assertThat(customPropertyMap["permissions"][0]["action"], equalTo("READ_ONLY")) - } - - @Test (groups = "group2") - void deleteUserTypeTest() { - String name = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(15) - - UserType createdUserType = client.createUserType(client.instantiate(UserType) - .setName(name) - .setDisplayName(name) - .setDescription(name + "_test_description")) - registerForCleanup(createdUserType) - - assertThat(createdUserType.getId(), notNullValue()) - - createdUserType.delete() - - assertNotPresent(client.listUserTypes(), createdUserType) - } - - @Test (groups = "group2") - void listAllUserTypesTest() { - String name1 = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(15) - - UserType createdUserType1 = client.createUserType(client.instantiate(UserType) - .setName(name1) - .setDisplayName(name1) - .setDescription(name1 + "_test_description")) - registerForCleanup(createdUserType1) - - assertThat(createdUserType1.getId(), notNullValue()) - - String name2 = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(15) - - UserType createdUserType2 = client.createUserType(client.instantiate(UserType) - .setName(name2) - .setDisplayName(name2) - .setDescription(name2 + "_test_description")) - registerForCleanup(createdUserType2) - - assertThat(client.listUserTypes(), notNullValue()) - assertPresent(client.listUserTypes(), createdUserType1) - assertPresent(client.listUserTypes(), createdUserType2) - } - - String getSchemaIdForUserType(UserType userType) { - def schema = userType.getLinks().get("schema") - assertThat(schema, notNullValue()) - assertThat(schema instanceof LinkedHashMap, equalTo(true)) - - def schemaHref = (schema as LinkedHashMap).get("href") - assertThat(schemaHref, notNullValue()) - - def schemaId = schemaHref.toString().split("/").last() - assertThat(schemaId, notNullValue()) - - return schemaId - } - - String getTypeIdFromUserSchema(UserSchema userSchema) { - - def type = userSchema.getLinks().get("type") - assertThat(type, notNullValue()) - assertThat(type instanceof LinkedHashMap, equalTo(true)) - - def typeHref = (type as LinkedHashMap).get("href") - assertThat(typeHref, notNullValue()) - - def typeId = typeHref.toString().split("/").last() - assertThat(typeId, notNullValue()) - - return typeId - } - - -} diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UsersIT.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UsersIT.groovy index 07d341123cb..94503cc2b39 100644 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UsersIT.groovy +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/UsersIT.groovy @@ -15,174 +15,48 @@ */ package com.okta.sdk.tests.it -import com.okta.sdk.client.Client +import com.okta.sdk.error.ResourceException import com.okta.sdk.impl.resource.DefaultGroupBuilder -import com.okta.sdk.resource.ExtensibleResource -import com.okta.sdk.resource.Resource -import com.okta.sdk.resource.ResourceException -import com.okta.sdk.resource.application.ApplicationGroupAssignment -import com.okta.sdk.resource.group.Group +import com.okta.sdk.resource.common.PagedList import com.okta.sdk.resource.group.GroupBuilder -import com.okta.sdk.resource.policy.PasswordPolicyPasswordSettings -import com.okta.sdk.resource.policy.PasswordPolicyPasswordSettingsAge -import com.okta.sdk.resource.policy.PasswordPolicyRule -import com.okta.sdk.resource.policy.PasswordPolicyRuleAction -import com.okta.sdk.resource.policy.PasswordPolicyRuleActions -import com.okta.sdk.resource.policy.PasswordPolicyRuleConditions -import com.okta.sdk.resource.policy.PasswordPolicySettings -import com.okta.sdk.resource.policy.PolicyNetworkCondition -import com.okta.sdk.resource.role.AssignRoleRequest -import com.okta.sdk.resource.role.RoleType -import com.okta.sdk.resource.user.AuthenticationProvider -import com.okta.sdk.resource.user.AuthenticationProviderType -import com.okta.sdk.resource.user.ChangePasswordRequest -import com.okta.sdk.resource.user.ForgotPasswordResponse -import com.okta.sdk.resource.user.PasswordCredential -import com.okta.sdk.resource.user.RecoveryQuestionCredential -import com.okta.sdk.resource.user.ResetPasswordToken -import com.okta.sdk.resource.user.Role -import com.okta.sdk.resource.user.User import com.okta.sdk.resource.user.UserBuilder -import com.okta.sdk.resource.user.UserCredentials -import com.okta.sdk.resource.user.UserList -import com.okta.sdk.resource.user.UserStatus -import com.okta.sdk.resource.user.type.UserType import com.okta.sdk.tests.Scenario import com.okta.sdk.tests.it.util.ITSupport -import org.testng.Assert -import org.testng.annotations.BeforeClass +import org.apache.commons.lang3.RandomStringUtils +import org.openapitools.client.api.* +import org.openapitools.client.model.* import org.testng.annotations.Test -import wiremock.org.apache.commons.lang3.RandomStringUtils -import java.time.Duration import java.nio.charset.StandardCharsets import java.security.MessageDigest import java.util.stream.Collectors -import static com.okta.sdk.tests.it.util.Util.assertGroupTargetPresent -import static com.okta.sdk.tests.it.util.Util.assertNotPresent -import static com.okta.sdk.tests.it.util.Util.assertPresent -import static com.okta.sdk.tests.it.util.Util.expect -import static com.okta.sdk.tests.it.util.Util.validateGroup -import static com.okta.sdk.tests.it.util.Util.validateUser +import static com.okta.sdk.tests.it.util.Util.* import static org.hamcrest.MatcherAssert.assertThat import static org.hamcrest.Matchers.* - /** * Tests for {@code /api/v1/users}. * @since 0.5.0 */ -class UsersIT extends ITSupport implements CrudTestSupport { - - @BeforeClass - void initCustomProperties() { - ensureCustomProperties() - } +class UsersIT extends ITSupport { @Test - void userProfileNumberValues() { + void doCrudTest() { - def email = "joe.coder+${uniqueTestName}@example.com" - User user = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .setSecurityQuestion("Favorite security question?") - .setSecurityQuestionAnswer("None of them!") - .putAllProfileProperties([ - customNumber: 1.5d, - customBoolean: true, - customInteger: 123, - customStringArray: ["one", "two", "three"], - customNumberArray: [1.5d, 2.5d, 3.5d], - customIntegerArray: [1, 2, 3] - ]) - .buildAndCreate(getClient()) + User user = randomUser() registerForCleanup(user) + assertThat(user.getStatus(), equalTo(UserStatus.PROVISIONED)) - // check the values after create - assertThat(user.getProfile().getString("firstName"), equalTo("Joe")) - assertThat(user.getProfile().getNumber("customNumber"), equalTo(1.5d)) - assertThat(user.getProfile().getBoolean("customBoolean"), equalTo(true)) - assertThat(user.getProfile().getInteger("customInteger"), equalTo(123)) - assertThat(user.getProfile().getStringList("customStringArray"), equalTo(["one", "two", "three"])) - assertThat(user.getProfile().getNumberList("customNumberArray"), equalTo([1.5d, 2.5d, 3.5d])) - assertThat(user.getProfile().getIntegerList("customIntegerArray"), equalTo([1, 2, 3])) - - // Use the 'get' to update the values to make sure there are no conversion issues - user.getProfile().putAll([ - customNumber: user.getProfile().getNumber("customNumber"), - customBoolean: true, - customStringArray: user.getProfile().getStringList("customStringArray"), - customNumberArray: user.getProfile().getNumberList("customNumberArray"), - customIntegerArray: user.getProfile().getIntegerList("customIntegerArray")]) - user.update() - - // same check as before - assertThat(user.getProfile().getNumber("customNumber"), equalTo(1.5d)) - assertThat(user.getProfile().getBoolean("customBoolean"), equalTo(true)) - assertThat(user.getProfile().getInteger("customInteger"), equalTo(123)) - assertThat(user.getProfile().getStringList("customStringArray"), equalTo(["one", "two", "three"])) - assertThat(user.getProfile().getNumberList("customNumberArray"), equalTo([1.5d, 2.5d, 3.5d])) - assertThat(user.getProfile().getIntegerList("customIntegerArray"), equalTo([1, 2, 3])) - - // test again but null out all of the values - user.getProfile().remove("customNumber") - user.getProfile().remove("customBoolean") - user.getProfile().remove("customInteger") - user.getProfile().remove("customStringArray") - user.getProfile().remove("customNumberArray") - user.getProfile().remove("customIntegerArray") - user.update() - - // everything should be null - assertThat(user.getProfile().getNumber("customNumber"), nullValue()) - assertThat(user.getProfile().getBoolean("customBoolean"), nullValue()) - assertThat(user.getProfile().getInteger("customInteger"), nullValue()) - assertThat(user.getProfile().getStringList("customStringArray"), nullValue()) - assertThat(user.getProfile().getNumberList("customNumberArray"), nullValue()) - assertThat(user.getProfile().getIntegerList("customIntegerArray"), nullValue()) - } - - - @Override - def create(Client client) { - def email = "joe.coder+${uniqueTestName}@example.com" - User user = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .setSecurityQuestion("Favorite security question?") - .setSecurityQuestionAnswer("None of them!") - .buildAndCreate(client) - registerForCleanup(user) - return user - } - - @Override - def read(Client client, String id) { - return client.getUser(id) - } - - @Override - void update(Client client, def user) { - user.getProfile().lastName = "Coder" - user.update() - } + UserApi userApi = new UserApi(getClient()) - @Override - void assertUpdate(Client client, Object resource) { - assertThat resource.getProfile().lastName, equalTo("Coder") - } + // deactivate + userApi.deactivateUser(user.getId(), false) - @Override - Iterator getResourceCollectionIterator(Client client) { - return client.listUsers().iterator() + User retrievedUser = userApi.getUser(user.getId()) + assertThat(retrievedUser.getStatus(), equalTo(UserStatus.DEPROVISIONED)) } - @Test (groups = "group3") + @Test (groups = "group2") @Scenario("create-user-with-user-type") void createUserWithUserTypeTest() { @@ -191,13 +65,17 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Activate' def email = "john-activate=${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + UserTypeApi userTypeApi = new UserTypeApi(getClient()) + // 1. Create a User Type - String name = "java_sdk_user_type_" + RandomStringUtils.randomAlphanumeric(15) + String name = "java_sdk_it_" + RandomStringUtils.randomAlphanumeric(15) - UserType createdUserType = client.createUserType(client.instantiate(UserType) - .setName(name) - .setDisplayName(name) - .setDescription(name + "_test_description")) + UserType userType = new UserType() + .name(name) + .displayName(name) + .description(name + "_test_description") + UserType createdUserType = userTypeApi.createUserType(userType) registerForCleanup(createdUserType) assertThat(createdUserType.getId(), notNullValue()) @@ -211,7 +89,7 @@ class UsersIT extends ITSupport implements CrudTestSupport { .setActive(true) // See https://developer.okta.com/docs/reference/api/user-types/#specify-the-user-type-of-a-new-user .setType(createdUserType.getId()) - .buildAndCreate(client) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) @@ -222,11 +100,12 @@ class UsersIT extends ITSupport implements CrudTestSupport { Thread.sleep(getTestOperationDelay()) // 4.Verify user in list of active users - UserList users = client.listUsers(null, 'status eq \"ACTIVE\"', null, null, null) - assertPresent(users, user) + List users = userApi.listUsers(null, null, null, 'status eq \"ACTIVE\"', null, null, null) + assertThat(users, hasSize(greaterThan(0))) + //assertPresent(users, user) } - @Test (groups = "group3") + @Test (groups = "group2") @Scenario("user-activate") void userActivateTest() { @@ -235,28 +114,31 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Activate' def email = "john-activate=${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(false) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(false) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) // 2. Activate the user and verify user in list of active users - user.activate(false) + userApi.activateUser(user.getId(), false) // fix flakiness seen in PDV tests Thread.sleep(getTestOperationDelay()) - UserList users = client.listUsers(null, 'status eq \"ACTIVE\"', null, null, null) - assertPresent(users, user) + List users = userApi.listUsers(null, null, null, 'status eq \"ACTIVE\"', null, null, null) + + assertUserPresent(users, user) } - @Test + @Test (groups = "group2") @Scenario("user-with-special-character") void userWithSpecialCharacterTest() { def password = 'Passw0rd!2@3#' @@ -264,20 +146,24 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'hashtag' def email = "john-${uniqueTestName}#@example.com" + UserApi userApi = new UserApi(getClient()) + User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) Thread.sleep(getTestOperationDelay()) - assertThat(client.getUser(email), equalTo(user)) + + User retrievedUser = userApi.getUser(email) + assertThat(retrievedUser.id, equalTo(user.id)) } - @Test (groups = "group3") + @Test (groups = "group2") @Scenario("user-role-assign") void roleAssignTest() { @@ -286,37 +172,45 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Role' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + RoleApi roleApi = new RoleApi(getClient()) + RoleAssignmentApi roleAssignmentApi = new RoleAssignmentApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(true) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) // 2. Assign USER_ADMIN role to the user - AssignRoleRequest assignRoleRequest = client.instantiate(AssignRoleRequest) + AssignRoleRequest assignRoleRequest = new AssignRoleRequest() assignRoleRequest.setType(RoleType.USER_ADMIN) - Role role = user.assignRole(assignRoleRequest) + Role role = roleAssignmentApi.assignRoleToUser(user.getId(), assignRoleRequest, true) // 3. List roles for the user and verify added role - assertPresent(user.listAssignedRoles(), role) + List roles = roleAssignmentApi.listAssignedRolesForUser(user.getId(), null) + Optional match = roles.stream().filter(r -> r.getId() == role.getId()).findAny() + assertThat(match.isPresent(), is(true)) // 4. Verify added role - assertThat(user.getRole(role.getId()).getId(), equalTo(role.getId())) + assertThat(roleAssignmentApi.getUserAssignedRole(user.getId(), role.getId()).getId(), equalTo(role.getId())) // 5. Remove role for the user - user.removeRole(role.getId()) + roleAssignmentApi.unassignRoleFromUser(user.getId(), role.getId()) // 6. List roles for user and verify role was removed - assertNotPresent(user.listAssignedRoles(), role) + roles = roleAssignmentApi.listAssignedRolesForUser(user.getId(), null) + match = roles.stream().filter(r -> r.getId() != role.getId()).findAny() + assertThat(match.isPresent(), is(false)) } - @Test (groups = "group3") + @Test (groups = "group2") @Scenario("user-change-password") void changePasswordTest() { @@ -325,29 +219,38 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Change-Password' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(true) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) // 2. Change the user's password - UserCredentials credentials = user.changePassword(client.instantiate(ChangePasswordRequest) - .setOldPassword(client.instantiate(PasswordCredential).setValue('Passw0rd!2@3#'.toCharArray())) - .setNewPassword(client.instantiate(PasswordCredential).setValue('!2@3#Passw0rd'.toCharArray())), true) - assertThat credentials.getProvider().getType(), equalTo(AuthenticationProviderType.OKTA) + ChangePasswordRequest changePasswordRequest = new ChangePasswordRequest() + PasswordCredential passwordCredentialOld = new PasswordCredential() + passwordCredentialOld.setValue("Passw0rd!2@3#") + changePasswordRequest.setOldPassword(passwordCredentialOld) + PasswordCredential passwordCredentialNew = new PasswordCredential() + passwordCredentialNew.setValue("!2@3#Passw0rd") + changePasswordRequest.setNewPassword(passwordCredentialNew) + + UserCredentials userCredentials = userApi.changePassword(user.getId(), changePasswordRequest, true) + assertThat userCredentials.getProvider().getType(), equalTo(AuthenticationProviderType.OKTA) // 3. make the test recording happy, and call a get on the user // TODO: fix har file - client.getUser(user.getId()) + userApi.getUser(user.getId()) } - @Test + // TODO: enable it after fixing the inheritance issue + @Test(expectedExceptions = ResourceException, groups = "group2", enabled = false) void changeStrictPasswordTest() { def password = 'Passw0rd!2@3#' @@ -355,58 +258,97 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Change-Password' def email = "john-${uniqueTestName}@example.com" - def group = randomGroup() - def policy = randomPasswordPolicy(group.getId()) - policy.setSettings(client.instantiate(PasswordPolicySettings) - .setPassword(client.instantiate(PasswordPolicyPasswordSettings) - .setAge(client.instantiate(PasswordPolicyPasswordSettingsAge) - .setMinAgeMinutes(Duration.ofDays(2L).toMinutes() as int)))) - .update() + UserApi userApi = new UserApi(getClient()) + GroupApi groupApi = new GroupApi(getClient()) + PolicyApi policyApi = new PolicyApi(getClient()) + + String name = "java-sdk-it-${UUID.randomUUID().toString()}" + + Group group = new Group() + GroupProfile groupProfile = new GroupProfile() + groupProfile.setName(name) + groupProfile.setDescription(name) + group.setProfile(groupProfile) + Group createdGroup = groupApi.createGroup(group) + registerForCleanup(createdGroup) + + assertThat createdGroup, notNullValue() + assertThat createdGroup.getId(), notNullValue() + + Policy policy = randomPasswordPolicy(createdGroup.getId()) + PasswordPolicyPasswordSettingsAge passwordPolicyPasswordSettingsAge = new PasswordPolicyPasswordSettingsAge() + passwordPolicyPasswordSettingsAge.setMinAgeMinutes(java.time.Duration.ofDays(2L).toMinutes() as int) + + PasswordPolicyPasswordSettings passwordPolicyPasswordSettings = new PasswordPolicyPasswordSettings() + passwordPolicyPasswordSettings.setAge(passwordPolicyPasswordSettingsAge) + + PasswordPolicySettings passwordPolicySettings = new PasswordPolicySettings() + passwordPolicySettings.setPassword(passwordPolicyPasswordSettings) + + policy.setSettings(passwordPolicySettings) + + policy = policyApi.updatePolicy(policy.getId(), policy) def policyRuleName = "policyRule+" + UUID.randomUUID().toString() - PasswordPolicyRule policyRule = policy.createRule(client.instantiate(PasswordPolicyRule) - .setConditions(client.instantiate(PasswordPolicyRuleConditions) - .setNetwork(client.instantiate(PolicyNetworkCondition) - .setConnection(PolicyNetworkCondition.ConnectionEnum.ANYWHERE))) - .setActions(client.instantiate(PasswordPolicyRuleActions) - .setPasswordChange(client.instantiate(PasswordPolicyRuleAction) - .setAccess(PasswordPolicyRuleAction.AccessEnum.ALLOW)) - .setSelfServicePasswordReset(client.instantiate(PasswordPolicyRuleAction) - .setAccess(PasswordPolicyRuleAction.AccessEnum.ALLOW)) - .setSelfServiceUnlock(client.instantiate(PasswordPolicyRuleAction) - .setAccess(PasswordPolicyRuleAction.AccessEnum.DENY))) - .setName(policyRuleName)) + + PolicyNetworkCondition policyNetworkCondition = new PolicyNetworkCondition() + policyNetworkCondition.setConnection(PolicyNetworkConnection.ANYWHERE) + + PasswordPolicyRuleConditions passwordPolicyRuleConditions = new PasswordPolicyRuleConditions() + passwordPolicyRuleConditions.setNetwork(policyNetworkCondition) + + PasswordPolicyRuleAction passwordPolicyRuleActionAllow = new PasswordPolicyRuleAction() + passwordPolicyRuleActionAllow.access(PolicyAccess.ALLOW) + + PasswordPolicyRuleAction passwordPolicyRuleActionDeny = new PasswordPolicyRuleAction() + passwordPolicyRuleActionDeny.access(PolicyAccess.DENY) + + PasswordPolicyRuleActions passwordPolicyRuleActions = new PasswordPolicyRuleActions() + passwordPolicyRuleActions.setPasswordChange(passwordPolicyRuleActionAllow) + passwordPolicyRuleActions.setSelfServicePasswordReset(passwordPolicyRuleActionAllow) + passwordPolicyRuleActions.setSelfServiceUnlock(passwordPolicyRuleActionDeny) + + PasswordPolicyRule passwordPolicyRule = new PasswordPolicyRule() + passwordPolicyRule.setConditions(passwordPolicyRuleConditions) + passwordPolicyRule.setActions(passwordPolicyRuleActions) + passwordPolicyRule.setName(policyRuleName) + + PolicyRule policyRule = policyApi.createPolicyRule(policy.getId(), passwordPolicyRule) registerForCleanup(policyRule) // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .setGroups(group.getId()) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(true) + .setGroups(createdGroup.getId()) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) // 2. Change the user's password - def request = client.instantiate(ChangePasswordRequest) - .setOldPassword(client.instantiate(PasswordCredential).setValue('Passw0rd!2@3#'.toCharArray())) - .setNewPassword(client.instantiate(PasswordCredential).setValue('!2@3#Passw0rd'.toCharArray())) + PasswordCredential passwordCredentialOld = new PasswordCredential() + .value("Passw0rd!2@3#") + PasswordCredential passwordCredentialNew = new PasswordCredential() + .value("!2@3#Passw0rd") + ChangePasswordRequest changePasswordRequest = new ChangePasswordRequest() + .oldPassword(passwordCredentialOld) + .newPassword(passwordCredentialNew) // would throw a HTTP 403 - def exception = expect ResourceException, {user.changePassword(request, true)} + userApi.changePassword(user.getId(), changePasswordRequest, true) - def credentials = user.changePassword(request, false) - assertThat credentials.getProvider().getType(), equalTo(AuthenticationProviderType.OKTA) + UserCredentials userCredentials = userApi.changePassword(user.getId(), changePasswordRequest, false) + assertThat userCredentials.getProvider().getType(), equalTo("OKTA") // 3. make the test recording happy, and call a get on the user // TODO: fix har file - client.getUser(user.getId()) + userApi.getUser(user.getId()) } - @Test(expectedExceptions = ResourceException, groups = "group3") + @Test(expectedExceptions = ResourceException, groups = "group2") @Scenario("user-change-recovery-question") void changeRecoveryQuestionTest() { @@ -415,6 +357,8 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Change-Recovery-Question' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user with password & recovery question User user = UserBuilder.instance() .setEmail(email) @@ -422,17 +366,23 @@ class UsersIT extends ITSupport implements CrudTestSupport { .setLastName(lastName) .setPassword(password.toCharArray()) .setActive(true) - .buildAndCreate(client) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) // 2. Change the recovery question - UserCredentials userCredentials = user.changeRecoveryQuestion(client.instantiate(UserCredentials) - .setPassword(client.instantiate(PasswordCredential) - .setValue('Passw0rd!2@3#'.toCharArray())) - .setRecoveryQuestion(client.instantiate(RecoveryQuestionCredential) - .setQuestion('How many roads must a man walk down?') - .setAnswer('forty two'))) + RecoveryQuestionCredential recoveryQuestionCredential = new RecoveryQuestionCredential() + recoveryQuestionCredential.setQuestion("How many roads must a man walk down?") + recoveryQuestionCredential.setAnswer("forty two") + + PasswordCredential passwordCredential = new PasswordCredential() + passwordCredential.setValue("Passw0rd!2@3#") + + UserCredentials userCredentials = new UserCredentials() + userCredentials.setPassword(passwordCredential) + userCredentials.setRecoveryQuestion(recoveryQuestionCredential) + + userCredentials = userApi.changeRecoveryQuestion(user.getId(), userCredentials) assertThat userCredentials.getProvider().getType(), equalTo(AuthenticationProviderType.OKTA) assertThat userCredentials.getRecoveryQuestion().question, equalTo('How many roads must a man walk down?') @@ -442,11 +392,11 @@ class UsersIT extends ITSupport implements CrudTestSupport { userCredentials.getRecoveryQuestion().answer = 'forty two' // below would throw HTTP 403 exception - user.changeRecoveryQuestion(userCredentials) + userApi.changeRecoveryQuestion(user.getId(), userCredentials) // 4. make the test recording happy, and call a get on the user // TODO: fix har file - client.getUser(user.getId()) + userApi.getUser(user.getId()) } @Test (groups = "bacon") @@ -457,22 +407,24 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Forgot-Password' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(true) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) - ResetPasswordToken response = user.resetPassword(false) + ResetPasswordToken response = userApi.resetPassword(user.getId(), false) assertThat response.getResetPasswordUrl(), containsString("/reset_password/") } - @Test + @Test (groups = "group2") @Scenario("user-expire-password") void expirePasswordTest() { @@ -481,25 +433,26 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Expire-Password' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(true) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) // 2. Expire the user's password - User updatedUser = user.expirePassword() + User updatedUser = userApi.expirePassword(user.getId()) assertThat updatedUser, notNullValue() - assertThat updatedUser.getStatus(), is(UserStatus.PASSWORD_EXPIRED) + assertThat updatedUser.getStatus().name(), equalTo("PASSWORD_EXPIRED") } - - @Test + @Test (groups = "group2") @Scenario("user-get-reset-password-url") void resetPasswordUrlTest() { @@ -508,23 +461,25 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Get-Reset-Password-URL' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(true) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) // 2. Get the reset password link - ResetPasswordToken token = user.resetPassword(false) + ResetPasswordToken token = userApi.resetPassword(user.getId(), false) assertThat token.getResetPasswordUrl(), notNullValue() } - @Test (groups = "group3") + @Test (groups = "group2") @Scenario("user-get") void getUserTest() { @@ -533,36 +488,38 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Get-User' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user - User createUser = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(false) - .buildAndCreate(client) - registerForCleanup(createUser) - validateUser(createUser, firstName, lastName, email) + User createdUser = UserBuilder.instance() + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(false) + .buildAndCreate(userApi) + registerForCleanup(createdUser) + validateUser(createdUser, firstName, lastName, email) // 2. Get the user by user ID - User user = client.getUser(createUser.getId()) + User user = userApi.getUser(createdUser.getId()) validateUser(user, firstName, lastName, email) // 3. Get the user by user login - User userByLogin = client.getUser(createUser.getProfile().getLogin()) + User userByLogin = userApi.getUser(createdUser.getProfile().getLogin()) validateUser(userByLogin, firstName, lastName, email) - // 3. delete the user - user.deactivate() - user.delete() + // 3. deactivate and delete the user + userApi.deactivateUser(user.getId(), false) + userApi.deleteUser(user.getId(), false) // 4. get user expect 404 expect(ResourceException) { - client.getUser(email) + userApi.getUser(email) } } - @Test + @Test (groups = "group2") @Scenario("user-group-target-role") void groupTargetRoleTest() { @@ -572,55 +529,63 @@ class UsersIT extends ITSupport implements CrudTestSupport { def email = "john-${uniqueTestName}@example.com" def groupName = "Group-Target Test Group ${uniqueTestName}" + UserApi userApi = new UserApi(getClient()) + GroupApi groupApi = new GroupApi(getClient()) + RoleAssignmentApi roleAssignmentApi = new RoleAssignmentApi(getClient()) + RoleTargetApi roleTargetApi = new RoleTargetApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(false) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(false) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) Group group = GroupBuilder.instance() .setName(groupName) - .buildAndCreate(client) + .buildAndCreate(groupApi) registerForCleanup(group) validateGroup(group, groupName) // 2. Assign USER_ADMIN role to the user - AssignRoleRequest assignRoleRequest = client.instantiate(AssignRoleRequest) + AssignRoleRequest assignRoleRequest = new AssignRoleRequest() assignRoleRequest.setType(RoleType.USER_ADMIN) - Role role = user.assignRole(assignRoleRequest) + Role role = roleAssignmentApi.assignRoleToUser(user.getId(), assignRoleRequest, true) // 3. Add Group Target to User Admin Role - user.addGroupTarget(role.getId(), group.getId()) + roleTargetApi.assignGroupTargetToUserRole(user.getId(), role.getId(), group.getId()) // 4. List Group Targets for Role - assertGroupTargetPresent(user, group, role) + List groupTargets = roleTargetApi.listGroupTargetsForRole(user.getId(), role.getId(), null, null) + Optional match = groupTargets.stream().filter(g -> g.getProfile().getName() == group.getProfile().getName()).findAny() + assertThat(match.isPresent(), is(true)) // 5. Remove Group Target from Admin User Role and verify removed // Note: Don’t remove the last group target from a role assignment, as this causes an exception. // To get around this, create a new group and add this group target to user admin role def adminGroupName = "Group-Target User Admin Test Group ${uniqueTestName}" - deleteGroup(adminGroupName, client) Group adminGroup = GroupBuilder.instance() .setName(adminGroupName) - .buildAndCreate(client) + .buildAndCreate(groupApi) registerForCleanup(adminGroup) validateGroup(adminGroup, adminGroupName) - user.addGroupTarget(role.getId(), adminGroup.getId()) - user.removeGroupTarget(role.getId(), adminGroup.getId()) + roleTargetApi.assignGroupTargetToUserRole(user.getId(), role.getId(), adminGroup.getId()) + roleTargetApi.unassignGroupTargetFromUserAdminRole(user.getId(), role.getId(), adminGroup.getId()) - assertGroupTargetPresent(user, group, role) + groupTargets = roleTargetApi.listGroupTargetsForRole(user.getId(), role.getId(), null, null) + match = groupTargets.stream().filter(g -> g.getProfile().getName() == group.getProfile().getName()).findAny() + assertThat(match.isPresent(), is(true)) } - @Test (groups = "group3") + @Test (groups = "group2") @Scenario("user-profile-update") void userProfileUpdate() { @@ -629,14 +594,16 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Profile-Update' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(false) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(false) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) @@ -645,14 +612,28 @@ class UsersIT extends ITSupport implements CrudTestSupport { // 2. Update the user profile and verify that profile was updated // Need to wait 1 second here as that is the minimum time resolution of the 'lastUpdated' field sleep(1000) - user.getProfile().put("nickName", "Batman") - user.update() - assertThat(user.lastUpdated, greaterThan(originalLastUpdated)) - User updatedUser = client.getUser(user.getId()) - assertThat(updatedUser.getProfile().get("nickName"), equalTo("Batman")) + + UpdateUserRequest updateUserRequest = new UpdateUserRequest() + UserProfile userProfile = new UserProfile() + userProfile.setNickName("Batman") + + // Note: Custom user profile properties can be added with something like below, but + // the respective property must first be associated to the User schema. + // You can use the Profile Editor in your Org's administrator UI or the Schemas API + // to manage schema extensions. + //userProfile.getAdditionalProperties().put("key1", "val1") + + updateUserRequest.setProfile(userProfile) + + userApi.updateUser(user.getId(), updateUserRequest, true) + + User updatedUser = userApi.getUser(user.getId()) + + assertThat(updatedUser.lastUpdated, greaterThan(originalLastUpdated)) + assertThat(updatedUser.getProfile().getProperties().get("nickName"), equalTo("Batman")) } - @Test + @Test (groups = "group2") @Scenario("user-suspend") void userSuspendTest() { @@ -661,62 +642,47 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Suspend' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(true) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) // 2. Suspend the user and verify user in list of suspended users - user.suspend() + userApi.suspendUser(user.getId()) // fix flakiness seen in PDV tests Thread.sleep(getTestOperationDelay()) - assertPresent(client.listUsers(null, 'status eq \"SUSPENDED\"', null, null, null), user) + List users = userApi.listUsers(null, null, null, 'status eq \"SUSPENDED\"',null, null, null) + Optional match = users.stream().filter(u -> u.getId() == user.getId()).findAny() + assertThat(match.isPresent(), is(true)) // 3. Unsuspend the user and verify user in list of active users - user.unsuspend() - assertPresent(client.listUsers(null, 'status eq \"ACTIVE\"', null, null, null), user) - } + userApi.unsuspendUser(user.getId()) - @Test - void getUserInvalidUserId() { - try { - def userId = "invalid-user-id-${uniqueTestName}@example.com" - getClient().getUser(userId) - Assert.fail("Expected ResourceException") - } catch(ResourceException e) { - assertThat e.getStatus(), equalTo(404) - } - } - - @Test - void getUserNullUserId() { - try { - getClient().getUser(null) - Assert.fail("Expected IllegalArgumentException") - } catch(IllegalArgumentException e) { - assertThat e.getMessage(), allOf(containsString("userId"), containsString("required")) - } + users = userApi.listUsers(null, null, null, 'status eq \"ACTIVE\"',null, null, null) + match = users.stream().filter(u -> u.getId() == user.getId()).findAny() + assertThat(match.isPresent(), is(true)) } - @Test - void getUserEmptyUserId() { - try { - getClient().getUser("") - Assert.fail("Expected IllegalArgumentException") - } catch(IllegalArgumentException e) { - assertThat e.getMessage(), allOf(containsString("userId"), containsString("required")) + @Test(groups = "group2") + void getUserInvalidUserId() { + def userId = "invalid-user-id-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + expect(ResourceException) { + userApi.getUser(userId) } } - @Test (groups = "group3") + @Test (groups = "group2") void createUserWithGroups() { def groupName = "Group-to-Assign-${uniqueTestName}" @@ -725,97 +691,76 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Create-User-With-Group' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + GroupApi groupApi = new GroupApi(getClient()) + // 1. Create group Group group = GroupBuilder.instance() .setName(groupName) - .buildAndCreate(client) + .buildAndCreate(groupApi) registerForCleanup(group) validateGroup(group, groupName) // 2. Create a user User createUser = UserBuilder.instance() - .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(false) - .addGroup(group.getId()) - .buildAndCreate(client) + .setEmail(email) + .setFirstName(firstName) + .setLastName(lastName) + .setPassword(password.toCharArray()) + .setActive(false) + .addGroup(group.getId()) + .buildAndCreate(userApi) registerForCleanup(createUser) validateUser(createUser, firstName, lastName, email) - List groups = createUser.listGroups().stream().collect(Collectors.toList()) + List groups = userApi.listUserGroups(createUser.getId()).stream().collect(Collectors.toList()) assertThat groups, allOf(hasSize(2)) assertThat groups.get(0).getProfile().name, equalTo("Everyone") assertThat groups.get(1).getId(), equalTo(group.id) } - @Test - void setUserPasswordWithoutReset() { - - def user = randomUser() - def userId = user.getId() - - Resource userPasswordRequest = client.instantiate(ExtensibleResource) - userPasswordRequest.put("credentials", client.instantiate(ExtensibleResource) - .put("password", client.instantiate(ExtensibleResource) - .put("value", "aPassword1!".toCharArray()))) +// @Test (groups = "group3") +// void setUserPasswordWithoutReset() { +// +// def user = randomUser() +// def userId = user.getId() +// +// Resource userPasswordRequest = client.instantiate(ExtensibleResource) +// userPasswordRequest.put("credentials", client.instantiate(ExtensibleResource) +// .put("password", client.instantiate(ExtensibleResource) +// .put("value", "aPassword1!".toCharArray()))) +// +// Resource result = client.getDataStore().http() +// .setBody(userPasswordRequest) +// .addQueryParameter("key1", "value1") +// .addQueryParameter("key2", "value2") +// .post("/api/v1/users/"+ userId, User.class) +// +// assertThat(result, instanceOf(User)) +// } - Resource result = client.getDataStore().http() - .setBody(userPasswordRequest) - .addQueryParameter("key1", "value1") - .addQueryParameter("key2", "value2") - .post("/api/v1/users/"+ userId, User.class) - - assertThat(result, instanceOf(User)) - } - - @Test + @Test (groups = "group3") void importUserWithSha512Password() { def salt = "aSalt" def hashedPassword = hashPassword("aPassword", salt) - def email = "joe.coder+${uniqueTestName}@example.com" - User user = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setSha512PasswordHash(hashedPassword, salt, "PREFIX") - .buildAndCreate(getClient()) - registerForCleanup(user) - assertThat user.getCredentials(), notNullValue() - assertThat user.getCredentials().getProvider().getType(), is(AuthenticationProviderType.IMPORT) - } + UserApi userApi = new UserApi(getClient()) - @Test - @Scenario("user-forgot-password-generate-one-time-token") - void forgotPasswordGenerateOttTest() { - - def password = 'Passw0rd!2@3#' - def firstName = 'John' - def lastName = 'Forgot-Password' - def email = "john-${uniqueTestName}@example.com" - - // 1. Create a user User user = UserBuilder.instance() .setEmail(email) - .setFirstName(firstName) - .setLastName(lastName) - .setPassword(password.toCharArray()) - .setActive(true) - .setSecurityQuestion("How many roads must a man walk down?") - .setSecurityQuestionAnswer("forty two") - .buildAndCreate(client) + .setFirstName("Joe") + .setLastName("Code") + .setSha512PasswordHash(hashedPassword, salt, "PREFIX") + .buildAndCreate(userApi) registerForCleanup(user) - validateUser(user, firstName, lastName, email) - ForgotPasswordResponse response = user.forgotPasswordGenerateOneTimeToken(false) - assertThat response.getResetPasswordUrl(), containsString("/signin/reset-password/") + assertThat user.getCredentials(), notNullValue() + assertThat user.getCredentials().getProvider().getType(), equalTo(AuthenticationProviderType.IMPORT) } - @Test + @Test (groups = "group3") @Scenario("user-forgot-password-set-new-password") void forgotPasswordSetNewPasswordTest() { @@ -824,6 +769,8 @@ class UsersIT extends ITSupport implements CrudTestSupport { def lastName = 'Forgot-Password' def email = "john-${uniqueTestName}@example.com" + UserApi userApi = new UserApi(getClient()) + // 1. Create a user User user = UserBuilder.instance() .setEmail(email) @@ -833,33 +780,39 @@ class UsersIT extends ITSupport implements CrudTestSupport { .setActive(true) .setSecurityQuestion("How many roads must a man walk down?") .setSecurityQuestionAnswer("forty two") - .buildAndCreate(client) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) - UserCredentials userCredentials = client.instantiate(UserCredentials) - .setPassword(client.instantiate(PasswordCredential) - .setValue('NewPassw0rd!2@3#'.toCharArray())) - .setRecoveryQuestion(client.instantiate(RecoveryQuestionCredential) - .setQuestion('How many roads must a man walk down?') - .setAnswer('forty two')) - - ForgotPasswordResponse response = user.forgotPasswordSetNewPassword(userCredentials, false) - assertThat response.get("recovery_question")["question"], equalTo("How many roads must a man walk down?") - assertThat response.get("provider")["type"], equalTo("OKTA") - assertThat response.get("provider")["name"], equalTo("OKTA") + PasswordCredential passwordCredential = new PasswordCredential() + passwordCredential.setValue("NewPassw0rd!2@3#") + + RecoveryQuestionCredential recoveryQuestionCredential = new RecoveryQuestionCredential() + recoveryQuestionCredential.setQuestion("How many roads must a man walk down?") + recoveryQuestionCredential.setAnswer("forty two") + + UserCredentials userCredentials = new UserCredentials() + userCredentials.setPassword(passwordCredential) + userCredentials.setRecoveryQuestion(recoveryQuestionCredential) + + userCredentials = userApi.forgotPasswordSetNewPassword(user.getId(), userCredentials, false) + assertThat userCredentials.getRecoveryQuestion().getQuestion(), equalTo("How many roads must a man walk down?") + assertThat userCredentials.getProvider().getType(), equalTo(AuthenticationProviderType.OKTA) + assertThat userCredentials.getProvider().getName(), equalTo("OKTA") } - @Test + @Test (groups = "group3") void userWithAuthenticationProviderTest() { def firstName = 'John' def lastName = 'Forgot-Password' def email = "john-${uniqueTestName}@example.com" - def authenticationProvider = client.instantiate(AuthenticationProvider) - .setName(AuthenticationProviderType.FEDERATION.name()) - .setType(AuthenticationProviderType.FEDERATION) + UserApi userApi = new UserApi(getClient()) + + AuthenticationProvider authenticationProvider = new AuthenticationProvider() + authenticationProvider.setName("FEDERATION") + authenticationProvider.setType(AuthenticationProviderType.FEDERATION) // 1. Create a user User user = UserBuilder.instance() @@ -868,53 +821,67 @@ class UsersIT extends ITSupport implements CrudTestSupport { .setLastName(lastName) .setLogin(email) .setProvider(authenticationProvider) - .buildAndCreate(client) + .buildAndCreate(userApi) registerForCleanup(user) validateUser(user, firstName, lastName, email) assertThat user.getCredentials(), notNullValue() - assertThat user.getCredentials().getProvider().getType(), is(AuthenticationProviderType.FEDERATION) - assertThat user.getCredentials().getProvider().getName(), equalTo(AuthenticationProviderType.FEDERATION.name()) + assertThat user.getCredentials().getProvider().getType(), equalTo(AuthenticationProviderType.FEDERATION) + assertThat user.getCredentials().getProvider().getName(), equalTo("FEDERATION") } - @Test - void testGetNextPageUrl() { - def user1 = create(client) - def user2 = create(client) - def user3 = create(client) + @Test (groups = "group3") + void testPagination() { + def user1 = randomUser() + def user2 = randomUser() + def user3 = randomUser() registerForCleanup(user1) registerForCleanup(user2) registerForCleanup(user3) - String pageSize = "2" + UserApi userApi = new UserApi(getClient()) + + // limit + int pageSize = 2 - def userListFirstPage = client.http() - .addQueryParameter("limit", pageSize) - .get("/api/v1/users", UserList.class) - assertThat userListFirstPage, notNullValue() - assertThat userListFirstPage.getNextPageUrl(), notNullValue() - assertThat userListFirstPage.getProperties().get("currentPage").getProperties().get("items").collect().size(), is(2) + PagedList usersPagedListOne = userApi.listUsersWithPaginationInfo(null, null, pageSize, null, null, null, null) - def userListSecondPage = client.http() - .addQueryParameter("limit", pageSize) - .get(userListFirstPage.getNextPageUrl(), UserList.class) - assertThat userListSecondPage, notNullValue() - assertThat userListSecondPage.getProperties().get("currentPage").getProperties().get("items").collect().size(), is(greaterThanOrEqualTo(1)) + assertThat usersPagedListOne, notNullValue() + assertThat usersPagedListOne.items().size(), is(2) + assertThat usersPagedListOne.self, notNullValue() + assertThat usersPagedListOne.nextPage, notNullValue() + + // e.g. https://example.okta.com/api/v1/users?after=000u3pfv9v4SQXvpBB0g7&limit=2 + String nextPageUrl = usersPagedListOne.nextPage + String after = splitQuery(new URL(nextPageUrl)).get("after") + + assertThat after, notNullValue() + + PagedList usersPagedListTwo = userApi.listUsersWithPaginationInfo(null, after, pageSize, null, null, null, null) + + assertThat usersPagedListTwo, notNullValue() + assertThat usersPagedListTwo.items().size(), is(greaterThanOrEqualTo(1)) + assertThat usersPagedListTwo.self, equalTo(usersPagedListOne.nextPage) } @Test (groups = "group3") void testListGroupAssignmentsWithExpand() { + GroupApi groupApi = new GroupApi(getClient()) + // Create more than 20 groups for (int i = 1; i < 30; i++) { - registerForCleanup(new DefaultGroupBuilder().setName("test-group_" + i + "_${uniqueTestName}").buildAndCreate(client)) + registerForCleanup(new DefaultGroupBuilder().setName("test-group_" + i + "_${uniqueTestName}").buildAndCreate(groupApi)) } + ApplicationApi applicationApi = new ApplicationApi(getClient()) + // Fetch the GroupAssignment list in two requests def expandParameter = "group" - List groupAssignments = client.listApplications().first() - .listGroupAssignments(null, expandParameter) - .stream() - .collect(Collectors.toList()) + List applicationList = + applicationApi.listApplications(null, null, null, null, null, null) + Application application = applicationList.first() + List groupAssignments = + applicationApi.listApplicationGroupAssignments(application.getId(), null, null, null, expandParameter) // Make sure both pages (all resources) contain an expand parameter for (ApplicationGroupAssignment groupAssignment : groupAssignments) { @@ -926,42 +893,27 @@ class UsersIT extends ITSupport implements CrudTestSupport { } } - private void ensureCustomProperties() { - def userSchemaUri = "/api/v1/meta/schemas/user/default" - - ExtensibleResource userSchema = getClient().http().get(userSchemaUri, ExtensibleResource) - Map customProperties = userSchema.get("definitions").get("custom").get("properties") - - boolean needsUpdate = - ensureCustomProperty("customNumber", [type: "number"], customProperties) && - ensureCustomProperty("customBoolean", [type: "boolean"], customProperties) && - ensureCustomProperty("customInteger", [type: "integer"], customProperties) && - ensureCustomProperty("customStringArray", [type: "array", items: [type: "string"]], customProperties) && - ensureCustomProperty("customNumberArray", [type: "array", items: [type: "number"]], customProperties) && - ensureCustomProperty("customIntegerArray", [type: "array", items: [type: "integer"]], customProperties) - - if (needsUpdate) { - getClient().http() - .setBody(userSchema) - .post(userSchemaUri, ExtensibleResource) - } - } - - private static boolean ensureCustomProperty(String name, Map body, Map customProperties) { - boolean addProperty = !customProperties.containsKey(name) - if (addProperty) { - body.putAll([ - title: name - ]) - customProperties.put(name, body) - } - return addProperty - } - - private String hashPassword(String password, String salt) { + private static String hashPassword(String password, String salt) { def messageDigest = MessageDigest.getInstance("SHA-512") messageDigest.update(salt.getBytes(StandardCharsets.UTF_8)) def bytes = messageDigest.digest(password.getBytes(StandardCharsets.UTF_8)) return Base64.getEncoder().encodeToString(bytes) } -} + + /** + * Split a URL with query strings into name value pairs. + * @param url + * @return map of query string name value pairs + * @throws UnsupportedEncodingException + */ + private static Map splitQuery(URL url) throws UnsupportedEncodingException { + Map query_pairs = new LinkedHashMap() + String query = url.getQuery() + String[] pairs = query.split("&") + for (String pair : pairs) { + int index = pair.indexOf("=") + query_pairs.put(URLDecoder.decode(pair.substring(0, index), "UTF-8"), URLDecoder.decode(pair.substring(index + 1), "UTF-8")) + } + return query_pairs + } +} \ No newline at end of file diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/ClientProvider.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/ClientProvider.groovy index 48b928b5cd2..c01bab435c6 100644 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/ClientProvider.groovy +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/ClientProvider.groovy @@ -16,26 +16,12 @@ package com.okta.sdk.tests.it.util import com.okta.commons.lang.Strings -import com.okta.sdk.authc.credentials.TokenClientCredentials -import com.okta.sdk.client.Client import com.okta.sdk.client.Clients -import com.okta.sdk.impl.cache.DisabledCacheManager -import com.okta.sdk.resource.Deletable -import com.okta.sdk.resource.ResourceException -import com.okta.sdk.resource.application.Application -import com.okta.sdk.resource.authorization.server.AuthorizationServer -import com.okta.sdk.resource.event.hook.EventHook -import com.okta.sdk.resource.group.GroupList -import com.okta.sdk.resource.group.rule.GroupRule -import com.okta.sdk.resource.group.rule.GroupRuleList -import com.okta.sdk.resource.group.rule.GroupRuleStatus -import com.okta.sdk.resource.identity.provider.IdentityProvider -import com.okta.sdk.resource.inline.hook.InlineHook -import com.okta.sdk.resource.linked.object.LinkedObject -import com.okta.sdk.resource.user.User -import com.okta.sdk.resource.user.UserStatus import com.okta.sdk.tests.Scenario import com.okta.sdk.tests.TestResources +import org.openapitools.client.ApiClient +import org.openapitools.client.api.* +import org.openapitools.client.model.* import org.slf4j.Logger import org.slf4j.LoggerFactory import org.testng.IHookCallBack @@ -44,7 +30,6 @@ import org.testng.ITestResult import org.testng.annotations.AfterMethod import org.testng.annotations.Listeners - /** * Creates a thread local client for a test method to use. The client may be connected to an actual Okta instance or a Test Server. */ @@ -53,14 +38,14 @@ trait ClientProvider implements IHookable { private Logger log = LoggerFactory.getLogger(ClientProvider) - private ThreadLocal threadLocal = new ThreadLocal<>() + private ThreadLocal threadLocal = new ThreadLocal<>() private ThreadLocal testName = new ThreadLocal<>() - private List toBeDeleted = [] + private List toBeDeleted = [] - Client getClient(String scenarioId = null) { - Client client = threadLocal.get() + ApiClient getClient(String scenarioId = null) { + ApiClient client = threadLocal.get() if (client == null) { - threadLocal.set(buildClient(scenarioId)) + threadLocal.set(buildClient()) } return threadLocal.get() } @@ -69,20 +54,11 @@ trait ClientProvider implements IHookable { return Strings.hasText(System.getProperty(TestServer.TEST_SERVER_BASE_URL)) } - private Client buildClient(String scenarioId = null) { - - String testServerBaseUrl = System.getProperty(TestServer.TEST_SERVER_BASE_URL) - if (isRunningWithTestServer() && scenarioId != null) { - return Clients.builder() - .setOrgUrl(testServerBaseUrl + scenarioId) - .setClientCredentials(new TokenClientCredentials("00ICU812")) - .setCacheManager(new DisabledCacheManager()) // disable cache when using mock server - .build() - } + private ApiClient buildClient() { - Client client = Clients.builder().build() - client.dataStore.requestExecutor.numRetries = 10 - return client + ApiClient apiClient = Clients.builder().build() + //apiClient.setDebugging(true) + return apiClient } @Override @@ -102,20 +78,20 @@ trait ClientProvider implements IHookable { if (scenario != null) scenarioId = scenario.value() } - Client client = getClient(scenarioId) + ApiClient client = getClient(scenarioId) if (!isRunningWithTestServer() && testResources != null) { // delete any users that may collide with the test that is about to run - testResources.users().each { email -> - deleteUser(email, client) + testResources.users().each { id -> + deleteUser(id, client) } - testResources.groups().each { groupName -> - deleteGroup(groupName, client) + testResources.groups().each { id -> + deleteGroup(id, client) } - testResources.rules().each { ruleName -> - deleteRule(ruleName, client) + testResources.rules().each { id -> + deleteGroupRule(id, client) } } // run the tests @@ -138,63 +114,161 @@ trait ClientProvider implements IHookable { /** * Registers a Deletable to be cleaned up after the test is run. - * @param deletable Resource to be deleted. */ - void registerForCleanup(Deletable deletable) { + void registerForCleanup(Object deletable) { toBeDeleted.add(deletable) } - void deleteUser(String email, Client client) { - Util.ignoring(ResourceException) { - User user = client.getUser(email) - if (user.status != UserStatus.DEPROVISIONED) { - user.deactivate() + void deleteApp(String id, ApiClient client) { + log.info("Deleting App: {}", id) + + ApplicationApi applicationApi = new ApplicationApi(client) + Application appToDelete = applicationApi.getApplication(id, null) + + if (appToDelete != null) { + if (appToDelete.getStatus() == ApplicationLifecycleStatus.ACTIVE) { + // deactivate + applicationApi.deactivateApplication(appToDelete.getId()) } - user.delete() + // delete + applicationApi.deleteApplication(appToDelete.getId()) } } - void deleteGroup(String groupName, Client client) { - Util.ignoring(ResourceException) { - GroupList groups = client.listGroups(groupName, null, null) - groups.each {group -> - if (groupName.equals(group.profile.name)) { - group.delete() - } + void deleteUser(String id, ApiClient client) { + log.info("Deleting User: {}", id) + UserApi userApi = new UserApi(client) + User userToDelete = userApi.getUser(id) + + if (userToDelete != null) { + if (userToDelete.getStatus() != UserStatus.DEPROVISIONED) { + // deactivate + userApi.deactivateUser(userToDelete.getId(), false) } + // delete + userApi.deleteUser(userToDelete.getId(), false) } } - void deleteRule(String ruleName, Client client) { - Util.ignoring(ResourceException) { - GroupRuleList rules = client.listGroupRules() - rules.each {rule -> - if (ruleName.equals(rule.name)) { - if (rule.status == GroupRuleStatus.ACTIVE) { - rule.deactivate() - } - rule.delete() - } + void deleteUserType(String id, ApiClient client) { + log.info("Deleting UserType: {}", id) + UserTypeApi userTypeApi= new UserTypeApi(client) + UserType userTypeToDelete = userTypeApi.getUserType(id) + + if (userTypeToDelete != null) { + userTypeApi.deleteUserType(userTypeToDelete.getId()) + } + } + + void deleteGroup(String id, ApiClient client) { + log.info("Deleting Group: {}", id) + GroupApi groupApi = new GroupApi(client) + Group groupToDelete = groupApi.getGroup(id) + + if (groupToDelete != null) { + groupApi.deleteGroup(groupToDelete.getId()) + } + } + + void deleteGroupRule(String id, ApiClient client) { + log.info("Deleting GroupRule: {}", id) + GroupApi groupApi = new GroupApi(client) + GroupRule groupRuleToDelete = groupApi.getGroupRule(id, null) + + if (groupRuleToDelete != null) { + groupApi.deleteGroup(groupRuleToDelete.getId()) + } + } + + void deleteIdp(String id, ApiClient client) { + log.info("Deleting IdP: {}", id) + IdentityProviderApi idpApi = new IdentityProviderApi(client) + IdentityProvider idpToDelete = idpApi.getIdentityProvider(id) + + if (idpToDelete != null) { + if (idpToDelete.getStatus() == LifecycleStatus.ACTIVE) { + // deactivate + idpApi.deactivateIdentityProvider(idpToDelete.getId()) + } + // delete + idpApi.deleteIdentityProvider(idpToDelete.getId()) + } + } + + void deleteInlineHook(String id, ApiClient client) { + log.info("Deleting InlineHook: {}", id) + InlineHookApi inlineHookApi = new InlineHookApi(client) + InlineHook inlineHookToDelete = inlineHookApi.getInlineHook(id) + + if (inlineHookToDelete != null) { + if (inlineHookToDelete.getStatus() == InlineHookStatus.ACTIVE) { + // deactivate + inlineHookApi.deactivateInlineHook(inlineHookToDelete.getId()) + } + // delete + inlineHookApi.deleteInlineHook(inlineHookToDelete.getId()) + } + } + + void deletePolicy(String id, ApiClient client) { + log.info("Deleting Policy: {}", id) + PolicyApi policyApi = new PolicyApi(client) + Policy policyToDelete = policyApi.getPolicy(id, "false") + + if (policyToDelete != null) { + if (policyToDelete.getStatus() == LifecycleStatus.ACTIVE) { + // deactivate + policyApi.deactivatePolicy(policyToDelete.getId()) } + // delete + policyApi.deletePolicy(policyToDelete.getId()) } } + void deletePolicyRule(String policyId, String ruleId, ApiClient client) { + log.info("Deleting PolicyRule: policyId {}, ruleId: {}", policyId, ruleId) + PolicyApi policyApi = new PolicyApi(client) + policyApi.deletePolicyRule(policyId, ruleId) + } + @AfterMethod (groups = ["group1", "group2", "group3"]) void clean() { if (!isRunningWithTestServer()) { // delete them in reverse order so dependencies are resolved toBeDeleted.reverse().each { deletable -> try { - if (deletable instanceof User || - deletable instanceof Application || - deletable instanceof AuthorizationServer || - deletable instanceof EventHook || - deletable instanceof InlineHook || - deletable instanceof GroupRule || - deletable instanceof IdentityProvider) { - deletable.deactivate() + if (deletable instanceof User) { + User tobeDeletedUser = (User) deletable + deleteUser(tobeDeletedUser.getId(), getClient()) + } + else if (deletable instanceof UserType) { + UserType tobeDeletedUserType = (UserType) deletable + deleteUserType(tobeDeletedUserType.getId(), getClient()) + } + else if (deletable instanceof Group) { + Group tobeDeletedGroup = (Group) deletable + deleteGroup(tobeDeletedGroup.getId(), getClient()) + } + else if (deletable instanceof GroupRule) { + GroupRule tobeDeletedGroupRule = (GroupRule) deletable + deleteGroupRule(tobeDeletedGroupRule.getId(), getClient()) + } + else if (deletable instanceof Application) { + Application tobeDeletedApp = (Application) deletable + deleteApp(tobeDeletedApp.getId(), getClient()) + } + else if (deletable instanceof IdentityProvider) { + IdentityProvider tobeDeletedIdp = (IdentityProvider) deletable + deleteIdp(tobeDeletedIdp.getId(), getClient()) + } + else if (deletable instanceof InlineHook) { + InlineHook tobeDeletedInlineHook = (InlineHook) deletable + deleteInlineHook(tobeDeletedInlineHook.getId(), getClient()) + } + else if (deletable instanceof Policy) { + Policy tobeDeletedPolicy = (Policy) deletable + deletePolicy(tobeDeletedPolicy.getId(), getClient()) } - deletable.delete() } catch (Exception e) { log.trace("Exception thrown during cleanup, it is ignored so the rest of the cleanup can be run:", e) diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/ITSupport.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/ITSupport.groovy index 555372241dc..4b7ea5afb2c 100644 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/ITSupport.groovy +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/ITSupport.groovy @@ -15,22 +15,42 @@ */ package com.okta.sdk.tests.it.util -import com.okta.sdk.client.Client -import com.okta.sdk.resource.ExtensibleResource -import com.okta.sdk.resource.group.Group import com.okta.sdk.resource.group.GroupBuilder -import com.okta.sdk.resource.policy.* -import com.okta.sdk.resource.user.User -import com.okta.sdk.resource.user.UserBuilder +import com.okta.sdk.resource.policy.OktaSignOnPolicyBuilder +import com.okta.sdk.resource.policy.PasswordPolicyBuilder +import com.okta.sdk.resource.policy.PolicyBuilder import com.okta.sdk.tests.ConditionalSkipTestAnalyzer import com.okta.sdk.tests.Scenario +import org.openapitools.client.api.GroupApi +import org.openapitools.client.api.PolicyApi +import org.openapitools.client.api.UserApi +import org.openapitools.client.model.CreateUserRequest +import org.openapitools.client.model.Group +import org.openapitools.client.model.LifecycleStatus +import org.openapitools.client.model.OktaSignOnPolicy +import org.openapitools.client.model.PasswordPolicy +import org.openapitools.client.model.Policy +import org.openapitools.client.model.PolicyType +import org.openapitools.client.model.User +import org.openapitools.client.model.UserProfile import org.slf4j.Logger import org.slf4j.LoggerFactory +import org.springframework.core.ParameterizedTypeReference +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity +import org.springframework.util.LinkedMultiValueMap import org.testng.ITestContext +import org.testng.ITestResult +import org.testng.annotations.AfterMethod import org.testng.annotations.AfterSuite +import org.testng.annotations.BeforeMethod import org.testng.annotations.BeforeSuite import org.testng.annotations.Listeners +import java.lang.reflect.Method + @Listeners(value = ConditionalSkipTestAnalyzer.class) abstract class ITSupport implements ClientProvider { @@ -69,6 +89,16 @@ abstract class ITSupport implements ClientProvider { isOIEEnvironment = isOIEEnvironment() } + @BeforeMethod + void log(Method method) { + log.info("Running" + " - " + method.getName() + " on " + getClient().getBasePath()) + } + + @AfterMethod + void afterMethod(ITestResult result) { + log.info("Finished " + result.getInstanceName() + " - " + result.getName()) + } + @AfterSuite() void stop() { if (testServer != null) { @@ -86,7 +116,7 @@ abstract class ITSupport implements ClientProvider { * - System property 'okta.it.operationDelay' * - Env variable 'OKTA_IT_OPERATION_DELAY' */ - long getTestOperationDelay() { + static long getTestOperationDelay() { Long testDelay = Long.getLong(IT_OPERATION_DELAY) if (testDelay == null) { @@ -98,31 +128,36 @@ abstract class ITSupport implements ClientProvider { } } - return testDelay == null ? 0 : testDelay; + return testDelay == null ? 0 : testDelay } User randomUser() { - Client client = getClient() def email = "joe.coder+" + UUID.randomUUID().toString() + "@example.com" - User user = UserBuilder.instance() - .setEmail(email) - .setFirstName("Joe") - .setLastName("Code") - .setPassword("Password1".toCharArray()) - .setActive(true) - .buildAndCreate(client) - registerForCleanup(user) - - return user + + UserProfile userProfile = new UserProfile() + .firstName("Joe") + .lastName("Coder") + .email(email) + .mobilePhone("1234567890") + .login(email) + + CreateUserRequest createUserRequest = new CreateUserRequest() + .profile(userProfile) + + UserApi userApi = new UserApi(getClient()) + User createdUser = userApi.createUser(createUserRequest, true, null, null) + return createdUser } Group randomGroup(String name = "java-sdk-it-${UUID.randomUUID().toString()}") { + GroupApi groupApi = new GroupApi(getClient()) + Group group = GroupBuilder.instance() .setName(name) .setDescription(name) - .buildAndCreate(getClient()) + .buildAndCreate(groupApi) registerForCleanup(group) return group @@ -130,15 +165,30 @@ abstract class ITSupport implements ClientProvider { PasswordPolicy randomPasswordPolicy(String groupId) { + PolicyApi policyApi = new PolicyApi(getClient()) + PasswordPolicy policy = PasswordPolicyBuilder.instance() .setName("java-sdk-it-" + UUID.randomUUID().toString()) - .setStatus(Policy.StatusEnum.ACTIVE) + .setStatus(LifecycleStatus.ACTIVE) .setDescription("IT created Policy") - .setStatus(Policy.StatusEnum.ACTIVE) .setPriority(1) .addGroup(groupId) - .buildAndCreate(client) + .buildAndCreate(policyApi) + registerForCleanup(policy) + return policy + } + + Policy randomPolicy() { + + PolicyApi policyApi = new PolicyApi(getClient()) + + Policy policy = PolicyBuilder.instance() + .setName("java-sdk-it-" + UUID.randomUUID().toString()) + .setStatus(LifecycleStatus.ACTIVE) + .setDescription("IT created Policy") + .setPriority(1) + .buildAndCreate(policyApi) registerForCleanup(policy) return policy @@ -146,13 +196,14 @@ abstract class ITSupport implements ClientProvider { OktaSignOnPolicy randomSignOnPolicy(String groupId) { + PolicyApi policyApi = new PolicyApi(getClient()) + OktaSignOnPolicy policy = OktaSignOnPolicyBuilder.instance() .setName("java-sdk-it-" + UUID.randomUUID().toString()) .setDescription("IT created Policy") - .setStatus(Policy.StatusEnum.ACTIVE) - .setType(PolicyType.OKTA_SIGN_ON) - .buildAndCreate(client) - + .setStatus(LifecycleStatus.ACTIVE) + .setType(PolicyType.OKTA_SIGN_ON) + .buildAndCreate(policyApi) registerForCleanup(policy) return policy @@ -160,12 +211,26 @@ abstract class ITSupport implements ClientProvider { boolean isOIEEnvironment() { - Object pipeline = client.http() - .get("/.well-known/okta-organization", ExtensibleResource.class) - .get("pipeline"); - if(pipeline != null && pipeline.toString().equals("idx")) { - return true; + ResponseEntity> responseEntity = getClient().invokeAPI("/.well-known/okta-organization", + HttpMethod.GET, + Collections.emptyMap(), + null, + null, + new HttpHeaders(), + new LinkedMultiValueMap(), + null, + Collections.singletonList(MediaType.APPLICATION_JSON), + null, + new String[]{ "apiToken" }, + new ParameterizedTypeReference>() {}) + + if (responseEntity != null && responseEntity.getBody() != null) { + String pipeline = responseEntity.getBody().get("pipeline") + if (Objects.equals(pipeline, "idx")) { + return true + } } - return false; + + return false } } \ No newline at end of file diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/OktaOrgCleaner.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/OktaOrgCleaner.groovy index 872abc97d25..8f4a5d2143b 100644 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/OktaOrgCleaner.groovy +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/OktaOrgCleaner.groovy @@ -15,12 +15,21 @@ */ package com.okta.sdk.tests.it.util -import com.okta.sdk.client.Client import com.okta.sdk.client.Clients -import com.okta.sdk.resource.ResourceException -import com.okta.sdk.resource.group.rule.GroupRule -import com.okta.sdk.resource.policy.PolicyType -import com.okta.sdk.resource.user.UserStatus +import org.openapitools.client.ApiClient +import org.openapitools.client.api.ApplicationApi +import org.openapitools.client.api.AuthorizationServerApi +import org.openapitools.client.api.EventHookApi +import org.openapitools.client.api.GroupApi +import org.openapitools.client.api.IdentityProviderApi +import org.openapitools.client.api.InlineHookApi +import org.openapitools.client.api.LinkedObjectApi +import org.openapitools.client.api.PolicyApi +import org.openapitools.client.api.TemplateApi +import org.openapitools.client.api.UserApi +import org.openapitools.client.api.UserTypeApi +import org.openapitools.client.model.GroupRule + import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -33,111 +42,146 @@ class OktaOrgCleaner { String prefix = "java-sdk-it-" String uuidRegex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" - Client client = Clients.builder().build() + ApiClient client = Clients.builder().build() + + log.info("Cleaning Okta Org: {}", client.getBasePath()) + + UserApi userApi = new UserApi(client) log.info("Deleting Active Users:") - client.listUsers().stream() + userApi.listUsers(null, null, null, 'status eq \"ACTIVE\"', null, null, null) + .stream() .filter { it.getProfile().getEmail().endsWith("@example.com") } .forEach { log.info("\t ${it.getProfile().getEmail()}") - it.deactivate() - it.delete() + // deactivate + userApi.deactivateUser(it.getId(),false) + // delete + userApi.deleteUser(it.getId(), false) } - client.listUsers(null, "status eq \"${UserStatus.DEPROVISIONED}\"", null, null, null).stream() + userApi.listUsers(null, null, null, 'status eq \"DEPROVISIONED\"', null, null, null) .forEach { log.info("Deleting deactivated user: ${it.getProfile().getEmail()}") - it.delete() + userApi.deleteUser(it.getId(), false) } + ApplicationApi applicationApi = new ApplicationApi(client) + log.info("Deleting Applications:") - client.listApplications().stream() + applicationApi.listApplications(null, null, 100, null, null, true).stream() .filter { it.getLabel().startsWith(prefix) && it.getLabel().matches(".*-${uuidRegex}.*") } .forEach { log.info("\t ${it.getLabel()}") - it.deactivate() - it.delete() + applicationApi.deactivateApplication(it.getId()) + applicationApi.deleteApplication(it.getId()) } + GroupApi groupApi = new GroupApi(client) + log.info("Deleting Groups:") - client.listGroups().stream() + groupApi.listGroups(null, null, null, 100, null, null).stream() .filter { it.getProfile().getName().matches(".*-${uuidRegex}.*") } .forEach { log.info("\t ${it.getProfile().getName()}") - it.delete() + groupApi.deleteGroup(it.getId()) } log.info("Deleting Group Rules:") - client.listGroupRules().stream() + groupApi.listGroupRules(1000, null, null, null).stream() .filter { it.getName().startsWith(prefix) && it.getName().matches(".*-${uuidRegex}.*") } .forEach { GroupRule rule = it log.info("\t ${rule.getName()}") Util.ignoring(ResourceException) { - rule.deactivate() + groupApi.deactivateGroupRule(rule.getId()) } - rule.delete() + groupApi.deleteGroupRule(rule.getId(), false) } + PolicyApi policyApi = new PolicyApi(client) + log.info("Deleting Policies:") - client.listPolicies(PolicyType.OKTA_SIGN_ON.toString()).stream() + policyApi.listPolicies("OKTA_SIGN_ON", null, null).stream() .filter { it.getName().startsWith(prefix) && it.getName().matches(".*-${uuidRegex}.*") } .forEach { - it.delete() + log.info("\t ${it.getName()}") + policyApi.deactivatePolicy(it.getId()) + policyApi.deletePolicy(it.getId()) } + LinkedObjectApi linkedObjectApi = new LinkedObjectApi(client) + log.info("Deleting LinkedObjectDefinitions:") - client.listLinkedObjectDefinitions().stream() + linkedObjectApi.listLinkedObjectDefinitions().stream() .filter { it.getPrimary().getName().startsWith("java_sdk_it_") } .forEach { - it.setName(it.getPrimary().getName()) - it.delete() + log.info("\t ${it.getPrimary().getName()}") + linkedObjectApi.deleteLinkedObjectDefinition(it.getPrimary().getName()) } + InlineHookApi inlineHookApi = new InlineHookApi(client) + log.info("Deleting InlineHooks:") - client.listInlineHooks().stream() + inlineHookApi.listInlineHooks(null).stream() .filter { it.getName().startsWith(prefix) && it.getName().matches(".*-${uuidRegex}.*") } .forEach { - it.deactivate() - it.delete() + log.info("\t ${it.getName()}") + inlineHookApi.deactivateInlineHook(it.getId()) + inlineHookApi.deleteInlineHook(it.getId()) } + EventHookApi eventHookApi = new EventHookApi(client) + log.info("Deleting EventHooks:") - client.listEventHooks().stream() + eventHookApi.listEventHooks().stream() .filter { it.getName().startsWith(prefix) && it.getName().matches(".*-${uuidRegex}.*") } .forEach { - it.deactivate() - it.delete() + log.info("\t ${it.getName()}") + eventHookApi.deactivateEventHook(it.getId()) + eventHookApi.deleteEventHook(it.getId()) } + UserTypeApi userTypeApi = new UserTypeApi(client) + log.info("Deleting UserTypes:") - client.listUserTypes().stream() - .filter { it.getName().startsWith("java_sdk_it_") && !it.getDefault() } + userTypeApi.listUserTypes().stream() + .filter { it.getName().startsWith(prefix.replaceAll("-","_")) && !it.getDefault() } .forEach { - it.delete() + log.info("\t ${it.getName()}") + userTypeApi.deleteUserType(it.getId()) } + AuthorizationServerApi authorizationServerApi = new AuthorizationServerApi(client) + log.info("Deleting AuthorizationServers:") - client.listAuthorizationServers().stream() + authorizationServerApi.listAuthorizationServers(null, 100, null).stream() .filter { it.getName().startsWith(prefix) && it.getName().matches(".*-${uuidRegex}.*") } .forEach { - it.deactivate() - it.delete() + log.info("\t ${it.getName()}") + authorizationServerApi.deactivateAuthorizationServer(it.getId()) + authorizationServerApi.deleteAuthorizationServer(it.getId()) } + IdentityProviderApi identityProviderApi = new IdentityProviderApi(client) + log.info("Deleting IdentityProviders:") - client.listIdentityProviders().stream() + identityProviderApi.listIdentityProviders(null, null, 100, null).stream() .filter { it.getName().startsWith(prefix) && it.getName().matches(".*-${uuidRegex}.*") } .forEach { - it.deactivate() - it.delete() + log.info("\t ${it.getName()}") + identityProviderApi.deactivateIdentityProvider(it.getId()) + identityProviderApi.deleteIdentityProvider(it.getId()) } + TemplateApi templateApi = new TemplateApi(client) + log.info("Deleting SmsTemplates:") - client.listSmsTemplates().stream() + templateApi.listSmsTemplates(null).stream() .filter { it.getName().matches(".*-${uuidRegex}.*") } .forEach { - it.delete() + log.info("\t ${it.getName()}") + templateApi.deleteSmsTemplate(it.getId()) } } -} +} \ No newline at end of file diff --git a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/Util.groovy b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/Util.groovy index 59faafbf6d0..e2dc59761d8 100644 --- a/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/Util.groovy +++ b/integration-tests/src/test/groovy/com/okta/sdk/tests/it/util/Util.groovy @@ -15,21 +15,17 @@ */ package com.okta.sdk.tests.it.util -import com.okta.sdk.resource.CollectionResource -import com.okta.sdk.resource.Resource -import com.okta.sdk.resource.group.Group -import com.okta.sdk.resource.group.GroupList -import com.okta.sdk.resource.linked.object.LinkedObject -import com.okta.sdk.resource.user.Role -import com.okta.sdk.resource.user.RoleList -import com.okta.sdk.resource.user.User +import org.openapitools.client.api.GroupApi +import org.openapitools.client.model.Group +import org.openapitools.client.model.GroupType +import org.openapitools.client.model.User import org.testng.Assert import java.util.stream.Collectors import java.util.stream.StreamSupport -import static org.hamcrest.MatcherAssert.* -import static org.hamcrest.Matchers.* +import static org.hamcrest.MatcherAssert.assertThat +import static org.hamcrest.Matchers.equalTo import static org.hamcrest.Matchers.hasSize import static org.hamcrest.Matchers.notNullValue @@ -48,23 +44,21 @@ class Util { assertThat(user, equalTo(expectedUser)) } - static void validateGroup(Group group, Group expectedGroup) { + static void validateGroup(Group group, Group expectedGroup) { validateGroup(group, expectedGroup.profile.name) } - static void validateGroup(Group group, String groupName) { - + static void validateGroup(Group group, String groupName) { assertThat(group.profile.name, equalTo(groupName)) - assertThat(group.type, equalTo("OKTA_GROUP")) + assertThat(group.type, equalTo(GroupType.OKTA_GROUP)) } - static void validateGroup(Group group, String groupName, String description) { - + static void validateGroup(Group group, String groupName, String description) { validateGroup(group, groupName) assertThat(group.profile.description, equalTo(description)) } - static void assertGroupPresent(GroupList results, Group expectedGroup) { + static void assertGroupPresent(List results, Group expectedGroup) { List groupsFound = StreamSupport.stream(results.spliterator(), false) .filter {group -> group.id == expectedGroup.id} @@ -73,7 +67,7 @@ class Util { assertThat(groupsFound, hasSize(1)) } - static void assertGroupAbsent(GroupList results, Group expectedGroup) { + static void assertGroupAbsent(List results, Group expectedGroup) { List groupsFound = StreamSupport.stream(results.spliterator(), false) .filter {group -> group.id == expectedGroup.id} @@ -82,74 +76,27 @@ class Util { assertThat(groupsFound, hasSize(0)) } - static void assertRolePresent(RoleList results, Role expectedRole) { - - List rolesFound = StreamSupport.stream(results.spliterator(), false) - .filter {role -> role.id == expectedRole.id} - .collect(Collectors.toList()) - - assertThat(rolesFound, hasSize(1)) - } - - static void assertRoleAbsent(RoleList results, Role expectedRole) { + static void assertUserPresent(List users, User expectedUser) { - List rolesFound = StreamSupport.stream(results.spliterator(), false) - .filter {role -> role.id == expectedRole.id} - .collect(Collectors.toList()) - - assertThat(rolesFound, hasSize(0)) - } - - static > void assertPresent(C results, T expected) { - - List resourcesFound = StreamSupport.stream(results.spliterator(), false) - .filter {listItem -> listItem.id == expected.id} + List usersFound = StreamSupport.stream(users.spliterator(), false) + .filter { user -> user.id == expectedUser.id } .collect(Collectors.toList()) - assertThat(resourcesFound, hasSize(1)) - } - - static > void assertNotPresent(C results, T expected) { - - List resourcesFound = StreamSupport.stream(results.spliterator(), false) - .filter {listItem -> listItem.id == expected.id} - .collect(Collectors.toList()) - - assertThat(resourcesFound, hasSize(0)) - } - - static > void assertLinkedObjectPresent(C results, T expected) { - - List resourcesFound = StreamSupport.stream(results.spliterator(), false) - .filter { listItem -> - ((listItem.primary.name == expected.primary.name) && - (listItem.associated.name == expected.associated.name))} - .collect(Collectors.toList()) - - assertThat(resourcesFound, hasSize(1)) - } - - static void assertGroupTargetPresent(User user, Group group, Role role) { - def groupTargets = user.listGroupTargets(role.id) - - assertThat "GroupTarget Present not found in User role", - StreamSupport.stream(groupTargets.spliterator(), false) - .filter{ groupTarget -> groupTarget.profile.name == group.profile.name} - .findFirst().isPresent() + assertThat(usersFound, hasSize(1)) } - static void assertUserInGroup(User user, Group group) { - assertThat "User was not found in group.", StreamSupport.stream(group.listUsers().spliterator(), false) + static void assertUserInGroup(User user, Group group, GroupApi groupApi) { + assertThat "User was not found in group.", StreamSupport.stream(groupApi.listGroupUsers(group.getId(), null, null).spliterator(), false) .filter{ listUser -> listUser.id == user.id} .findFirst().isPresent() } - static void assertUserInGroup(User user, Group group, int times, long delayInMilliseconds, boolean present=true) { + static void assertUserInGroup(User user, Group group, GroupApi groupApi, int times, long delayInMilliseconds, boolean present=true) { for (int ii=0; ii listUser.id == user.id} .findFirst().isPresent()) { return @@ -160,18 +107,18 @@ class Util { if (!present) Assert.fail("User found in group") } - static void assertUserNotInGroup(User user, Group group) { - assertThat "User was found in group.", !StreamSupport.stream(group.listUsers().spliterator(), false) + static void assertUserNotInGroup(User user, Group group, GroupApi groupApi) { + assertThat "User was found in group.", !StreamSupport.stream(groupApi.listGroupUsers(group.getId(), null, null).spliterator(), false) .filter{ listUser -> listUser.id == user.id} .findFirst().isPresent() } - static void assertUserNotInGroup(User user, Group group, int times, long delayInMilliseconds, boolean present=true) { + static void assertUserNotInGroup(User user, Group group, GroupApi groupApi, int times, long delayInMilliseconds, boolean present=true) { for (int ii=0; ii listUser.id == user.id} .findFirst().isPresent()) { return diff --git a/integration-tests/src/test/resources/okta_logo_favicon.png b/integration-tests/src/test/resources/okta_logo_favicon.png deleted file mode 100644 index d57806898a0..00000000000 Binary files a/integration-tests/src/test/resources/okta_logo_favicon.png and /dev/null differ diff --git a/pom.xml b/pom.xml index c6d79fed6c0..20ecdb08177 100644 --- a/pom.xml +++ b/pom.xml @@ -20,12 +20,12 @@ com.okta okta-parent - 24 + 25 com.okta.sdk okta-sdk-root - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT pom Okta Java SDK @@ -34,25 +34,18 @@ 2017 - 1.5.8 - 2.13.4 + 2.14.0-rc1 1.33 1.70 0.11.5 - 8.2.1 - 1.3.1 - + 10.0.0-beta + 1.3.2 okta/okta-sdk-java - false - - swagger-templates api impl - httpclients/httpclient - httpclients/okhttp integration-tests examples coverage @@ -73,27 +66,12 @@ com.okta.sdk okta-sdk-api - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT com.okta.sdk okta-sdk-impl - 8.2.3-SNAPSHOT - - - com.okta.sdk - okta-api-swagger-templates - 8.2.3-SNAPSHOT - - - com.okta.sdk - okta-sdk-httpclient - 8.2.3-SNAPSHOT - - - com.okta.sdk - okta-sdk-okhttp - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT @@ -112,16 +90,7 @@ okta-http-api ${okta.commons.version} - - com.okta.commons - okta-http-httpclient - ${okta.commons.version} - - - com.okta.commons - okta-http-okhttp - ${okta.commons.version} - + javax.annotation javax.annotation-api @@ -132,14 +101,14 @@ com.okta.sdk okta-sdk-integration-tests - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT com.okta.sdk okta-sdk-examples-quickstart - 8.2.3-SNAPSHOT + 10.0.0-SNAPSHOT @@ -199,21 +168,10 @@ com.google.auto.service auto-service - 1.0-rc6 + 1.0.1 true - - org.jetbrains.kotlin - kotlin-stdlib - 1.6.0 - - - org.jetbrains.kotlin - kotlin-stdlib-common - 1.6.0 - - org.testng testng @@ -258,42 +216,6 @@ - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - npm install (initialize) - - exec - - generate-sources - - ${npm.exec.skip} - npm - - install - - - - - copy to swagger - - exec - - generate-sources - - ${npm.exec.skip} - sh - - -c - mkdir -p ${project.basedir}/../src/swagger && cp ${project.basedir}/../node_modules/@okta/openapi/dist/spec.yaml ${project.basedir}/../src/swagger/api.yaml - - - - - org.apache.maven.plugins maven-surefire-plugin @@ -312,11 +234,9 @@ false true - - - + 5--> @@ -325,7 +245,7 @@ - ${project.build.directory}/generated-sources/swagger-codegen + ${project.build.directory}/generated-sources/openapi @@ -349,29 +269,10 @@ - - org.zalando.maven.plugins - swagger-codegen-maven-plugin - 0.5.0-beta-1 - - - ${project.basedir}/../src/swagger/api.yaml - - ${project.basedir}/../src/swagger/api.yaml - - - - - com.okta.sdk - okta-api-swagger-templates - 8.2.3-SNAPSHOT - - - org.codehaus.mojo versions-maven-plugin - 2.10.0 + 2.11.0 false @@ -391,8 +292,8 @@ true - true - true + false + false ${root.dir}/src/japicmp/postAnalysisScript.groovy @@ -407,6 +308,7 @@ org.owasp dependency-check-maven + 7.1.1 false @@ -457,4 +359,4 @@ - + \ No newline at end of file diff --git a/src/japicmp/postAnalysisScript.groovy b/src/japicmp/postAnalysisScript.groovy index aa82eb12152..28e448e46f3 100644 --- a/src/japicmp/postAnalysisScript.groovy +++ b/src/japicmp/postAnalysisScript.groovy @@ -22,12 +22,6 @@ while (it.hasNext()) { def jApiClass = it.next() def fqn = jApiClass.getFullyQualifiedName() - // false positive due to moving methods to new parent BaseClient - // future changes would be reported under the parent class directly anyway - if (fqn.startsWith("com.okta.sdk.impl.client.DefaultClient")) { - jApiClass.getCompatibilityChanges().remove(METHOD_REMOVED_IN_SUPERCLASS) - } - if (jApiClass.getChangeStatus() != UNCHANGED) { println("class ${fqn}: ${jApiClass.getChangeStatus()}") diff --git a/src/license/mapping.xml b/src/license/mapping.xml index f4cc796c3ca..72af2085279 100644 --- a/src/license/mapping.xml +++ b/src/license/mapping.xml @@ -77,4 +77,20 @@ auto-service Apache License, Version 2.0 + + javax.ws.rs + javax.ws.rs + Common Development and Distribution License, Version 1.0 + + + com.google.code.gson + gson-extras + Apache License, Version 2.0 + + + org.openapitools + jackson-databind-nullable + Apache License, Version 2.0 + + diff --git a/src/owasp/owasp-suppression.xml b/src/owasp/owasp-suppression.xml index ff95fdaddd3..ca4bcd430e7 100644 --- a/src/owasp/owasp-suppression.xml +++ b/src/owasp/owasp-suppression.xml @@ -19,36 +19,10 @@ --> - + - - CVE-2016-6199 - CVE-2019-11065 - CVE-2019-11405 - CVE-2019-15052 - CVE-2019-16370 - CVE-2020-11979 - CVE-2021-21364 - CVE-2021-29428 - CVE-2021-29429 - CVE-2021-32751 - CVE-2022-25364 - - - - - - ^com\.google\.guava:.*$ - CVE-2020-8908 - - - - - - CVE-2021-38542 - CVE-2021-40110 - CVE-2021-40111 - CVE-2021-40525 + + CVE-2016-1000027 @@ -57,12 +31,10 @@ CVE-2021-3765 - - - - ^pkg:maven/org\.yaml/snakeyaml@.*$ + + + CVE-2022-38752 - - + \ No newline at end of file diff --git a/src/swagger/api.yaml b/src/swagger/api.yaml new file mode 100644 index 00000000000..34011e91b12 --- /dev/null +++ b/src/swagger/api.yaml @@ -0,0 +1,25982 @@ +# +# Copyright 2022-Present Okta, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +openapi: 3.0.3 +info: + title: Okta Management + description: Allows customers to easily access the Okta Management APIs + termsOfService: https://developer.okta.com/terms/ + contact: + name: Okta Developer Team + url: https://developer.okta.com/ + email: devex-public@okta.com + license: + name: Apache-2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + version: 3.0.0 + x-logo: + url: logo.svg + backgroundColor: transparent + altText: Okta Developer +externalDocs: + description: Find more info here + url: https://developer.okta.com/docs/api/getting_started/design_principles.html +servers: + - url: https://{yourOktaDomain} + variables: + yourOktaDomain: + default: subdomain.okta.com + description: The domain of your organization. This can be a provided subdomain of an official okta domain (okta.com, oktapreview.com, etc) or one of your configured custom domains. +tags: + - name: AgentPools + x-displayName: Agent Pools + description: The Agent Pools API provides operation to manage the update settings of the agents for your organization. + - name: ApiToken + x-displayName: API Tokens + description: The API Tokens API provides operations to manage SSWS API tokens for your organization. + - name: Application + x-displayName: Applications + description: The Applications API provides operations to manage applications and/or assignments to users or groups for your organization. + - name: Authenticator + x-displayName: Authenticators + description: |- + The Authenticators Administration API provides operations to configure which Authenticators are available to end users for use when signing in to applications. + + End users are required to use one or more Authenticators depending on the security requirements of the authentication policy. + + Okta Identity Engine currently supports Authenticators for the following factors: + + **Knowledge-based:** + + * Password + * Security Question + + **Possession-based:** + + * Phone (SMS, Voice Call) + * Email + * WebAuthn + * Duo + * Custom App Early Access + - name: AuthorizationServer + x-displayName: Authorization Servers + description: Authorization Servers generate OAuth 2.0 and OpenID Connect tokens, including access tokens and ID tokens. The Okta Management API gives you the ability to configure and manage Authorization Servers and the security policies that are attached to them. + - name: Behavior + x-displayName: Behavior Rules + description: The Behavior Rules API provides operations to manage the behavior detection rules for your organization. + - name: CAPTCHA + x-displayName: CAPTCHAs + description: |- + As an option to increase org security, Okta supports CAPTCHA services to prevent automated sign-in attempts. You can integrate one of two providers: [hCaptcha](https://www.hcaptcha.com/) or [reCAPTCHA v2](https://developers.google.com/recaptcha/docs/invisible). + + The vendor implementations supported by Okta are both invisible. They each run risk-analysis software in the background during user sign in to determine the likelihood that the user is a bot. This risk analysis is based on the settings that you configure with the provider that you choose. + + Before you configure your org to use CAPTCHA, sign in to the vendor of your choice or sign up for an account. For more details, refer to [CAPTCHA integration](https://help.okta.com/okta_help.htm?type=oie&id=csh-captcha). + - name: Customization + x-displayName: Customizations + description: |- + The Brands API allows you to customize the look and feel of pages and templates, such as the Okta-hosted sign-in page, error pages, email templates, and the Okta End-User Dashboard. + + Each org starts off with Okta's default branding. You can upload your own assets (colors, background image, logo, and favicon) to replace Okta's default brand assets. You can then publish these assets directly to your pages and templates. + + >**Important:** Despite being called the Brands API (due to conventions around REST API naming), each org can currently contain only one brand and one theme. We will likely allow multiple brands and themes per org at some point in the future, so stay tuned! + - name: Device + x-displayName: Devices + description: |- + The Okta Devices API provides a centralized integration platform to fetch and manage device information. Okta administrators can use these APIs to manage workforce identity Device object information. + + The Devices API supports the following **Device Operations**: + * Get, Delete Device objects. + * Perform lifecycle transitions on the Device objects. + + The Devices API supports the following **Authorization Schemes**: + * SSWS - [API tokens](https://developer.okta.com/docs/reference/core-okta-api/#authentication) + * Bearer - [OAuth2.0 and OpenID Connect](https://developer.okta.com/docs/concepts/oauth-openid/) + + > **Note:** For devices to enroll in Okta and show up in the Devices API, the following actions are required: + > 1. Admins - Enable Okta FastPass. See [Enable FastPass](https://help.okta.com/okta_help.htm?type=oie&id=ext-fp-enable) + > 2. End users with existing mobile Okta Verify enrollments - After you upgrade your org to Okta Identity Engine, direct end users with existing Okta Verify enrollments to use [FastPass](https://help.okta.com/okta_help.htm?type=oie&id=csh-fp-main). + + > End users with a new enrollment in Okta Verify on an Okta Identity Engine org have a device record created in the device inventory by default. + See [Device Registration](https://help.okta.com/okta_help.htm?type=oie&id=csh-device-registration), [Login Using Okta Verify](https://help.okta.com/okta_help.htm?type=eu&id=ext-ov-user-overview). + - name: DeviceAssurance + x-displayName: Device Assurance Policies + description: The Device Assurance Policies API provides operations to manage device assurance policies in your organization. + - name: Domain + x-displayName: Domains + description: The Domains API provides operations to manage custom domains for your organization. + - name: EmailDomain + x-displayName: Email Domains + description: The Email Domains API provides operations to manage custom domains for your organization. + - name: EventHook + x-displayName: Event Hooks + description: |- + The Event Hooks API provides operations to manage event hooks for your organization. + + For general information on event hooks and how to create and use them, see [Event hooks](https://developer.okta.com/docs/concepts/event-hooks/). The following documentation is only for the management API, which provides a CRUD interface for registering event hooks. + + For a step-by-step guide on implementing an example event hook, see the [Event hook](https://developer.okta.com/docs/guides/event-hook-implementation/) guide. + - name: Feature + x-displayName: Features + description: |- + The Okta Features API provides operations to manage self-service Early Access (EA) and Beta features in your org. + + > **Note:** Important background information for this API is available on the [Feature Lifecycle Management](https://developer.okta.com/docs/concepts/feature-lifecycle-management/) page. + - name: Group + x-displayName: Groups + description: The Groups API provides operations to manage Okta Groups and their user members for your organization. + - name: IdentityProvider + x-displayName: Identity Providers + description: The Identity Providers API provides operations to manage federations with external Identity Providers (IdP). For example, your app can support signing in with credentials from Apple, Facebook, Google, LinkedIn, Microsoft, an enterprise IdP using SAML 2.0, or an IdP using the OpenID Connect (`OIDC`) protocol. + - name: InlineHook + x-displayName: Inline Hooks + description: |- + The Inline Hooks API provides operations to manage inline hooks for your organization. + + For general information on inline hooks and how to create and use them, see [inline hooks](https://developer.okta.com/docs/concepts/inline-hooks/). The following documentation is only for the management API, which provides a CRUD interface for registering inline hooks. + - name: LinkedObject + x-displayName: Linked Objects + description: |- + Users have relationships to each other, like manager and subordinate or customer and sales representative. You can create users with relationships by using the Linked Objects API to represent the relationship. + + 1. Create a Linked Object definition such as Manager:Subordinate or Case Worker:Client. These pairs are represented by a `primary` attribute and an `associated` attribute. + 2. Link users together to create the relationship between the two. You create a Linked Object value with a single request that links one `primary` and one `associated` user. + + For each relationship: + + * A user has at most one `primary` link (a user has a single manager), but can have many `associated` links (a user can have many subordinates). + * A user can be the `primary` in one relationship and the `associated` in another. + * A user can be both the `primary` and `associated` in the same relationship. + + Okta Expression Language function for [Linked Objects](https://developer.okta.com/docs/reference/okta-expression-language/#linked-object-function) provides access to the details about a linked user. + + > **Note:** The Linked Objects feature isn't available for OpenID Connect claims. + + ## Example usage + + Okta allows you to create up to 200 Linked Object definitions. These definitions are one-to-many, for example: + + * A manager has many subordinates. Each subordinate has one manager. + * A sales representative has many customers. Each customer has one sales rep. + * A case worker has many clients. Each client has one case worker. + + Most organizations have more than one manager or sales representative. You can create the Linked Object definition once, and then assign the `primary` relationship to as many users as you have people in that relationship. + + You can assign the `associated` relationship for a single `primary` user to as many users as needed. The `associated` user can be related to only one `primary` per Linked Object definition. But a user can be assigned to more than one Linked Object definition. + + For example, assume that you've created one Linked Object definition for manager (`primary`) and for subordinates (`associated`): + + * Joe is Frank's manager. + * Bob is Joe's manager, but Jane's subordinate. + * Jane is the CEO, so she reports to herself. + + Thus, you can create chains of relationships (Jane > Bob > Joe > Frank) or terminal relationships (Jane is both `primary` and `associated` user). + + Then, if you create another Linked Object relationship for scrum team membership, you could assign relationships to the same four users: + + * Bob is the scrum lead for the Identity Scrum team. + * Joe and Frank are both contributors to the team. + + Bob can be the `primary` for a Manager:Subordinate, an `associated` user for that same Linked Object definition, and also the `primary` for the Scrumlead:Contributor Linked Object definition. + + To represent a relationship, create a Linked Object definition that specifies a `primary` (parent) relationship and an `associated` (child) relationship, and then add a link in which the appropriate user is assigned to each side of that link type. + + ## Links between User Types + + If you created multiple User Types, they all share the same Linked Object definitions. For example, if you have separate User Types for employees and contractors, a link could designate an employee as the manager for a contractor, with the contractor being a subordinate of that employee. + - name: LogStream + x-displayName: Log Streaming + description: The Log Streaming API provides operations to manage Log Stream configurations for an org. You can configure up to two Log Stream integrations per org. + - name: NetworkZone + x-displayName: Network Zones + description: |- + The Okta Zones API provides operations to manage Zones in your organization. There are two usage Zone types: Policy Network Zones and Blocklist Network Zones. Policy Network Zones are used to guide policy decisions. Blocklist Network Zones are used to deny access from certain IP addresses, locations, proxy types, or Autonomous System Numbers (ASNs) before policy evaluation. + + A default system Policy Network Zone is provided in your Okta org. You can use the Zones API to modify the default Policy Network Zone or to create a custom Policy or Blocklist Network Zone. When you create your custom Zone, you can specify if the Zone is an IP Zone or a Dynamic Zone. An IP Zone allows you to define network perimeters around a set of IPs, whereas a Dynamic Zone allows you to define network perimeters around location, IP type, and ASNs. + - name: OrgSetting + x-displayName: Org Settings + description: The Org Settings API provides operations to manage your org account settings such as contact information, granting Okta Support access, and more. + - name: Policy + x-displayName: Policies + description: |- + The Okta Policy API enables an Administrator to perform Policy and Policy Rule operations. The Policy framework is used by Okta to control Rules and settings that govern, among other things, user session lifetime, whether multi-factor authentication is required when logging in, what MFA factors may be employed, password complexity requirements, what types of self-service operations are permitted under various circumstances, and what identity provider to route users to. + + Policy settings for a particular Policy type, such as Sign On Policy, consist of one or more Policy objects, each of which contains one or more Policy Rules. Policies and Rules contain conditions that determine whether they are applicable to a particular user at a particular time. + - name: PrincipalRateLimit + x-displayName: Principal Rate Limits + description: The Principal Rate Limits API provides operations to manage Principal Rate Limits for your organization. + - name: ProfileMapping + x-displayName: Profile Mappings + description: The Mappings API provides operations to manage the mapping of properties between an Okta User's and an App User's Profile properties using [Okta Expression Language](https://developer.okta.com/docs/reference/okta-expression-language). More information on Okta User and App User Profiles can be found in Okta's [User profiles](https://developer.okta.com/docs/concepts/user-profiles/#what-is-the-okta-universal-directory). + - name: PushProvider + x-displayName: Push Providers + description: The Push Providers API provides operations to manage Push Providers for your organization. + - name: RateLimitSettings + x-displayName: Rate Limit Settings + description: The Rate Limit Settings APIs provide operations to manage settings and configurations surrounding rate limiting in your Okta organization. + - name: ResourceSet + x-displayName: Resource Sets + description: The Resource Sets API provides operations to manage Resource Sets as custom collections of resources. You can use Resource Sets to assign Custom Roles to administrators who are scoped to the designated resources. See [Supported Resources](https://developer.okta.com/docs/concepts/role-assignment/#supported-resources). + - name: RiskEvent + x-displayName: Risk Events + description: The Risk Events API provides the ability for third-party Risk Providers to send Risk Events to Okta. See [Third-party risk provider integration overview](https://developer.okta.com/docs/guides/third-party-risk-integration/) for guidance on integrating third-party risk providers with Okta. + - name: RiskProvider + x-displayName: Risk Providers + description: The Risk Providers API provides the ability to manage the Risk Providers within Okta. See [Third-party risk provider integration overview](https://developer.okta.com/docs/guides/third-party-risk-integration/) for guidance on integrating third-party risk providers with Okta. + - name: Role + x-displayName: Roles + description: |- + The Roles API provides operations to manage administrative Role assignments for a User. + + Role listing APIs provide a union of both standard and Custom Roles assigned to a User or Group. + - name: RoleAssignment + x-displayName: Role Assignments + description: These APIs allow you to assign custom roles to user and groups, as well as designate Third-Party Administrator status to a user or group. + - name: RoleTarget + x-displayName: Role Targets + description: |- + Role targets are a way of defining permissions for admin roles into a smaller subset of Groups or Apps within your org. Targets limit an admin's permissions to a targeted area of the org. You can define admin roles to target Groups, Applications, and Application Instances. + + * **Group targets:** Grant an admin permission to manage only a specified Group. For example, an admin role may be assigned to manage only the IT Group. + * **App targets:** Grant an admin permission to manage all instances of the specified Apps. Target Apps are Okta catalog Apps. For example, you can have multiple configurations of an Okta catalog App, such as Salesforce or Facebook. When you add a Salesforce or Facebook App as a target, that grants the admin permission to manage all the instances of those Apps and create new instances of them. + * **App Instance targets:** Grant an admin permission to manage an instance of one App or instances of multiple Apps. App Instances are specific Apps that admins have created in their org. For example, there may be a Salesforce App configured differently for each sales region of a company. When you create an App Instance target, you can assign an admin to manage only two instances of the configured Salesforce Apps and then also to manage an instance of another configured App such as Workday. + + > **Note:** Don't use these operations with a Custom Role ID. Custom Role assignments always require a target Resource Set. See [Role Assignments](https://developer.okta.com/docs/concepts/role-assignment/) for more information. + - name: Schema + x-displayName: Schemas + description: |- + The Schemas API provides operations to manage custom User profiles as well as endpoints to discover the structure of the Log Stream configuration. + + Okta's [Universal Directory](https://help.okta.com/okta_help.htm?id=ext_About_Universal_Directory) allows administrators to define custom User profiles for Okta Users and Applications. + Okta adopts a subset of [JSON Schema Draft 4](https://tools.ietf.org/html/draft-zyp-json-schema-04) as the schema language to describe and validate extensible User profiles. + For Log Stream Schemas, Okta uses [JSON Schema Draft 2020-12](https://json-schema.org/specification.html). + [JSON Schema](http://json-schema.org/) is a lightweight declarative format for describing the structure, constraints, and validation of JSON documents. + + > **Note:** Okta implements only a subset of [JSON Schema Draft 4](https://tools.ietf.org/html/draft-zyp-json-schema-04) and [JSON Schema Draft 2020-12](https://json-schema.org/specification.html). This document describes which parts apply to Okta, and any extensions Okta has made to [JSON Schema Draft 4](https://tools.ietf.org/html/draft-zyp-json-schema-04) and [JSON Schema Draft 2020-12](https://json-schema.org/specification.html). + - name: Session + x-displayName: Sessions + description: |- + Okta uses a cookie-based authentication mechanism to maintain a user's authentication Session across web requests. The Okta Sessions API provides operations to create and manage authentication Sessions for users in your Okta organization. + + >**Note:** Some browsers block third-party cookies by default, which disrupts Okta functionality in certain flows. See [FAQ: How Blocked Third Party Cookies Can Potentially Impact Your Okta Environment](https://support.okta.com/help/s/article/FAQ-How-Blocking-Third-Party-Cookies-Can-Potentially-Impact-Your-Okta-Environment). + + >**Note:** The Sessions API doesn't support direct authentication. Direct authentication is supported through the [Authentication API](https://developer.okta.com/docs/reference/api/authn/#authentication-operations) or through OIDC using the [Resource Owner Password flow](https://developer.okta.com/docs/guides/implement-grant-type/ropassword/main/). + + ### Session cookie + + Okta uses an HTTP session cookie to provide access to your Okta organization and applications across web requests for an interactive user agent such as a web browser. A session cookie has an expiration configurable by an administrator for the organization and is valid until the cookie expires or the user closes the Session (logout) or browser application. + + ### Session token + + A [session token](https://developer.okta.com/docs/reference/api/authn/#session-token) is a one-time bearer token that provides proof of authentication and may be redeemed for an interactive SSO session in Okta in a user agent. Session tokens can only be used **once** to establish a Session for a user and are revoked when the token expires. + + Okta provides a very rich [Authentication API](https://developer.okta.com/docs/reference/api/authn/) to validate a [user's primary credentials](https://developer.okta.com/docs/reference/api/authn/#primary-authentication) and secondary [MFA factor](https://developer.okta.com/docs/reference/api/authn/#verify-factor). A session token is returned after successful authentication, which can be later exchanged for a session cookie that uses one of the following flows: + + - [Retrieve a session cookie by visiting the OpenID Connect Authorization Endpoint](https://developer.okta.com/docs/guides/session-cookie/main/#retrieve-a-session-cookie-through-the-openid-connect-authorization-endpoint) + - [Retrieve a session cookie by visiting a session redirect link](https://developer.okta.com/docs/guides/session-cookie/main/#retrieve-a-session-cookie-by-visiting-a-session-redirect-link) + - [Retrieve a session cookie by visiting an application embed link](https://developer.okta.com/docs/guides/session-cookie/main/#retrieve-a-session-cookie-by-visiting-an-application-embed-link) + + >**Note:** **Session tokens** are secrets and should be protected at rest and during transit. A session token for a user is equivalent to having the user's actual credentials. + - name: Subscription + x-displayName: Subscriptions + description: The Subscriptions API provides operations to manage email subscription settings for Okta administrator notifications. + - name: SystemLog + x-displayName: System Log + description: |- + The System Log records system events that are related to your organization in order to provide an audit trail that can be used to understand platform activity and to diagnose problems. + + The System Log API provides near real-time, read-only access to your organization's system log and is the programmatic counterpart of the [System Log UI](https://help.okta.com/okta_help.htm?id=ext_Reports_SysLog). + + The terms "event" and "log event" are often used interchangeably. In the context of this API, an "event" is an occurrence of interest within the system, and a "log" or "log event" is the recorded fact. + + The System Log API supports these primary use cases: + * Event data export into a security information and event management system (SIEM) + * System monitoring + * Development debugging + * Event introspection and audit + + The System Log API isn't intended for use as a Database as a Service (DBaaS) or to serve data directly to downstream consumers without an intermediate data store. + + See [Events API Migration](https://developer.okta.com/docs/concepts/events-api-migration/) for information on migrating from the Events API to the System Log API. + - name: Template + x-displayName: SMS Templates + description: |- + The SMS Templates API provides operations to manage custom SMS templates for verification. + + > **Note:** Only SMS custom Templates are available through the API. + + SMS Templates customize the SMS message that is sent to users. One default SMS Template is provided. All custom Templates must have the variable `${code}` as part of the text. The `${code}` variable is replaced with the actual SMS code when the message is sent. Optionally, you can also use the variable `${org.name}`. If a Template contains `${org.name}`, it is replaced with the organization name before the SMS message is sent. + - name: ThreatInsight + x-displayName: ThreatInsight + description: |- + [Okta ThreatInsight](https://help.okta.com/okta_help.htm?id=ext_threatinsight) maintains a constantly evolving list of IPs that exhibit suspicious behaviors suggestive of malicious activity. Authentication requests associated with an IP in this list can be logged in [System Log](https://help.okta.com/okta_help.htm?id=ext_Reports_SysLog) and blocked. The Okta ThreatInsight Configuration API provides operations to manage your ThreatInsight configuration. + + In order to prevent abuse, Okta ThreatInsight works in a limited capacity for free trial editions. Please contact Okta support if fully functional Okta ThreatInsight is required. + - name: TrustedOrigin + x-displayName: Trusted Origins + description: |- + The Trusted Origins API provides operations to manage Trusted Origins and sources. + + When external URLs are requested during sign-in, sign-out, or recovery operations, Okta checks those URLs against the allowed list of Trusted Origins. Trusted Origins also enable browser-based applications to access Okta APIs from JavaScript (CORS). If the origins aren't specified, the related operation (redirect or Okta API access) isn't permitted. + + You can also configure Trusted Origins to allow iFrame embedding of Okta resources, such as Okta sign-in pages and the Okta End-User Dashboard, within that origin. This is an Early Access feature. To enable it, contact [Okta Support](https://support.okta.com/help/s/). + + > **Note:** This Early Access feature is supported for Okta domains only. It isn't currently supported for custom domains. + - name: User + x-displayName: Users + description: The User API provides operations to manage users in your organization. + - name: UserFactor + x-displayName: Factors + description: The Factors API provides operations to enroll, manage, and verify factors for multifactor authentication (MFA). Manage both administration and end-user accounts, or verify an individual factor at any time. + - name: UserType + x-displayName: User Types + description: The User Types API provides operations to manage User Types. +paths: + /.well-known/okta-organization: + get: + summary: Retrieve the Well-Known Org Metadata + description: Retrieves the well-known org metadata, which includes the id, configured custom domains, authentication pipeline, and various other org settings + operationId: getWellknownOrgMetadata + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/WellKnownOrgMetadata' + examples: + Identity Engine Org with Custom Domain: + $ref: '#/components/examples/WellKnownOrgMetadataResponseCustomUrlOie' + Classic Org: + $ref: '#/components/examples/WellKnownOrgMetadataResponseClassic' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + tags: + - OrgSetting + /api/v1/agentPools: + get: + summary: List all Agent Pools + description: Lists all agent pools with pagination support + operationId: listAgentPools + parameters: + - $ref: '#/components/parameters/queryLimitPerPoolType' + - $ref: '#/components/parameters/queryPoolType' + - $ref: '#/components/parameters/queryAfter' + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AgentPool' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.read + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates: + get: + summary: List all Agent Pool updates + description: Lists all agent pool updates + operationId: listAgentPoolsUpdates + parameters: + - $ref: '#/components/parameters/pathPoolId' + - $ref: '#/components/parameters/queryScheduled' + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AgentPoolUpdate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.read + tags: + - AgentPools + post: + summary: Create an Agent Pool update + description: Creates an Agent pool update \n For user flow 2 manual update, starts the update immediately. \n For user flow 3, schedules the update based on the configured update window and delay. + operationId: createAgentPoolsUpdate + parameters: + - $ref: '#/components/parameters/pathPoolId' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates/settings: + parameters: + - $ref: '#/components/parameters/pathPoolId' + get: + summary: Retrieve an Agent Pool update's settings + description: Retrieves the current state of the agent pool update instance settings + operationId: getAgentPoolsUpdateSettings + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdateSetting' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.read + tags: + - AgentPools + post: + summary: Update an Agent Pool update settings + description: Updates an agent pool update settings + operationId: updateAgentPoolsUpdateSettings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdateSetting' + required: true + responses: + '201': + description: Updated + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdateSetting' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates/{updateId}: + parameters: + - $ref: '#/components/parameters/pathPoolId' + - $ref: '#/components/parameters/pathUpdateId' + get: + summary: Retrieve an Agent Pool update by id + description: Retrieves Agent pool update from updateId + operationId: getAgentPoolsUpdateInstance + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.read + tags: + - AgentPools + post: + summary: Update an Agent Pool update by id + description: Updates Agent pool update and return latest agent pool update + operationId: updateAgentPoolsUpdate + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + required: true + responses: + '201': + description: Updated + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + delete: + summary: Delete an Agent Pool update + description: Deletes Agent pool update + operationId: deleteAgentPoolsUpdate + responses: + '204': + description: Deleted + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates/{updateId}/activate: + parameters: + - $ref: '#/components/parameters/pathPoolId' + - $ref: '#/components/parameters/pathUpdateId' + post: + summary: Activate an Agent Pool update + description: Activates scheduled Agent pool update + operationId: activateAgentPoolsUpdate + responses: + '201': + description: Activated + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates/{updateId}/deactivate: + parameters: + - $ref: '#/components/parameters/pathPoolId' + - $ref: '#/components/parameters/pathUpdateId' + post: + summary: Deactivate an Agent Pool update + description: Deactivates scheduled Agent pool update + operationId: deactivateAgentPoolsUpdate + responses: + '201': + description: Deactivated + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates/{updateId}/pause: + parameters: + - $ref: '#/components/parameters/pathPoolId' + - $ref: '#/components/parameters/pathUpdateId' + post: + summary: Pause an Agent Pool update + description: Pauses running or queued Agent pool update + operationId: pauseAgentPoolsUpdate + responses: + '201': + description: Paused + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates/{updateId}/resume: + parameters: + - $ref: '#/components/parameters/pathPoolId' + - $ref: '#/components/parameters/pathUpdateId' + post: + summary: Resume an Agent Pool update + description: Resumes running or queued Agent pool update + operationId: resumeAgentPoolsUpdate + responses: + '201': + description: Resumed + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates/{updateId}/retry: + parameters: + - $ref: '#/components/parameters/pathPoolId' + - $ref: '#/components/parameters/pathUpdateId' + post: + summary: Retry an Agent Pool update + description: Retries Agent pool update + operationId: retryAgentPoolsUpdate + responses: + '201': + description: Retried + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/agentPools/{poolId}/updates/{updateId}/stop: + parameters: + - $ref: '#/components/parameters/pathPoolId' + - $ref: '#/components/parameters/pathUpdateId' + post: + summary: Stop an Agent Pool update + description: Stops Agent pool update + operationId: stopAgentPoolsUpdate + responses: + '201': + description: Stopped + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPoolUpdate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.agentPools.manage + tags: + - AgentPools + /api/v1/api-tokens: + get: + summary: List all API Token Metadata + description: Lists all the metadata of the active API tokens + operationId: listApiTokens + parameters: + - $ref: '#/components/parameters/queryAfter' + - $ref: '#/components/parameters/queryLimit' + - name: q + in: query + description: Finds a token that matches the name or clientName. + schema: + type: string + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApiToken' + examples: + List Tokens: + $ref: '#/components/examples/ApiTokenListMetadataResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apiTokens.read + tags: + - ApiToken + /api/v1/api-tokens/current: + delete: + summary: Revoke the Current API Token + description: Revokes the API token provided in the Authorization header + operationId: revokeCurrentApiToken + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + tags: + - ApiToken + /api/v1/api-tokens/{apiTokenId}: + parameters: + - $ref: '#/components/parameters/pathApiTokenId' + get: + summary: Retrieve an API Token's Metadata + description: Retrieves the metadata for an active API token by id + operationId: getApiToken + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ApiToken' + examples: + HCaptcha: + $ref: '#/components/examples/ApiTokenMetadataResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apiTokens.read + tags: + - ApiToken + delete: + summary: Revoke an API Token + description: Revoke an API token by id + operationId: revokeApiToken + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apiTokens.manage + tags: + - ApiToken + /api/v1/apps: + get: + summary: List all Applications + description: Lists all applications with pagination. A subset of apps can be returned that match a supported filter expression or query. + operationId: listApplications + parameters: + - name: q + in: query + schema: + type: string + - name: after + in: query + description: Specifies the pagination cursor for the next page of apps + schema: + type: string + - name: limit + in: query + description: Specifies the number of results for a page + schema: + type: integer + format: int32 + default: -1 + - name: filter + in: query + description: Filters apps by status, user.id, group.id or credentials.signing.kid expression + schema: + type: string + - name: expand + in: query + description: Traverses users link relationship and optionally embeds Application User resource + schema: + type: string + - name: includeNonDeleted + in: query + schema: + type: boolean + default: false + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Application' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + post: + summary: Create an Application + description: Creates a new application to your Okta organization + operationId: createApplication + parameters: + - name: activate + in: query + description: Executes activation lifecycle operation when creating the app + schema: + type: boolean + default: true + - name: OktaAccessGateway-Agent + in: header + schema: + type: string + x-codegen-request-body-name: application + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Application' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Application' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}: + get: + summary: Retrieve an Application + description: Retrieves an application from your Okta organization by `id` + operationId: getApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Application' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + put: + summary: Replace an Application + description: Replaces an application + operationId: replaceApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: application + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Application' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Application' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + delete: + summary: Delete an Application + description: Deletes an inactive application + operationId: deleteApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/connections/default: + get: + summary: Retrieve the default Provisioning Connection + description: Retrieves the default Provisioning Connection for application + operationId: getDefaultProvisioningConnectionForApplication + parameters: + - in: path + name: appId + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ProvisioningConnection' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + post: + summary: Update the default Provisioning Connection + description: Updates the default provisioning connection for application + operationId: updateDefaultProvisioningConnectionForApplication + parameters: + - in: path + name: appId + required: true + schema: + type: string + - in: query + name: activate + schema: + type: boolean + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProvisioningConnectionRequest' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/ProvisioningConnection' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/connections/default/lifecycle/activate: + post: + summary: Activate the default Provisioning Connection + description: Activates the default Provisioning Connection for an application + operationId: activateDefaultProvisioningConnectionForApplication + parameters: + - in: path + name: appId + required: true + schema: + type: string + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/connections/default/lifecycle/deactivate: + post: + summary: Deactivate the default Provisioning Connection for an Application + description: Deactivates the default Provisioning Connection for an application + operationId: deactivateDefaultProvisioningConnectionForApplication + parameters: + - in: path + name: appId + required: true + schema: + type: string + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/credentials/csrs: + get: + summary: List all Certificate Signing Requests + description: Lists all Certificate Signing Requests for an application + operationId: listCsrsForApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Csr' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + post: + summary: Generate a Certificate Signing Request + description: Generates a new key pair and returns the Certificate Signing Request for it + operationId: generateCsrForApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: metadata + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CsrMetadata' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/Csr' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/credentials/csrs/{csrId}: + get: + summary: Retrieve a Certificate Signing Request + description: Retrieves a certificate signing request for the app by `id` + operationId: getCsrForApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: csrId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Csr' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + delete: + summary: Revoke a Certificate Signing Request + description: Revokes a certificate signing request and deletes the key pair from the application + operationId: revokeCsrFromApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: csrId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/credentials/csrs/{csrId}/lifecycle/publish: + post: + summary: Publish a Certificate Signing Request + description: Updates a certificate signing request for the app with a signed X.509 certificate and adds it into the application key credentials + operationId: publishCsrFromApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: csrId + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/x-x509-ca-cert: + schema: + type: string + format: binary + x-okta-operationId: publishBinaryCerCert + application/pkix-cert: + schema: + type: string + format: binary + x-okta-operationId: publishBinaryDerCert + application/x-pem-file: + schema: + type: string + format: binary + x-okta-operationId: publishBinaryPemCert + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/credentials/keys: + get: + summary: List all Key Credentials + description: Lists all key credentials for an application + operationId: listApplicationKeys + parameters: + - name: appId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + /api/v1/apps/{appId}/credentials/keys/generate: + post: + summary: Generate a Key Credential + description: Generates a new X.509 certificate for an application key credential + operationId: generateApplicationKey + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: validityYears + in: query + schema: + type: integer + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/credentials/keys/{keyId}: + get: + summary: Retrieve a Key Credential + description: Retrieves a specific application key credential by kid + operationId: getApplicationKey + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: keyId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + /api/v1/apps/{appId}/credentials/keys/{keyId}/clone: + post: + summary: Clone a Key Credential + description: Clones a X.509 certificate for an application key credential from a source application to target application. + operationId: cloneApplicationKey + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: keyId + in: path + required: true + schema: + type: string + - name: targetAid + in: query + description: Unique key of the target Application + required: true + schema: + type: string + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/features: + get: + summary: List all Features + description: Lists all features for an application + operationId: listFeaturesForApplication + parameters: + - in: path + name: appId + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ApplicationFeature' + type: array + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + /api/v1/apps/{appId}/features/{name}: + get: + summary: Retrieve a Feature + description: Retrieves a Feature object for an application + operationId: getFeatureForApplication + parameters: + - in: path + name: appId + required: true + schema: + type: string + - in: path + name: name + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationFeature' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + put: + summary: Update a Feature + description: Updates a Feature object for an application + operationId: updateFeatureForApplication + parameters: + - in: path + name: appId + required: true + schema: + type: string + - in: path + name: name + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CapabilitiesObject' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationFeature' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/grants: + get: + summary: List all Scope Consent Grants + description: Lists all scope consent grants for the application + operationId: listScopeConsentGrants + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2ScopeConsentGrant' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + tags: + - Application + post: + summary: Grant Consent to Scope + description: Grants consent for the application to request an OAuth 2.0 Okta scope + operationId: grantConsentToScope + parameters: + - name: appId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: oAuth2ScopeConsentGrant + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2ScopeConsentGrant' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2ScopeConsentGrant' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + tags: + - Application + /api/v1/apps/{appId}/grants/{grantId}: + get: + summary: Retrieve a Scope Consent Grant + description: Retrieves a single scope consent grant for the application + operationId: getScopeConsentGrant + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: grantId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2ScopeConsentGrant' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + tags: + - Application + delete: + summary: Revoke a Scope Consent Grant + description: Revokes permission for the application to request the given scope + operationId: revokeScopeConsentGrant + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: grantId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + tags: + - Application + /api/v1/apps/{appId}/groups: + get: + summary: List all Assigned Groups + description: Lists all group assignments for an application + operationId: listApplicationGroupAssignments + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: q + in: query + schema: + type: string + - name: after + in: query + description: Specifies the pagination cursor for the next page of assignments + schema: + type: string + - name: limit + in: query + description: Specifies the number of results for a page + schema: + type: integer + format: int32 + default: -1 + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ApplicationGroupAssignment' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + /api/v1/apps/{appId}/groups/{groupId}: + get: + summary: Retrieve an Assigned Group + description: Retrieves an application group assignment + operationId: getApplicationGroupAssignment + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: groupId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationGroupAssignment' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + put: + summary: Assign a Group + description: Assigns a group to an application + operationId: assignGroupToApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: groupId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: applicationGroupAssignment + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationGroupAssignment' + required: false + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationGroupAssignment' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + delete: + summary: Unassign a Group + description: Unassigns a group from an application + operationId: unassignApplicationFromGroup + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: groupId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/lifecycle/activate: + post: + summary: Activate an Application + description: Activates an inactive application + operationId: activateApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/lifecycle/deactivate: + post: + summary: Deactivate an Application + description: Deactivates an active application + operationId: deactivateApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/logo: + post: + summary: Upload a Logo + description: The file must be in PNG, JPG, or GIF format, and less than 1 MB in size. For best results use landscape orientation, a transparent background, and a minimum size of 420px by 120px to prevent upscaling. + operationId: uploadApplicationLogo + parameters: + - in: path + name: appId + required: true + schema: + type: string + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + required: + - file + responses: + '201': + description: Created + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/policies/{policyId}: + put: + summary: Assign an application to a specific policy + description: Assign an application to a specific policy. This unassigns the application from its currently assigned policy. + operationId: assignApplicationPolicy + parameters: + - in: path + name: appId + required: true + schema: + type: string + - in: path + name: policyId + required: true + schema: + type: string + responses: + '204': + description: No Content + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/tokens: + get: + summary: List all OAuth 2.0 Tokens + description: Lists all tokens for the application + operationId: listOAuth2TokensForApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2Token' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + delete: + summary: Revoke all OAuth 2.0 Tokens + description: Revokes all tokens for the specified application + operationId: revokeOAuth2TokensForApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/tokens/{tokenId}: + get: + summary: Retrieve an OAuth 2.0 Token + description: Retrieves a token for the specified application + operationId: getOAuth2TokenForApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: tokenId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Token' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + delete: + summary: Revoke an OAuth 2.0 Token + description: Revokes the specified token for the specified application + operationId: revokeOAuth2TokenForApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: tokenId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/users: + get: + summary: List all Assigned Users + description: Lists all assigned [application users](#application-user-model) for an application + operationId: listApplicationUsers + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: q + in: query + schema: + type: string + - name: query_scope + in: query + schema: + type: string + - name: after + in: query + description: specifies the pagination cursor for the next page of assignments + schema: + type: string + - name: limit + in: query + description: specifies the number of results for a page + schema: + type: integer + format: int32 + default: -1 + - name: filter + in: query + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AppUser' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + post: + summary: Assign a User + description: Assigns an user to an application with [credentials](#application-user-credentials-object) and an app-specific [profile](#application-user-profile-object). Profile mappings defined for the application are first applied before applying any profile properties specified in the request. + operationId: assignUserToApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: appUser + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AppUser' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AppUser' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/apps/{appId}/users/{userId}: + get: + summary: Retrieve an Assigned User + description: Retrieves a specific user assignment for application by `id` + operationId: getApplicationUser + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AppUser' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.read + tags: + - Application + post: + summary: Update an Application Profile for Assigned User + description: Updates a user's profile for an application + operationId: updateApplicationUser + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: appUser + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AppUser' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AppUser' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + delete: + summary: Unassign a User + description: Unassigns a user from an application + operationId: unassignUserFromApplication + parameters: + - name: appId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + - name: sendEmail + in: query + schema: + type: boolean + default: false + x-okta-added-version: 1.5.0 + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - Application + /api/v1/authenticators: + get: + summary: List all Authenticators + description: Lists all authenticators + operationId: listAuthenticators + responses: + '200': + description: Success + content: + application/json: + schema: + items: + $ref: '#/components/schemas/Authenticator' + type: array + examples: + Org Authenticators: + $ref: '#/components/examples/AuthenticatorsResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authenticators.read + tags: + - Authenticator + post: + summary: Create an Authenticator + description: Creates an authenticator. You can use this operation as part of the "Create a custom authenticator" flow. See the [Custom authenticator integration guide](https://developer.okta.com/docs/guides/authenticators-custom-authenticator/android/main/). + operationId: createAuthenticator + parameters: + - in: query + name: activate + description: Whether to execute the activation lifecycle operation when Okta creates the authenticator + schema: + type: boolean + default: false + x-codegen-request-body-name: authenticator + requestBody: + $ref: '#/components/requestBodies/AuthenticatorRequestBody' + responses: + '200': + $ref: '#/components/responses/AuthenticatorResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authenticators.manage + tags: + - Authenticator + /api/v1/authenticators/{authenticatorId}: + get: + summary: Retrieve an Authenticator + description: Retrieves an authenticator from your Okta organization by `authenticatorId` + operationId: getAuthenticator + parameters: + - in: path + name: authenticatorId + required: true + schema: + type: string + responses: + '200': + $ref: '#/components/responses/AuthenticatorResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authenticators.read + tags: + - Authenticator + put: + summary: Replace an Authenticator + description: Replaces an authenticator + operationId: replaceAuthenticator + parameters: + - in: path + name: authenticatorId + required: true + schema: + type: string + x-codegen-request-body-name: authenticator + requestBody: + $ref: '#/components/requestBodies/AuthenticatorRequestBody' + responses: + '200': + $ref: '#/components/responses/AuthenticatorResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authenticators.manage + tags: + - Authenticator + /api/v1/authenticators/{authenticatorId}/lifecycle/activate: + post: + summary: Activate an Authenticator + description: Activates an authenticator by `authenticatorId` + operationId: activateAuthenticator + parameters: + - in: path + name: authenticatorId + required: true + schema: + type: string + responses: + '200': + $ref: '#/components/responses/AuthenticatorResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authenticators.manage + tags: + - Authenticator + /api/v1/authenticators/{authenticatorId}/lifecycle/deactivate: + post: + summary: Deactivate an Authenticator + description: Deactivates an authenticator by `authenticatorId` + operationId: deactivateAuthenticator + parameters: + - in: path + name: authenticatorId + required: true + schema: + type: string + responses: + '200': + $ref: '#/components/responses/AuthenticatorResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authenticators.manage + tags: + - Authenticator + /api/v1/authorizationServers: + get: + summary: List all Authorization Servers + description: Lists all authorization servers + operationId: listAuthorizationServers + parameters: + - name: q + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 200 + - name: after + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AuthorizationServer' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + post: + summary: Create an Authorization Server + description: Creates an authorization server + operationId: createAuthorizationServer + x-codegen-request-body-name: authorizationServer + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServer' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServer' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}: + get: + summary: Retrieve an Authorization Server + description: Retrieves an authorization server + operationId: getAuthorizationServer + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServer' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + put: + summary: Replace an Authorization Server + description: Replace an authorization server + operationId: replaceAuthorizationServer + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: authorizationServer + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServer' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServer' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + delete: + summary: Delete an Authorization Server + description: Deletes an authorization server + operationId: deleteAuthorizationServer + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/claims: + get: + summary: List all Custom Token Claims + description: Lists all custom token claims + operationId: listOAuth2Claims + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2Claim' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + post: + summary: Create a Custom Token Claim + description: Creates a custom token claim + operationId: createOAuth2Claim + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: oAuth2Claim + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Claim' + required: true + responses: + '201': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Claim' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/claims/{claimId}: + get: + summary: Retrieve a Custom Token Claim + description: Retrieves a custom token claim + operationId: getOAuth2Claim + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: claimId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Claim' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + put: + summary: Replace a Custom Token Claim + description: Replace a custom token claim + operationId: replaceOAuth2Claim + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: claimId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: oAuth2Claim + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Claim' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Claim' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + delete: + summary: Delete a Custom Token Claim + description: Deletes a custom token claim + operationId: deleteOAuth2Claim + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: claimId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/clients: + get: + summary: List all Clients + description: Lists all clients + operationId: listOAuth2ClientsForAuthorizationServer + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2Client' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/clients/{clientId}/tokens: + get: + summary: List all Refresh Tokens for a Client + description: Lists all refresh tokens for a client + operationId: listRefreshTokensForAuthorizationServerAndClient + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: -1 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2RefreshToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + delete: + summary: Revoke all Refresh Tokens for a Client + description: Revoke all refresh tokens for a client + operationId: revokeRefreshTokensForAuthorizationServerAndClient + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/clients/{clientId}/tokens/{tokenId}: + get: + summary: Retrieve a Refresh Token for a Client + description: Retrieves a refresh token for a client + operationId: getRefreshTokenForAuthorizationServerAndClient + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + - name: tokenId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2RefreshToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + delete: + summary: Revoke a Refresh Token for a Client + description: Revoke a refresh token for a client + operationId: revokeRefreshTokenForAuthorizationServerAndClient + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + - name: tokenId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/credentials/keys: + get: + summary: List all Credential Keys + description: Lists all credential keys + operationId: listAuthorizationServerKeys + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/credentials/lifecycle/keyRotate: + post: + summary: Rotate all Credential Keys + description: Rotate all credential keys + operationId: rotateAuthorizationServerKeys + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: use + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/JwkUse' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/JsonWebKey' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/lifecycle/activate: + post: + summary: Activate an Authorization Server + description: Activates an authorization server + operationId: activateAuthorizationServer + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/lifecycle/deactivate: + post: + summary: Deactivate an Authorization Server + description: Deactivates an authorization server + operationId: deactivateAuthorizationServer + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/policies: + get: + summary: List all Policies + description: Lists all policies + operationId: listAuthorizationServerPolicies + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AuthorizationServerPolicy' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + post: + summary: Create a Policy + description: Creates a policy + operationId: createAuthorizationServerPolicy + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: policy + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicy' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicy' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/policies/{policyId}: + get: + summary: Retrieve a Policy + description: Retrieves a policy + operationId: getAuthorizationServerPolicy + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: policyId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicy' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + put: + summary: Replace a Policy + description: Replaces a policy + operationId: replaceAuthorizationServerPolicy + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: policyId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: policy + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicy' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicy' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + delete: + summary: Delete a Policy + description: Deletes a policy + operationId: deleteAuthorizationServerPolicy + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: policyId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/policies/{policyId}/lifecycle/activate: + post: + summary: Activate a Policy + description: Activates an authorization server policy + operationId: activateAuthorizationServerPolicy + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: policyId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/policies/{policyId}/lifecycle/deactivate: + post: + summary: Deactivate a Policy + description: Deactivates an authorization server policy + operationId: deactivateAuthorizationServerPolicy + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: policyId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/policies/{policyId}/rules: + get: + summary: List all Policy Rules + description: Lists all policy rules for the specified Custom Authorization Server and Policy + operationId: listAuthorizationServerPolicyRules + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: authServerId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AuthorizationServerPolicyRule' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + post: + summary: Create a Policy Rule + description: Creates a policy rule for the specified Custom Authorization Server and Policy + operationId: createAuthorizationServerPolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: authServerId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: policyRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicyRule' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicyRule' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/policies/{policyId}/rules/{ruleId}: + get: + summary: Retrieve a Policy Rule + description: Returns a Policy Rule by ID that is defined in the specified Custom Authorization Server and Policy + operationId: getAuthorizationServerPolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: authServerId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicyRule' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + put: + summary: Replace a Policy Rule + description: Replaces the configuration of the Policy Rule defined in the specified Custom Authorization Server and Policy + operationId: replaceAuthorizationServerPolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: authServerId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: policyRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicyRule' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizationServerPolicyRule' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + delete: + summary: Delete a Policy Rule + description: Deletes a Policy Rule defined in the specified Custom Authorization Server and Policy + operationId: deleteAuthorizationServerPolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: authServerId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/policies/{policyId}/rules/{ruleId}/lifecycle/activate: + post: + summary: Activate a Policy Rule + description: Activates an authorization server policy rule + operationId: activateAuthorizationServerPolicyRule + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: policyId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/policies/{policyId}/rules/{ruleId}/lifecycle/deactivate: + post: + summary: Deactivate a Policy Rule + description: Deactivates an authorization server policy rule + operationId: deactivateAuthorizationServerPolicyRule + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: policyId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/scopes: + get: + summary: List all Custom Token Scopes + description: Lists all custom token scopes + operationId: listOAuth2Scopes + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: q + in: query + schema: + type: string + - name: filter + in: query + schema: + type: string + - name: cursor + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: -1 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2Scope' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + post: + summary: Create a Custom Token Scope + description: Creates a custom token scope + operationId: createOAuth2Scope + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: oAuth2Scope + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Scope' + required: true + responses: + '201': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Scope' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/authorizationServers/{authServerId}/scopes/{scopeId}: + get: + summary: Retrieve a Custom Token Scope + description: Retrieves a custom token scope + operationId: getOAuth2Scope + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: scopeId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Scope' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.read + tags: + - AuthorizationServer + put: + summary: Replace a Custom Token Scope + description: Replace a custom token scope + operationId: replaceOAuth2Scope + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: scopeId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: oAuth2Scope + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Scope' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2Scope' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + delete: + summary: Delete a Custom Token Scope + description: Deletes a custom token scope + operationId: deleteOAuth2Scope + parameters: + - name: authServerId + in: path + required: true + schema: + type: string + - name: scopeId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.authorizationServers.manage + tags: + - AuthorizationServer + /api/v1/behaviors: + get: + summary: List all Behavior Detection Rules + description: Lists all behavior detection rules with pagination support + operationId: listBehaviorDetectionRules + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BehaviorRule' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.behaviors.read + tags: + - Behavior + post: + summary: Create a Behavior Detection Rule + description: Creates a new behavior detection rule + operationId: createBehaviorDetectionRule + x-codegen-request-body-name: rule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BehaviorRule' + examples: + BehaviorRuleRequest: + $ref: '#/components/examples/BehaviorRuleRequest' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/BehaviorRule' + examples: + BehaviorRuleReSponse: + $ref: '#/components/examples/BehaviorRuleResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + API Validation Failed: + $ref: '#/components/examples/ErrorApiValidationFailed' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.behaviors.manage + tags: + - Behavior + /api/v1/behaviors/{behaviorId}: + parameters: + - $ref: '#/components/parameters/pathBehaviorId' + get: + summary: Retrieve a Behavior Detection Rule + description: Retrieves a Behavior Detection Rule by `behaviorId` + operationId: getBehaviorDetectionRule + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/BehaviorRule' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Resource Not Found: + $ref: '#/components/examples/ErrorResourceNotFound' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.behaviors.read + tags: + - Behavior + put: + summary: Replace a Behavior Detection Rule + description: Replaces a Behavior Detection Rule by `behaviorId` + operationId: replaceBehaviorDetectionRule + x-codegen-request-body-name: rule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BehaviorRule' + examples: + BehaviorRuleRequest: + $ref: '#/components/examples/BehaviorRuleRequest' + required: true + responses: + '200': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/BehaviorRule' + examples: + BehaviorRuleReSponse: + $ref: '#/components/examples/BehaviorRuleResponse' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + API Validation Failed: + $ref: '#/components/examples/ErrorApiValidationFailed' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Resource Not Found: + $ref: '#/components/examples/ErrorResourceNotFound' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.behaviors.manage + tags: + - Behavior + delete: + summary: Delete a Behavior Detection Rule + description: Deletes a Behavior Detection Rule by `behaviorId` + operationId: deleteBehaviorDetectionRule + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Resource Not Found: + $ref: '#/components/examples/ErrorResourceNotFound' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.behaviors.manage + tags: + - Behavior + /api/v1/behaviors/{behaviorId}/lifecycle/activate: + post: + summary: Activate a Behavior Detection Rule + description: Activates a behavior detection rule + operationId: activateBehaviorDetectionRule + parameters: + - $ref: '#/components/parameters/pathBehaviorId' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/BehaviorRule' + examples: + BehaviorRuleReSponse: + $ref: '#/components/examples/BehaviorRuleResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.behaviors.manage + tags: + - Behavior + /api/v1/behaviors/{behaviorId}/lifecycle/deactivate: + post: + summary: Deactivate a Behavior Detection Rule + description: Deactivates a behavior detection rule + operationId: deactivateBehaviorDetectionRule + parameters: + - $ref: '#/components/parameters/pathBehaviorId' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/BehaviorRule' + examples: + BehaviorRuleReSponse: + $ref: '#/components/examples/BehaviorRuleResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.behaviors.manage + tags: + - Behavior + /api/v1/brands: + get: + summary: List all Brands + description: Lists all the brands in your org + operationId: listBrands + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Brand' + examples: + Get brands response: + $ref: '#/components/examples/ListBrandsResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + post: + summary: Create a Brand + description: Creates new brand in your org + operationId: createBrand + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateBrandRequest' + examples: + Create brand request: + $ref: '#/components/examples/CreateBrandRequest' + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/Brand' + examples: + Create brand response: + $ref: '#/components/examples/CreateBrandResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: Retrieve a Brand + description: Retrieves a brand by `brandId` + operationId: getBrand + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Brand' + examples: + Get brand response: + $ref: '#/components/examples/GetBrandResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + put: + summary: Replace a Brand + description: Replaces a brand by `brandId` + operationId: replaceBrand + x-codegen-request-body-name: brand + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BrandRequest' + examples: + Update brand request: + $ref: '#/components/examples/UpdateBrandRequest' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Brand' + examples: + Update brand response: + $ref: '#/components/examples/UpdateBrandResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + delete: + summary: Delete a brand + description: Deletes a brand by its unique identifier + operationId: deleteBrand + responses: + '204': + description: Successfully deleted the brand. + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '409': + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Cannot delete default brand: + $ref: '#/components/examples/ErrorDeleteDefaultBrand' + Cannot delete brand associated with a domain: + $ref: '#/components/examples/ErrorDeleteBrandAssociatedWithDomain' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/domains: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: List all Domains associated with a Brand + description: Lists all domains associated with a brand by `brandId` + operationId: listBrandDomains + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/BrandDomains' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + post: + summary: Link a Brand to a Domain + description: Link a Brand to a Domain by `domainId` + operationId: linkBrandDomain + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateBrandDomainRequest' + examples: + Create brand request: + $ref: '#/components/examples/CreateBrandDomainRequest' + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/BrandDomain' + examples: + Link a brand with a domain: + $ref: '#/components/examples/LinkBrandDomain' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '409': + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Cannot link default brand with a domain: + $ref: '#/components/examples/ErrorLinkDefaultBrand' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/domains/{domainId}: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathDomainId' + delete: + summary: Unlink a Brand from a Domain + description: Unlink brand and domain by its unique identifier + operationId: unlinkBrandDomain + responses: + '204': + description: Successfully unlinked the domain from the brand + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/pages/error: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/queryExpandPageRoot' + get: + summary: Retrieve the Error Page + description: Retrieves the error page + operationId: getErrorPage + responses: + '200': + description: Successfully retrieved the error page. + content: + application/json: + schema: + $ref: '#/components/schemas/PageRoot' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + /api/v1/brands/{brandId}/pages/error/customized: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: Retrieve the Customized Error Page + description: Retrieves the customized error page + operationId: getCustomizedErrorPage + responses: + '200': + description: Successfully retrieved the customized error page. + headers: + Location: + schema: + type: string + format: uri + content: + application/json: + schema: + $ref: '#/components/schemas/CustomizablePage' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + put: + summary: Replace the Customized Error Page + description: Replaces the customized error page + operationId: replaceCustomizedErrorPage + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CustomizablePage' + required: true + responses: + '200': + description: Successfully replaced the customized error page. + headers: + Location: + schema: + type: string + format: uri + content: + application/json: + schema: + $ref: '#/components/schemas/CustomizablePage' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + delete: + summary: Reset the Customized Error Page + description: Resets the customized error page + operationId: resetCustomizedErrorPage + responses: + '204': + description: Successfully reset the customized error page. + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/pages/error/default: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: Retrieve the Default Error Page + description: Retrieves the default error page + operationId: getDefaultErrorPage + responses: + '200': + description: Successfully retrieved the default error page. + content: + application/json: + schema: + $ref: '#/components/schemas/CustomizablePage' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + /api/v1/brands/{brandId}/pages/error/preview: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: Retrieve the Preview Error Page Preview + description: Retrieves the preview error page + operationId: getPreviewErrorPage + responses: + '200': + description: Successfully retrieved the preview error page. + headers: + Location: + schema: + type: string + format: uri + content: + application/json: + schema: + $ref: '#/components/schemas/CustomizablePage' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + put: + summary: Replace the Preview Error Page + description: Replace the preview error page + operationId: replacePreviewErrorPage + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CustomizablePage' + required: true + responses: + '200': + description: Successfully replaced the preview error page. + headers: + Location: + schema: + type: string + format: uri + content: + application/json: + schema: + $ref: '#/components/schemas/CustomizablePage' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + delete: + summary: Reset the Preview Error Page + description: Reset the preview error page + operationId: resetPreviewErrorPage + responses: + '204': + description: Successfully reset the preview error page. + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/pages/sign-in: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/queryExpandPageRoot' + get: + summary: Retrieve the Sign-in Page + description: Retrieves the sign-in page + operationId: getSignInPage + responses: + '200': + description: Successfully retrieved the sign-in page. + content: + application/json: + schema: + $ref: '#/components/schemas/PageRoot' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + /api/v1/brands/{brandId}/pages/sign-in/customized: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: Retrieve the Customized Sign-in Page + description: Retrieves the customized sign-in page + operationId: getCustomizedSignInPage + responses: + '200': + description: Successfully retrieved the customized sign-in page. + headers: + Location: + schema: + type: string + format: uri + content: + application/json: + schema: + $ref: '#/components/schemas/SignInPage' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + put: + summary: Replace the Customized Sign-in Page + description: Replaces the customized sign-in page + operationId: replaceCustomizedSignInPage + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SignInPage' + required: true + responses: + '200': + description: Successfully replaced the customized sign-in page. + headers: + Location: + schema: + type: string + format: uri + content: + application/json: + schema: + $ref: '#/components/schemas/SignInPage' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + delete: + summary: Reset the Customized Sign-in Page + description: Reset the customized sign-in page + operationId: resetCustomizedSignInPage + responses: + '204': + description: Successfully reset the sign-in page. + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/pages/sign-in/default: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: Retrieve the Default Sign-in Page + description: Retrieves the default sign-in page + operationId: getDefaultSignInPage + responses: + '200': + description: Successfully retrieved the default sign-in page. + content: + application/json: + schema: + $ref: '#/components/schemas/SignInPage' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + /api/v1/brands/{brandId}/pages/sign-in/preview: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: Retrieve the Preview Sign-in Page Preview + description: Retrieves the preview sign-in page + operationId: getPreviewSignInPage + responses: + '200': + description: Successfully retrieved the preview sign-in page. + headers: + Location: + schema: + type: string + format: uri + content: + application/json: + schema: + $ref: '#/components/schemas/SignInPage' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + put: + summary: Replace the Preview Sign-in Page + description: Replace the preview sign-in page + operationId: replacePreviewSignInPage + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SignInPage' + required: true + responses: + '200': + description: Successfully replaced the preview sign-in page. + headers: + Location: + schema: + type: string + format: uri + content: + application/json: + schema: + $ref: '#/components/schemas/SignInPage' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + delete: + summary: Reset the Preview Sign-in Page + description: Reset the preview sign-in page + operationId: resetPreviewSignInPage + responses: + '204': + description: Successfully reset the preview sign-in page. + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/pages/sign-in/widget-versions: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: List all Sign-in Widget Versions + description: Lists all sign-in widget versions + operationId: listAllSignInWidgetVersions + responses: + '200': + description: Successfully listed the sign-in widget versions. + content: + application/json: + schema: + type: array + items: + type: string + pattern: ^\d+\.\d+$ + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + /api/v1/brands/{brandId}/pages/sign-out/customized: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: Retrieve the Sign-out Page Settings + description: Retrieves the sign-out page settings + operationId: getSignOutPageSettings + responses: + '200': + description: Successfully retrieved the sign-out page settings. + content: + application/json: + schema: + $ref: '#/components/schemas/HostedPage' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + put: + summary: Replace the Sign-out Page Settings + description: Replaces the sign-out page settings + operationId: replaceSignOutPageSettings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/HostedPage' + required: true + responses: + '200': + description: Successfully replaced the sign-out page settings. + content: + application/json: + schema: + $ref: '#/components/schemas/HostedPage' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/templates/email: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: List all Email Templates + description: Lists all email templates + operationId: listEmailTemplates + parameters: + - $ref: '#/components/parameters/queryAfter' + - $ref: '#/components/parameters/queryLimit' + - $ref: '#/components/parameters/queryExpandEmailTemplate' + responses: + '200': + description: Successfully returned the list of email templates. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/EmailTemplate' + examples: + List email templates response: + $ref: '#/components/examples/ListEmailTemplateResponse' + headers: + Link: + schema: + type: string + description: The pagination header containing links to the current and next page of results. See [Pagination](/#pagination) for more information. + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + /api/v1/brands/{brandId}/templates/email/{templateName}: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathTemplateName' + get: + summary: Retrieve an Email Template + description: Retrieves the details of an email template by name + operationId: getEmailTemplate + parameters: + - $ref: '#/components/parameters/queryExpandEmailTemplate' + responses: + '200': + description: Successfully retrieved the email template. + content: + application/json: + schema: + $ref: '#/components/schemas/EmailTemplate' + examples: + Get email template response: + $ref: '#/components/examples/GetEmailTemplateResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + /api/v1/brands/{brandId}/templates/email/{templateName}/customizations: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathTemplateName' + get: + summary: List all Email Customizations + description: Lists all customizations of an email template + operationId: listEmailCustomizations + parameters: + - $ref: '#/components/parameters/queryAfter' + - $ref: '#/components/parameters/queryLimit' + responses: + '200': + description: Successfully retrieved all email customizations for the specified email template. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/EmailCustomization' + examples: + List Email customizations response: + $ref: '#/components/examples/ListEmailCustomizationResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + post: + summary: Create an Email Customization + description: Creates a new email customization + operationId: createEmailCustomization + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EmailCustomization' + examples: + Create email customization request: + $ref: '#/components/examples/CreateUpdateEmailCustomizationRequest' + responses: + '201': + description: Successfully created the email customization. + content: + application/json: + schema: + $ref: '#/components/schemas/EmailCustomization' + examples: + Create email customization response: + $ref: '#/components/examples/CreateUpdateEmailCustomizationResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '409': + description: Could not create the email customization because it conflicts with an existing email customization. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Default email customization already exists: + $ref: '#/components/examples/ErrorEmailCustomizationDefaultAlreadyExists' + Email customization already exists for the specified language: + $ref: '#/components/examples/ErrorEmailCustomizationLanguageAlreadyExists' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Customization + delete: + summary: Delete all Email Customizations + description: Deletes all customizations for an email template + operationId: deleteAllCustomizations + responses: + '204': + description: Successfully deleted all customizations for the email template. + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Customization + /api/v1/brands/{brandId}/templates/email/{templateName}/customizations/{customizationId}: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathTemplateName' + - $ref: '#/components/parameters/pathCustomizationId' + get: + summary: Retrieve an Email Customization + description: Retrieves an email customization by its unique identifier + operationId: getEmailCustomization + responses: + '200': + description: Successfully retrieved the email customization. + content: + application/json: + schema: + $ref: '#/components/schemas/EmailCustomization' + examples: + Get email customization response: + $ref: '#/components/examples/EmailCustomizationResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + put: + summary: Replace an Email Customization + description: Replaces an existing email customization using the property values provided + operationId: replaceEmailCustomization + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EmailCustomization' + examples: + Update email customization request: + $ref: '#/components/examples/CreateUpdateEmailCustomizationRequest' + description: Request + responses: + '200': + description: Successfully updated the email customization. + content: + application/json: + schema: + $ref: '#/components/schemas/EmailCustomization' + examples: + Update email customization response: + $ref: '#/components/examples/CreateUpdateEmailCustomizationResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '409': + description: Could not update the email customization because the update would cause a conflict with an existing email customization. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Default email customization already exists: + $ref: '#/components/examples/ErrorEmailCustomizationDefaultAlreadyExists' + Email customization already exists for the specified language: + $ref: '#/components/examples/ErrorEmailCustomizationLanguageAlreadyExists' + Cannot set the default email customization's isDefault to false: + $ref: '#/components/examples/ErrorEmailCustomizationCannotClearDefault' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Customization + delete: + summary: Delete an Email Customization + description: Deletes an email customization by its unique identifier + operationId: deleteEmailCustomization + responses: + '204': + description: Successfully deleted the email customization. + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '409': + description: Could not delete the email customization deleted because it is the default email customization. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Cannot delete default email customization: + $ref: '#/components/examples/ErrorEmailCustomizationCannotDeleteDefault' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Customization + /api/v1/brands/{brandId}/templates/email/{templateName}/customizations/{customizationId}/preview: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathTemplateName' + - $ref: '#/components/parameters/pathCustomizationId' + get: + summary: Retrieve a Preview of an Email Customization + description: Generates a preview of an email customization. All variable references (e.g., `${user.profile.firstName}`) are populated using the current user's context. + operationId: getCustomizationPreview + responses: + '200': + description: Successfully generated a preview of the email customization. + content: + application/json: + schema: + $ref: '#/components/schemas/EmailPreview' + examples: + Preview email customization response: + $ref: '#/components/examples/PreviewEmailCustomizationResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + /api/v1/brands/{brandId}/templates/email/{templateName}/default-content: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathTemplateName' + get: + summary: Retrieve an Email Template Default Content + description: Retrieves an email template's default content + operationId: getEmailDefaultContent + parameters: + - $ref: '#/components/parameters/queryLanguage' + responses: + '200': + description: Successfully retrieved the email template's default content. + content: + application/json: + schema: + $ref: '#/components/schemas/EmailDefaultContent' + examples: + Get email template default content response: + $ref: '#/components/examples/EmailTemplateDefaultContentResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + /api/v1/brands/{brandId}/templates/email/{templateName}/default-content/preview: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathTemplateName' + get: + summary: Retrieve a Preview of the Email Template Default Content + description: Generates a preview of an email template's default content. All variable references (e.g., `${user.profile.firstName}`) are populated using the current user's context. + operationId: getEmailDefaultPreview + parameters: + - $ref: '#/components/parameters/queryLanguage' + responses: + '200': + description: Successfully generated a preview of the email template's default content. + content: + application/json: + schema: + $ref: '#/components/schemas/EmailPreview' + examples: + Preview email template default content response: + $ref: '#/components/examples/PreviewEmailTemplateDefaultContentResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + /api/v1/brands/{brandId}/templates/email/{templateName}/settings: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathTemplateName' + get: + summary: Retrieve the Email Template Settings + description: Retrieves an email template's settings + operationId: getEmailSettings + responses: + '200': + description: Successfully retrieved the email template's settings. + content: + application/json: + schema: + $ref: '#/components/schemas/EmailSettings' + examples: + Get email template settings response: + $ref: '#/components/examples/EmailSettingsResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + put: + summary: Replace the Email Template Settings + description: Replaces an email template's settings + operationId: replaceEmailSettings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EmailSettings' + responses: + '204': + description: Successfully updated the email template's settings. + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '422': + description: Could not update the email template's settings due to an invalid setting value. + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Invalid email template recipients: + $ref: '#/components/examples/ErrorInvalidEmailTemplateRecipients' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Customization + /api/v1/brands/{brandId}/templates/email/{templateName}/test: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathTemplateName' + post: + summary: Send a Test Email + description: |- + Sends a test email to the current user’s primary and secondary email addresses. The email content is selected based on the following priority: + 1. The email customization for the language specified in the `language` query parameter. + 2. The email template's default customization. + 3. The email template’s default content, translated to the current user's language. + operationId: sendTestEmail + parameters: + - $ref: '#/components/parameters/queryLanguage' + responses: + '204': + description: Successfully sent a test email. + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Customization + /api/v1/brands/{brandId}/themes: + parameters: + - $ref: '#/components/parameters/pathBrandId' + get: + summary: List all Themes + description: Lists all the themes in your brand + operationId: listBrandThemes + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ThemeResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + /api/v1/brands/{brandId}/themes/{themeId}: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathThemeId' + get: + summary: Retrieve a Theme + description: Retrieves a theme for a brand + operationId: getBrandTheme + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ThemeResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.read + tags: + - Customization + put: + summary: Replace a Theme + description: Replaces a theme for a brand + operationId: replaceBrandTheme + x-codegen-request-body-name: theme + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Theme' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ThemeResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/themes/{themeId}/background-image: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathThemeId' + post: + summary: Upload the Background Image + description: Updates the background image for your Theme + operationId: uploadBrandThemeBackgroundImage + requestBody: + content: + multipart/form-data: + schema: + type: object + description: The file must be in PNG, JPG, or GIF format and less than 2 MB in size. + properties: + file: + type: string + format: binary + required: + - file + description: background image file + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploadResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + delete: + summary: Delete the Background Image + description: Deletes a Theme background image + operationId: deleteBrandThemeBackgroundImage + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/themes/{themeId}/favicon: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathThemeId' + post: + summary: Upload the Favicon + description: Updates the favicon for your theme + operationId: uploadBrandThemeFavicon + requestBody: + content: + multipart/form-data: + schema: + type: object + description: The file must be in PNG, or ico format and less than ?? in size and 128 x 128 dimensions + properties: + file: + type: string + format: binary + required: + - file + description: favicon file + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploadResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + delete: + summary: Delete the Favicon + description: Deletes a Theme favicon. The theme will use the default Okta favicon. + operationId: deleteBrandThemeFavicon + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/brands/{brandId}/themes/{themeId}/logo: + parameters: + - $ref: '#/components/parameters/pathBrandId' + - $ref: '#/components/parameters/pathThemeId' + post: + summary: Upload the Logo + description: Updates the logo for your Theme + operationId: uploadBrandThemeLogo + requestBody: + content: + multipart/form-data: + schema: + description: The file must be in PNG, JPG, or GIF format and less than 100kB in size. For best results use landscape orientation, a transparent background, and a minimum size of 300px by 50px to prevent upscaling. + type: object + properties: + file: + type: string + format: binary + required: + - file + description: logo file + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ImageUploadResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + delete: + summary: Delete the Logo + description: Deletes a Theme logo. The theme will use the default Okta logo. + operationId: deleteBrandThemeLogo + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.brands.manage + tags: + - Customization + /api/v1/captchas: + get: + summary: List all CAPTCHA instances + description: Lists all CAPTCHA instances with pagination support. A subset of CAPTCHA instances can be returned that match a supported filter expression or query. + operationId: listCaptchaInstances + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/CAPTCHAInstance' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.captchas.read + tags: + - CAPTCHA + post: + summary: Create a CAPTCHA instance + description: Creates a new CAPTCHA instance. In the current release, we only allow one CAPTCHA instance per org. + operationId: createCaptchaInstance + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CAPTCHAInstance' + examples: + HCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceRequestHCaptcha' + ReCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceRequestReCaptcha' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/CAPTCHAInstance' + examples: + HCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceResponseHCaptcha' + ReCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceResponseReCaptcha' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + Error Limit of One CAPTCHA instance per org: + $ref: '#/components/examples/ErrorCAPTCHALimitOfOne' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.captchas.manage + tags: + - CAPTCHA + /api/v1/captchas/{captchaId}: + parameters: + - $ref: '#/components/parameters/pathCaptchaId' + get: + summary: Retrieve a CAPTCHA Instance + description: Retrieves a CAPTCHA instance by `captchaId` + operationId: getCaptchaInstance + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CAPTCHAInstance' + examples: + HCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceResponseHCaptcha' + ReCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceResponseReCaptcha' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.captchas.read + tags: + - CAPTCHA + post: + summary: Update a CAPTCHA instance + description: Partially updates a CAPTCHA instance by `captchaId` + operationId: updateCaptchaInstance + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CAPTCHAInstance' + examples: + HCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceRequestHCaptcha' + ReCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceRequestReCaptcha' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CAPTCHAInstance' + examples: + HCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceResponseHCaptcha' + ReCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceResponseReCaptcha' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.captchas.manage + tags: + - CAPTCHA + put: + summary: Replace a CAPTCHA instance + description: Replaces a CAPTCHA instance by `captchaId` + operationId: replaceCaptchaInstance + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CAPTCHAInstance' + examples: + HCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceRequestHCaptcha' + ReCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceRequestReCaptcha' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/CAPTCHAInstance' + examples: + HCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceResponseHCaptcha' + ReCaptcha: + $ref: '#/components/examples/CAPTCHAInstanceResponseReCaptcha' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.captchas.manage + tags: + - CAPTCHA + delete: + summary: Delete a CAPTCHA Instance + description: Deletes a CAPTCHA instance by `captchaId`. If the CAPTCHA instance is currently being used in the org, the delete will not be allowed. + operationId: deleteCaptchaInstance + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + Cannot remove CAPTCHA in use: + $ref: '#/components/examples/ErrorCAPTCHAOrgWideSetting' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.captchas.manage + tags: + - CAPTCHA + /api/v1/device-assurances: + get: + summary: List all Device Assurance Policies + description: Lists all device assurance policies + operationId: listDeviceAssurancePolicies + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/DeviceAssurance' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.deviceAssurance.read + tags: + - DeviceAssurance + post: + summary: Create a Device Assurance Policy + description: Creates a new Device Assurance Policy + operationId: createDeviceAssurancePolicy + x-codegen-request-body-name: deviceAssurance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DeviceAssurance' + examples: + ANDROID: + $ref: '#/components/examples/DeviceAssuranceAndroidRequest' + MACOS: + $ref: '#/components/examples/DeviceAssuranceMacOSRequest' + WINDOWS: + $ref: '#/components/examples/DeviceAssuranceWindowsRequest' + IOS: + $ref: '#/components/examples/DeviceAssuranceIosRequest' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/DeviceAssurance' + examples: + DeviceAssuranceResponse: + $ref: '#/components/examples/DeviceAssuranceResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.deviceAssurance.manage + tags: + - DeviceAssurance + /api/v1/device-assurances/{deviceAssuranceId}: + get: + summary: Retrieve a Device Assurance Policy + description: Retrieves a Device Assurance Policy by `deviceAssuranceId` + operationId: getDeviceAssurancePolicy + parameters: + - $ref: '#/components/parameters/pathDeviceAssuranceId' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/DeviceAssurance' + examples: + DeviceAssuranceResponse: + $ref: '#/components/examples/DeviceAssuranceResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.deviceAssurance.read + tags: + - DeviceAssurance + put: + summary: Replace a Device Assurance Policy + description: Replaces a Device Assurance Policy by `deviceAssuranceId` + operationId: replaceDeviceAssurancePolicy + parameters: + - $ref: '#/components/parameters/pathDeviceAssuranceId' + x-codegen-request-body-name: deviceAssurance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DeviceAssurance' + examples: + DeviceAssuranceResponse: + $ref: '#/components/examples/DeviceAssuranceResponse' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/DeviceAssurance' + examples: + DeviceAssuranceResponse: + $ref: '#/components/examples/DeviceAssuranceResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.deviceAssurance.manage + tags: + - DeviceAssurance + delete: + summary: Delete a Device Assurance Policy + description: Deletes a Device Assurance Policy by `deviceAssuranceId`. If the Device Assurance Policy is currently being used in the org Authentication Policies, the delete will not be allowed. + operationId: deleteDeviceAssurancePolicy + parameters: + - $ref: '#/components/parameters/pathDeviceAssuranceId' + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '409': + description: Conflict + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Cannot delete device assurance policy in use by authentication policies: + $ref: '#/components/examples/ErrorDeviceAssuranceInUse' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.deviceAssurance.manage + tags: + - DeviceAssurance + /api/v1/devices: + get: + summary: List all Devices + description: |- + Lists all devices with pagination support. + + A subset of Devices can be returned that match a supported search criteria using the `search` query parameter. + + Searches for devices based on the properties specified in the `search` parameter conforming SCIM filter specifications (case-insensitive). This data is eventually consistent. The API returns different results depending on specified queries in the request. Empty list is returned if no objects match `search` request. + + > **Note:** Listing devices with `search` should not be used as a part of any critical flows—such as authentication or updates—to prevent potential data loss. `search` results may not reflect the latest information, as this endpoint uses a search index which may not be up-to-date with recent updates to the object.
    Don't use search results directly for record updates, as the data might be stale and therefore overwrite newer data, resulting in data loss.
    Use an `id` lookup for records that you update to ensure your results contain the latest data. + + This operation equires [URL encoding](http://en.wikipedia.org/wiki/Percent-encoding). For example, `search=profile.displayName eq "Bob"` is encoded as `search=profile.displayName%20eq%20%22Bob%22`. + operationId: listDevices + parameters: + - $ref: '#/components/parameters/queryAfter' + - $ref: '#/components/parameters/queryLimit' + - name: search + in: query + description: SCIM filter expression that filters the results. Searches include all Device `profile` properties, as well as the Device `id`, `status` and `lastUpdated` properties. + schema: + type: string + examples: + Devices that have a `status` of `ACTIVE`: + value: status eq "ACTIVE" + Devices last updated after a specific timestamp: + value: lastUpdated gt "yyyy-MM-dd'T'HH:mm:ss.SSSZ" + Devices with a specified `id`: + value: id eq "guo4a5u7JHHhjXrMK0g4" + Devices that have a `displayName` of `Bob`: + value: profile.displayName eq "Bob" + Devices that have an `platform` of `WINDOWS`: + value: profile.platform eq "WINDOWS" + Devices whose `sid` starts with `S-1`: + value: profile.sid sw "S-1" + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Device' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.devices.read + tags: + - Device + /api/v1/devices/{deviceId}: + parameters: + - $ref: '#/components/parameters/pathDeviceId' + get: + summary: Retrieve a Device + description: Retrieves a device by `deviceId` + operationId: getDevice + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Device' + examples: + Example Response: + $ref: '#/components/examples/DeviceResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.devices.read + tags: + - Device + delete: + summary: Delete a Device + description: Deletes a device by `deviceId` + operationId: deleteDevice + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.devices.manage + tags: + - Device + /api/v1/devices/{deviceId}/lifecycle/activate: + parameters: + - $ref: '#/components/parameters/pathDeviceId' + post: + summary: Activate a Device + description: Activates a device by `deviceId` + operationId: activateDevice + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.devices.manage + tags: + - Device + /api/v1/devices/{deviceId}/lifecycle/deactivate: + parameters: + - $ref: '#/components/parameters/pathDeviceId' + post: + summary: Deactivate a Device + description: Deactivates a device by `deviceId` + operationId: deactivateDevice + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.devices.manage + tags: + - Device + /api/v1/devices/{deviceId}/lifecycle/suspend: + parameters: + - $ref: '#/components/parameters/pathDeviceId' + post: + summary: Suspend a Device + description: Suspends a device by `deviceId` + operationId: suspendDevice + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.devices.manage + tags: + - Device + /api/v1/devices/{deviceId}/lifecycle/unsuspend: + parameters: + - $ref: '#/components/parameters/pathDeviceId' + post: + summary: Unsuspend a Device + description: Unsuspends a device by `deviceId` + operationId: unsuspendDevice + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.devices.manage + tags: + - Device + /api/v1/domains: + get: + summary: List all Domains + description: Lists all verified custom Domains for the org + operationId: listDomains + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/DomainListResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.domains.read + tags: + - Domain + post: + summary: Create a Domain + description: Creates your domain + operationId: createDomain + x-codegen-request-body-name: domain + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Domain' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/DomainResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.domains.manage + tags: + - Domain + /api/v1/domains/{domainId}: + get: + summary: Retrieve a Domain + description: Retrieves a Domain by `id` + operationId: getDomain + parameters: + - name: domainId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/DomainResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.domains.read + tags: + - Domain + put: + summary: Replace a Domain's brandId + description: Replaces a Domain by `id` + operationId: replaceDomain + parameters: + - name: domainId + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateDomain' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/DomainResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.domains.manage + tags: + - Domain + delete: + summary: Delete a Domain + description: Deletes a Domain by `id` + operationId: deleteDomain + parameters: + - name: domainId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.domains.manage + tags: + - Domain + /api/v1/domains/{domainId}/certificate: + put: + summary: Upsert the Certificate + description: Creates or replaces the certificate for the domain + operationId: upsertCertificate + parameters: + - name: domainId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: certificate + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/DomainCertificate' + required: true + responses: + '204': + description: No Content + content: {} + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.domains.manage + tags: + - Domain + /api/v1/domains/{domainId}/verify: + post: + summary: Verify a Domain + description: Verifies the Domain by `id` + operationId: verifyDomain + parameters: + - name: domainId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/DomainResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.domains.manage + tags: + - Domain + /api/v1/email-domains: + get: + summary: List all email domains + description: Lists all the email domains in your org + operationId: listEmailDomains + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/EmailDomainListResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.email-domains.read + tags: + - EmailDomain + post: + summary: Create an Email Domain + description: Creates a custom email domain + operationId: createEmailDomain + x-codegen-request-body-name: emailDomain + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EmailDomain' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EmailDomainResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.email-domains.manage + tags: + - EmailDomain + /api/v1/email-domains/{emailDomainId}: + get: + summary: Retrieve a Email Domain + description: Retrieves an Email Domain by `emailDomainId` + operationId: getEmailDomain + parameters: + - $ref: '#/components/parameters/pathEmailDomainId' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EmailDomainResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.email-domains.read + tags: + - EmailDomain + put: + summary: Replace an Email Domain + description: Replaces an email domain by `emailDomainId` + operationId: replaceEmailDomain + parameters: + - $ref: '#/components/parameters/pathEmailDomainId' + x-codegen-request-body-name: updateEmailDomain + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateEmailDomain' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/EmailDomainResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.email-domains.manage + tags: + - EmailDomain + delete: + summary: Delete an Email Domain + description: Deletes an Email Domain by `emailDomainId` + operationId: deleteEmailDomain + parameters: + - $ref: '#/components/parameters/pathEmailDomainId' + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.email-domains.manage + tags: + - EmailDomain + /api/v1/email-domains/{emailDomainId}/brands: + get: + summary: List all brands linked to an email domain + description: Lists all brands linked to an email domain + operationId: listEmailDomainBrands + parameters: + - $ref: '#/components/parameters/pathEmailDomainId' + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Brand' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.email-domains.read + tags: + - EmailDomain + /api/v1/email-domains/{emailDomainId}/verify: + post: + summary: Verify an Email Domain + description: Verifies an Email Domain by `emailDomainId` + operationId: verifyEmailDomain + parameters: + - $ref: '#/components/parameters/pathEmailDomainId' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EmailDomainResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.email-domains.manage + tags: + - EmailDomain + /api/v1/eventHooks: + get: + summary: List all Event Hooks + description: Lists all event hooks + operationId: listEventHooks + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/EventHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.eventHooks.read + tags: + - EventHook + post: + summary: Create an Event Hook + description: Creates an event hook + operationId: createEventHook + x-codegen-request-body-name: eventHook + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EventHook' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EventHook' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.eventHooks.manage + tags: + - EventHook + /api/v1/eventHooks/{eventHookId}: + get: + summary: Retrieve an Event Hook + description: Retrieves an event hook + operationId: getEventHook + parameters: + - name: eventHookId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EventHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.eventHooks.read + tags: + - EventHook + put: + summary: Replace an Event Hook + description: Replaces an event hook + operationId: replaceEventHook + parameters: + - name: eventHookId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: eventHook + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/EventHook' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EventHook' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.eventHooks.manage + tags: + - EventHook + delete: + summary: Delete an Event Hook + description: Deletes an event hook + operationId: deleteEventHook + parameters: + - name: eventHookId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.eventHooks.manage + tags: + - EventHook + /api/v1/eventHooks/{eventHookId}/lifecycle/activate: + post: + summary: Activate an Event Hook + description: Activates an event hook + operationId: activateEventHook + parameters: + - name: eventHookId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EventHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.eventHooks.manage + tags: + - EventHook + /api/v1/eventHooks/{eventHookId}/lifecycle/deactivate: + post: + summary: Deactivate an Event Hook + description: Deactivates an event hook + operationId: deactivateEventHook + parameters: + - name: eventHookId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EventHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.eventHooks.manage + tags: + - EventHook + /api/v1/eventHooks/{eventHookId}/lifecycle/verify: + post: + summary: Verify an Event Hook + description: Verifies an event hook + operationId: verifyEventHook + parameters: + - name: eventHookId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/EventHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.eventHooks.manage + tags: + - EventHook + /api/v1/features: + get: + summary: List all Features + description: Lists all features + operationId: listFeatures + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Feature' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.features.read + tags: + - Feature + /api/v1/features/{featureId}: + get: + summary: Retrieve a Feature + description: Retrieves a feature + operationId: getFeature + parameters: + - name: featureId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Feature' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.features.read + tags: + - Feature + /api/v1/features/{featureId}/dependencies: + get: + summary: List all Dependencies + description: Lists all dependencies + operationId: listFeatureDependencies + parameters: + - name: featureId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Feature' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.features.read + tags: + - Feature + /api/v1/features/{featureId}/dependents: + get: + summary: List all Dependents + description: Lists all dependents + operationId: listFeatureDependents + parameters: + - name: featureId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Feature' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.features.read + tags: + - Feature + /api/v1/features/{featureId}/{lifecycle}: + post: + summary: Update a Feature Lifecycle + description: Update a feature lifecycle + operationId: updateFeatureLifecycle + parameters: + - name: featureId + in: path + required: true + schema: + type: string + - name: lifecycle + in: path + required: true + schema: + type: string + - name: mode + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Feature' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.features.manage + tags: + - Feature + /api/v1/groups: + get: + summary: List all Groups + description: Lists all groups with pagination support. A subset of groups can be returned that match a supported filter expression or query. + operationId: listGroups + parameters: + - name: q + in: query + description: Searches the name property of groups for matching value + schema: + type: string + - name: filter + in: query + description: Filter expression for groups + schema: + type: string + - name: after + in: query + description: Specifies the pagination cursor for the next page of groups + schema: + type: string + - name: limit + in: query + description: Specifies the number of group results in a page + schema: + type: integer + format: int32 + default: 10000 + - name: expand + in: query + description: If specified, it causes additional metadata to be included in the response. + schema: + type: string + - name: search + in: query + description: Searches for groups with a supported filtering expression for all attributes except for _embedded, _links, and objectClass + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Group' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.read + tags: + - Group + post: + summary: Create a Group + description: Creates a new group with `OKTA_GROUP` type + operationId: createGroup + x-codegen-request-body-name: group + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Group' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Group' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/groups/rules: + get: + summary: List all Group Rules + description: Lists all group rules + operationId: listGroupRules + parameters: + - name: limit + in: query + description: Specifies the number of rule results in a page + schema: + type: integer + format: int32 + default: 50 + - name: after + in: query + description: Specifies the pagination cursor for the next page of rules + schema: + type: string + - name: search + in: query + description: Specifies the keyword to search fules for + schema: + type: string + - name: expand + in: query + description: If specified as `groupIdToGroupNameMap`, then show group names + schema: + type: string + x-okta-added-version: 1.3.0 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GroupRule' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.read + tags: + - Group + post: + summary: Create a Group Rule + description: Creates a group rule to dynamically add users to the specified group if they match the condition + operationId: createGroupRule + x-codegen-request-body-name: groupRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GroupRule' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/GroupRule' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/groups/rules/{ruleId}: + get: + summary: Retrieve a Group Rule + description: Retrieves a specific group rule by `ruleId` + operationId: getGroupRule + parameters: + - name: ruleId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/GroupRule' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.read + tags: + - Group + put: + summary: Replace a Group Rule + description: Replaces a group rule. Only `INACTIVE` rules can be updated. + operationId: replaceGroupRule + parameters: + - name: ruleId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: groupRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GroupRule' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/GroupRule' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + delete: + summary: Delete a group Rule + description: Deletes a specific group rule by `ruleId` + operationId: deleteGroupRule + parameters: + - name: ruleId + in: path + required: true + schema: + type: string + - name: removeUsers + in: query + description: Indicates whether to keep or remove users from groups assigned by this rule. + schema: + type: boolean + responses: + '202': + description: Accepted + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/groups/rules/{ruleId}/lifecycle/activate: + post: + summary: Activate a Group Rule + description: Activates a specific group rule by `ruleId` + operationId: activateGroupRule + parameters: + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/groups/rules/{ruleId}/lifecycle/deactivate: + post: + summary: Deactivate a Group Rule + description: Deactivates a specific group rule by `ruleId` + operationId: deactivateGroupRule + parameters: + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/groups/{groupId}: + get: + summary: Retrieve a Group + description: Retrieves a group by `groupId` + operationId: getGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Group' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.read + tags: + - Group + put: + summary: Replace a Group + description: Replaces the profile for a group with `OKTA_GROUP` type + operationId: replaceGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: group + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Group' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Group' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + delete: + summary: Delete a Group + description: Deletes a group with `OKTA_GROUP` type + operationId: deleteGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/groups/{groupId}/apps: + get: + summary: List all Assigned Applications + description: Lists all applications that are assigned to a group + operationId: listAssignedApplicationsForGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: after + in: query + description: Specifies the pagination cursor for the next page of apps + schema: + type: string + - name: limit + in: query + description: Specifies the number of app results for a page + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Application' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.read + tags: + - Group + /api/v1/groups/{groupId}/owners: + get: + summary: List all Group Owners + description: Lists all owners for a specific group + operationId: listGroupOwners + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: filter + in: query + description: SCIM Filter expression for group owners. Allows to filter owners by type. + schema: + type: string + - name: after + in: query + description: Specifies the pagination cursor for the next page of owners + schema: + type: string + - name: limit + in: query + description: Specifies the number of owner results in a page + schema: + type: integer + format: int32 + default: 1000 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/GroupOwner' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.read + tags: + - Group + post: + summary: Assign a Group Owner + description: Assigns a group owner + operationId: assignGroupOwner + parameters: + - name: groupId + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GroupOwner' + required: true + responses: + '201': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/GroupOwner' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/groups/{groupId}/owners/{ownerId}: + delete: + summary: Delete a Group Owner + description: Deletes a group owner from a specific group + operationId: deleteGroupOwner + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: ownerId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/groups/{groupId}/roles: + get: + summary: List all Assigned Roles of Group + description: Lists all assigned roles of group identified by `groupId` + operationId: listGroupAssignedRoles + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Role' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - RoleAssignment + post: + summary: Assign a Role to a Group + description: Assigns a role to a group + operationId: assignRoleToGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: disableNotifications + in: query + description: Setting this to `true` grants the group third-party admin status + schema: + type: boolean + x-codegen-request-body-name: assignRoleRequest + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AssignRoleRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Role' + '201': + description: Success + content: {} + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleAssignment + /api/v1/groups/{groupId}/roles/{roleId}: + get: + summary: Retrieve a Role assigned to Group + description: Retrieves a role identified by `roleId` assigned to group identified by `groupId` + operationId: getGroupAssignedRole + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Role' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - RoleAssignment + delete: + summary: Unassign a Role from a Group + description: Unassigns a role identified by `roleId` assigned to group identified by `groupId` + operationId: unassignRoleFromGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleAssignment + /api/v1/groups/{groupId}/roles/{roleId}/targets/catalog/apps: + get: + summary: List all Application Targets for an Application Administrator Role + description: Lists all App targets for an `APP_ADMIN` Role assigned to a Group. This methods return list may include full Applications or Instances. The response for an instance will have an `ID` value, while Application will not have an ID. + operationId: listApplicationTargetsForApplicationAdministratorRoleForGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/CatalogApplication' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - RoleTarget + /api/v1/groups/{groupId}/roles/{roleId}/targets/catalog/apps/{appName}: + put: + summary: Assign an Application Target to Administrator Role + description: Assigns an application target to administrator role + operationId: assignAppTargetToAdminRoleForGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: appName + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + delete: + summary: Unassign an Application Target from Application Administrator Role + description: Unassigns an application target from application administrator role + operationId: unassignAppTargetToAdminRoleForGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: appName + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + /api/v1/groups/{groupId}/roles/{roleId}/targets/catalog/apps/{appName}/{applicationId}: + put: + summary: Assign an Application Instance Target to Application Administrator Role + description: Assigns App Instance Target to App Administrator Role given to a Group + operationId: assignAppInstanceTargetToAppAdminRoleForGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: appName + in: path + required: true + schema: + type: string + - name: applicationId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + delete: + summary: Unassign an Application Instance Target from an Application Administrator Role + description: Unassigns an application instance target from application administrator role + operationId: unassignAppInstanceTargetToAppAdminRoleForGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: appName + in: path + required: true + schema: + type: string + - name: applicationId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + /api/v1/groups/{groupId}/roles/{roleId}/targets/groups: + get: + summary: List all Group Targets for a Group Role + description: Lists all group targets for a group role + operationId: listGroupTargetsForGroupRole + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Group' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - RoleTarget + /api/v1/groups/{groupId}/roles/{roleId}/targets/groups/{targetGroupId}: + put: + summary: Assign a Group Target to a Group Role + description: Assigns a group target to a group role + operationId: assignGroupTargetToGroupAdminRole + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: targetGroupId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + delete: + summary: Unassign a Group Target from a Group Role + description: Unassigns a group target from a group role + operationId: unassignGroupTargetFromGroupAdminRole + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: targetGroupId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + /api/v1/groups/{groupId}/users: + get: + summary: List all Member Users + description: Lists all users that are a member of a group + operationId: listGroupUsers + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: after + in: query + description: Specifies the pagination cursor for the next page of users + schema: + type: string + - name: limit + in: query + description: Specifies the number of user results in a page + schema: + type: integer + format: int32 + default: 1000 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.read + tags: + - Group + /api/v1/groups/{groupId}/users/{userId}: + put: + summary: Assign a User + description: Assigns a user to a group with 'OKTA_GROUP' type + operationId: assignUserToGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + delete: + summary: Unassign a User + description: Unassigns a user from a group with 'OKTA_GROUP' type + operationId: unassignUserFromGroup + parameters: + - name: groupId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.groups.manage + tags: + - Group + /api/v1/hook-keys: + get: + summary: List all keys + description: Lists all keys + operationId: listHookKeys + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/HookKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.read + tags: + - HookKey + post: + summary: Create a key + description: Creates a key + operationId: createHookKey + x-codegen-request-body-name: keyRequest + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/KeyRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/HookKey' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - HookKey + /api/v1/hook-keys/public/{keyId}: + get: + summary: Retrieve a public key + description: Retrieves a public key by `keyId` + operationId: getPublicKey + parameters: + - name: keyId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.read + tags: + - HookKey + /api/v1/hook-keys/{hookKeyId}: + get: + summary: Retrieve a key + description: Retrieves a key by `hookKeyId` + operationId: getHookKey + parameters: + - name: hookKeyId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/HookKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.read + tags: + - HookKey + put: + summary: Replace a key + description: Replace a key by `hookKeyId` + operationId: replaceHookKey + parameters: + - name: hookKeyId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: keyRequest + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/KeyRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/HookKey' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - HookKey + delete: + summary: Delete a key + description: Deletes a key by `hookKeyId`. Once deleted, the Hook Key is unrecoverable. As a safety precaution, unused keys are eligible for deletion. + operationId: deleteHookKey + parameters: + - name: hookKeyId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - HookKey + /api/v1/iam/resource-sets: + get: + summary: List all Resource Sets + description: Lists all resource sets with pagination support + operationId: listResourceSets + parameters: + - $ref: '#/components/parameters/queryAfter' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSets' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetsResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - ResourceSet + post: + summary: Create a Resource Set + description: Creates a new resource set + operationId: createResourceSet + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSet' + examples: + Example Request: + $ref: '#/components/examples/ResourceSetRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSet' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + /api/v1/iam/resource-sets/{resourceSetId}: + parameters: + - $ref: '#/components/parameters/pathResourceSetId' + get: + summary: Retrieve a Resource Set + description: Retrieves a resource set by `resourceSetId` + operationId: getResourceSet + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSet' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - ResourceSet + put: + summary: Replace a Resource Set + description: Replaces a resource set by `resourceSetId` + operationId: replaceResourceSet + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSet' + examples: + Example Request: + $ref: '#/components/examples/ResourceSetRequest' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSet' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + delete: + summary: Delete a Resource Set + description: Deletes a role by `resourceSetId` + operationId: deleteResourceSet + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + /api/v1/iam/resource-sets/{resourceSetId}/bindings: + parameters: + - $ref: '#/components/parameters/pathResourceSetId' + get: + summary: List all Bindings + description: Lists all resource set bindings with pagination support + operationId: listBindings + parameters: + - $ref: '#/components/parameters/queryAfter' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetBindings' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetBindingsResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - ResourceSet + post: + summary: Create a Resource Set Binding + description: Creates a new resource set binding + operationId: createResourceSetBinding + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetBindingCreateRequest' + examples: + Example Request: + $ref: '#/components/examples/ResourceSetBindingCreateRequestExample' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetBindingResponse' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetBindingResponseExample' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + /api/v1/iam/resource-sets/{resourceSetId}/bindings/{roleIdOrLabel}: + parameters: + - $ref: '#/components/parameters/pathResourceSetId' + - $ref: '#/components/parameters/pathRoleIdOrLabel' + get: + summary: Retrieve a Binding + description: Retrieves a resource set binding by `resourceSetId` and `roleIdOrLabel` + operationId: getBinding + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetBindingResponse' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetBindingResponseWithIdExample' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - ResourceSet + delete: + summary: Delete a Binding + description: Deletes a resource set binding by `resourceSetId` and `roleIdOrLabel` + operationId: deleteBinding + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + /api/v1/iam/resource-sets/{resourceSetId}/bindings/{roleIdOrLabel}/members: + parameters: + - $ref: '#/components/parameters/pathResourceSetId' + - $ref: '#/components/parameters/pathRoleIdOrLabel' + get: + summary: List all Members of a binding + description: Lists all members of a resource set binding with pagination support + operationId: listMembersOfBinding + parameters: + - $ref: '#/components/parameters/queryAfter' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetBindingMembers' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetBindingMembersResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - ResourceSet + patch: + summary: Add more Members to a binding + description: Creates more members to a resource set binding + operationId: addMembersToBinding + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetBindingAddMembersRequest' + examples: + Example Request: + $ref: '#/components/examples/ResourceSetBindingAddMembersRequestExample' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetBindingResponse' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetBindingResponseExample' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + /api/v1/iam/resource-sets/{resourceSetId}/bindings/{roleIdOrLabel}/members/{memberId}: + parameters: + - $ref: '#/components/parameters/pathResourceSetId' + - $ref: '#/components/parameters/pathRoleIdOrLabel' + - $ref: '#/components/parameters/pathMemberId' + get: + summary: Retrieve a Member of a binding + description: Retreieves a member identified by `memberId` for a binding + operationId: getMemberOfBinding + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetBindingMember' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetBindingMemberResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - ResourceSet + delete: + summary: Unassign a Member from a binding + description: Unassigns a member identified by `memberId` from a binding + operationId: unassignMemberFromBinding + x-codegen-request-body-name: instance + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + /api/v1/iam/resource-sets/{resourceSetId}/resources: + parameters: + - $ref: '#/components/parameters/pathResourceSetId' + get: + summary: List all Resources of a resource set + description: Lists all resources that make up the resource set + operationId: listResourceSetResources + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetResources' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetResourcesResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - ResourceSet + patch: + summary: Add a Resource to a resource set + description: Creates more resources to a resource set + operationId: addResourceSetResource + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSetResourcePatchRequest' + examples: + Example Request: + $ref: '#/components/examples/ResourceSetResourcePatchRequestExample' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceSet' + examples: + Example Response: + $ref: '#/components/examples/ResourceSetResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + /api/v1/iam/resource-sets/{resourceSetId}/resources/{resourceId}: + parameters: + - $ref: '#/components/parameters/pathResourceSetId' + - $ref: '#/components/parameters/pathResourceId' + delete: + summary: Delete a Resource from a resource set + description: Deletes a resource identified by `resourceId` from a resource set + operationId: deleteResourceSetResource + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - ResourceSet + /api/v1/iam/roles: + get: + summary: List all Roles + description: Lists all roles with pagination support + operationId: listRoles + parameters: + - $ref: '#/components/parameters/queryAfter' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/IamRoles' + examples: + Example Response: + $ref: '#/components/examples/RolesResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - Role + post: + summary: Create a Role + description: Creates a new role + operationId: createRole + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IamRole' + examples: + Example Request: + $ref: '#/components/examples/RoleRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/IamRole' + examples: + Example Response: + $ref: '#/components/examples/RoleResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - Role + /api/v1/iam/roles/{roleIdOrLabel}: + parameters: + - $ref: '#/components/parameters/pathRoleIdOrLabel' + get: + summary: Retrieve a Role + description: Retrieves a role by `roleIdOrLabel` + operationId: getRole + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/IamRole' + examples: + Example Response: + $ref: '#/components/examples/RoleResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - Role + put: + summary: Replace a Role + description: Replaces a role by `roleIdOrLabel` + operationId: replaceRole + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IamRole' + examples: + Example Request: + $ref: '#/components/examples/RoleRequest' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/IamRole' + examples: + Example Response: + $ref: '#/components/examples/RoleResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - Role + delete: + summary: Delete a Role + description: Deletes a role by `roleIdOrLabel` + operationId: deleteRole + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - Role + /api/v1/iam/roles/{roleIdOrLabel}/permissions: + parameters: + - $ref: '#/components/parameters/pathRoleIdOrLabel' + get: + summary: List all Permissions + description: Lists all permissions of the role by `roleIdOrLabel` + operationId: listRolePermissions + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Permissions' + examples: + Example Response: + $ref: '#/components/examples/PermissionsResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - Role + /api/v1/iam/roles/{roleIdOrLabel}/permissions/{permissionType}: + parameters: + - $ref: '#/components/parameters/pathRoleIdOrLabel' + - $ref: '#/components/parameters/pathPermissionType' + get: + summary: Retrieve a Permission + description: Retrieves a permission by `permissionType` + operationId: getRolePermission + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Permission' + examples: + Example Response: + $ref: '#/components/examples/PermissionResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - Role + post: + summary: Create a Permission + description: Creates a permission specified by `permissionType` to the role + operationId: createRolePermission + x-codegen-request-body-name: instance + responses: + '204': + description: No Content + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - Role + delete: + summary: Delete a Permission + description: Deletes a permission from a role by `permissionType` + operationId: deleteRolePermission + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - Role + /api/v1/idps: + get: + summary: List all Identity Providers + description: Lists all identity provider integrations with pagination. A subset of IdPs can be returned that match a supported filter expression or query. + operationId: listIdentityProviders + parameters: + - name: q + in: query + description: Searches the name property of IdPs for matching value + schema: + type: string + - name: after + in: query + description: Specifies the pagination cursor for the next page of IdPs + schema: + type: string + - name: limit + in: query + description: Specifies the number of IdP results in a page + schema: + type: integer + format: int32 + default: 20 + - name: type + in: query + description: Filters IdPs by type + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/IdentityProvider' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + post: + summary: Create an Identity Provider + description: Creates a new identity provider integration + operationId: createIdentityProvider + x-codegen-request-body-name: identityProvider + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProvider' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProvider' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/credentials/keys: + get: + summary: List all Credential Keys + description: Lists all IdP key credentials + operationId: listIdentityProviderKeys + parameters: + - name: after + in: query + description: Specifies the pagination cursor for the next page of keys + schema: + type: string + - name: limit + in: query + description: Specifies the number of key results in a page + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + post: + summary: Create an X.509 Certificate Public Key + description: Creates a new X.509 certificate credential to the IdP key store. + operationId: createIdentityProviderKey + x-codegen-request-body-name: jsonWebKey + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/credentials/keys/{keyId}: + get: + summary: Retrieve an Credential Key + description: Retrieves a specific IdP Key Credential by `kid` + operationId: getIdentityProviderKey + parameters: + - name: keyId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + delete: + summary: Delete a Signing Credential Key + description: Deletes a specific IdP Key Credential by `kid` if it is not currently being used by an Active or Inactive IdP + operationId: deleteIdentityProviderKey + parameters: + - name: keyId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}: + get: + summary: Retrieve an Identity Provider + description: Retrieves an identity provider integration by `idpId` + operationId: getIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProvider' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + put: + summary: Replace an Identity Provider + description: Replaces an identity provider integration by `idpId` + operationId: replaceIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: identityProvider + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProvider' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProvider' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + delete: + summary: Delete an Identity Provider + description: Deletes an identity provider integration by `idpId` + operationId: deleteIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/credentials/csrs: + get: + summary: List all Certificate Signing Requests + description: Lists all Certificate Signing Requests for an IdP + operationId: listCsrsForIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Csr' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + post: + summary: Generate a Certificate Signing Request + description: Generates a new key pair and returns a Certificate Signing Request for it + operationId: generateCsrForIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: metadata + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CsrMetadata' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/Csr' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/credentials/csrs/{csrId}: + get: + summary: Retrieve a Certificate Signing Request + description: Retrieves a specific Certificate Signing Request model by id + operationId: getCsrForIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: csrId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Csr' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + delete: + summary: Revoke a Certificate Signing Request + description: Revoke a Certificate Signing Request and delete the key pair from the IdP + operationId: revokeCsrForIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: csrId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/credentials/csrs/{csrId}/lifecycle/publish: + post: + summary: Publish a Certificate Signing Request + description: Update the Certificate Signing Request with a signed X.509 certificate and add it into the signing key credentials for the IdP. + operationId: publishCsrForIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: csrId + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/x-x509-ca-cert: + schema: + type: string + format: binary + x-okta-operationId: publishBinaryCerCertForIdentityProvider + application/pkix-cert: + schema: + type: string + format: binary + x-okta-operationId: publishBinaryDerCertForIdentityProvider + application/x-pem-file: + schema: + type: string + format: binary + x-okta-operationId: publishBinaryPemCertForIdentityProvider + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/credentials/keys: + get: + summary: List all Signing Credential Keys + description: Lists all signing key credentials for an IdP + operationId: listIdentityProviderSigningKeys + parameters: + - name: idpId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + /api/v1/idps/{idpId}/credentials/keys/generate: + post: + summary: Generate a new Signing Credential Key + description: Generates a new X.509 certificate for an IdP signing key credential to be used for signing assertions sent to the IdP + operationId: generateIdentityProviderSigningKey + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: validityYears + in: query + description: expiry of the IdP Key Credential + required: true + schema: + type: integer + format: int32 + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/credentials/keys/{keyId}: + get: + summary: Retrieve a Signing Credential Key + description: Retrieves a specific IdP Key Credential by `kid` + operationId: getIdentityProviderSigningKey + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: keyId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + /api/v1/idps/{idpId}/credentials/keys/{keyId}/clone: + post: + summary: Clone a Signing Credential Key + description: Clones a X.509 certificate for an IdP signing key credential from a source IdP to target IdP + operationId: cloneIdentityProviderKey + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: keyId + in: path + required: true + schema: + type: string + - name: targetIdpId + in: query + required: true + schema: + type: string + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/JsonWebKey' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/lifecycle/activate: + post: + summary: Activate an Identity Provider + description: Activates an inactive IdP + operationId: activateIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProvider' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/lifecycle/deactivate: + post: + summary: Deactivate an Identity Provider + description: Deactivates an active IdP + operationId: deactivateIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProvider' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/users: + get: + summary: List all Users + description: Find all the users linked to an identity provider + operationId: listIdentityProviderApplicationUsers + parameters: + - name: idpId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/IdentityProviderApplicationUser' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + /api/v1/idps/{idpId}/users/{userId}: + get: + summary: Retrieve a User + description: Retrieves a linked IdP user by ID + operationId: getIdentityProviderApplicationUser + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProviderApplicationUser' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + post: + summary: Link a User to a Social IdP + description: Links an Okta user to an existing Social Identity Provider. This does not support the SAML2 Identity Provider Type + operationId: linkUserToIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: userIdentityProviderLinkRequest + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserIdentityProviderLinkRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/IdentityProviderApplicationUser' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - IdentityProvider + delete: + summary: Unlink a User from IdP + description: Unlinks the link between the Okta user and the IdP user + operationId: unlinkUserFromIdentityProvider + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.manage + tags: + - IdentityProvider + /api/v1/idps/{idpId}/users/{userId}/credentials/tokens: + get: + summary: List all Tokens from a OIDC Identity Provider + description: Lists the tokens minted by the Social Authentication Provider when the user authenticates with Okta via Social Auth + operationId: listSocialAuthTokens + parameters: + - name: idpId + in: path + required: true + schema: + type: string + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SocialAuthToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.idps.read + tags: + - IdentityProvider + /api/v1/inlineHooks: + get: + summary: List all Inline Hooks + description: Lists all inline hooks + operationId: listInlineHooks + parameters: + - name: type + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/InlineHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.read + tags: + - InlineHook + post: + summary: Create an Inline Hook + description: Creates an inline hook + operationId: createInlineHook + x-codegen-request-body-name: inlineHook + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHook' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHook' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - InlineHook + /api/v1/inlineHooks/{inlineHookId}: + get: + summary: Retrieve an Inline Hook + description: Retrieves an inline hook by `inlineHookId` + operationId: getInlineHook + parameters: + - name: inlineHookId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.read + tags: + - InlineHook + put: + summary: Replace an Inline Hook + description: Replaces an inline hook by `inlineHookId` + operationId: replaceInlineHook + parameters: + - name: inlineHookId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: inlineHook + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHook' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHook' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - InlineHook + delete: + summary: Delete an Inline Hook + description: Deletes an inline hook by `inlineHookId`. Once deleted, the Inline Hook is unrecoverable. As a safety precaution, only Inline Hooks with a status of INACTIVE are eligible for deletion. + operationId: deleteInlineHook + parameters: + - name: inlineHookId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - InlineHook + /api/v1/inlineHooks/{inlineHookId}/execute: + post: + summary: Execute an Inline Hook + description: Executes the inline hook by `inlineHookId` using the request body as the input. This will send the provided data through the Channel and return a response if it matches the correct data contract. This execution endpoint should only be used for testing purposes. + operationId: executeInlineHook + parameters: + - name: inlineHookId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: payloadData + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHookPayload' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHookResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - InlineHook + /api/v1/inlineHooks/{inlineHookId}/lifecycle/activate: + post: + summary: Activate an Inline Hook + description: Activates the inline hook by `inlineHookId` + operationId: activateInlineHook + parameters: + - name: inlineHookId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - InlineHook + /api/v1/inlineHooks/{inlineHookId}/lifecycle/deactivate: + post: + summary: Deactivate an Inline Hook + description: Deactivates the inline hook by `inlineHookId` + operationId: deactivateInlineHook + parameters: + - name: inlineHookId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/InlineHook' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.inlineHooks.manage + tags: + - InlineHook + /api/v1/logStreams: + get: + summary: List all Log Streams + description: Lists all log streams. You can request a paginated list or a subset of Log Streams that match a supported filter expression. + operationId: listLogStreams + parameters: + - $ref: '#/components/parameters/queryAfter' + - $ref: '#/components/parameters/queryLimit' + - name: filter + in: query + description: SCIM filter expression that filters the results. This expression only supports the `eq` operator on either the `status` or `type`. + schema: + type: string + examples: + Filter on type for AWS EventBridge: + value: type eq "aws_eventbridge" + Filter on status for `ACTIVE` Log Streams: + value: status eq "ACTIVE" + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LogStream' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.read + tags: + - LogStream + post: + summary: Create a Log Stream + description: Creates a new log stream + operationId: createLogStream + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/LogStream' + examples: + Example Request: + $ref: '#/components/examples/LogStreamRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/LogStream' + examples: + Example Response: + $ref: '#/components/examples/LogStreamResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.manage + tags: + - LogStream + /api/v1/logStreams/{logStreamId}: + parameters: + - $ref: '#/components/parameters/pathLogStreamId' + get: + summary: Retrieve a Log Stream + description: Retrieves a log stream by `logStreamId` + operationId: getLogStream + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/LogStream' + examples: + Example Response: + $ref: '#/components/examples/LogStreamResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.read + tags: + - LogStream + put: + summary: Replace a Log Stream + description: Replaces a log stream by `logStreamId` + operationId: replaceLogStream + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/LogStream' + examples: + Example Request: + $ref: '#/components/examples/LogStreamRequest' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/LogStream' + examples: + Example Response: + $ref: '#/components/examples/LogStreamResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.manage + tags: + - LogStream + delete: + summary: Delete a Log Stream + description: Deletes a log stream by `logStreamId` + operationId: deleteLogStream + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.manage + tags: + - LogStream + /api/v1/logStreams/{logStreamId}/lifecycle/activate: + parameters: + - $ref: '#/components/parameters/pathLogStreamId' + post: + summary: Activate a Log Stream + description: Activates a log stream by `logStreamId` + operationId: activateLogStream + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/LogStream' + examples: + Example Response: + $ref: '#/components/examples/LogStreamResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.manage + tags: + - LogStream + /api/v1/logStreams/{logStreamId}/lifecycle/deactivate: + parameters: + - $ref: '#/components/parameters/pathLogStreamId' + post: + summary: Deactivate a Log Stream + description: Deactivates a log stream by `logStreamId` + operationId: deactivateLogStream + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/LogStream' + examples: + Example Response: + $ref: '#/components/examples/LogStreamResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.manage + tags: + - LogStream + /api/v1/logs: + get: + summary: List all System Log Events + description: The Okta System Log API provides read access to your organization’s system log. This API provides more functionality than the Events API + operationId: listLogEvents + parameters: + - name: since + in: query + schema: + type: string + format: date-time + - name: until + in: query + schema: + type: string + format: date-time + - name: filter + in: query + schema: + type: string + - name: q + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + default: 100 + - name: sortOrder + in: query + schema: + type: string + default: ASCENDING + - name: after + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LogEvent' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logs.read + tags: + - SystemLog + /api/v1/mappings: + get: + summary: List all Profile Mappings + description: Lists all profile mappings with pagination + operationId: listProfileMappings + parameters: + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: -1 + - name: sourceId + in: query + schema: + type: string + - name: targetId + in: query + schema: + type: string + default: '' + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ProfileMapping' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.profileMappings.read + tags: + - ProfileMapping + /api/v1/mappings/{mappingId}: + get: + summary: Retrieve a Profile Mapping + description: Retrieves a single Profile Mapping referenced by its ID + operationId: getProfileMapping + parameters: + - name: mappingId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileMapping' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.profileMappings.read + tags: + - ProfileMapping + post: + summary: Update a Profile Mapping + description: Updates an existing Profile Mapping by adding, updating, or removing one or many Property Mappings + operationId: updateProfileMapping + parameters: + - name: mappingId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: profileMapping + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileMapping' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ProfileMapping' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.profileMappings.manage + tags: + - ProfileMapping + /api/v1/meta/layouts/apps/{appName}: + get: + summary: Retrieve the UI Layout for an Application + description: Takes an Application name as an input parameter and retrieves the App Instance page Layout for that Application + operationId: getApplicationLayout + parameters: + - name: appName + in: path + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ApplicationLayout' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.schemas.read + tags: + - Schema + /api/v1/meta/schemas/apps/{appInstanceId}/default: + get: + summary: Retrieve the default Application User Schema for an Application + description: Retrieves the Schema for an App User + operationId: getApplicationUserSchema + parameters: + - name: appInstanceId + in: path + required: true + schema: + type: string + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/UserSchema' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.schemas.read + tags: + - Schema + post: + summary: Update the default Application User Schema for an Application + description: Partial updates on the User Profile properties of the Application User Schema + operationId: updateApplicationUserProfile + parameters: + - name: appInstanceId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: body + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserSchema' + examples: + Add a custom property to the app user schema: + $ref: '#/components/examples/AppUserSchemaAddRequest' + required: false + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/UserSchema' + examples: + Response with a subset of properties for brevity: + $ref: '#/components/examples/AppUserSchemaResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.schemas.manage + tags: + - Schema + /api/v1/meta/schemas/group/default: + get: + summary: Retrieve the default Group Schema + description: Retrieves the group schema + operationId: getGroupSchema + parameters: [] + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/GroupSchema' + examples: + Response with a subset of properties for brevity: + $ref: '#/components/examples/GroupSchemaResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.schemas.read + tags: + - Schema + post: + summary: Update the default Group Schema + description: Updates, adds or removes one or more custom Group Profile properties in the schema + operationId: updateGroupSchema + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/GroupSchema' + examples: + Add a custom property to the group schema: + $ref: '#/components/examples/GroupSchemaAddRequest' + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/GroupSchema' + example: + Response with a subset of properties for brevity: + $ref: '#/components/examples/GroupSchemaResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.schemas.manage + tags: + - Schema + /api/v1/meta/schemas/logStream: + get: + summary: List the Log Stream Schemas + description: Lists the schema for all log stream types visible for this org + operationId: listLogStreamSchemas + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LogStreamSchema' + examples: + All log stream schemas for your org: + $ref: '#/components/examples/LogStreamSchemaList' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.read + tags: + - Schema + /api/v1/meta/schemas/logStream/{logStreamType}: + parameters: + - name: logStreamType + in: path + required: true + schema: + $ref: '#/components/schemas/LogStreamType' + get: + summary: Retrieve the Log Stream Schema for the schema type + description: Retrieves the schema for a Log Stream type. The `logStreamType` element in the URL specifies the Log Stream type, which is either `aws_eventbridge` or `splunk_cloud_logstreaming`. Use the `aws_eventbridge` literal to retrieve the AWS EventBridge type schema, and use the `splunk_cloud_logstreaming` literal retrieve the Splunk Cloud type schema. + operationId: getLogStreamSchema + responses: + '200': + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/LogStreamSchema' + examples: + Schema for type `aws_eventbridge`: + $ref: '#/components/examples/LogStreamSchemaAws' + Schema for type `splunk_cloud_logstreaming`: + $ref: '#/components/examples/LogStreamSchemaSplunk' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.logStreams.read + tags: + - Schema + /api/v1/meta/schemas/user/linkedObjects: + get: + summary: List all Linked Object Definitions + description: Lists all linked object definitions + operationId: listLinkedObjectDefinitions + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/LinkedObject' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.linkedObjects.read + tags: + - LinkedObject + post: + summary: Create a Linked Object Definition + description: Creates a linked object definition + operationId: createLinkedObjectDefinition + x-codegen-request-body-name: linkedObject + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/LinkedObject' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/LinkedObject' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.linkedObjects.manage + tags: + - LinkedObject + /api/v1/meta/schemas/user/linkedObjects/{linkedObjectName}: + parameters: + - name: linkedObjectName + in: path + required: true + schema: + type: string + get: + summary: Retrieve a Linked Object Definition + description: Retrieves a linked object definition + operationId: getLinkedObjectDefinition + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/LinkedObject' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.linkedObjects.read + tags: + - LinkedObject + delete: + summary: Delete a Linked Object Definition + description: Deletes a linked object definition + operationId: deleteLinkedObjectDefinition + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.linkedObjects.manage + tags: + - LinkedObject + /api/v1/meta/schemas/user/{schemaId}: + parameters: + - name: schemaId + in: path + required: true + schema: + type: string + get: + summary: Retrieve a User Schema + description: Retrieves the schema for a Schema Id + operationId: getUserSchema + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserSchema' + examples: + Response with a subset of properties for brevity: + $ref: '#/components/examples/UserSchemaResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.schemas.read + tags: + - Schema + post: + summary: Update a User Schema + description: Partial updates on the User Profile properties of the user schema + operationId: updateUserProfile + x-codegen-request-body-name: userSchema + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserSchema' + examples: + Add a custom property to the user schema: + $ref: '#/components/examples/UserSchemaAddRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserSchema' + examples: + Response with a subset of properties for brevity: + $ref: '#/components/examples/UserSchemaResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.schemas.manage + tags: + - Schema + /api/v1/meta/types/user: + get: + summary: List all User Types + description: Lists all User Types in your org + operationId: listUserTypes + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UserType' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.userTypes.read + tags: + - UserType + post: + summary: Create a User Type + description: Creates a new User Type. A default User Type is automatically created along with your org, and you may add another 9 User Types for a maximum of 10. + operationId: createUserType + x-codegen-request-body-name: userType + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserType' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserType' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.userTypes.manage + tags: + - UserType + /api/v1/meta/types/user/{typeId}: + parameters: + - name: typeId + in: path + required: true + schema: + type: string + get: + summary: Retrieve a User Type + description: Retrieves a User Type by ID. The special identifier `default` may be used to fetch the default User Type. + operationId: getUserType + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserType' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.userTypes.read + tags: + - UserType + post: + summary: Update a User Type + description: Updates an existing User Type + operationId: updateUserType + x-codegen-request-body-name: userType + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserType' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserType' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.userTypes.manage + tags: + - UserType + put: + summary: Replace a User Type + description: Replace an existing User Type + operationId: replaceUserType + x-codegen-request-body-name: userType + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserType' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserType' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.userTypes.manage + tags: + - UserType + delete: + summary: Delete a User Type + description: Deletes a User Type permanently. This operation is not permitted for the default type, nor for any User Type that has existing users + operationId: deleteUserType + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.userTypes.manage + tags: + - UserType + /api/v1/org: + get: + summary: Retrieve the Org Settings + description: Retrieves the org settings + operationId: getOrgSettings + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgSetting' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.read + tags: + - OrgSetting + post: + summary: Update the Org Settings + description: Partially update the org settings depending on provided fields + operationId: updateOrgSettings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OrgSetting' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgSetting' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + put: + summary: Replace the Org Settings + description: Replaces the settings of your organization + operationId: replaceOrgSettings + x-codegen-request-body-name: orgSetting + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OrgSetting' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgSetting' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/contacts: + get: + summary: Retrieve the Org Contact Types + description: Retrieves Contact Types of your organization + operationId: getOrgContactTypes + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + items: + $ref: '#/components/schemas/OrgContactTypeObj' + type: array + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.read + tags: + - OrgSetting + /api/v1/org/contacts/{contactType}: + get: + summary: Retrieve the User of the Contact Type + description: Retrieves the URL of the User associated with the specified Contact Type + operationId: getOrgContactUser + parameters: + - in: path + name: contactType + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgContactUser' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.read + tags: + - OrgSetting + put: + summary: Replace the User of the Contact Type + description: Replaces the User associated with the specified Contact Type + operationId: replaceOrgContactUser + parameters: + - in: path + name: contactType + required: true + schema: + type: string + x-codegen-request-body-name: orgContactUser + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/OrgContactUser' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgContactUser' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/email/bounces/remove-list: + post: + summary: Remove Emails from Email Provider Bounce List + description: A list of email addresses to be removed from the set of email addresses that are bounced + operationId: bulkRemoveEmailAddressBounces + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/BouncesRemoveListObj' + examples: + example-1: + value: + emailAddresses: + - name@company.com + - unknown.email@okta.com + - name@okta@com + responses: + '200': + description: Deletes the provided list of emails from the set of email addresses that are bounced so that the provider resumes sending emails to those addresses. + content: + application/json: + schema: + $ref: '#/components/schemas/BouncesRemoveListResult' + examples: + example-1: + value: + errors: + - emailAddress: unknown.email@okta.com + reason: This email address does not belong to any user in your organization. + - emailAddress: name@okta@com + reason: Invalid email address. The provided email address failed validation against RFC 3696. + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/logo: + post: + summary: Upload the Org Logo + description: Uploads and replaces the logo for your organization + operationId: uploadOrgLogo + requestBody: + content: + multipart/form-data: + schema: + description: The file must be in PNG, JPG, or GIF format and less than 100kB in size. For best results use landscape orientation, a transparent background, and a minimum size of 300px by 50px to prevent upscaling. + type: object + properties: + file: + type: string + format: binary + required: + - file + description: logo file + responses: + '201': + description: Created + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.apps.manage + tags: + - OrgSetting + /api/v1/org/preferences: + get: + summary: Retrieve the Org Preferences + description: Retrieves preferences of your organization + operationId: getOrgPreferences + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgPreferences' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.read + tags: + - OrgSetting + /api/v1/org/preferences/hideEndUserFooter: + post: + summary: Update the Preference to Hide the Okta Dashboard Footer + description: Hide the Okta UI footer for all end users of your organization + operationId: updateOrgHideOktaUIFooter + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgPreferences' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/preferences/showEndUserFooter: + post: + summary: Update the Preference to Show the Okta Dashboard Footer + description: Makes the Okta UI footer visible for all end users of your organization + operationId: updateOrgShowOktaUIFooter + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgPreferences' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/privacy/oktaCommunication: + get: + summary: Retrieve the Okta Communication Settings + description: Retrieves Okta Communication Settings of your organization + operationId: getOktaCommunicationSettings + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgOktaCommunicationSetting' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.read + tags: + - OrgSetting + /api/v1/org/privacy/oktaCommunication/optIn: + post: + summary: Opt in all Users to Okta Communication emails + description: Opts in all users of this org to Okta Communication emails + operationId: optInUsersToOktaCommunicationEmails + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgOktaCommunicationSetting' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/privacy/oktaCommunication/optOut: + post: + summary: Opt out all Users from Okta Communication emails + description: Opts out all users of this org from Okta Communication emails + operationId: optOutUsersFromOktaCommunicationEmails + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgOktaCommunicationSetting' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/privacy/oktaSupport: + get: + summary: Retrieve the Okta Support Settings + description: Retrieves Okta Support Settings of your organization + operationId: getOrgOktaSupportSettings + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgOktaSupportSettingsObj' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.read + tags: + - OrgSetting + /api/v1/org/privacy/oktaSupport/extend: + post: + summary: Extend Okta Support Access + description: Extends the length of time that Okta Support can access your org by 24 hours. This means that 24 hours are added to the remaining access time. + operationId: extendOktaSupport + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgOktaSupportSettingsObj' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/privacy/oktaSupport/grant: + post: + summary: Grant Okta Support Access to your Org + description: Enables you to temporarily allow Okta Support to access your org as an administrator for eight hours + operationId: grantOktaSupport + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgOktaSupportSettingsObj' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/org/privacy/oktaSupport/revoke: + post: + summary: Revoke Okta Support Access + description: Revokes Okta Support access to your organization + operationId: revokeOktaSupport + parameters: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OrgOktaSupportSettingsObj' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.orgs.manage + tags: + - OrgSetting + /api/v1/policies: + get: + summary: List all Policies + description: Lists all policies with the specified type + operationId: listPolicies + parameters: + - name: type + in: query + required: true + schema: + type: string + - name: status + in: query + schema: + type: string + - name: expand + in: query + schema: + type: string + default: '' + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Policy' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.read + tags: + - Policy + post: + summary: Create a Policy + description: Creates a policy + operationId: createPolicy + parameters: + - name: activate + in: query + schema: + type: boolean + default: true + x-codegen-request-body-name: policy + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Policy' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Policy' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/policies/{policyId}: + get: + summary: Retrieve a Policy + description: Retrieves a policy + operationId: getPolicy + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + default: '' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Policy' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.read + tags: + - Policy + put: + summary: Replace a Policy + description: Replaces a policy + operationId: replacePolicy + parameters: + - name: policyId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: policy + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Policy' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Policy' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + delete: + summary: Delete a Policy + description: Deletes a policy + operationId: deletePolicy + parameters: + - name: policyId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/policies/{policyId}/clone: + post: + summary: Clone an existing policy + description: Clones an existing policy + operationId: clonePolicy + parameters: + - name: policyId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Policy' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/policies/{policyId}/lifecycle/activate: + post: + summary: Activate a Policy + description: Activates a policy + operationId: activatePolicy + parameters: + - name: policyId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/policies/{policyId}/lifecycle/deactivate: + post: + summary: Deactivate a Policy + description: Deactivates a policy + operationId: deactivatePolicy + parameters: + - name: policyId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/policies/{policyId}/rules: + get: + summary: List all Policy Rules + description: Lists all policy rules + operationId: listPolicyRules + parameters: + - name: policyId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PolicyRule' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.read + tags: + - Policy + post: + summary: Create a Policy Rule + description: Creates a policy rule + operationId: createPolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: policyRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyRule' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyRule' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/policies/{policyId}/rules/{ruleId}: + get: + summary: Retrieve a Policy Rule + description: Retrieves a policy rule + operationId: getPolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyRule' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.read + tags: + - Policy + put: + summary: Replace a Policy Rule + description: Replaces a policy rules + operationId: replacePolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: policyRule + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyRule' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/PolicyRule' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + delete: + summary: Delete a Policy Rule + description: Deletes a policy rule + operationId: deletePolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/policies/{policyId}/rules/{ruleId}/lifecycle/activate: + post: + summary: Activate a Policy Rule + description: Activates a policy rule + operationId: activatePolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/policies/{policyId}/rules/{ruleId}/lifecycle/deactivate: + post: + summary: Deactivate a Policy Rule + description: Deactivates a policy rule + operationId: deactivatePolicyRule + parameters: + - name: policyId + in: path + required: true + schema: + type: string + - name: ruleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.policies.manage + tags: + - Policy + /api/v1/principal-rate-limits: + get: + summary: List all Principal Rate Limits + description: Lists all Principal Rate Limit entities considering the provided parameters + operationId: listPrincipalRateLimitEntities + parameters: + - name: filter + in: query + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + maximum: 50 + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PrincipalRateLimitEntity' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.principalRateLimits.read + tags: + - PrincipalRateLimit + post: + summary: Create a Principal Rate Limit + description: Creates a new Principal Rate Limit entity. In the current release, we only allow one Principal Rate Limit entity per org and principal. + operationId: createPrincipalRateLimitEntity + x-codegen-request-body-name: entity + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PrincipalRateLimitEntity' + examples: + SSWSToken: + $ref: '#/components/examples/PrincipalRateLimitEntityRequestSSWSToken' + EmptyPercentages: + $ref: '#/components/examples/PrincipalRateLimitEntityRequestEmptyPercentages' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/PrincipalRateLimitEntity' + examples: + SSWSToken: + $ref: '#/components/examples/PrincipalRateLimitEntityResponseSSWSToken' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.principalRateLimits.manage + tags: + - PrincipalRateLimit + /api/v1/principal-rate-limits/{principalRateLimitId}: + parameters: + - $ref: '#/components/parameters/pathPrincipalRateLimitId' + get: + summary: Retrieve a Principal Rate Limit + description: Retrieves a Principal Rate Limit entity by `principalRateLimitId` + operationId: getPrincipalRateLimitEntity + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PrincipalRateLimitEntity' + examples: + SSWSToken: + $ref: '#/components/examples/PrincipalRateLimitEntityResponseSSWSToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.principalRateLimits.read + tags: + - PrincipalRateLimit + put: + summary: Replace a Principal Rate Limit + description: Replaces a principal rate limit entity by `principalRateLimitId` + operationId: replacePrincipalRateLimitEntity + x-codegen-request-body-name: entity + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PrincipalRateLimitEntity' + examples: + SSWSToken: + $ref: '#/components/examples/PrincipalRateLimitEntityRequestSSWSToken' + EmptyPercentages: + $ref: '#/components/examples/PrincipalRateLimitEntityRequestEmptyPercentages' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PrincipalRateLimitEntity' + examples: + SSWSToken: + $ref: '#/components/examples/PrincipalRateLimitEntityResponseSSWSToken' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.principalRateLimits.manage + tags: + - PrincipalRateLimit + /api/v1/push-providers: + get: + summary: List all Push Providers + description: Lists all push providers + operationId: listPushProviders + parameters: + - name: type + in: query + description: Filters push providers by `providerType` + schema: + $ref: '#/components/schemas/ProviderType' + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PushProvider' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.pushProviders.read + tags: + - PushProvider + post: + summary: Create a Push Provider + description: Creates a new push provider + operationId: createPushProvider + x-codegen-request-body-name: pushProvider + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PushProvider' + examples: + APNs: + $ref: '#/components/examples/PushProviderAPNsRequest' + FCM: + $ref: '#/components/examples/PushProviderFCMRequest' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PushProvider' + examples: + APNs: + $ref: '#/components/examples/PushProviderAPNsResponse' + FCM: + $ref: '#/components/examples/PushProviderFCMResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.pushProviders.manage + tags: + - PushProvider + /api/v1/push-providers/{pushProviderId}: + get: + summary: Retrieve a Push Provider + description: Retrieves a push provider by `pushProviderId` + operationId: getPushProvider + parameters: + - $ref: '#/components/parameters/pathPushProviderId' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PushProvider' + examples: + APNs: + $ref: '#/components/examples/PushProviderAPNsResponse' + FCM: + $ref: '#/components/examples/PushProviderFCMResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.pushProviders.read + tags: + - PushProvider + put: + summary: Replace a Push Provider + description: Replaces a push provider by `pushProviderId` + operationId: replacePushProvider + parameters: + - $ref: '#/components/parameters/pathPushProviderId' + x-codegen-request-body-name: pushProvider + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PushProvider' + examples: + APNs: + $ref: '#/components/examples/PushProviderAPNsRequest' + FCM: + $ref: '#/components/examples/PushProviderFCMRequest' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PushProvider' + examples: + APNs: + $ref: '#/components/examples/PushProviderAPNsResponse' + FCM: + $ref: '#/components/examples/PushProviderFCMResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.pushProviders.manage + tags: + - PushProvider + delete: + summary: Delete a Push Provider + description: Deletes a push provider by `pushProviderId`. If the push provider is currently being used in the org by a custom authenticator, the delete will not be allowed. + operationId: deletePushProvider + parameters: + - $ref: '#/components/parameters/pathPushProviderId' + responses: + '204': + description: No Content + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '409': + description: Conflict + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Cannot remove push provider in use by a custom app authenticator: + $ref: '#/components/examples/ErrorPushProviderUsedByCustomAppAuthenticator' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.pushProviders.manage + tags: + - PushProvider + /api/v1/rate-limit-settings/admin-notifications: + get: + summary: Retrieve the Rate Limit Admin Notification Settings + description: Retrieves the currently configured Rate Limit Admin Notification Settings + operationId: getRateLimitSettingsAdminNotifications + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RateLimitAdminNotifications' + examples: + Enabled: + $ref: '#/components/examples/RateLimitAdminNotificationsEnabled' + Disabled: + $ref: '#/components/examples/RateLimitAdminNotificationsDisabled' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.rateLimits.read + tags: + - RateLimitSettings + put: + summary: Replace the Rate Limit Admin Notification Settings + description: Replaces the Rate Limit Admin Notification Settings and returns the configured properties + operationId: replaceRateLimitSettingsAdminNotifications + x-codegen-request-body-name: RateLimitAdminNotifications + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RateLimitAdminNotifications' + examples: + Enabled: + $ref: '#/components/examples/RateLimitAdminNotificationsEnabled' + Disabled: + $ref: '#/components/examples/RateLimitAdminNotificationsDisabled' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/RateLimitAdminNotifications' + examples: + Enabled: + $ref: '#/components/examples/RateLimitAdminNotificationsEnabled' + Disabled: + $ref: '#/components/examples/RateLimitAdminNotificationsDisabled' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.rateLimits.manage + tags: + - RateLimitSettings + /api/v1/rate-limit-settings/per-client: + get: + summary: Retrieve the Per-Client Rate Limit Settings + description: Retrieves the currently configured Per-Client Rate Limit Settings + operationId: getRateLimitSettingsPerClient + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PerClientRateLimitSettings' + examples: + EnforceDefault: + $ref: '#/components/examples/PerClientRateLimitSettingsEnforceDefault' + EnforceDefaultWithOverrides: + $ref: '#/components/examples/PerClientRateLimitSettingsEnforceDefaultWithOverrides' + PreviewDefaultWithOverrides: + $ref: '#/components/examples/PerClientRateLimitSettingsPreviewDefaultWithOverrides' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.rateLimits.read + tags: + - RateLimitSettings + put: + summary: Replace the Per-Client Rate Limit Settings + description: Replaces the Per-Client Rate Limit Settings and returns the configured properties + operationId: replaceRateLimitSettingsPerClient + x-codegen-request-body-name: perClientRateLimitSettings + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PerClientRateLimitSettings' + examples: + EnforceDefault: + $ref: '#/components/examples/PerClientRateLimitSettingsEnforceDefault' + EnforceDefaultWithOverrides: + $ref: '#/components/examples/PerClientRateLimitSettingsEnforceDefaultWithOverrides' + PreviewDefaultWithOverrides: + $ref: '#/components/examples/PerClientRateLimitSettingsPreviewDefaultWithOverrides' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/PerClientRateLimitSettings' + examples: + EnforceDefault: + $ref: '#/components/examples/PerClientRateLimitSettingsEnforceDefault' + EnforceDefaultWithOverrides: + $ref: '#/components/examples/PerClientRateLimitSettingsEnforceDefaultWithOverrides' + PreviewDefaultWithOverrides: + $ref: '#/components/examples/PerClientRateLimitSettingsPreviewDefaultWithOverrides' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.rateLimits.manage + tags: + - RateLimitSettings + /api/v1/risk/events/ip: + post: + summary: Send multiple Risk Events + description: A Risk Provider can send Risk Events to Okta using this API. This API has a rate limit of 30 requests per minute. The caller should include multiple Risk Events (up to a maximum of 20 events) in a single payload to reduce the number of API calls. If a client has more risk signals to send than what the API supports, we recommend prioritizing posting high risk signals. + operationId: sendRiskEvents + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/RiskEvent' + examples: + Example Request: + $ref: '#/components/examples/RiskEventsRequest' + required: true + responses: + '202': + description: Accepted + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.riskEvents.manage + tags: + - RiskEvent + /api/v1/risk/providers: + get: + summary: List all Risk Providers + description: Lists all Risk Providers + operationId: listRiskProviders + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/RiskProvider' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.riskProviders.read + tags: + - RiskProvider + post: + summary: Create a Risk Provider + description: Creates a risk provider. A maximum of 3 providers can be created. By default, one risk provider is created by Okta. + operationId: createRiskProvider + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RiskProvider' + examples: + Request Example: + $ref: '#/components/examples/RiskProviderRequest' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/RiskProvider' + examples: + Example Response: + $ref: '#/components/examples/RiskProviderResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.riskProviders.manage + tags: + - RiskProvider + /api/v1/risk/providers/{riskProviderId}: + parameters: + - $ref: '#/components/parameters/pathRiskProviderId' + get: + summary: Retrieve a Risk Provider + description: Retrieves a risk provider by `riskProviderId` + operationId: getRiskProvider + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RiskProvider' + examples: + Example Response: + $ref: '#/components/examples/RiskProviderResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.riskProviders.read + tags: + - RiskProvider + put: + summary: Replace a Risk Provider + description: Replaces a risk provider by `riskProviderId` + operationId: replaceRiskProvider + x-codegen-request-body-name: instance + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RiskProvider' + examples: + Request Example: + $ref: '#/components/examples/RiskProviderRequest' + required: true + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RiskProvider' + examples: + Example Response: + $ref: '#/components/examples/RiskProviderResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.riskProviders.manage + tags: + - RiskProvider + delete: + summary: Delete a Risk Provider + description: Deletes a CAPTCHA instance by `riskProviderId` + operationId: deleteRiskProvider + responses: + '204': + description: No Content + '403': + description: Forbidden + headers: {} + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.riskProviders.manage + tags: + - RiskProvider + /api/v1/roles/{roleTypeOrRoleId}/subscriptions: + get: + summary: List all Subscriptions of a Custom Role + description: When roleType List all subscriptions of a Role. Else when roleId List subscriptions of a Custom Role + operationId: listRoleSubscriptions + parameters: + - in: path + name: roleTypeOrRoleId + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + items: + $ref: '#/components/schemas/Subscription' + type: array + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - Subscription + /api/v1/roles/{roleTypeOrRoleId}/subscriptions/{notificationType}: + get: + summary: List all Subscriptions of a Custom Role with a specific notification type + description: When roleType Get subscriptions of a Role with a specific notification type. Else when roleId Get subscription of a Custom Role with a specific notification type. + operationId: listRoleSubscriptionsByNotificationType + parameters: + - in: path + name: roleTypeOrRoleId + required: true + schema: + type: string + - in: path + name: notificationType + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Subscription' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - Subscription + /api/v1/roles/{roleTypeOrRoleId}/subscriptions/{notificationType}/subscribe: + post: + summary: Subscribe a Custom Role to a specific notification type + description: When roleType Subscribes a Role to a specific notification type. When you change the subscription status of a Role, it overrides the subscription of any individual user of that Role. Else when roleId Subscribes a Custom Role to a specific notification type. When you change the subscription status of a Custom Role, it overrides the subscription of any individual user of that Custom Role. + operationId: subscribeRoleSubscriptionByNotificationType + parameters: + - in: path + name: roleTypeOrRoleId + required: true + schema: + type: string + - in: path + name: notificationType + required: true + schema: + type: string + responses: + '200': + description: Success + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - Subscription + /api/v1/roles/{roleTypeOrRoleId}/subscriptions/{notificationType}/unsubscribe: + post: + summary: Unsubscribe a Custom Role from a specific notification type + description: When roleType Unsubscribes a Role from a specific notification type. When you change the subscription status of a Role, it overrides the subscription of any individual user of that Role. Else when roleId Unsubscribes a Custom Role from a specific notification type. When you change the subscription status of a Custom Role, it overrides the subscription of any individual user of that Custom Role. + operationId: unsubscribeRoleSubscriptionByNotificationType + parameters: + - in: path + name: roleTypeOrRoleId + required: true + schema: + type: string + - in: path + name: notificationType + required: true + schema: + type: string + responses: + '200': + description: Success + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - Subscription + /api/v1/sessions: + post: + summary: Create a Session with Session Token + description: Creates a new session for a user with a valid session token. Use this API if, for example, you want to set the session cookie yourself instead of allowing Okta to set it, or want to hold the session ID in order to delete a session via the API instead of visiting the logout URL. + operationId: createSession + x-codegen-request-body-name: createSessionRequest + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateSessionRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Session' + '400': + description: Bad Request + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + tags: + - Session + /api/v1/sessions/{sessionId}: + get: + summary: Retrieve a Session + description: Retrieves the details about a session + operationId: getSession + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Session' + '400': + description: Bad Request + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.sessions.read + tags: + - Session + delete: + summary: Revoke a Session + description: Revokes a session + operationId: revokeSession + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.sessions.manage + tags: + - Session + /api/v1/sessions/{sessionId}/lifecycle/refresh: + post: + summary: Refresh a Session + description: Refresh a session + operationId: refreshSession + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Session' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.sessions.manage + tags: + - Session + /api/v1/templates/sms: + get: + summary: List all SMS Templates + description: Lists all custom SMS templates. A subset of templates can be returned that match a template type. + operationId: listSmsTemplates + parameters: + - name: templateType + in: query + schema: + $ref: '#/components/schemas/SmsTemplateType' + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SmsTemplate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Template + post: + summary: Create an SMS Template + description: Creates a new custom SMS template + operationId: createSmsTemplate + x-codegen-request-body-name: smsTemplate + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SmsTemplate' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/SmsTemplate' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Template + /api/v1/templates/sms/{templateId}: + get: + summary: Retrieve an SMS Template + description: Retrieves a specific template by `id` + operationId: getSmsTemplate + parameters: + - name: templateId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/SmsTemplate' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.read + tags: + - Template + post: + summary: Update an SMS Template + description: Updates an SMS template + operationId: updateSmsTemplate + parameters: + - name: templateId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: smsTemplate + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SmsTemplate' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/SmsTemplate' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Template + put: + summary: Replace an SMS Template + description: Replaces the SMS template + operationId: replaceSmsTemplate + parameters: + - name: templateId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: smsTemplate + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/SmsTemplate' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/SmsTemplate' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Template + delete: + summary: Delete an SMS Template + description: Deletes an SMS template + operationId: deleteSmsTemplate + parameters: + - name: templateId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.templates.manage + tags: + - Template + /api/v1/threats/configuration: + get: + summary: Retrieve the ThreatInsight Configuration + description: Retrieves current ThreatInsight configuration + operationId: getCurrentConfiguration + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ThreatInsightConfiguration' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.threatInsights.read + tags: + - ThreatInsight + post: + summary: Update the ThreatInsight Configuration + description: Updates ThreatInsight configuration + operationId: updateConfiguration + x-codegen-request-body-name: threatInsightConfiguration + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ThreatInsightConfiguration' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ThreatInsightConfiguration' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.threatInsights.manage + tags: + - ThreatInsight + /api/v1/trustedOrigins: + get: + summary: List all Trusted Origins + description: Lists all trusted origins + operationId: listTrustedOrigins + parameters: + - name: q + in: query + schema: + type: string + - name: filter + in: query + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: -1 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TrustedOrigin' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.trustedOrigins.read + tags: + - TrustedOrigin + post: + summary: Create a Trusted Origin + description: Creates a trusted origin + operationId: createTrustedOrigin + x-codegen-request-body-name: trustedOrigin + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TrustedOrigin' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/TrustedOrigin' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.trustedOrigins.manage + tags: + - TrustedOrigin + /api/v1/trustedOrigins/{trustedOriginId}: + get: + summary: Retrieve a Trusted Origin + description: Retrieves a trusted origin + operationId: getTrustedOrigin + parameters: + - name: trustedOriginId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/TrustedOrigin' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.trustedOrigins.read + tags: + - TrustedOrigin + put: + summary: Replace a Trusted Origin + description: Replaces a trusted origin + operationId: replaceTrustedOrigin + parameters: + - name: trustedOriginId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: trustedOrigin + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TrustedOrigin' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/TrustedOrigin' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.trustedOrigins.manage + tags: + - TrustedOrigin + delete: + summary: Delete a Trusted Origin + description: Deletes a trusted origin + operationId: deleteTrustedOrigin + parameters: + - name: trustedOriginId + in: path + required: true + schema: + type: string + responses: + '204': + description: Success + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.trustedOrigins.manage + tags: + - TrustedOrigin + /api/v1/trustedOrigins/{trustedOriginId}/lifecycle/activate: + post: + summary: Activate a Trusted Origin + description: Activates a trusted origin + operationId: activateTrustedOrigin + parameters: + - name: trustedOriginId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/TrustedOrigin' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.trustedOrigins.manage + tags: + - TrustedOrigin + /api/v1/trustedOrigins/{trustedOriginId}/lifecycle/deactivate: + post: + summary: Deactivate a Trusted Origin + description: Deactivates a trusted origin + operationId: deactivateTrustedOrigin + parameters: + - name: trustedOriginId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/TrustedOrigin' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.trustedOrigins.manage + tags: + - TrustedOrigin + /api/v1/users: + get: + summary: List all Users + description: Lists all users with pagination. A subset of users can be returned that match a supported filter expression or search criteria. + operationId: listUsers + parameters: + - name: q + in: query + description: Finds a user that matches firstName, lastName, and email properties + schema: + type: string + - $ref: '#/components/parameters/queryAfter' + - name: limit + in: query + description: Specifies the number of results returned. Defaults to 10 if `q` is provided. + schema: + type: integer + format: int32 + default: 200 + - name: filter + in: query + description: Filters users with a supported expression for a subset of properties + schema: + type: string + - name: search + in: query + description: Searches for users with a supported filtering expression for most properties. Okta recommends using this parameter for search for best performance. + schema: + type: string + - name: sortBy + in: query + schema: + type: string + - name: sortOrder + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + examples: + User List: + $ref: '#/components/examples/ListUsersResponse' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + post: + summary: Create a User + description: Creates a new user in your Okta organization with or without credentials + operationId: createUser + parameters: + - name: activate + in: query + description: Executes activation lifecycle operation when creating the user + schema: + type: boolean + default: true + - name: provider + in: query + description: Indicates whether to create a user with a specified authentication provider + schema: + type: boolean + default: false + - name: nextLogin + in: query + description: With activate=true, set nextLogin to "changePassword" to have the password be EXPIRED, so user must change it the next time they log in. + schema: + $ref: '#/components/schemas/UserNextLogin' + x-okta-added-version: 0.14.0 + x-codegen-request-body-name: body + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/CreateUserRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Create user with too many groups specified: + $ref: '#/components/examples/ErrorCreateUserWithTooManyManyGroupsResponse' + Create user with expired password and activate set to `false`: + $ref: '#/components/examples/ErrorCreateUserWithExpiredPasswordWithoutActivation' + Create user with expired password and `null` password: + $ref: '#/components/examples/ErrorCreateUserWithExpiredPasswordWithNullPassword' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{associatedUserId}/linkedObjects/{primaryRelationshipName}/{primaryUserId}: + put: + summary: Create a Linked Object for two User + description: Creates a linked object for two users + operationId: setLinkedObjectForUser + parameters: + - name: associatedUserId + in: path + required: true + schema: + type: string + - name: primaryRelationshipName + in: path + required: true + schema: + type: string + - name: primaryUserId + in: path + required: true + schema: + type: string + responses: + '204': + description: Success + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}: + get: + summary: Retrieve a User + description: Retrieves a user from your Okta organization + operationId: getUser + parameters: + - $ref: '#/components/parameters/pathUserId' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + post: + summary: Update a User + description: Updates a user partially determined by the request parameters + operationId: updateUser + parameters: + - $ref: '#/components/parameters/pathUserId' + - name: strict + in: query + schema: + type: boolean + x-codegen-request-body-name: user + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateUserRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + put: + summary: Replace a User + description: Replaces a user's profile and/or credentials using strict-update semantics + operationId: replaceUser + parameters: + - $ref: '#/components/parameters/pathUserId' + - name: strict + in: query + schema: + type: boolean + x-okta-added-version: 1.10.0 + x-codegen-request-body-name: user + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UpdateUserRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + delete: + summary: Delete a User + description: Deletes a user permanently. This operation can only be performed on users that have a `DEPROVISIONED` status. **This action cannot be recovered!**. Calling this on an `ACTIVE` user will transition the user to `DEPROVISIONED`. + operationId: deleteUser + parameters: + - $ref: '#/components/parameters/pathUserId' + - name: sendEmail + in: query + schema: + type: boolean + default: false + x-okta-added-version: 1.5.0 + responses: + '204': + description: No Content + content: {} + '400': + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '404': + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/appLinks: + get: + summary: List all Assigned Application Links + description: Lists all appLinks for all direct or indirect (via group membership) assigned applications + operationId: listAppLinks + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/AppLink' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + /api/v1/users/{userId}/clients: + get: + summary: List all Clients + description: Lists all client resources for which the specified user has grants or tokens + operationId: listUserClients + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2Client' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + /api/v1/users/{userId}/clients/{clientId}/grants: + get: + summary: List all Grants for a Client + description: Lists all grants for a specified user and client + operationId: listGrantsForUserAndClient + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2ScopeConsentGrant' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + delete: + summary: Revoke all Grants for a Client + description: Revokes all grants for the specified user and client + operationId: revokeGrantsForUserAndClient + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/clients/{clientId}/tokens: + get: + summary: List all Refresh Tokens for a Client + description: Lists all refresh tokens issued for the specified User and Client + operationId: listRefreshTokensForUserAndClient + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2RefreshToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + delete: + summary: Revoke all Refresh Tokens for a Client + description: Revokes all refresh tokens issued for the specified User and Client + operationId: revokeTokensForUserAndClient + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/clients/{clientId}/tokens/{tokenId}: + get: + summary: Retrieve a Refresh Token for a Client + description: Retrieves a refresh token issued for the specified User and Client + operationId: getRefreshTokenForUserAndClient + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + - name: tokenId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + default: 20 + - name: after + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2RefreshToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + delete: + summary: Revoke a Token for a Client + description: Revokes the specified refresh token + operationId: revokeTokenForUserAndClient + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: clientId + in: path + required: true + schema: + type: string + - name: tokenId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/credentials/change_password: + post: + summary: Change Password + description: Changes a user's password by validating the user's current password. This operation can only be performed on users in `STAGED`, `ACTIVE`, `PASSWORD_EXPIRED`, or `RECOVERY` status that have a valid password credential + operationId: changePassword + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: strict + in: query + schema: + type: boolean + x-okta-added-version: 1.10.0 + x-codegen-request-body-name: changePasswordRequest + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ChangePasswordRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserCredentials' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/credentials/change_recovery_question: + post: + summary: Change Recovery Question + description: Changes a user's recovery question & answer credential by validating the user's current password. This operation can only be performed on users in **STAGED**, **ACTIVE** or **RECOVERY** `status` that have a valid password credential + operationId: changeRecoveryQuestion + parameters: + - name: userId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: userCredentials + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCredentials' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserCredentials' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/credentials/forgot_password: + post: + summary: Initiate Forgot Password + description: Initiate forgot password flow. Generates a one-time token (OTT) that can be used to reset a user's password. + operationId: forgotPassword + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: sendEmail + in: query + required: false + schema: + type: boolean + default: true + responses: + '200': + description: Reset url + content: + application/json: + schema: + $ref: '#/components/schemas/ForgotPasswordResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/credentials/forgot_password_recovery_question: + post: + summary: Reset Password with Recovery Question + description: Resets the user's password to the specified password if the provided answer to the recovery question is correct + operationId: forgotPasswordSetNewPassword + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: sendEmail + in: query + required: false + schema: + type: boolean + default: true + x-codegen-request-body-name: userCredentials + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/UserCredentials' + required: true + responses: + '200': + description: Credentials + content: + application/json: + schema: + $ref: '#/components/schemas/UserCredentials' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/factors: + get: + summary: List all Factors + description: Lists all the enrolled factors for the specified user + operationId: listFactors + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UserFactor' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - UserFactor + post: + summary: Enroll a Factor + description: Enrolls a user with a supported factor + operationId: enrollFactor + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: updatePhone + in: query + schema: + type: boolean + default: false + - name: templateId + in: query + description: id of SMS template (only for SMS factor) + schema: + type: string + - name: tokenLifetimeSeconds + in: query + schema: + type: integer + format: int32 + default: 300 + x-okta-added-version: 1.3.0 + - name: activate + in: query + schema: + type: boolean + default: false + x-okta-added-version: 1.3.0 + x-codegen-request-body-name: body + requestBody: + description: Factor + content: + application/json: + schema: + $ref: '#/components/schemas/UserFactor' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserFactor' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - UserFactor + /api/v1/users/{userId}/factors/catalog: + get: + summary: List all Supported Factors + description: Lists all the supported factors that can be enrolled for the specified user + operationId: listSupportedFactors + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UserFactor' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - UserFactor + /api/v1/users/{userId}/factors/questions: + get: + summary: List all Supported Security Questions + description: Lists all available security questions for a user's `question` factor + operationId: listSupportedSecurityQuestions + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SecurityQuestion' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + tags: + - UserFactor + /api/v1/users/{userId}/factors/{factorId}: + get: + summary: Retrieve a Factor + description: Retrieves a factor for the specified user + operationId: getFactor + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: factorId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserFactor' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - UserFactor + delete: + summary: Delete a Factor + description: Unenrolls an existing factor for the specified user, allowing the user to enroll a new factor + operationId: deleteFactor + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: factorId + in: path + required: true + schema: + type: string + - name: removeEnrollmentRecovery + in: query + schema: + type: boolean + default: false + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - UserFactor + /api/v1/users/{userId}/factors/{factorId}/lifecycle/activate: + post: + summary: Activate a Factor + description: The `sms` and `token:software:totp` factor types require activation to complete the enrollment process + operationId: activateFactor + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: factorId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: body + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ActivateFactorRequest' + required: false + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserFactor' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - UserFactor + /api/v1/users/{userId}/factors/{factorId}/transactions/{transactionId}: + get: + summary: Retrieve a Factor Transaction Status + description: Polls factors verification transaction for status + operationId: getFactorTransactionStatus + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: factorId + in: path + required: true + schema: + type: string + - name: transactionId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/VerifyUserFactorResponse' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - UserFactor + /api/v1/users/{userId}/factors/{factorId}/verify: + post: + summary: Verify an MFA Factor + description: Verifies an OTP for a `token` or `token:hardware` factor + operationId: verifyFactor + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: factorId + in: path + required: true + schema: + type: string + - name: templateId + in: query + schema: + type: string + - name: tokenLifetimeSeconds + in: query + schema: + type: integer + format: int32 + default: 300 + x-okta-added-version: 1.3.0 + - name: X-Forwarded-For + in: header + schema: + type: string + x-okta-added-version: 1.11.0 + - name: User-Agent + in: header + schema: + type: string + x-okta-added-version: 1.11.0 + - name: Accept-Language + in: header + schema: + type: string + x-codegen-request-body-name: body + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/VerifyFactorRequest' + required: false + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/VerifyUserFactorResponse' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - UserFactor + /api/v1/users/{userId}/grants: + get: + summary: List all User Grants + description: Lists all grants for the specified user + operationId: listUserGrants + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: scopeId + in: query + schema: + type: string + - name: expand + in: query + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OAuth2ScopeConsentGrant' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + delete: + summary: Revoke all User Grants + description: Revokes all grants for a specified user + operationId: revokeUserGrants + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/grants/{grantId}: + get: + summary: Retrieve a User Grant + description: Retrieves a grant for the specified user + operationId: getUserGrant + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: grantId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/OAuth2ScopeConsentGrant' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + delete: + summary: Revoke a User Grant + description: Revokes one grant for a specified user + operationId: revokeUserGrant + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: grantId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/groups: + get: + summary: List all Groups + description: Lists all groups of which the user is a member + operationId: listUserGroups + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Group' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + /api/v1/users/{userId}/idps: + get: + summary: List all Identity Providers + description: Lists the IdPs associated with the user + operationId: listUserIdentityProviders + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/IdentityProvider' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + /api/v1/users/{userId}/lifecycle/activate: + post: + summary: Activate a User + description: Activates a user. This operation can only be performed on users with a `STAGED` status. Activation of a user is an asynchronous operation. The user will have the `transitioningToStatus` property with a value of `ACTIVE` during activation to indicate that the user hasn't completed the asynchronous operation. The user will have a status of `ACTIVE` when the activation process is complete. + operationId: activateUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: sendEmail + in: query + description: Sends an activation email to the user if true + required: true + schema: + type: boolean + default: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserActivationToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/deactivate: + post: + summary: Deactivate a User + description: 'Deactivates a user. This operation can only be performed on users that do not have a `DEPROVISIONED` status. While the asynchronous operation (triggered by HTTP header `Prefer: respond-async`) is proceeding the user''s `transitioningToStatus` property is `DEPROVISIONED`. The user''s status is `DEPROVISIONED` when the deactivation process is complete.' + operationId: deactivateUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: sendEmail + in: query + schema: + type: boolean + default: false + x-okta-added-version: 1.5.0 + responses: + '200': + description: OK + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/expire_password: + post: + summary: Expire Password + description: This operation transitions the user to the status of `PASSWORD_EXPIRED` so that the user is required to change their password at their next login + operationId: expirePassword + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/expire_password_with_temp_password: + post: + summary: Expire Password and Set Temporary Password + description: This operation transitions the user to the status of `PASSWORD_EXPIRED` so that the user is required to change their password at their next login, and also sets the user's password to a temporary password returned in the response + operationId: expirePasswordAndGetTemporaryPassword + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/TempPassword' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/reactivate: + post: + summary: Reactivate a User + description: Reactivates a user. This operation can only be performed on users with a `PROVISIONED` status. This operation restarts the activation workflow if for some reason the user activation was not completed when using the activationToken from [Activate User](#activate-user). + operationId: reactivateUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: sendEmail + in: query + description: Sends an activation email to the user if true + schema: + type: boolean + default: false + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserActivationToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/reset_factors: + post: + summary: Reset all Factors + description: This operation resets all factors for the specified user. All MFA factor enrollments returned to the unenrolled state. The user's status remains ACTIVE. This link is present only if the user is currently enrolled in one or more MFA factors. + operationId: resetFactors + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/reset_password: + post: + summary: Reset Password + description: Generates a one-time token (OTT) that can be used to reset a user's password. The OTT link can be automatically emailed to the user or returned to the API caller and distributed using a custom flow. + operationId: resetPassword + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: sendEmail + in: query + required: true + schema: + type: boolean + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ResetPasswordToken' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/suspend: + post: + summary: Suspend a User + description: Suspends a user. This operation can only be performed on users with an `ACTIVE` status. The user will have a status of `SUSPENDED` when the process is complete. + operationId: suspendUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/unlock: + post: + summary: Unlock a User + description: Unlocks a user with a `LOCKED_OUT` status and returns them to `ACTIVE` status. Users will be able to login with their current password. + operationId: unlockUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/lifecycle/unsuspend: + post: + summary: Unsuspend a User + description: Unsuspends a user and returns them to the `ACTIVE` state. This operation can only be performed on users that have a `SUSPENDED` status. + operationId: unsuspendUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/linkedObjects/{relationshipName}: + get: + summary: List all Linked Objects + description: Lists all linked objects for a user, relationshipName can be a primary or associated relationship name + operationId: listLinkedObjectsForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: relationshipName + in: path + required: true + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: -1 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ResponseLinks' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - User + delete: + summary: Delete a Linked Object + description: Deletes linked objects for a user, relationshipName can be ONLY a primary relationship name + operationId: deleteLinkedObjectForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: relationshipName + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/roles: + get: + summary: List all Roles assigned to a User + description: Lists all roles assigned to a user identified by `userId` + operationId: listAssignedRolesForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: expand + in: query + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Role' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - RoleAssignment + post: + summary: Assign a Role to a User + description: Assigns a role to a user identified by `userId` + operationId: assignRoleToUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: disableNotifications + description: Setting this to `true` grants the user third-party admin status + in: query + schema: + type: boolean + x-codegen-request-body-name: assignRoleRequest + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AssignRoleRequest' + required: true + responses: + '201': + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/Role' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleAssignment + /api/v1/users/{userId}/roles/{roleId}: + get: + summary: Retrieve a Role assigned to a User + description: Retrieves a role identified by `roleId` assigned to a user identified by `userId` + operationId: getUserAssignedRole + parameters: + - in: path + name: userId + required: true + schema: + type: string + - in: path + name: roleId + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Role' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - RoleAssignment + delete: + summary: Unassign a Role from a User + description: Unassigns a role identified by `roleId` from a user identified by `userId` + operationId: unassignRoleFromUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleAssignment + /api/v1/users/{userId}/roles/{roleId}/targets/catalog/apps: + get: + summary: List all Application Targets for Application Administrator Role + description: Lists all App targets for an `APP_ADMIN` Role assigned to a User. This methods return list may include full Applications or Instances. The response for an instance will have an `ID` value, while Application will not have an ID. + operationId: listApplicationTargetsForApplicationAdministratorRoleForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/CatalogApplication' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - RoleTarget + put: + summary: Assign all Apps as Target to Role + description: Assigns all Apps as Target to Role + operationId: assignAllAppsAsTargetToRoleForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + /api/v1/users/{userId}/roles/{roleId}/targets/catalog/apps/{appName}: + put: + summary: Assign an Application Target to Administrator Role + description: Assigns an application target to administrator role + operationId: assignAppTargetToAdminRoleForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: appName + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + delete: + summary: Unassign an Application Target from an Application Administrator Role + description: Unassigns an application target from application administrator role + operationId: unassignAppTargetFromAppAdminRoleForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: appName + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + /api/v1/users/{userId}/roles/{roleId}/targets/catalog/apps/{appName}/{applicationId}: + put: + summary: Assign an Application Instance Target to an Application Administrator Role + description: Assigns anapplication instance target to appplication administrator role + operationId: assignAppInstanceTargetToAppAdminRoleForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: appName + in: path + required: true + schema: + type: string + - name: applicationId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + delete: + summary: Unassign an Application Instance Target from an Application Administrator Role + description: Unassigns an application instance target from an application administrator role + operationId: unassignAppInstanceTargetFromAdminRoleForUser + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: appName + in: path + required: true + schema: + type: string + - name: applicationId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + /api/v1/users/{userId}/roles/{roleId}/targets/groups: + get: + summary: List all Group Targets for Role + description: Lists all group targets for role + operationId: listGroupTargetsForRole + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: after + in: query + schema: + type: string + - name: limit + in: query + schema: + type: integer + format: int32 + default: 20 + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Group' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.read + tags: + - RoleTarget + /api/v1/users/{userId}/roles/{roleId}/targets/groups/{groupId}: + put: + summary: Assign a Group Target to Role + description: Assigns a Group Target to Role + operationId: assignGroupTargetToUserRole + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: groupId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + delete: + summary: Unassign a Group Target from Role + description: Unassigns a Group Target from Role + operationId: unassignGroupTargetFromUserAdminRole + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: roleId + in: path + required: true + schema: + type: string + - name: groupId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.roles.manage + tags: + - RoleTarget + /api/v1/users/{userId}/sessions: + delete: + summary: Revoke all User Sessions + description: Revokes all active identity provider sessions of the user. This forces the user to authenticate on the next operation. Optionally revokes OpenID Connect and OAuth refresh and access tokens issued to the user. + operationId: revokeUserSessions + parameters: + - name: userId + in: path + required: true + schema: + type: string + - name: oauthTokens + in: query + description: Revoke issued OpenID Connect and OAuth refresh and access tokens + schema: + type: boolean + default: false + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - User + /api/v1/users/{userId}/subscriptions: + get: + summary: List all Subscriptions + description: Lists all subscriptions of a user. Only lists subscriptions for current user. An AccessDeniedException message is sent if requests are made from other users. + operationId: listUserSubscriptions + parameters: + - in: path + name: userId + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + items: + $ref: '#/components/schemas/Subscription' + type: array + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - Subscription + /api/v1/users/{userId}/subscriptions/{notificationType}: + get: + summary: List all Subscriptions by type + description: Lists all the subscriptions of a User with a specific notification type. Only gets subscriptions for current user. An AccessDeniedException message is sent if requests are made from other users. + operationId: listUserSubscriptionsByNotificationType + parameters: + - in: path + name: userId + required: true + schema: + type: string + - in: path + name: notificationType + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/Subscription' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.read + tags: + - Subscription + /api/v1/users/{userId}/subscriptions/{notificationType}/subscribe: + post: + summary: Subscribe to a specific notification type + description: Subscribes a User to a specific notification type. Only the current User can subscribe to a specific notification type. An AccessDeniedException message is sent if requests are made from other users. + operationId: subscribeUserSubscriptionByNotificationType + parameters: + - in: path + name: userId + required: true + schema: + type: string + - in: path + name: notificationType + required: true + schema: + type: string + responses: + '200': + description: Success + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - Subscription + /api/v1/users/{userId}/subscriptions/{notificationType}/unsubscribe: + post: + summary: Unsubscribe from a specific notification type + description: Unsubscribes a User from a specific notification type. Only the current User can unsubscribe from a specific notification type. An AccessDeniedException message is sent if requests are made from other users. + operationId: unsubscribeUserSubscriptionByNotificationType + parameters: + - in: path + name: userId + required: true + schema: + type: string + - in: path + name: notificationType + required: true + schema: + type: string + responses: + '200': + description: Success + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + description: Not Found + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.users.manage + tags: + - Subscription + /api/v1/zones: + get: + summary: List all Network Zones + description: Lists all network zones with pagination. A subset of zones can be returned that match a supported filter expression or query. + operationId: listNetworkZones + parameters: + - name: after + in: query + description: Specifies the pagination cursor for the next page of network zones + schema: + type: string + - name: limit + in: query + description: Specifies the number of results for a page + schema: + type: integer + format: int32 + default: -1 + - name: filter + in: query + description: Filters zones by usage or id expression + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/NetworkZone' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.networkZones.read + tags: + - NetworkZone + post: + summary: Create a Network Zone + description: Creates a new network zone to your Okta organization + operationId: createNetworkZone + x-codegen-request-body-name: zone + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkZone' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkZone' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.networkZones.manage + tags: + - NetworkZone + /api/v1/zones/{zoneId}: + get: + summary: Retrieve a Network Zone + description: Retrieves a network zone from your Okta organization by `id` + operationId: getNetworkZone + parameters: + - name: zoneId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkZone' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.networkZones.read + tags: + - NetworkZone + put: + summary: Replace a Network Zone + description: Replaces a network zone + operationId: replaceNetworkZone + parameters: + - name: zoneId + in: path + required: true + schema: + type: string + x-codegen-request-body-name: zone + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkZone' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkZone' + '400': + $ref: '#/components/responses/ErrorApiValidationFailed400' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.networkZones.manage + tags: + - NetworkZone + delete: + summary: Delete a Network Zone + description: Deletes network zone + operationId: deleteNetworkZone + parameters: + - name: zoneId + in: path + required: true + schema: + type: string + responses: + '204': + description: No Content + content: {} + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.networkZones.manage + tags: + - NetworkZone + /api/v1/zones/{zoneId}/lifecycle/activate: + post: + summary: Activate a Network Zone + description: Activates a network zone + operationId: activateNetworkZone + parameters: + - name: zoneId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkZone' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.networkZones.manage + tags: + - NetworkZone + /api/v1/zones/{zoneId}/lifecycle/deactivate: + post: + summary: Deactivate a Network Zone + description: Deactivates a network zone + operationId: deactivateNetworkZone + parameters: + - name: zoneId + in: path + required: true + schema: + type: string + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/NetworkZone' + '403': + $ref: '#/components/responses/ErrorAccessDenied403' + '404': + $ref: '#/components/responses/ErrorResourceNotFound404' + '429': + $ref: '#/components/responses/ErrorTooManyRequests429' + security: + - apiToken: [] + - oauth2: + - okta.networkZones.manage + tags: + - NetworkZone +components: + securitySchemes: + apiToken: + description: 'Pass the API token as the Authorization header value prefixed with SSWS: `Authorization: SSWS {API Token}`' + name: Authorization + type: apiKey + in: header + oauth2: + type: oauth2 + description: 'Pass the access_token as the value of the Authorization header: `Authorization: Bearer {access_token}`' + flows: + authorizationCode: + authorizationUrl: /oauth2/v1/authorize + tokenUrl: /oauth2/v1/token + scopes: + okta.agentPools.manage: Allows the app to create and manage agent pools in your Okta organization. + okta.agentPools.read: Allows the app to read agent pools in your Okta organization. + okta.apiToken.manage: Allows the app to manage API Tokens in your Okta organization. + okta.apiToken.read: Allows the app to read API Tokens in your Okta organization. + okta.apps.manage: Allows the app to create and manage Apps in your Okta organization. + okta.apps.read: Allows the app to read information about Apps in your Okta organization. + okta.authenticators.manage: Allows the app to manage all authenticators (e.g. enrollments, reset). + okta.authenticators.read: Allows the app to read org authenticators information. + okta.authorizationServers.manage: Allows the app to create and manage Authorization Servers in your Okta organization. + okta.authorizationServers.read: Allows the app to read information about Authorization Servers in your Okta organization. + okta.behaviors.manage: Allows the app to create and manage behavior detection rules in your Okta organization. + okta.behaviors.read: Allows the app to read behavior detection rules in your Okta organization. + okta.brands.manage: Allows the app to create and manage Brands and Themes in your Okta organization. + okta.brands.read: Allows the app to read information about Brands and Themes in your Okta organization. + okta.captchas.manage: Allows the app to create and manage CAPTCHAs in your Okta organization. + okta.captchas.read: Allows the app to read information about CAPTCHAs in your Okta organization. + okta.deviceAssurance.manage: Allows the app to manage device assurances. + okta.deviceAssurance.read: Allows the app to read device assurances. + okta.devices.manage: Allows the app to manage device status transitions and delete a device. + okta.devices.read: Allows the app to read the existing device's profile and search devices. + okta.domains.manage: Allows the app to manage custom Domains for your Okta organization. + okta.domains.read: Allows the app to read information about custom Domains for your Okta organization. + okta.eventHooks.manage: Allows the app to create and manage Event Hooks in your Okta organization. + okta.eventHooks.read: Allows the app to read information about Event Hooks in your Okta organization. + okta.groups.manage: Allows the app to manage existing groups in your Okta organization. + okta.groups.read: Allows the app to read information about groups and their members in your Okta organization. + okta.idps.manage: Allows the app to create and manage Identity Providers in your Okta organization. + okta.idps.read: Allows the app to read information about Identity Providers in your Okta organization. + okta.inlineHooks.manage: Allows the app to create and manage Inline Hooks in your Okta organization. + okta.inlineHooks.read: Allows the app to read information about Inline Hooks in your Okta organization. + okta.linkedObjects.manage: Allows the app to manage linked object definitions in your Okta organization. + okta.linkedObjects.read: Allows the app to read linked object definitions in your Okta organization. + okta.logStreams.manage: Allows the app to create and manage log streams in your Okta organization. + okta.logStreams.read: Allows the app to read information about log streams in your Okta organization. + okta.logs.read: Allows the app to read information about System Log entries in your Okta organization. + okta.orgs.manage: Allows the app to manage organization-specific details for your Okta organization. + okta.orgs.read: Allows the app to read organization-specific details about your Okta organization. + okta.policies.manage: Allows the app to manage policies in your Okta organization. + okta.policies.read: Allows the app to read information about policies in your Okta organization. + okta.principalRateLimits.manage: Allows the app to create and manage Principal Rate Limits in your Okta organization. + okta.principalRateLimits.read: Allows the app to read information about Principal Rate Limits in your Okta organization. + okta.profileMappings.manage: Allows the app to manage user profile mappings in your Okta organization. + okta.profileMappings.read: Allows the app to read user profile mappings in your Okta organization. + okta.pushProviders.manage: Allows the app to create and manage push notification providers such as APNs and FCM. + okta.pushProviders.read: Allows the app to read push notification providers such as APNs and FCM. + okta.rateLimits.manage: Allows the app to create and manage rate limits in your Okta organization. + okta.rateLimits.read: Allows the app to read information about rate limits in your Okta organization. + okta.riskEvents.manage: Allows the app to publish risk events to your Okta organization. + okta.riskProviders.manage: Allows the app to create and manage risk provider integrations in your Okta organization. + okta.riskProviders.read: Allows the app to read all risk provider integrations in your Okta organization. + okta.roles.manage: Allows the app to manage administrative role assignments for users in your Okta organization. + okta.roles.read: Allows the app to read administrative role assignments for users in your Okta organization. + okta.schemas.manage: Allows the app to create and manage Schemas in your Okta organization. + okta.schemas.read: Allows the app to read information about Schemas in your Okta organization. + okta.sessions.manage: Allows the app to manage all sessions in your Okta organization. + okta.sessions.read: Allows the app to read all sessions in your Okta organization. + okta.templates.manage: Allows the app to manage all custom templates in your Okta organization. + okta.templates.read: Allows the app to read all custom templates in your Okta organization. + okta.trustedOrigins.manage: Allows the app to manage all Trusted Origins in your Okta organization. + okta.trustedOrigins.read: Allows the app to read all Trusted Origins in your Okta organization. + okta.userTypes.manage: Allows the app to manage user types in your Okta organization. + okta.userTypes.read: Allows the app to read user types in your Okta organization. + okta.users.manage: Allows the app to create new users and to manage all users' profile and credentials information. + okta.users.read: Allows the app to read the existing users' profiles and credentials. + examples: + ApiTokenListMetadataResponse: + value: + - name: My API Token + userId: 00uabcdefg1234567890 + tokenWindow: P30D + id: 00Tabcdefg1234567890 + clientName: Okta API + expiresAt: 2021-12-11T20:38:10.000Z + created: 2021-11-09T20:38:10.000Z + lastUpdated: 2021-11-11T20:38:10.000Z + _links: + self: + href: https://{yourOktaDomain}/api/v1/api-tokens/00Tabcdefg1234567890 + hints: + allow: + - GET + - DELETE + user: + href: https://{yourOktaDomain}/api/v1/users/00uabcdefg1234567890 + hints: + allow: + - GET + - name: Another API Token + userId: 00uabcdefg1234567890 + tokenWindow: PT5M + id: 00T1234567890abcdefg + clientName: Okta API + expiresAt: 2021-11-11T20:43:10.000Z + created: 2021-11-09T20:38:10.000Z + lastUpdated: 2021-11-11T20:38:10.000Z + _links: + self: + href: https://{yourOktaDomain}/api/v1/api-tokens/00T1234567890abcdefg + hints: + allow: + - GET + - DELETE + user: + href: https://{yourOktaDomain}/api/v1/users/00uabcdefg1234567890 + hints: + allow: + - GET + ApiTokenMetadataResponse: + value: + name: My API Token + userId: 00uXXXXXXXXXXXXXXXXX + tokenWindow: P30D + id: 00Tabcdefg1234567890 + clientName: Okta API + expiresAt: 2021-12-11T20:38:10.000Z + created: 2021-11-09T20:38:10.000Z + lastUpdated: 2021-11-11T20:38:10.000Z + _links: + self: + href: https://{yourOktaDomain}/api/v1/api-tokens/00Tabcdefg1234567890 + hints: + allow: + - GET + - DELETE + user: + href: https://{yourOktaDomain}/api/v1/users/00uXXXXXXXXXXXXXXXXX + hints: + allow: + - GET + AppUserSchemaAddRequest: + value: + definitions: + custom: + id: '#custom' + type: object + properties: + twitterUserName: + title: Twitter username + description: User's username for twitter.com + type: string + required: false + minLength: 1 + maxLength: 20 + required: [] + AppUserSchemaResponse: + value: + id: https://{yourOktaDomain}/meta/schemas/apps/0oa25gejWwdXNnFH90g4/default + $schema: http://json-schema.org/draft-04/schema# + name: Example App + title: Example App User + lastUpdated: '2017-07-18T23:18:43.000Z' + created: '2017-07-18T22:35:30.000Z' + definitions: + base: + id: '#base' + type: object + properties: + userName: + title: Username + type: string + required: true + scope: NONE + maxLength: 100 + required: + - userName + custom: + id: '#custom' + type: object + properties: + twitterUserName: + title: Twitter username + description: User's username for twitter.com + type: string + scope: NONE + minLength: 1 + maxLength: 20 + required: [] + type: object + properties: + profile: + allOf: + - $ref: '#/definitions/base' + - $ref: '#/definitions/custom' + AuthenticatorRequestDuo: + value: + key: duo + name: Duo Security + provider: + type: DUO + configuration: + userNameTemplate: + template: oktaId + integrationKey: testIntegrationKey + secretKey: testSecretKey + host: https://api-xxxxxxxx.duosecurity.com + AuthenticatorResponseDuo: + value: + type: app + id: aut9gnvcjUHIWb37J0g4 + key: duo + status: ACTIVE + name: Duo Security + created: '2022-07-15T21:14:02.000Z' + lastUpdated: '2022-07-15T21:14:02.000Z' + settings: {} + provider: + type: DUO + configuration: + host: https://api-xxxxxxxx.duosecurity.com + userNameTemplate: + template: oktaId + _links: + self: + href: https://{yourOktaDomain}/api/v1/authenticators/aut5gnvcjUHIWb25J0g4 + hints: + allow: + - GET + - PUT + deactivate: + href: https://{yourOktaDomain}/api/v1/authenticators/aut5gnvcjUHIWb25J0g4/lifecycle/deactivate + hints: + allow: + - POST + methods: + href: https://{yourOktaDomain}/api/v1/authenticators/aut5gnvcjUHIWb25J0g4/methods + hints: + allow: + - GET + AuthenticatorResponseEmail: &ref_0 + value: + type: email + id: aut1nbsPHh7jNjjyP0g4 + key: okta_email + status: ACTIVE + name: Email + created: '2020-07-26T21:05:23.000Z' + lastUpdated: '2020-07-28T21:45:52.000Z' + settings: + allowedFor: any + tokenLifetimeInMinutes: 5 + _links: + self: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbsPHh7jNjjyP0g4 + hints: + allow: + - GET + - PUT + methods: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbsPHh7jNjjyP0g4/methods + hints: + allow: + - GET + deactivate: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbsPHh7jNjjyP0g4/lifecycle/deactivate + hints: + allow: + - POST + AuthenticatorResponsePassword: &ref_1 + value: + type: password + id: aut1nbtrJKKA9m45a0g4 + key: okta_password + status: ACTIVE + name: Password + created: '2020-07-26T21:05:23.000Z' + lastUpdated: '2020-07-26T21:05:23.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbtrJKKA9m45a0g4 + hints: + allow: + - GET + - PUT + methods: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbtrJKKA9m45a0g4/methods + hints: + allow: + - GET + AuthenticatorResponsePhone: &ref_2 + value: + type: phone + id: aut1nbuyD8m1ckAYc0g4 + key: phone_number + status: INACTIVE + name: Phone + created: '2020-07-26T21:05:23.000Z' + lastUpdated: '2020-07-29T00:21:29.000Z' + settings: + allowedFor: none + _links: + self: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbuyD8m1ckAYc0g4 + hints: + allow: + - GET + - PUT + methods: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbuyD8m1ckAYc0g4/methods + hints: + allow: + - GET + activate: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbuyD8m1ckAYc0g4/lifecycle/activate + hints: + allow: + - POST + AuthenticatorResponseSecurityQuestion: + value: + type: security_question + id: aut1nbvIgEenhwE6c0g4 + key: security_question + status: ACTIVE + name: Security Question + created: '2020-07-26T21:05:23.000Z' + lastUpdated: '2020-07-26T21:05:23.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbvIgEenhwE6c0g4 + hints: + allow: + - GET + methods: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbvIgEenhwE6c0g4/methods + hints: + allow: + - GET + deactivate: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nbvIgEenhwE6c0g4/lifecycle/deactivate + hints: + allow: + - POST + AuthenticatorResponseWebAuthn: &ref_3 + value: + type: security_key + id: aut1nd8PQhGcQtSxB0g4 + key: webauthn + status: ACTIVE + name: Security Key or Biometric + created: '2020-07-26T21:16:37.000Z' + lastUpdated: '2020-07-27T18:59:30.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nd8PQhGcQtSxB0g4 + hints: + allow: + - GET + - PUT + methods: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nd8PQhGcQtSxB0g4/methods + hints: + allow: + - GET + deactivate: + href: https://{yourOktaDomain}/api/v1/authenticators/aut1nd8PQhGcQtSxB0g4/lifecycle/deactivate + hints: + allow: + - POST + AuthenticatorsResponse: + value: + - *ref_0 + - *ref_1 + - *ref_2 + - *ref_3 + BehaviorRuleRequest: + value: + name: My Behavior Rule + type: VELOCITY + BehaviorRuleResponse: + value: + id: abcd1234 + name: My Behavior Rule + type: VELOCITY + settings: + velocityKph: 805 + status: ACTIVE + created: 2021-11-09T20:38:10.000Z + lastUpdated: 2021-11-11T20:38:10.000Z + _link: + self: + href: https://your-subdomain.okta.com/api/v1/behaviors/abcd1234 + hints: + allow: + - GET + - POST + - PUT + - DELETE + CAPTCHAInstanceRequestHCaptcha: + value: + name: myHCaptcha + secretKey: xxxxxxxxxxx + siteKey: xxxxxxxxxxx + type: HCAPTCHA + CAPTCHAInstanceRequestReCaptcha: + value: + name: myReCaptcha + secretKey: xxxxxxxxxxx + siteKey: yyyyyyyyyyyyyyy + type: RECAPTCHA_V2 + CAPTCHAInstanceResponseHCaptcha: + value: + id: abcd1234 + name: myHCaptcha + siteKey: xxxxxxxxxxx + type: HCAPTCHA + _links: + self: + href: https://your-subdomain.okta.com/api/v1/captchas/abcd1234 + hints: + allow: + - GET + - POST + - PUT + - DELETE + CAPTCHAInstanceResponseReCaptcha: + value: + id: abcd4567 + name: myReCaptcha + siteKey: yyyyyyyyyyyyyyy + type: RECAPTCHA_V2 + _links: + self: + href: https://your-subdomain.okta.com/api/v1/captchas/abcd4567 + hints: + allow: + - GET + - POST + - PUT + - DELETE + CreateBrandDomainRequest: + value: + domainId: OcD11vyscTlIkpC7i0g4 + CreateBrandRequest: + value: + name: My Awesome Brand + CreateBrandResponse: + value: + id: bnd114iNkrcN6aR680g5 + removePoweredByOkta: false + customPrivacyPolicyUrl: null + name: My Awesome Brand + isDefault: false + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g5 + hints: + allow: + - GET + - PUT + - DELETE + themes: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g5/themes + hints: + allow: + - GET + CreateUpdateEmailCustomizationRequest: + value: + language: fr + subject: Bienvenue dans ${org.name}! + body:

    Bonjour ${user.profile.firstName}. Activer le compte

    + isDefault: false + CreateUpdateEmailCustomizationResponse: + value: + language: fr + subject: Bienvenue dans ${org.name}! + body:

    Bonjour ${user.profile.firstName}. Activer le compte

    + isDefault: false + id: oel11u6DqUiMbQkpl0g4 + created: 2021-11-09T20:38:10.000Z + lastUpdated: 2021-11-11T20:38:10.000Z + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations/oel11u6DqUiMbQkpl0g4 + hints: + allow: + - GET + - PUT + - DELETE + template: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + preview: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations/oel11u6DqUiMbQkpl0g4/preview + hints: + allow: + - GET + test: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/test + hints: + allow: + - POST + DeviceAssuranceAndroidRequest: + value: + name: Device Assurance Android + osVersion: + minimum: 12.4.5 + diskEncryptionType: + include: + - USER + - FULL + jailbreak: false + platform: ANDROID + screenLockType: + include: + - BIOMETRIC + secureHardwarePresent: true + DeviceAssuranceIosRequest: + value: + name: Device Assurance IOS + osVersion: + minimum: 12.4.5 + jailbreak: false + platform: IOS + screenLockType: + include: + - BIOMETRIC + DeviceAssuranceMacOSRequest: + value: + name: Device Assurance macOS + osVersion: + minimum: 12.4.5 + diskEncryptionType: + include: + - ALL_INTERNAL_VOLUMES + platform: MACOS + screenLockType: + include: + - PASSCODE + - BIOMETRIC + secureHardwarePresent: true + DeviceAssuranceResponse: + value: + id: dae3m8o4rWhwReDeM1c5 + name: Device Assurance Example + lastUpdate: 2022-01-01T00:00:00.000Z + createdUpdate: 2022-01-01T00:00:00.000Z + lastUpdatedBy: 00u217pyf72CdUrBt1c5 + createdBy: 00u217pyf72CdUrBt1c5 + osVersion: + minimum: 12.4.5.9 + diskEncryptionType: + include: + - ALL_INTERNAL_VOLUMES + platform: WINDOWS + screenLockType: + include: + - PASSCODE + - BIOMETRIC + secureHardwarePresent: true + _links: + self: + href: https://your-subdomain.okta.com/api/v1/device-assurances/dae3m8o4rWhwReDeM1c5 + hints: + allow: + - DELETE + - GET + - PUT + DeviceAssuranceWindowsRequest: + value: + name: Device Assurance Windows + osVersion: + minimum: 12.4.5.9 + diskEncryptionType: + include: + - ALL_INTERNAL_VOLUMES + platform: WINDOWS + screenLockType: + include: + - PASSCODE + - BIOMETRIC + secureHardwarePresent: true + DeviceResponse: + value: + id: guo8jx5vVoxfvJeLb0w4 + status: ACTIVE + created: '2020-11-03T21:47:01.000Z' + lastUpdated: '2020-11-03T23:46:27.000Z' + profile: + displayName: DESKTOP-EHAD3IE + platform: WINDOWS + manufacturer: International Corp + model: VMware7,1 + osVersion: 10.0.18362 + serialNumber: 56 4d 4f 95 74 c5 d3 e7-fc 3a 57 9c c2 f8 5d ce + udid: 954F4D56-C574-E7D3-FC3A-579CC2F85DCE + sid: S-1-5-21-3992267483-1860856704-2413701314-500 + registered: true + secureHardwarePresent: false + resourceId: guo8jx5vVoxfvJeLb0w4 + resourceDisplayName: + value: DESKTOP-EHAD3IE + sensitive: false + resourceType: UDDevice + resourceAlternateId: null + _links: + suspend: + href: https://{yourOktaDomain}/api/v1/devices/guo8jx5vVoxfvJeLb0w4/lifecycle/suspend + hints: + allow: + - POST + self: + href: https://{yourOktaDomain}/api/v1/devices/guo8jx5vVoxfvJeLb0w4 + hints: + allow: + - GET + - PATCH + - PUT + users: + href: https://{yourOktaDomain}/api/v1/devices/guo8jx5vVoxfvJeLb0w4/users + hints: + allow: + - GET + deactivate: + href: https://{yourOktaDomain}/api/v1/devices/guo8jx5vVoxfvJeLb0w4/lifecycle/deactivate + hints: + allow: + - POST + EmailCustomizationResponse: + value: + language: en + isDefault: true + subject: Welcome to ${org.name}! + body:

    Hello, ${user.profile.firstName}. Click here to activate your account. + id: oel11u6DqUiMbQkpl0g4 + created: 2021-11-09T20:38:10.000Z + lastUpdated: 2021-11-11T20:38:10.000Z + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations/oel11u6DqUiMbQkpl0g4 + hints: + allow: + - GET + - PUT + - DELETE + template: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + preview: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations/oel11u6DqUiMbQkpl0g4/preview + hints: + allow: + - GET + test: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/test + hints: + allow: + - POST + EmailSettingsResponse: + value: + recipients: ALL_USERS + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/settings + hints: + allow: + - GET + - PUT + template: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + EmailTemplateDefaultContentResponse: + value: + subject: Welcome to ${org.name}! + body:

    Hello, ${user.profile.firstName}. Click here to activate your account. + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/default-content + hints: + allow: + - GET + template: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + preview: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/default-content/preview + hints: + allow: + - GET + ErrorAccessDenied: + value: + errorCode: E0000006 + errorSummary: You do not have permission to perform the requested action + errorLink: E0000006 + errorId: sampleNUSD_8fdkFd8fs8SDBK + errorCauses: [] + ErrorApiValidationFailed: + value: + errorCode: E0000001 + errorSummary: 'Api validation failed: {0}' + errorLink: E0000001 + errorId: sampleiCF-8D5rLW6myqiPItW + errorCauses: [] + ErrorCAPTCHALimitOfOne: + value: + errorCode: E0000165 + errorSummary: CAPTCHA count limit reached. At most one CAPTCHA instance is allowed per Org. + errorLink: E0000165 + errorId: oaejrB1fWL1S7mc-2KcG-SOtw + errorCauses: [] + ErrorCAPTCHAOrgWideSetting: + value: + errorCode: E0000149 + errorSummary: Current CAPTCHA is associated with org-wide settings, cannot be removed. + errorLink: E0000149 + errorId: samplezsusshPdiTWiITwqBt8 + errorCauses: [] + ErrorCreateUserWithExpiredPasswordWithNullPassword: + value: + errorCode: E0000124 + errorSummary: Could not create user. To create a user and expire their password immediately, a password must be specified + errorLink: E0000124 + errorId: oaeXxuZgXBySvqi1FvtkwoYCA + errorCauses: + - errorSummary: Could not create user. To create a user and expire their password immediately, a password must be specified + ErrorCreateUserWithExpiredPasswordWithoutActivation: + value: + errorCode: E0000125 + errorSummary: Could not create user. To create a user and expire their password immediately, "activate" must be true + errorLink: E0000125 + errorId: oaeDd77L9R-TJaD7j_rXsQ31w + errorCauses: + - errorSummary: Could not create user. To create a user and expire their password immediately, "activate" must be true + ErrorCreateUserWithTooManyManyGroupsResponse: + value: + errorCode: E0000093 + errorSummary: Target count limit exceeded + errorLink: E0000093 + errorId: oaePVSLIYnIQsC0B-ptBIllVA + errorCauses: + - errorSummary: The number of group targets is too large. + ErrorDeleteBrandAssociatedWithDomain: + value: + errorCode: E0000201 + errorSummary: A brand associated with a domain cannot be deleted + errorLink: E0000201 + errorId: oaeAdRqprFuTyKokyYPbURJkA + errorCauses: [] + ErrorDeleteDefaultBrand: + value: + errorCode: E0000200 + errorSummary: A default brand cannot be deleted + errorLink: E0000200 + errorId: oaeAdRqprFuTyKokyYPbURJkA + errorCauses: [] + ErrorDeviceAssuranceInUse: + value: + errorSummary: Device assurance is in use and cannot be deleted. + errorId: oaenwA1ra80S9W-pvbh4m6haA + errorCauses: [] + ErrorEmailCustomizationCannotClearDefault: + value: + errorCode: E0000185 + errorSummary: The isDefault parameter of the default email template customization can't be set to false. + errorLink: E0000185 + errorId: oaejrB1fWL1S7mc-2KcG-SOtw + errorCauses: [] + ErrorEmailCustomizationCannotDeleteDefault: + value: + errorCode: E0000184 + errorSummary: A default email template customization can't be deleted. + errorLink: E0000184 + errorId: oaeAdRqprFuTyKokyYPbURJkA + errorCauses: [] + ErrorEmailCustomizationDefaultAlreadyExists: + value: + errorCode: E0000182 + errorSummary: A default email template customization already exists. + errorLink: E0000182 + errorId: oaeXYwTiMvASsC3O4HCzjFaCA + errorCauses: [] + ErrorEmailCustomizationLanguageAlreadyExists: + value: + errorCode: E0000183 + errorSummary: An email template customization for that language already exists. + errorLink: E0000183 + errorId: oaeUcGELffqRay0u1OPdnPypw + errorCauses: [] + ErrorInvalidEmailTemplateRecipients: + value: + errorCode: E0000189 + errorSummary: This template does not support the recipients value. + errorLink: E0000189 + errorId: oae8L1-UkcNTeGi5xVQ28_lww + errorCauses: [] + ErrorLinkDefaultBrand: + value: + errorCode: E0000203 + errorSummary: Failed to associate this domain with the given brandId + errorLink: E0000203 + errorId: oaeAdRqprFuTyKokyYPbURJkA + errorCauses: + - errorSummary: The default brand cannot be mapped to a domain + ErrorPushProviderUsedByCustomAppAuthenticator: + value: + errorCode: E0000187 + errorSummary: Cannot delete push provider because it is being used by a custom app authenticator. + errorLink: E0000187 + errorId: oaenwA1ra80S9W-pvbh4m6haA + errorCauses: [] + ErrorResourceNotFound: + value: + errorCode: E0000007 + errorSummary: 'Not found: {0}' + errorLink: E0000007 + errorId: sampleMlLvGUj_YD5v16vkYWY + errorCauses: [] + ErrorTooManyRequests: + value: + errorCode: E0000047 + errorSummary: You exceeded the maximum number of requests. Try again in a while. + errorLink: E0000047 + errorId: sampleQPivGUj_ND5v78vbYWW + errorCauses: [] + GetBrandResponse: + value: + id: bnd114iNkrcN6aR680g4 + removePoweredByOkta: false + customPrivacyPolicyUrl: null + name: Okta Default + isDefault: true + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g4 + hints: + allow: + - GET + - PUT + - DELETE + themes: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g4/themes + hints: + allow: + - GET + GetEmailTemplateResponse: + value: + name: UserActivation + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + settings: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/settings + hints: + allow: + - GET + - PUT + defaultContent: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/default-content + hints: + allow: + - GET + customizations: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations + hints: + allow: + - GET + - POST + - DELETE + test: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/test + hints: + allow: + - POST + GroupSchemaAddRequest: + value: + definitions: + custom: + id: '#custom' + type: object + properties: + groupContact: + title: Group administrative contact + description: Group administrative contact + type: string + required: false + minLength: 1 + maxLength: 20 + permissions: + - principal: SELF + action: READ_WRITE + required: [] + GroupSchemaResponse: + value: + $schema: http://json-schema.org/draft-04/schema# + _links: + self: + href: https://{yourOktaDomain}/api/v1/meta/schemas/group/default + method: GET + rel: self + created: '2021-01-30T00:18:24.000Z' + definitions: + base: + id: '#base' + properties: {} + required: + - name + type: object + custom: + id: '#custom' + properties: + groupContact: + description: Group administrative contact + master: + type: PROFILE_MASTER + mutability: READ_WRITE + permissions: + - action: READ_WRITE + principal: SELF + scope: NONE + title: Group administrative contact + type: string + required: [] + type: object + description: Okta group profile template + id: https://{yourOktaDomain}/meta/schemas/group/default + lastUpdated: '2021-02-25T23:05:31.000Z' + name: group + properties: + profile: + allOf: + - $ref: '#/definitions/custom' + - $ref: '#/definitions/base' + title: Okta group + type: object + LinkBrandDomain: + value: + domainId: OcD11vyscTlIkpC7i0g4 + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g4/domains/OcD11vyscTlIkpC7i0g4 + hints: + allow: + - PUT + - DELETE + brand: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g4 + hints: + allow: + - GET + - PUT + - DELETE + domain: + href: https://{yourOktaDomain}/api/v1/domains/OcD11vyscTlIkpC7i0g4 + hints: + allow: + - GET + - PUT + - DELETE + ListBrandsResponse: + value: + - id: bnd114iNkrcN6aR680g4 + name: Okta Default + isDefault: true + removePoweredByOkta: false + customPrivacyPolicyUrl: null + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g4 + hints: + allow: + - GET + - PUT + - DELETE + themes: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g4/themes + hints: + allow: + - GET + ListEmailCustomizationResponse: + value: + - language: en + isDefault: true + subject: Welcome to ${org.name}! + body:

    Hello, ${user.profile.firstName}. Click here to activate your account. + id: oel11u6DqUiMbQkpl0g4 + created: 2021-11-09T20:38:10.000Z + lastUpdated: 2021-11-11T20:38:10.000Z + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations/oel11u6DqUiMbQkpl0g4 + hints: + allow: + - GET + - PUT + - DELETE + template: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + preview: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations/oel11u6DqUiMbQkpl0g4/preview + hints: + allow: + - GET + test: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/test + hints: + allow: + - POST + ListEmailTemplateResponse: + value: + - name: UserActivation + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + settings: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/settings + hints: + allow: + - GET + - PUT + defaultContent: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/default-content + hints: + allow: + - GET + customizations: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations + hints: + allow: + - GET + - POST + - DELETE + test: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/test + hints: + allow: + - POST + ListUsersResponse: + value: + - id: 00u118oQYT4TBGuay0g4 + status: ACTIVE + created: 2022-04-04T15:56:05.000Z + activated: null + statusChanged: null + lastLogin: 2022-05-04T19:50:52.000Z + lastUpdated: 2022-05-05T18:15:44.000Z + passwordChanged: 2022-04-04T16:00:22.000Z + type: + id: oty1162QAr8hJjTaq0g4 + profile: + firstName: Alice + lastName: Smith + mobilePhone: null + secondEmail: null + login: alice.smith@example.com + email: alice.smith@example.com + credentials: + password: {} + provider: + type: OKTA + name: OKTA + _links: + self: + href: http://your-subdomain.okta.com/api/v1/users/00u118oQYT4TBGuay0g4 + LogStreamRequest: + value: + type: aws_eventbridge + name: Example AWS EventBridge + settings: + eventSourceName: your-event-source-name + accountId: '123456789012' + region: us-east-2 + LogStreamResponse: + value: + id: 0oa1orqUGCIoCGNxf0g4 + type: aws_eventbridge + name: Example AWS EventBridge + lastUpdated: '2021-10-21T16:55:30.000Z' + created: '2021-10-21T16:55:29.000Z' + status: ACTIVE + settings: + accountId: '123456789012' + eventSourceName: your-event-source-name + region: us-east-2 + _links: + self: + href: http://{yourOktaDomain}/api/v1/logStreams/0oa1orqUGCIoCGNxf0g4 + method: GET + deactivate: + href: http://{yourOktaDomain}/api/v1/logStreams/0oa1orqUGCIoCGNxf0g4/lifecycle/deactivate + method: POST + LogStreamSchemaAws: + value: &ref_4 + $schema: https://json-schema.org/draft/2020-12/schema + $id: http://{yourOktaDomain}/api/v1/meta/schemas/logStream/aws_eventbridge + title: AWS EventBridge + type: object + properties: + settings: + description: Configuration properties specific to AWS EventBridge + type: object + properties: + accountId: + title: AWS Account ID + description: Your Amazon AWS Account ID. + type: string + writeOnce: true + pattern: ^\d{12}$ + eventSourceName: + title: AWS Event Source Name + description: An alphanumeric name (no spaces) to identify this event source in AWS EventBridge. + type: string + writeOnce: true + pattern: ^[\.\-_A-Za-z0-9]{1,75}$ + region: + title: AWS Region + description: The destination AWS region for your system log events. + type: string + writeOnce: true + oneOf: + - title: US East (Ohio) + const: us-east-2 + - title: US East (N. Virginia) + const: us-east-1 + - title: US West (N. California) + const: us-west-1 + - title: US West (Oregon) + const: us-west-2 + - title: Canada (Central) + const: ca-central-1 + - title: Europe (Frankfurt) + const: eu-central-1 + - title: Europe (Ireland) + const: eu-west-1 + - title: Europe (London) + const: eu-west-2 + - title: Europe (Paris) + const: eu-west-3 + - title: Europe (Milan) + const: eu-south-1 + - title: Europe (Stockholm) + const: eu-north-1 + required: + - eventSourceName + - accountId + - region + errorMessage: + properties: + accountId: Account number must be 12 digits. + eventSourceName: Event source name can use numbers, letters, the symbols ".", "-" or "_". It must use fewer than 76 characters. + name: + title: Name + description: A name for this log stream in Okta + type: string + writeOnce: false + pattern: ^.{1,100}$ + required: + - name + - settings + errorMessage: + properties: + name: Name can't exceed 100 characters. + LogStreamSchemaList: + value: + - *ref_4 + - &ref_5 + $schema: https://json-schema.org/draft/2020-12/schema + $id: http://{yourOktaDomain}/api/v1/meta/schemas/logStream/splunk_cloud_logstreaming + title: Splunk Cloud + type: object + properties: + settings: + description: Configuration properties specific to Splunk Cloud + type: object + properties: + host: + title: Host + description: 'The domain for your Splunk Cloud instance without http or https. For example: acme.splunkcloud.com' + type: string + writeOnce: false + pattern: ^([a-z0-9]+(-[a-z0-9]+)*){1,100}\.splunkcloud(gc|fed)?\.com$ + token: + title: HEC Token + description: The token from your Splunk Cloud HTTP Event Collector (HEC). + type: string + writeOnce: false + pattern: '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}' + required: + - host + - token + errorMessage: + properties: + host: 'Host should be a domain without http or https. For example: acme.splunkcloud.com' + name: + title: Name + description: A name for this log stream in Okta + type: string + writeOnce: false + pattern: ^.{1,100}$ + required: + - name + - settings + errorMessage: + properties: + name: Name can't exceed 100 characters. + LogStreamSchemaSplunk: + value: *ref_5 + PerClientRateLimitSettingsEnforceDefault: + value: + defaultMode: ENFORCE + PerClientRateLimitSettingsEnforceDefaultWithOverrides: + value: + defaultMode: ENFORCE + useCaseModeOverrides: + OAUTH2_AUTHORIZE: PREVIEW + OIE_APP_INTENT: DISABLE + PerClientRateLimitSettingsPreviewDefaultWithOverrides: + value: + defaultMode: PREVIEW + useCaseModeOverrides: + LOGIN_PAGE: ENFORCE + PermissionResponse: + value: + label: okta.users.manage + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + role: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3 + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3/permissions/okta.users.manage + PermissionsResponse: + value: + permissions: + - label: okta.users.create + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + role: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3 + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3/permissions/okta.users.create + - label: okta.users.read + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + role: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3 + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3/permissions/okta.users.read + - label: okta.groups.read + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + role: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3 + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3/permissions/okta.groups.read + - label: okta.users.userprofile.manage + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + role: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3 + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3/permissions/okta.users.userprofile.manage + PreviewEmailCustomizationResponse: + value: + subject: Welcome to Okta! + body:

    Hello, John. Click here to activate your account. + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/customizations/oel2kk1zYJBJbeaGo0g4/preview + hints: + allow: + - GET + template: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + test: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/test + hints: + allow: + - POST + PreviewEmailTemplateDefaultContentResponse: + value: + subject: Welcome to Okta! + body:

    Hello, John. Click here to activate your account. + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/default-content/preview + hints: + allow: + - GET + template: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation + hints: + allow: + - GET + defaultContent: + href: https://{yourOktaDomain}/api/v1/brands/{brandId}/templates/email/UserActivation/test/default-content + hints: + allow: + - POST + PrincipalRateLimitEntityRequestEmptyPercentages: + value: + principalId: token1234 + principalType: SSWS_TOKEN + PrincipalRateLimitEntityRequestSSWSToken: + value: + principalId: token1234 + principalType: SSWS_TOKEN + defaultPercentage: 50 + defaultConcurrencyPercentage: 75 + PrincipalRateLimitEntityResponseSSWSToken: + value: + id: abcd1234 + orgId: org1234 + principalId: token1234 + principalType: SSWS_TOKEN + defaultPercentage: 50 + defaultConcurrencyPercentage: 75 + createdDate: '2022-05-19T20:05:32.720Z' + createdBy: user1234 + lastUpdate: '2022-05-20T21:13:07.410Z' + lastUpdatedBy: user4321 + PushProviderAPNsRequest: + value: + name: APNs Example + providerType: APNS + configuration: + keyId: KEY_ID + teamId: TEAM_ID + tokenSigningKey: '-----BEGIN PRIVATE KEY-----\nPRIVATE_KEY\n-----END PRIVATE KEY-----\n' + fileName: fileName.p8 + PushProviderAPNsResponse: + value: + id: ppctekcmngGaqeiBxB0g4 + name: APNs Example + providerType: APNS + lastUpdatedDate: 2022-01-01T00:00:00.000Z + configuration: + keyId: KEY_ID + teamId: TEAM_ID + fileName: fileName.p8 + _links: + self: + href: https://your-subdomain.okta.com/api/v1/push-providers/ppctekcmngGaqeiBxB0g4 + hints: + allow: + - DELETE + - GET + - PUT + PushProviderFCMRequest: + value: + name: FCM Example + providerType: FCM + configuration: + serviceAccountJson: + type: service_account + project_id: PROJECT_ID + private_key_id: KEY_ID + private_key: '-----BEGIN PRIVATE KEY-----\nPRIVATE_KEY\n-----END PRIVATE KEY-----\n' + client_email: SERVICE_ACCOUNT_EMAIL + client_id: CLIENT_ID + auth_uri: https://accounts.google.com/o/oauth2/auth + token_uri: https://accounts.google.com/o/oauth2/token + auth_provider_x509_cert_url: https://www.googleapis.com/oauth2/v1/certs + client_x509_cert_url: https://www.googleapis.com/robot/v1/metadata/x509/SERVICE_ACCOUNT_EMAIL + fileName: fileName.json + PushProviderFCMResponse: + value: + id: ppctekcmngGaqeiBxB0g4 + name: FCM Example + providerType: FCM + lastUpdatedDate: 2022-01-01T00:00:00.000Z + configuration: + projectId: PROJECT_ID + fileName: fileName.p8 + _links: + self: + href: https://your-subdomain.okta.com/api/v1/push-providers/ppctekcmngGaqeiBxB0g4 + hints: + allow: + - DELETE + - GET + - PUT + RateLimitAdminNotificationsDisabled: + value: + notificationsEnabled: false + RateLimitAdminNotificationsEnabled: + value: + notificationsEnabled: true + ResourceSetBindingAddMembersRequestExample: + value: + additions: + - https://{yourOktaDomain}/api/v1/groups/00guaxWZ0AOa5NFAj0g3 + - https://{yourOktaDomain}/api/v1/users/00u67DU2qNCjNZYO0g3 + ResourceSetBindingCreateRequestExample: + value: + role: cr0Yq6IJxGIr0ouum0g3 + members: + - https://{yourOktaDomain}/api/v1/groups/00guaxWZ0AOa5NFAj0g3 + ResourceSetBindingMemberResponse: + value: + id: irb1qe6PGuMc7Oh8N0g4 + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/users/00uuk41Hjga5qGfQ30g3 + ResourceSetBindingMembersResponse: + value: + members: + - id: irb1qe6PGuMc7Oh8N0g4 + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/users/00uuk41Hjga5qGfQ30g3 + - id: irb1q92TFAHzySt3x0g4 + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/groups/00guaxWZ0AOa5NFAj0g3 + _links: + binding: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings/cr0Yq6IJxGIr0ouum0g3 + next: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings/cr0Yq6IJxGIr0ouum0g3/members?after=0ouRq6IJmGIr3ouum0g3 + ResourceSetBindingResponseExample: + value: + _links: + self: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings/cr0Yq6IJxGIr0ouum0g3 + bindings: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings + resource-set: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g + ResourceSetBindingResponseWithIdExample: + value: + id: cr0Yq6IJxGIr0ouum0g3 + _links: + self: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings/cr0Yq6IJxGIr0ouum0g3 + bindings: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings + resource-set: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g + ResourceSetBindingsResponse: + value: + roles: + - id: cr0WxyzJxGIr0ouum0g4 + _links: + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0WxyzJxGIr0ouum0g4 + members: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings/cr0WxyzJxGIr0ouum0g4/members + _links: + self: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings + resource-set: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g + next: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings?after=cr0WxyzJxGIr0ouum0g4 + ResourceSetRequest: + value: + label: SF-IT-People + description: People in the IT department of San Francisco + resources: + - https://{yourOktaDomain}/api/v1/groups/00guaxWZ0AOa5NFAj0g3 + - https://{yourOktaDomain}/api/v1/groups/00gu67DU2qNCjNZYO0g3/users + - https://{yourOktaDomain}/api/v1/users + ResourceSetResourcePatchRequestExample: + value: + additions: + - https://{yourOktaDomain}/api/v1/groups/00guaxWZ0AOa5NFAj0g3 + - https://{yourOktaDomain}/api/v1/groups/00gu67DU2qNCjNZYO0g3/users + ResourceSetResourcesResponse: + value: + resources: + - id: ire106sQKoHoXXsAe0g4 + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/groups/00guaxWZ0AOa5NFAj0g3 + - id: ire106riDrTYl4qA70g4 + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/groups/00gu67DU2qNCjNZYO0g3/users + - id: irezvo4AwE2ngpMw40g3 + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + users: + href: https://{yourOktaDomain}/api/v1/users + groups: + href: https://{yourOktaDomain}/api/v1/groups + _links: + next: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/resources?after=irezvn1ZZxLSIBM2J0g3 + resource-set: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g + ResourceSetResponse: + value: + id: iamoJDFKaJxGIr0oamd9g + label: SF-IT-People + description: People in the IT department of San Francisco + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g + resources: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/resources + bindings: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings + ResourceSetsResponse: + value: + resource-sets: + - id: iamoJDFKaJxGIr0oamd9g + label: SF-IT-1 + description: First San Francisco IT Resource Set + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g + resources: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/resources + bindings: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd9g/bindings + - id: iamoJDFKaJxGIr0oamd0q + label: SF-IT-2 + description: Second San Francisco IT Resource Set + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + self: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd0q + resources: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd0q/resources + bindings: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets/iamoJDFKaJxGIr0oamd0q/bindings + _links: + next: + href: https://{yourOktaDomain}/api/v1/iam/resource-sets?after=iamoJDFKaJxGIr0oamd0q + RiskEventsRequest: + value: + - timestamp: '2021-01-20T00:00:00.001Z' + subjects: + - ip: 6.7.6.7 + riskLevel: MEDIUM + - ip: 1.1.1.1 + riskLevel: HIGH + message: Detected Attack tooling and suspicious activity + - timestamp: '2021-01-20T01:00:00.001Z' + subjects: + - ip: 6.7.6.7 + riskLevel: LOW + - ip: 2.2.2.2 + riskLevel: HIGH + RiskProviderRequest: + value: + name: Risk-Partner-X + action: log_only + clientId: 00ckjsfgjkdkjdkkljjsd + RiskProviderResponse: + value: + id: 00rp12r4skkjkjgsn + action: log_only + name: Risk-Partner-X + clientId: 00ckjsfgjkdkjdkkljjsd + created: '2021-01-05 22:18:30' + lastUpdated: '2021-01-05 21:23:10' + _links: + self: + href: https://{yourOktaDomain}/api/v1/risk/providers/00rp12r4skkjkjgsn + hints: + allow: + - GET + - PUT + RoleRequest: + value: + label: UserCreator + description: Create users + permissions: + - okta.users.create + - okta.users.read + - okta.groups.read + - okta.users.userprofile.manage + RoleResponse: + value: + id: cr0Yq6IJxGIr0ouum0g3 + label: UserCreator + description: Create users + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + permissions: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3/permissions + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3 + RolesResponse: + value: + roles: + - id: cr0Yq6IJxGIr0ouum0g3 + label: UserCreator + description: Create users + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + permissions: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3/permissions + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Yq6IJxGIr0ouum0g3 + - id: cr0Fw7HKcWIroo88m3r1 + label: GroupMembershipManager + description: Manage group membership + created: '2021-02-06T16:20:57.000Z' + lastUpdated: '2021-02-06T16:20:57.000Z' + _links: + permissions: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Fw7HKcWIroo88m3r1/permissions + self: + href: https://{yourOktaDomain}/api/v1/iam/roles/cr0Fw7HKcWIroo88m3r1 + _links: + next: + href: https://{yourOktaDomain}/api/v1/iam/roles?after=cr0Fw7HKcWIroo88m3r1 + UpdateBrandRequest: + value: + customPrivacyPolicyUrl: https://www.someHost.com/privacy-policy + agreeToCustomPrivacyPolicy: true + removePoweredByOkta: true + name: New Name For Brand + UpdateBrandResponse: + value: + id: bnd114iNkrcN6aR680g4 + removePoweredByOkta: true + agreeToCustomPrivacyPolicy: true + name: New Name For Brand + isDefault: true + customPrivacyPolicyUrl: https://www.someHost.com/privacy-policy + _links: + self: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g4 + hints: + allow: + - GET + - PUT + - DELETE + themes: + href: https://{yourOktaDomain}/api/v1/brands/bnd114iNkrcN6aR680g4/themes + hints: + allow: + - GET + UserSchemaAddRequest: + value: + definitions: + custom: + id: '#custom' + type: object + properties: + twitterUserName: + title: Twitter username + description: Twitter Username + type: string + required: false + minLength: 1 + maxLength: 20 + permissions: + - principal: SELF + action: READ_WRITE + required: [] + UserSchemaResponse: + value: + id: https://{yourOktaDomain}/meta/schemas/user/default + $schema: http://json-schema.org/draft-04/schema# + name: user + title: Default Okta User + lastUpdated: '2015-09-05T10:40:45.000Z' + created: '2015-02-02T10:27:36.000Z' + definitions: + base: + id: '#base' + type: object + properties: + login: + title: Username + type: string + required: true + minLength: 5 + maxLength: 100 + permissions: + - principal: SELF + action: READ_WRITE + firstName: + title: First name + type: string + required: true + minLength: 1 + maxLength: 50 + permissions: + - principal: SELF + action: READ_WRITE + lastName: + title: Last name + type: string + required: true + minLength: 1 + maxLength: 50 + permissions: + - principal: SELF + action: READ_WRITE + email: + title: Primary email + type: string + required: true + format: email + permissions: + - principal: SELF + action: READ_WRITE + required: + - login + - firstName + - lastName + - email + custom: + id: '#custom' + type: object + properties: + twitterUserName: + title: Twitter username + description: User's username for twitter.com + type: string + required: false + minLength: 1 + maxLength: 20 + permissions: + - principal: SELF + action: READ_WRITE + required: [] + type: object + properties: + profile: + allOf: + - $ref: '#/definitions/base' + - $ref: '#/definitions/custom' + WellKnownOrgMetadataResponseClassic: + value: + id: 00o5rb5mt2H3d1TJd0h7 + _links: + organization: + href: https://{{yourOktaDomain}} + pipeline: v1 + settings: + analyticsCollectionEnabled: false + bugReportingEnabled: true + omEnabled: true + WellKnownOrgMetadataResponseCustomUrlOie: + value: + id: 00o47wwoytgsDqEtz0g7 + _links: + organization: + href: https://{{yourSubdomain}}.okta.com + alternate: + href: https://{{yourCustomDomain}} + pipeline: idx + settings: + analyticsCollectionEnabled: false + bugReportingEnabled: true + omEnabled: false + parameters: + pathApiTokenId: + name: apiTokenId + in: path + schema: + type: string + example: 00Tabcdefg1234567890 + required: true + description: id of the API Token + pathBehaviorId: + name: behaviorId + in: path + schema: + type: string + example: abcd1234 + required: true + description: id of the Behavior Detection Rule + pathBrandId: + name: brandId + in: path + required: true + schema: + type: string + description: The ID of the brand. + pathCaptchaId: + name: captchaId + in: path + schema: + type: string + example: abcd1234 + required: true + description: id of the CAPTCHA + pathCustomizationId: + name: customizationId + in: path + required: true + schema: + type: string + description: The ID of the email customization. + pathDeviceAssuranceId: + in: path + name: deviceAssuranceId + required: true + description: Id of the Device Assurance Policy + schema: + type: string + pathDeviceId: + name: deviceId + in: path + schema: + type: string + example: guo4a5u7JHHhjXrMK0g4 + required: true + description: '`id` of the device' + pathDomainId: + name: domainId + in: path + required: true + schema: + type: string + description: The ID of the domain. + pathEmailDomainId: + name: emailDomainId + in: path + required: true + schema: + type: string + description: The ID of the email domain. + pathLogStreamId: + name: logStreamId + in: path + schema: + type: string + example: abcd1234 + required: true + description: id of the log stream + pathMemberId: + name: memberId + in: path + schema: + type: string + example: irb1qe6PGuMc7Oh8N0g4 + required: true + description: '`id` of a member' + pathPermissionType: + name: permissionType + in: path + schema: + type: string + example: okta.users.manage + required: true + description: An okta permission type + pathPoolId: + name: poolId + in: path + description: Id of the agent pool for which the settings will apply + schema: + type: string + required: true + pathPrincipalRateLimitId: + name: principalRateLimitId + in: path + schema: + type: string + example: abcd1234 + required: true + description: id of the Principal Rate Limit + pathPushProviderId: + in: path + name: pushProviderId + required: true + description: Id of the push provider + schema: + type: string + pathResourceId: + name: resourceId + in: path + schema: + type: string + example: ire106sQKoHoXXsAe0g4 + required: true + description: '`id` of a resource' + pathResourceSetId: + name: resourceSetId + in: path + schema: + type: string + example: iamoJDFKaJxGIr0oamd9g + required: true + description: '`id` of a resource set' + pathRiskProviderId: + name: riskProviderId + in: path + schema: + type: string + example: 00rp12r4skkjkjgsn + required: true + description: '`id` of the risk provider' + pathRoleIdOrLabel: + name: roleIdOrLabel + in: path + schema: + type: string + example: cr0Yq6IJxGIr0ouum0g3 + required: true + description: '`id` or `label` of the role' + pathTemplateName: + name: templateName + in: path + required: true + schema: + type: string + description: The name of the email template. + pathThemeId: + name: themeId + in: path + required: true + schema: + type: string + description: The ID of the theme. + pathUpdateId: + name: updateId + in: path + description: Id of the update + schema: + type: string + required: true + pathUserId: + name: userId + in: path + required: true + schema: + type: string + queryAfter: + name: after + in: query + schema: + type: string + description: The cursor to use for pagination. It is an opaque string that specifies your current location in the list and is obtained from the `Link` response header. See [Pagination](/#pagination) for more information. + queryExpandEmailTemplate: + name: expand + in: query + style: form + explode: false + required: false + schema: + type: array + items: + type: string + enum: + - settings + - customizationCount + description: Specifies additional metadata to be included in the response. + queryExpandPageRoot: + name: expand + in: query + style: form + explode: false + required: false + schema: + type: array + items: + type: string + enum: + - default + - customized + - customizedUrl + - preview + - previewUrl + description: Specifies additional metadata to be included in the response. + queryLanguage: + name: language + schema: + $ref: '#/components/schemas/Language' + in: query + description: The language to use for the email. Defaults to the current user's language if unspecified. + queryLimit: + name: limit + in: query + schema: + type: integer + minimum: 1 + maximum: 200 + default: 20 + description: A limit on the number of objects to return. + queryLimitPerPoolType: + name: limitPerPoolType + in: query + schema: + type: integer + default: 5 + required: false + description: Maximum number of AgentPools being returned + queryPoolType: + name: poolType + in: query + schema: + $ref: '#/components/schemas/AgentType' + required: false + description: Agent type to search for + queryScheduled: + name: scheduled + in: query + description: Scope the list only to scheduled or ad-hoc updates. If the parameter is not provided we will return the whole list of updates. + schema: + type: boolean + required: false + schemas: + APNSConfiguration: + properties: + fileName: + type: string + description: (Optional) File name for Admin Console display + keyId: + type: string + description: 10-character Key ID obtained from the Apple developer account + teamId: + type: string + description: 10-character Team ID used to develop the iOS app + tokenSigningKey: + type: string + description: APNs private authentication token signing key + writeOnly: true + APNSPushProvider: + allOf: + - $ref: '#/components/schemas/PushProvider' + - type: object + properties: + configuration: + $ref: '#/components/schemas/APNSConfiguration' + AccessPolicy: + allOf: + - $ref: '#/components/schemas/Policy' + - type: object + properties: + conditions: + $ref: '#/components/schemas/PolicyRuleConditions' + AccessPolicyConstraint: + type: object + properties: + methods: + items: + type: string + type: array + reauthenticateIn: + type: string + types: + items: + type: string + type: array + AccessPolicyConstraints: + type: object + properties: + knowledge: + $ref: '#/components/schemas/KnowledgeConstraint' + possession: + $ref: '#/components/schemas/PossessionConstraint' + AccessPolicyRule: + allOf: + - $ref: '#/components/schemas/PolicyRule' + - type: object + properties: + actions: + $ref: '#/components/schemas/AccessPolicyRuleActions' + conditions: + $ref: '#/components/schemas/AccessPolicyRuleConditions' + AccessPolicyRuleActions: + allOf: + - $ref: '#/components/schemas/PolicyRuleActions' + - type: object + properties: + appSignOn: + $ref: '#/components/schemas/AccessPolicyRuleApplicationSignOn' + AccessPolicyRuleApplicationSignOn: + type: object + properties: + access: + type: string + verificationMethod: + $ref: '#/components/schemas/VerificationMethod' + AccessPolicyRuleConditions: + allOf: + - $ref: '#/components/schemas/PolicyRuleConditions' + - type: object + properties: + device: + $ref: '#/components/schemas/DeviceAccessPolicyRuleCondition' + elCondition: + $ref: '#/components/schemas/AccessPolicyRuleCustomCondition' + userType: + $ref: '#/components/schemas/UserTypeCondition' + AccessPolicyRuleCustomCondition: + properties: + condition: + type: string + AcsEndpoint: + type: object + properties: + index: + type: integer + url: + type: string + ActivateFactorRequest: + type: object + properties: + attestation: + type: string + clientData: + type: string + passCode: + type: string + registrationData: + type: string + stateToken: + type: string + Agent: + description: Agent details + type: object + properties: + id: + type: string + readOnly: true + isHidden: + type: boolean + isLatestGAedVersion: + type: boolean + lastConnection: + type: string + format: date-time + name: + type: string + operationalStatus: + $ref: '#/components/schemas/OperationalStatus' + poolId: + type: string + type: + $ref: '#/components/schemas/AgentType' + updateMessage: + type: string + updateStatus: + $ref: '#/components/schemas/AgentUpdateInstanceStatus' + version: + type: string + _links: + $ref: '#/components/schemas/HrefObject' + AgentPool: + description: An AgentPool is a collection of agents that serve a common purpose. An AgentPool has a unique ID within an org, and contains a collection of agents disjoint to every other AgentPool (i.e. no two AgentPools share an Agent). + type: object + properties: + agents: + type: array + items: + $ref: '#/components/schemas/Agent' + id: + type: string + readOnly: true + name: + type: string + operationalStatus: + $ref: '#/components/schemas/OperationalStatus' + type: + $ref: '#/components/schemas/AgentType' + AgentPoolUpdate: + description: Various information about agent auto update configuration + type: object + properties: + agents: + type: array + items: + $ref: '#/components/schemas/Agent' + agentType: + $ref: '#/components/schemas/AgentType' + enabled: + type: boolean + id: + type: string + readOnly: true + name: + type: string + notifyAdmin: + type: boolean + reason: + type: string + schedule: + $ref: '#/components/schemas/AutoUpdateSchedule' + sortOrder: + type: integer + status: + $ref: '#/components/schemas/AgentUpdateJobStatus' + targetVersion: + type: string + _links: + $ref: '#/components/schemas/HrefObject' + AgentPoolUpdateSetting: + description: Setting for auto-update + type: object + properties: + agentType: + $ref: '#/components/schemas/AgentType' + continueOnError: + type: boolean + latestVersion: + type: string + minimalSupportedVersion: + type: string + poolId: + type: string + readOnly: true + poolName: + type: string + releaseChannel: + $ref: '#/components/schemas/ReleaseChannel' + AgentType: + description: Agent types that are being monitored + type: string + enum: + - AD + - IWA + - LDAP + - MFA + - OPP + - RUM + - Radius + AgentUpdateInstanceStatus: + description: Status for one agent regarding the status to auto-update that agent + type: string + enum: + - Cancelled + - Failed + - InProgress + - PendingCompletion + - Scheduled + - Success + AgentUpdateJobStatus: + description: Overall state for the auto-update job from admin perspective + type: string + enum: + - Cancelled + - Failed + - InProgress + - Paused + - Scheduled + - Success + AllowedForEnum: + type: string + enum: + - any + - none + - recovery + - sso + ApiToken: + title: API Token + description: An API token for an Okta User. This token is NOT scoped any further and can be used for any API the user has permissions to call. + type: object + properties: + clientName: + type: string + readOnly: true + created: + type: string + format: date-time + readOnly: true + expiresAt: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + tokenWindow: + $ref: '#/components/schemas/TimeDuration' + userId: + type: string + _link: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + readOnly: true + required: + - name + AppAndInstanceConditionEvaluatorAppOrInstance: + type: object + properties: + id: + type: string + readOnly: true + name: + type: string + type: + $ref: '#/components/schemas/AppAndInstanceType' + AppAndInstancePolicyRuleCondition: + type: object + properties: + exclude: + type: array + items: + $ref: '#/components/schemas/AppAndInstanceConditionEvaluatorAppOrInstance' + include: + type: array + items: + $ref: '#/components/schemas/AppAndInstanceConditionEvaluatorAppOrInstance' + AppAndInstanceType: + type: string + enum: + - APP + - APP_TYPE + AppInstancePolicyRuleCondition: + type: object + properties: + exclude: + type: array + items: + type: string + include: + type: array + items: + type: string + AppLink: + type: object + properties: + appAssignmentId: + type: string + readOnly: true + appInstanceId: + type: string + readOnly: true + appName: + type: string + readOnly: true + credentialsSetup: + type: boolean + readOnly: true + hidden: + type: boolean + readOnly: true + id: + type: string + readOnly: true + label: + type: string + readOnly: true + linkUrl: + type: string + readOnly: true + logoUrl: + type: string + readOnly: true + sortOrder: + type: integer + readOnly: true + AppUser: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + credentials: + $ref: '#/components/schemas/AppUserCredentials' + externalId: + type: string + readOnly: true + id: + type: string + readOnly: false + lastSync: + type: string + format: date-time + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + passwordChanged: + type: string + format: date-time + readOnly: true + profile: + type: object + additionalProperties: + type: object + properties: {} + scope: + type: string + status: + type: string + readOnly: true + statusChanged: + type: string + format: date-time + readOnly: true + syncState: + type: string + readOnly: true + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + AppUserCredentials: + type: object + properties: + password: + $ref: '#/components/schemas/AppUserPasswordCredential' + userName: + type: string + AppUserPasswordCredential: + type: object + properties: + value: + type: string + format: password + Application: + type: object + properties: + accessibility: + $ref: '#/components/schemas/ApplicationAccessibility' + created: + type: string + format: date-time + readOnly: true + features: + type: array + items: + type: string + id: + type: string + readOnly: true + label: + $ref: '#/components/schemas/ApplicationLabel' + lastUpdated: + type: string + format: date-time + readOnly: true + licensing: + $ref: '#/components/schemas/ApplicationLicensing' + profile: + type: object + additionalProperties: + type: object + properties: {} + signOnMode: + $ref: '#/components/schemas/ApplicationSignOnMode' + status: + $ref: '#/components/schemas/ApplicationLifecycleStatus' + visibility: + $ref: '#/components/schemas/ApplicationVisibility' + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + $ref: '#/components/schemas/ApplicationLinks' + discriminator: + propertyName: signOnMode + mapping: + AUTO_LOGIN: '#/components/schemas/AutoLoginApplication' + BASIC_AUTH: '#/components/schemas/BasicAuthApplication' + BOOKMARK: '#/components/schemas/BookmarkApplication' + BROWSER_PLUGIN: '#/components/schemas/BrowserPluginApplication' + OPENID_CONNECT: '#/components/schemas/OpenIdConnectApplication' + SAML_1_1: '#/components/schemas/SamlApplication' + SAML_2_0: '#/components/schemas/SamlApplication' + SECURE_PASSWORD_STORE: '#/components/schemas/SecurePasswordStoreApplication' + WS_FEDERATION: '#/components/schemas/WsFederationApplication' + ApplicationAccessibility: + type: object + properties: + errorRedirectUrl: + type: string + loginRedirectUrl: + type: string + selfService: + type: boolean + ApplicationCredentials: + type: object + properties: + signing: + $ref: '#/components/schemas/ApplicationCredentialsSigning' + userNameTemplate: + $ref: '#/components/schemas/ApplicationCredentialsUsernameTemplate' + ApplicationCredentialsOAuthClient: + type: object + properties: + autoKeyRotation: + type: boolean + client_id: + type: string + client_secret: + type: string + token_endpoint_auth_method: + $ref: '#/components/schemas/OAuthEndpointAuthenticationMethod' + ApplicationCredentialsScheme: + type: string + enum: + - ADMIN_SETS_CREDENTIALS + - EDIT_PASSWORD_ONLY + - EDIT_USERNAME_AND_PASSWORD + - EXTERNAL_PASSWORD_SYNC + - SHARED_USERNAME_AND_PASSWORD + ApplicationCredentialsSigning: + type: object + properties: + kid: + type: string + lastRotated: + type: string + format: date-time + readOnly: true + nextRotation: + type: string + format: date-time + readOnly: true + rotationMode: + type: string + use: + $ref: '#/components/schemas/ApplicationCredentialsSigningUse' + ApplicationCredentialsSigningUse: + type: string + enum: + - sig + ApplicationCredentialsUsernameTemplate: + type: object + properties: + pushStatus: + type: string + suffix: + type: string + template: + type: string + type: + type: string + ApplicationFeature: + type: object + properties: + capabilities: + $ref: '#/components/schemas/CapabilitiesObject' + description: + type: string + name: + type: string + status: + $ref: '#/components/schemas/EnabledStatus' + _links: + additionalProperties: + type: object + readOnly: true + type: object + ApplicationGroupAssignment: + type: object + properties: + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + priority: + type: integer + profile: + type: object + additionalProperties: + type: object + properties: {} + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + ApplicationLabel: + type: string + ApplicationLayout: + type: object + properties: + elements: + type: array + items: + type: object + additionalProperties: true + label: + type: string + options: + type: object + additionalProperties: {} + rule: + type: object + properties: + effect: + type: string + condition: + $ref: '#/components/schemas/ApplicationLayoutRuleCondition' + scope: + type: string + type: + type: string + ApplicationLayoutRuleCondition: + type: object + properties: + schema: + type: object + additionalProperties: {} + scope: + type: string + ApplicationLicensing: + type: object + properties: + seatCount: + type: integer + ApplicationLifecycleStatus: + type: string + enum: + - ACTIVE + - DELETED + - INACTIVE + readOnly: true + ApplicationLinks: + additionalProperties: true + type: object + properties: + accessPolicy: + $ref: '#/components/schemas/HrefObject' + activate: + $ref: '#/components/schemas/HrefObject' + deactivate: + $ref: '#/components/schemas/HrefObject' + groups: + $ref: '#/components/schemas/HrefObject' + logo: + type: array + items: + $ref: '#/components/schemas/HrefObject' + metadata: + $ref: '#/components/schemas/HrefObject' + self: + $ref: '#/components/schemas/HrefObject' + users: + $ref: '#/components/schemas/HrefObject' + readOnly: true + ApplicationSettings: + type: object + properties: + identityStoreId: + type: string + implicitAssignment: + type: boolean + inlineHookId: + type: string + notes: + $ref: '#/components/schemas/ApplicationSettingsNotes' + notifications: + $ref: '#/components/schemas/ApplicationSettingsNotifications' + ApplicationSettingsNotes: + type: object + properties: + admin: + type: string + enduser: + type: string + ApplicationSettingsNotifications: + type: object + properties: + vpn: + $ref: '#/components/schemas/ApplicationSettingsNotificationsVpn' + ApplicationSettingsNotificationsVpn: + type: object + properties: + helpUrl: + type: string + message: + type: string + network: + $ref: '#/components/schemas/ApplicationSettingsNotificationsVpnNetwork' + ApplicationSettingsNotificationsVpnNetwork: + type: object + properties: + connection: + type: string + exclude: + type: array + items: + type: string + include: + type: array + items: + type: string + ApplicationSignOnMode: + type: string + enum: + - AUTO_LOGIN + - BASIC_AUTH + - BOOKMARK + - BROWSER_PLUGIN + - OPENID_CONNECT + - SAML_1_1 + - SAML_2_0 + - SECURE_PASSWORD_STORE + - WS_FEDERATION + ApplicationVisibility: + type: object + properties: + appLinks: + type: object + additionalProperties: + type: boolean + autoLaunch: + type: boolean + autoSubmitToolbar: + type: boolean + hide: + $ref: '#/components/schemas/ApplicationVisibilityHide' + ApplicationVisibilityHide: + type: object + properties: + iOS: + type: boolean + web: + type: boolean + AssignRoleRequest: + type: object + properties: + type: + $ref: '#/components/schemas/RoleType' + AuthenticationProvider: + type: object + properties: + name: + type: string + type: + $ref: '#/components/schemas/AuthenticationProviderType' + AuthenticationProviderType: + type: string + enum: + - ACTIVE_DIRECTORY + - FEDERATION + - IMPORT + - LDAP + - OKTA + - SOCIAL + Authenticator: + type: object + properties: + created: + format: date-time + readOnly: true + type: string + id: + readOnly: true + type: string + key: + type: string + lastUpdated: + format: date-time + readOnly: true + type: string + name: + type: string + provider: + $ref: '#/components/schemas/AuthenticatorProvider' + settings: + $ref: '#/components/schemas/AuthenticatorSettings' + status: + $ref: '#/components/schemas/AuthenticatorStatus' + type: + $ref: '#/components/schemas/AuthenticatorType' + _links: + additionalProperties: + type: object + readOnly: true + type: object + AuthenticatorProvider: + properties: + configuration: + $ref: '#/components/schemas/AuthenticatorProviderConfiguration' + type: + type: string + AuthenticatorProviderConfiguration: + properties: + authPort: + type: integer + hostName: + type: string + instanceId: + type: string + sharedSecret: + type: string + userNameTemplate: + $ref: '#/components/schemas/AuthenticatorProviderConfigurationUserNameTemplate' + AuthenticatorProviderConfigurationUserNameTemplate: + properties: + template: + type: string + AuthenticatorSettings: + type: object + properties: + allowedFor: + $ref: '#/components/schemas/AllowedForEnum' + appInstanceId: + type: string + channelBinding: + $ref: '#/components/schemas/ChannelBinding' + compliance: + $ref: '#/components/schemas/Compliance' + tokenLifetimeInMinutes: + type: integer + userVerification: + $ref: '#/components/schemas/UserVerificationEnum' + AuthenticatorStatus: + type: string + enum: + - ACTIVE + - INACTIVE + AuthenticatorType: + type: string + enum: + - app + - email + - federated + - password + - phone + - security_key + - security_question + AuthorizationServer: + type: object + properties: + audiences: + type: array + items: + type: string + created: + type: string + format: date-time + readOnly: true + credentials: + $ref: '#/components/schemas/AuthorizationServerCredentials' + description: + type: string + id: + type: string + readOnly: true + issuer: + type: string + issuerMode: + $ref: '#/components/schemas/IssuerMode' + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + status: + $ref: '#/components/schemas/LifecycleStatus' + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + AuthorizationServerCredentials: + type: object + properties: + signing: + $ref: '#/components/schemas/AuthorizationServerCredentialsSigningConfig' + AuthorizationServerCredentialsRotationMode: + type: string + enum: + - AUTO + - MANUAL + AuthorizationServerCredentialsSigningConfig: + type: object + properties: + kid: + type: string + lastRotated: + type: string + format: date-time + readOnly: true + nextRotation: + type: string + format: date-time + readOnly: true + rotationMode: + $ref: '#/components/schemas/AuthorizationServerCredentialsRotationMode' + use: + $ref: '#/components/schemas/AuthorizationServerCredentialsUse' + AuthorizationServerCredentialsUse: + type: string + enum: + - sig + AuthorizationServerPolicy: + allOf: + - $ref: '#/components/schemas/Policy' + - type: object + properties: + conditions: + $ref: '#/components/schemas/PolicyRuleConditions' + AuthorizationServerPolicyRule: + allOf: + - $ref: '#/components/schemas/PolicyRule' + - type: object + properties: + actions: + $ref: '#/components/schemas/AuthorizationServerPolicyRuleActions' + conditions: + $ref: '#/components/schemas/AuthorizationServerPolicyRuleConditions' + AuthorizationServerPolicyRuleActions: + allOf: + - $ref: '#/components/schemas/PolicyRuleActions' + - type: object + properties: + token: + $ref: '#/components/schemas/TokenAuthorizationServerPolicyRuleAction' + AuthorizationServerPolicyRuleConditions: + allOf: + - $ref: '#/components/schemas/PolicyRuleConditions' + - type: object + properties: + clients: + $ref: '#/components/schemas/ClientPolicyCondition' + grantTypes: + $ref: '#/components/schemas/GrantTypePolicyRuleCondition' + people: + $ref: '#/components/schemas/PolicyPeopleCondition' + scopes: + $ref: '#/components/schemas/OAuth2ScopesMediationPolicyRuleCondition' + AutoLoginApplication: + allOf: + - $ref: '#/components/schemas/Application' + - type: object + properties: + credentials: + $ref: '#/components/schemas/SchemeApplicationCredentials' + name: + type: string + settings: + $ref: '#/components/schemas/AutoLoginApplicationSettings' + AutoLoginApplicationSettings: + allOf: + - $ref: '#/components/schemas/ApplicationSettings' + - type: object + properties: + signOn: + $ref: '#/components/schemas/AutoLoginApplicationSettingsSignOn' + AutoLoginApplicationSettingsSignOn: + type: object + properties: + loginUrl: + type: string + redirectUrl: + type: string + AutoUpdateSchedule: + description: The schedule of auto-update configured by admin. + type: object + properties: + cron: + type: string + delay: + description: delay in days + type: integer + duration: + description: duration in minutes + type: integer + lastUpdated: + description: last time when the updated finished (success or failed, exclude cancelled), null if job haven't finished once yet. + type: string + format: date-time + timezone: + type: string + AwsRegion: + description: An AWS region + type: string + enum: + - ca-central-1 + - eu-central-1 + - eu-north-1 + - eu-south-1 + - eu-west-1 + - eu-west-2 + - eu-west-3 + - us-east-1 + - us-east-2 + - us-west-1 + - us-west-2 + BaseEmailDomain: + type: object + properties: + displayName: + type: string + userName: + type: string + required: + - displayName + - userName + BasicApplicationSettings: + allOf: + - $ref: '#/components/schemas/ApplicationSettings' + - type: object + properties: + app: + $ref: '#/components/schemas/BasicApplicationSettingsApplication' + BasicApplicationSettingsApplication: + type: object + properties: + authURL: + type: string + url: + type: string + BasicAuthApplication: + x-okta-defined-as: + name: template_basic_auth + allOf: + - $ref: '#/components/schemas/Application' + - type: object + properties: + credentials: + $ref: '#/components/schemas/SchemeApplicationCredentials' + name: + type: string + default: template_basic_auth + settings: + $ref: '#/components/schemas/BasicApplicationSettings' + BeforeScheduledActionPolicyRuleCondition: + type: object + properties: + duration: + $ref: '#/components/schemas/Duration' + lifecycleAction: + $ref: '#/components/schemas/ScheduledUserLifecycleAction' + BehaviorRule: + title: Behavior Detection Rule + type: object + properties: + created: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + maxLength: 128 + status: + $ref: '#/components/schemas/LifecycleStatus' + type: + $ref: '#/components/schemas/BehaviorRuleType' + _link: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + readOnly: true + required: + - name + - type + discriminator: + propertyName: type + mapping: + ANOMALOUS_LOCATION: '#/components/schemas/BehaviorRuleAnomalousLocation' + ANOMALOUS_IP: '#/components/schemas/BehaviorRuleAnomalousIP' + ANOMALOUS_DEVICE: '#/components/schemas/BehaviorRuleAnomalousDevice' + VELOCITY: '#/components/schemas/BehaviorRuleVelocity' + BehaviorRuleAnomalousDevice: + allOf: + - $ref: '#/components/schemas/BehaviorRule' + - type: object + properties: + settings: + $ref: '#/components/schemas/BehaviorRuleSettingsAnomalousDevice' + BehaviorRuleAnomalousIP: + allOf: + - $ref: '#/components/schemas/BehaviorRule' + - type: object + properties: + settings: + $ref: '#/components/schemas/BehaviorRuleSettingsAnomalousIP' + BehaviorRuleAnomalousLocation: + allOf: + - $ref: '#/components/schemas/BehaviorRule' + - type: object + properties: + settings: + $ref: '#/components/schemas/BehaviorRuleSettingsAnomalousLocation' + BehaviorRuleSettings: + title: Behavior Detection Rule Settings + type: object + BehaviorRuleSettingsAnomalousDevice: + allOf: + - $ref: '#/components/schemas/BehaviorRuleSettingsHistoryBased' + BehaviorRuleSettingsAnomalousIP: + allOf: + - $ref: '#/components/schemas/BehaviorRuleSettingsHistoryBased' + - type: object + properties: + maxEventsUsedForEvaluation: + type: integer + minimum: 0 + maximum: 100 + default: 50 + BehaviorRuleSettingsAnomalousLocation: + allOf: + - $ref: '#/components/schemas/BehaviorRuleSettingsHistoryBased' + - type: object + properties: + granularity: + $ref: '#/components/schemas/LocationGranularity' + radiusKilometers: + type: integer + description: Required when `granularity` is `LAT_LONG`. Radius from the provided coordinates in kilometers. + required: + - granularity + BehaviorRuleSettingsHistoryBased: + allOf: + - $ref: '#/components/schemas/BehaviorRuleSettings' + - title: Behavior Detection Rule Settings based on Event History + type: object + properties: + maxEventsUsedForEvaluation: + type: integer + minimum: 1 + maximum: 100 + default: 20 + minEventsNeededForEvaluation: + type: integer + minimum: 0 + maximum: 10 + default: 0 + BehaviorRuleSettingsVelocity: + allOf: + - $ref: '#/components/schemas/BehaviorRuleSettings' + - title: Behavior Detection Rule Settings based on device velocity in kilometers per hour. + type: object + properties: + velocityKph: + type: integer + minimum: 1 + default: 805 + required: + - velocityKph + BehaviorRuleType: + type: string + enum: + - ANOMALOUS_DEVICE + - ANOMALOUS_IP + - ANOMALOUS_LOCATION + - VELOCITY + BehaviorRuleVelocity: + allOf: + - $ref: '#/components/schemas/BehaviorRule' + - type: object + properties: + settings: + $ref: '#/components/schemas/BehaviorRuleSettingsVelocity' + BookmarkApplication: + x-okta-defined-as: + name: bookmark + allOf: + - $ref: '#/components/schemas/Application' + - type: object + properties: + credentials: + $ref: '#/components/schemas/ApplicationCredentials' + name: + type: string + default: bookmark + settings: + $ref: '#/components/schemas/BookmarkApplicationSettings' + BookmarkApplicationSettings: + allOf: + - $ref: '#/components/schemas/ApplicationSettings' + - type: object + properties: + app: + $ref: '#/components/schemas/BookmarkApplicationSettingsApplication' + BookmarkApplicationSettingsApplication: + type: object + properties: + requestIntegration: + type: boolean + url: + type: string + BouncesRemoveListError: + type: object + properties: + emailAddress: + type: string + reason: + type: string + BouncesRemoveListObj: + type: object + properties: + emailAddresses: + type: array + items: + type: string + BouncesRemoveListResult: + type: object + properties: + errors: + type: array + items: + $ref: '#/components/schemas/BouncesRemoveListError' + Brand: + type: object + properties: + agreeToCustomPrivacyPolicy: + type: boolean + customPrivacyPolicyUrl: + type: string + defaultApp: + type: object + properties: + appInstanceId: + type: string + appLinkName: + type: string + displayLanguage: + $ref: '#/components/schemas/Language' + id: + readOnly: true + type: string + isDefault: + readOnly: true + type: boolean + name: + type: string + removePoweredByOkta: + type: boolean + _links: + properties: + self: + $ref: '#/components/schemas/HrefObject' + themes: + $ref: '#/components/schemas/HrefObject' + readOnly: true + type: object + BrandDomain: + type: object + properties: + domainId: + type: string + readOnly: true + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + brand: + $ref: '#/components/schemas/HrefObject' + domain: + $ref: '#/components/schemas/HrefObject' + readOnly: true + description: Links to resources related to this brand domain + BrandDomains: + title: BrandDomains + items: + $ref: '#/components/schemas/DomainResponse' + type: array + BrandRequest: + type: object + properties: + agreeToCustomPrivacyPolicy: + type: boolean + customPrivacyPolicyUrl: + type: string + name: + type: string + removePoweredByOkta: + type: boolean + BrowserPluginApplication: + allOf: + - $ref: '#/components/schemas/Application' + - type: object + properties: + credentials: + $ref: '#/components/schemas/SchemeApplicationCredentials' + name: + type: string + settings: + $ref: '#/components/schemas/SwaApplicationSettings' + CAPTCHAInstance: + title: CAPTCHAInstance + description: '' + type: object + properties: + id: + type: string + readOnly: true + name: + type: string + secretKey: + type: string + writeOnly: true + siteKey: + type: string + type: + $ref: '#/components/schemas/CAPTCHAType' + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + readOnly: true + CAPTCHAType: + type: string + enum: + - HCAPTCHA + - RECAPTCHA_V2 + CallUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/CallUserFactorProfile' + CallUserFactorProfile: + type: object + properties: + phoneExtension: + type: string + phoneNumber: + type: string + CapabilitiesCreateObject: + type: object + properties: + lifecycleCreate: + $ref: '#/components/schemas/LifecycleCreateSettingObject' + CapabilitiesObject: + type: object + properties: + create: + $ref: '#/components/schemas/CapabilitiesCreateObject' + update: + $ref: '#/components/schemas/CapabilitiesUpdateObject' + CapabilitiesUpdateObject: + type: object + properties: + lifecycleDeactivate: + $ref: '#/components/schemas/LifecycleDeactivateSettingObject' + password: + $ref: '#/components/schemas/PasswordSettingObject' + profile: + $ref: '#/components/schemas/ProfileSettingObject' + CatalogApplication: + type: object + properties: + category: + type: string + description: + type: string + displayName: + type: string + features: + type: array + items: + type: string + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + signOnModes: + type: array + items: + type: string + status: + $ref: '#/components/schemas/CatalogApplicationStatus' + verificationStatus: + type: string + website: + type: string + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + CatalogApplicationStatus: + type: string + enum: + - ACTIVE + - INACTIVE + ChangeEnum: + type: string + enum: + - CHANGE + - KEEP_EXISTING + ChangePasswordRequest: + type: object + properties: + newPassword: + $ref: '#/components/schemas/PasswordCredential' + oldPassword: + $ref: '#/components/schemas/PasswordCredential' + ChannelBinding: + type: object + properties: + required: + $ref: '#/components/schemas/RequiredEnum' + style: + type: string + ClientPolicyCondition: + type: object + properties: + include: + type: array + items: + type: string + Compliance: + type: object + properties: + fips: + $ref: '#/components/schemas/FipsEnum' + ContextPolicyRuleCondition: + allOf: + - $ref: '#/components/schemas/DevicePolicyRuleCondition' + - type: object + properties: + expression: + type: string + CreateBrandDomainRequest: + title: CreateBrandDomainRequest + type: object + properties: + domainId: + type: string + CreateBrandRequest: + title: CreateBrandRequest + type: object + properties: + name: + type: string + CreateSessionRequest: + type: object + properties: + sessionToken: + type: string + CreateUserRequest: + type: object + properties: + credentials: + $ref: '#/components/schemas/UserCredentials' + groupIds: + type: array + items: + type: string + profile: + $ref: '#/components/schemas/UserProfile' + type: + $ref: '#/components/schemas/UserType' + required: + - profile + Csr: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + csr: + type: string + readOnly: true + id: + type: string + readOnly: true + kty: + type: string + readOnly: true + CsrMetadata: + type: object + properties: + subject: + $ref: '#/components/schemas/CsrMetadataSubject' + subjectAltNames: + $ref: '#/components/schemas/CsrMetadataSubjectAltNames' + CsrMetadataSubject: + type: object + properties: + commonName: + type: string + countryName: + type: string + localityName: + type: string + organizationalUnitName: + type: string + organizationName: + type: string + stateOrProvinceName: + type: string + CsrMetadataSubjectAltNames: + type: object + properties: + dnsNames: + type: array + items: + type: string + CustomHotpUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + factorProfileId: + type: string + profile: + $ref: '#/components/schemas/CustomHotpUserFactorProfile' + CustomHotpUserFactorProfile: + type: object + properties: + sharedSecret: + type: string + CustomizablePage: + type: object + properties: + pageContent: + type: string + DNSRecord: + type: object + properties: + expiration: + type: string + fqdn: + type: string + recordType: + $ref: '#/components/schemas/DNSRecordType' + values: + type: array + items: + type: string + DNSRecordType: + type: string + enum: + - CNAME + - TXT + Device: + type: object + properties: + created: + type: string + format: date-time + description: Timestamp when the device was created + readOnly: true + id: + type: string + description: Unique key for the device + readOnly: true + lastUpdated: + type: string + format: date-time + description: Timestamp when the device was last updated + readOnly: true + profile: + $ref: '#/components/schemas/DeviceProfile' + resourceAlternateId: + type: string + readOnly: true + resourceDisplayName: + $ref: '#/components/schemas/DeviceDisplayName' + resourceId: + type: string + description: Alternate key for the `id` + readOnly: true + resourceType: + type: string + default: UDDevice + readOnly: true + status: + $ref: '#/components/schemas/DeviceStatus' + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + users: + $ref: '#/components/schemas/HrefObject' + activate: + $ref: '#/components/schemas/HrefObject' + deactivate: + $ref: '#/components/schemas/HrefObject' + suspend: + $ref: '#/components/schemas/HrefObject' + unsuspend: + $ref: '#/components/schemas/HrefObject' + readOnly: true + DeviceAccessPolicyRuleCondition: + allOf: + - $ref: '#/components/schemas/DevicePolicyRuleCondition' + - type: object + properties: + managed: + type: boolean + registered: + type: boolean + DeviceAssurance: + title: DeviceAssurance + type: object + properties: + createdBy: + type: string + readOnly: true + createdDate: + type: string + readOnly: true + diskEncryptionType: + type: object + properties: + include: + type: array + items: + $ref: '#/components/schemas/DiskEncryptionType' + id: + type: string + readOnly: true + jailbreak: + type: boolean + lastUpdatedBy: + type: string + readOnly: true + lastUpdatedDate: + type: string + readOnly: true + name: + type: string + description: Display name of the Device Assurance Policy + osVersion: + $ref: '#/components/schemas/VersionObject' + platform: + $ref: '#/components/schemas/Platform' + screenLockType: + type: object + properties: + include: + type: array + items: + $ref: '#/components/schemas/ScreenLockType' + secureHardwarePresent: + type: boolean + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + readOnly: true + DeviceDisplayName: + type: object + properties: + sensitive: + type: boolean + value: + type: string + DevicePlatform: + description: OS platform of the device + type: string + enum: + - ANDROID + - IOS + - MACOS + - WINDOWS + DevicePolicyMDMFramework: + type: string + enum: + - AFW + - NATIVE + - SAFE + DevicePolicyPlatformType: + type: string + enum: + - ANDROID + - IOS + - OSX + - WINDOWS + DevicePolicyRuleCondition: + type: object + properties: + migrated: + type: boolean + platform: + $ref: '#/components/schemas/DevicePolicyRuleConditionPlatform' + rooted: + type: boolean + trustLevel: + $ref: '#/components/schemas/DevicePolicyTrustLevel' + DevicePolicyRuleConditionPlatform: + type: object + properties: + supportedMDMFrameworks: + type: array + items: + $ref: '#/components/schemas/DevicePolicyMDMFramework' + types: + type: array + items: + $ref: '#/components/schemas/DevicePolicyPlatformType' + DevicePolicyTrustLevel: + type: string + enum: + - ANY + - TRUSTED + DeviceProfile: + type: object + properties: + displayName: + type: string + description: Display name of the device + minLength: 1 + maxLength: 255 + imei: + type: string + description: International Mobile Equipment Identity of the device + minLength: 14 + maxLength: 17 + manufacturer: + type: string + description: Name of the manufacturer of the device + maxLength: 127 + meid: + type: string + description: Mobile equipment identifier of the device + maxLength: 14 + model: + type: string + description: Model of the device + maxLength: 127 + osVersion: + type: string + description: Version of the device OS + maxLength: 127 + platform: + $ref: '#/components/schemas/DevicePlatform' + registered: + type: boolean + description: Indicates if the device is registered at Okta + secureHardwarePresent: + type: boolean + description: Indicates if the device constains a secure hardware functionality + serialNumber: + type: string + description: Serial number of the device + maxLength: 127 + sid: + type: string + description: Windows Security identifier of the device + maxLength: 256 + tpmPublicKeyHash: + type: string + description: Windows Trsted Platform Module hash value + udid: + type: string + description: macOS Unique Device identifier of the device + maxLength: 47 + required: + - displayName + - platform + - registered + DeviceStatus: + type: string + enum: + - ACTIVE + - CREATED + - DEACTIVATED + - SUSPENDED + DiskEncryptionType: + type: string + enum: + - ALL_INTERNAL_VOLUMES + - FULL + - USER + Domain: + type: object + properties: + brandId: + type: string + certificateSourceType: + $ref: '#/components/schemas/DomainCertificateSourceType' + dnsRecords: + type: array + items: + $ref: '#/components/schemas/DNSRecord' + domain: + type: string + id: + type: string + publicCertificate: + $ref: '#/components/schemas/DomainCertificateMetadata' + validationStatus: + $ref: '#/components/schemas/DomainValidationStatus' + DomainCertificate: + type: object + properties: + certificate: + type: string + certificateChain: + type: string + privateKey: + type: string + type: + $ref: '#/components/schemas/DomainCertificateType' + DomainCertificateMetadata: + type: object + properties: + expiration: + type: string + fingerprint: + type: string + subject: + type: string + DomainCertificateSourceType: + type: string + enum: + - MANUAL + - OKTA_MANAGED + DomainCertificateType: + type: string + enum: + - PEM + DomainLinks: + type: object + properties: + brand: + $ref: '#/components/schemas/HrefObject' + certificate: + $ref: '#/components/schemas/HrefObject' + self: + $ref: '#/components/schemas/HrefObject' + verify: + $ref: '#/components/schemas/HrefObject' + DomainListResponse: + type: object + properties: + domains: + type: array + items: + $ref: '#/components/schemas/DomainResponse' + DomainResponse: + type: object + properties: + brandId: + type: string + certificateSourceType: + $ref: '#/components/schemas/DomainCertificateSourceType' + dnsRecords: + type: array + items: + $ref: '#/components/schemas/DNSRecord' + domain: + type: string + id: + type: string + publicCertificate: + $ref: '#/components/schemas/DomainCertificateMetadata' + validationStatus: + $ref: '#/components/schemas/DomainValidationStatus' + _links: + $ref: '#/components/schemas/DomainLinks' + DomainValidationStatus: + type: string + enum: + - COMPLETED + - IN_PROGRESS + - NOT_STARTED + - VERIFIED + Duration: + type: object + properties: + number: + type: integer + unit: + type: string + EmailContent: + type: object + properties: + body: + type: string + description: The email's HTML body. May contain [variable references](https://velocity.apache.org/engine/1.7/user-guide.html#references). + subject: + type: string + description: The email's subject. May contain [variable references](https://velocity.apache.org/engine/1.7/user-guide.html#references). + required: + - subject + - body + EmailCustomization: + allOf: + - $ref: '#/components/schemas/EmailContent' + - type: object + properties: + created: + type: string + format: date-time + readOnly: true + description: The UTC time at which this email customization was created. + id: + type: string + readOnly: true + description: A unique identifier for this email customization. + isDefault: + type: boolean + description: Whether this is the default customization for the email template. Each customized email template must have exactly one default customization. Defaults to `true` for the first customization and `false` thereafter. + language: + $ref: '#/components/schemas/Language' + lastUpdated: + type: string + format: date-time + readOnly: true + description: The UTC time at which this email customization was last updated. + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + template: + $ref: '#/components/schemas/HrefObject' + preview: + $ref: '#/components/schemas/HrefObject' + test: + $ref: '#/components/schemas/HrefObject' + readOnly: true + description: Links to resources related to this email customization. + required: + - language + EmailDefaultContent: + allOf: + - $ref: '#/components/schemas/EmailContent' + - type: object + properties: + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + template: + $ref: '#/components/schemas/HrefObject' + preview: + $ref: '#/components/schemas/HrefObject' + test: + $ref: '#/components/schemas/HrefObject' + readOnly: true + description: Links to resources related to this email template's default content. + EmailDomain: + allOf: + - $ref: '#/components/schemas/BaseEmailDomain' + type: object + properties: + domain: + type: string + required: + - domain + EmailDomainListResponse: + type: object + properties: + email-domains: + type: array + items: + $ref: '#/components/schemas/EmailDomainResponse' + EmailDomainResponse: + allOf: + - $ref: '#/components/schemas/BaseEmailDomain' + type: object + properties: + dnsValidationRecords: + type: array + items: + $ref: '#/components/schemas/DNSRecord' + domain: + type: string + id: + type: string + validationStatus: + $ref: '#/components/schemas/EmailDomainStatus' + EmailDomainStatus: + type: string + enum: + - DELETED + - ERROR + - NOT_STARTED + - POLLING + - VERIFIED + EmailPreview: + type: object + properties: + body: + type: string + readOnly: true + description: The email's HTML body. + subject: + type: string + readOnly: true + description: The email's subject. + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + contentSource: + $ref: '#/components/schemas/HrefObject' + template: + $ref: '#/components/schemas/HrefObject' + test: + $ref: '#/components/schemas/HrefObject' + defaultContent: + $ref: '#/components/schemas/HrefObject' + readOnly: true + description: Links to resources related to this email preview. + EmailSettings: + type: object + properties: + recipients: + type: string + enum: + - ALL_USERS + - ADMINS_ONLY + - NO_USERS + required: + - recipients + EmailTemplate: + type: object + properties: + name: + type: string + readOnly: true + description: The name of this email template. + _embedded: + type: object + properties: + settings: + $ref: '#/components/schemas/EmailSettings' + customizationCount: + type: integer + readOnly: true + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + settings: + $ref: '#/components/schemas/HrefObject' + defaultContent: + $ref: '#/components/schemas/HrefObject' + customizations: + $ref: '#/components/schemas/HrefObject' + test: + $ref: '#/components/schemas/HrefObject' + readOnly: true + description: Links to resources related to this email template. + EmailTemplateTouchPointVariant: + type: string + enum: + - FULL_THEME + - OKTA_DEFAULT + EmailUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/EmailUserFactorProfile' + EmailUserFactorProfile: + type: object + properties: + email: + type: string + EnabledStatus: + type: string + enum: + - DISABLED + - ENABLED + EndUserDashboardTouchPointVariant: + type: string + enum: + - FULL_THEME + - LOGO_ON_FULL_WHITE_BACKGROUND + - OKTA_DEFAULT + - WHITE_LOGO_BACKGROUND + Error: + title: Error + type: object + properties: + errorCauses: + type: array + items: + type: object + properties: + errorSummary: + type: string + errorCode: + type: string + description: An Okta code for this type of error + errorId: + type: string + description: A unique identifier for this error. This can be used by Okta Support to help with troubleshooting. + errorLink: + type: string + description: An Okta code for this type of error + errorSummary: + type: string + description: A short description of what caused this error. Sometimes this contains dynamically-generated information about your specific error. + ErrorPageTouchPointVariant: + type: string + enum: + - BACKGROUND_IMAGE + - BACKGROUND_SECONDARY_COLOR + - OKTA_DEFAULT + EventHook: + type: object + properties: + channel: + $ref: '#/components/schemas/EventHookChannel' + created: + type: string + format: date-time + readOnly: true + createdBy: + type: string + events: + $ref: '#/components/schemas/EventSubscriptions' + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + status: + $ref: '#/components/schemas/LifecycleStatus' + verificationStatus: + $ref: '#/components/schemas/EventHookVerificationStatus' + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + EventHookChannel: + type: object + properties: + config: + $ref: '#/components/schemas/EventHookChannelConfig' + type: + $ref: '#/components/schemas/EventHookChannelType' + version: + type: string + EventHookChannelConfig: + type: object + properties: + authScheme: + $ref: '#/components/schemas/EventHookChannelConfigAuthScheme' + headers: + type: array + items: + $ref: '#/components/schemas/EventHookChannelConfigHeader' + uri: + type: string + EventHookChannelConfigAuthScheme: + type: object + properties: + key: + type: string + type: + $ref: '#/components/schemas/EventHookChannelConfigAuthSchemeType' + value: + type: string + EventHookChannelConfigAuthSchemeType: + type: string + enum: + - HEADER + EventHookChannelConfigHeader: + type: object + properties: + key: + type: string + value: + type: string + EventHookChannelType: + type: string + enum: + - HTTP + EventHookVerificationStatus: + type: string + enum: + - UNVERIFIED + - VERIFIED + EventSubscriptionType: + type: string + enum: + - EVENT_TYPE + - FLOW_EVENT + EventSubscriptions: + type: object + properties: + items: + type: array + items: + type: string + type: + $ref: '#/components/schemas/EventSubscriptionType' + discriminator: + propertyName: type + FCMConfiguration: + properties: + fileName: + type: string + description: (Optional) File name for Admin Console display + projectId: + type: string + description: Project ID of FCM configuration + readOnly: true + serviceAccountJson: + type: object + description: JSON containing the private service account key and service account details. See [Creating and managing service account keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) for more information on creating service account keys in JSON. + writeOnly: true + FCMPushProvider: + allOf: + - $ref: '#/components/schemas/PushProvider' + - type: object + properties: + configuration: + $ref: '#/components/schemas/FCMConfiguration' + FactorProvider: + type: string + enum: + - CUSTOM + - DUO + - FIDO + - GOOGLE + - OKTA + - RSA + - SYMANTEC + - YUBICO + FactorResultType: + type: string + enum: + - CANCELLED + - CHALLENGE + - ERROR + - FAILED + - PASSCODE_REPLAYED + - REJECTED + - SUCCESS + - TIMEOUT + - TIME_WINDOW_EXCEEDED + - WAITING + FactorStatus: + type: string + enum: + - ACTIVE + - DISABLED + - ENROLLED + - EXPIRED + - INACTIVE + - NOT_SETUP + - PENDING_ACTIVATION + FactorType: + type: string + enum: + - call + - email + - hotp + - push + - question + - sms + - token + - token:hardware + - token:hotp + - token:software:totp + - u2f + - web + - webauthn + Feature: + type: object + properties: + description: + type: string + id: + type: string + readOnly: true + name: + type: string + stage: + $ref: '#/components/schemas/FeatureStage' + status: + $ref: '#/components/schemas/EnabledStatus' + type: + $ref: '#/components/schemas/FeatureType' + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + FeatureStage: + type: object + properties: + state: + $ref: '#/components/schemas/FeatureStageState' + value: + $ref: '#/components/schemas/FeatureStageValue' + FeatureStageState: + type: string + enum: + - CLOSED + - OPEN + FeatureStageValue: + type: string + enum: + - BETA + - EA + FeatureType: + type: string + enum: + - self-service + FipsEnum: + type: string + enum: + - OPTIONAL + - REQUIRED + ForgotPasswordResponse: + type: object + properties: + resetPasswordUrl: + type: string + readOnly: true + GrantOrTokenStatus: + type: string + enum: + - ACTIVE + - REVOKED + GrantTypePolicyRuleCondition: + type: object + properties: + include: + type: array + items: + type: string + Group: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + lastMembershipUpdated: + type: string + format: date-time + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + objectClass: + type: array + readOnly: true + items: + type: string + profile: + $ref: '#/components/schemas/GroupProfile' + type: + $ref: '#/components/schemas/GroupType' + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + properties: + apps: + $ref: '#/components/schemas/HrefObject' + logo: + type: array + items: + $ref: '#/components/schemas/HrefObject' + self: + $ref: '#/components/schemas/HrefObject' + source: + $ref: '#/components/schemas/HrefObject' + users: + $ref: '#/components/schemas/HrefObject' + readOnly: true + GroupCondition: + type: object + properties: + exclude: + type: array + items: + type: string + include: + type: array + items: + type: string + GroupOwner: + type: object + properties: + displayName: + type: string + readOnly: true + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + originId: + type: string + originType: + $ref: '#/components/schemas/GroupOwnerOriginType' + resolved: + type: boolean + type: + $ref: '#/components/schemas/GroupOwnerType' + GroupOwnerOriginType: + type: string + enum: + - APPLICATION + - OKTA_DIRECTORY + GroupOwnerType: + type: string + enum: + - GROUP + - UNKNOWN + - USER + GroupPolicyRuleCondition: + type: object + properties: + exclude: + type: array + items: + type: string + include: + type: array + items: + type: string + GroupProfile: + type: object + properties: + description: + type: string + name: + type: string + x-okta-extensible: true + GroupRule: + type: object + properties: + actions: + $ref: '#/components/schemas/GroupRuleAction' + conditions: + $ref: '#/components/schemas/GroupRuleConditions' + created: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + status: + $ref: '#/components/schemas/GroupRuleStatus' + type: + type: string + GroupRuleAction: + type: object + properties: + assignUserToGroups: + $ref: '#/components/schemas/GroupRuleGroupAssignment' + GroupRuleConditions: + type: object + properties: + expression: + $ref: '#/components/schemas/GroupRuleExpression' + people: + $ref: '#/components/schemas/GroupRulePeopleCondition' + GroupRuleExpression: + type: object + properties: + type: + type: string + value: + type: string + GroupRuleGroupAssignment: + type: object + properties: + groupIds: + type: array + items: + type: string + GroupRuleGroupCondition: + type: object + properties: + exclude: + type: array + items: + type: string + include: + type: array + items: + type: string + GroupRulePeopleCondition: + type: object + properties: + groups: + $ref: '#/components/schemas/GroupRuleGroupCondition' + users: + $ref: '#/components/schemas/GroupRuleUserCondition' + GroupRuleStatus: + type: string + enum: + - ACTIVE + - INACTIVE + - INVALID + GroupRuleUserCondition: + type: object + properties: + exclude: + type: array + items: + type: string + include: + type: array + items: + type: string + GroupSchema: + type: object + properties: + $schema: + readOnly: true + type: string + created: + readOnly: true + type: string + definitions: + $ref: '#/components/schemas/GroupSchemaDefinitions' + description: + type: string + id: + readOnly: true + type: string + lastUpdated: + readOnly: true + type: string + name: + readOnly: true + type: string + properties: + $ref: '#/components/schemas/UserSchemaProperties' + title: + type: string + type: + readOnly: true + type: string + _links: + additionalProperties: + type: object + readOnly: true + type: object + x-okta-allow-null-property-value-for-updates: true + GroupSchemaAttribute: + type: object + properties: + description: + type: string + enum: + items: + type: string + type: array + externalName: + type: string + externalNamespace: + type: string + items: + $ref: '#/components/schemas/UserSchemaAttributeItems' + master: + $ref: '#/components/schemas/UserSchemaAttributeMaster' + maxLength: + type: integer + minLength: + type: integer + mutability: + type: string + oneOf: + items: + $ref: '#/components/schemas/UserSchemaAttributeEnum' + type: array + permissions: + items: + $ref: '#/components/schemas/UserSchemaAttributePermission' + type: array + required: + type: boolean + scope: + $ref: '#/components/schemas/UserSchemaAttributeScope' + title: + type: string + type: + $ref: '#/components/schemas/UserSchemaAttributeType' + union: + $ref: '#/components/schemas/UserSchemaAttributeUnion' + unique: + type: string + GroupSchemaBase: + type: object + properties: + id: + readOnly: true + type: string + properties: + $ref: '#/components/schemas/GroupSchemaBaseProperties' + required: + items: + type: string + type: array + type: + type: string + GroupSchemaBaseProperties: + type: object + properties: + description: + $ref: '#/components/schemas/GroupSchemaAttribute' + name: + $ref: '#/components/schemas/GroupSchemaAttribute' + GroupSchemaCustom: + type: object + properties: + id: + readOnly: true + type: string + properties: + additionalProperties: + $ref: '#/components/schemas/GroupSchemaAttribute' + type: object + required: + items: + type: string + type: array + type: + type: string + GroupSchemaDefinitions: + type: object + properties: + base: + $ref: '#/components/schemas/GroupSchemaBase' + custom: + $ref: '#/components/schemas/GroupSchemaCustom' + GroupType: + type: string + enum: + - APP_GROUP + - BUILT_IN + - OKTA_GROUP + HardwareUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/HardwareUserFactorProfile' + HardwareUserFactorProfile: + type: object + properties: + credentialId: + type: string + HookKey: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + isUsed: + type: string + format: boolean + keyId: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + readOnly: false + _embedded: + $ref: '#/components/schemas/JsonWebKey' + HostedPage: + type: object + properties: + type: + $ref: '#/components/schemas/HostedPageType' + url: + type: string + required: + - type + HostedPageType: + type: string + enum: + - EXTERNALLY_HOSTED + - OKTA_DEFAULT + HrefObject: + title: Link Object + description: Singular link objected returned in HAL `_links` object. + type: object + properties: + hints: + type: object + properties: + allow: + type: array + items: + $ref: '#/components/schemas/HttpMethod' + href: + type: string + name: + type: string + type: + type: string + description: The media type of the link. If omitted, it is implicitly `application/json`. + required: + - href + HttpMethod: + type: string + enum: + - DELETE + - GET + - POST + - PUT + IamRole: + type: object + properties: + created: + type: string + format: date-time + description: Timestamp when the role was created + readOnly: true + description: + type: string + description: Description of the role + id: + type: string + description: Unique key for the role + readOnly: true + label: + type: string + description: Unique label for the role + lastUpdated: + type: string + format: date-time + description: Timestamp when the role was last updated + readOnly: true + permissions: + type: array + description: Array of permissions that the role will grant. See [Permission Types](https://developer.okta.com/docs/concepts/role-assignment/#permission-types). + items: + $ref: '#/components/schemas/RolePermissionType' + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + permissions: + $ref: '#/components/schemas/HrefObject' + readOnly: true + required: + - label + - description + - permissions + IamRoles: + type: object + properties: + roles: + type: array + items: + $ref: '#/components/schemas/IamRole' + _links: + type: object + properties: + next: + $ref: '#/components/schemas/HrefObject' + readOnly: true + IdentityProvider: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + nullable: true + id: + type: string + readOnly: true + issuerMode: + $ref: '#/components/schemas/IssuerMode' + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + policy: + $ref: '#/components/schemas/IdentityProviderPolicy' + protocol: + $ref: '#/components/schemas/Protocol' + status: + $ref: '#/components/schemas/LifecycleStatus' + type: + $ref: '#/components/schemas/IdentityProviderType' + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + IdentityProviderApplicationUser: + type: object + properties: + created: + type: string + externalId: + type: string + id: + type: string + readOnly: true + lastUpdated: + type: string + profile: + type: object + additionalProperties: + type: object + properties: {} + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + IdentityProviderCredentials: + type: object + properties: + client: + $ref: '#/components/schemas/IdentityProviderCredentialsClient' + signing: + $ref: '#/components/schemas/IdentityProviderCredentialsSigning' + trust: + $ref: '#/components/schemas/IdentityProviderCredentialsTrust' + IdentityProviderCredentialsClient: + type: object + properties: + client_id: + type: string + client_secret: + type: string + IdentityProviderCredentialsSigning: + type: object + properties: + kid: + type: string + IdentityProviderCredentialsTrust: + type: object + properties: + audience: + type: string + issuer: + type: string + kid: + type: string + revocation: + $ref: '#/components/schemas/IdentityProviderCredentialsTrustRevocation' + revocationCacheLifetime: + type: integer + IdentityProviderCredentialsTrustRevocation: + type: string + enum: + - CRL + - DELTA_CRL + - OCSP + IdentityProviderPolicy: + allOf: + - $ref: '#/components/schemas/Policy' + - type: object + properties: + accountLink: + $ref: '#/components/schemas/PolicyAccountLink' + conditions: + $ref: '#/components/schemas/PolicyRuleConditions' + maxClockSkew: + type: integer + provisioning: + $ref: '#/components/schemas/Provisioning' + subject: + $ref: '#/components/schemas/PolicySubject' + IdentityProviderPolicyProvider: + type: string + enum: + - ANY + - OKTA + - SPECIFIC_IDP + IdentityProviderPolicyRuleCondition: + type: object + properties: + idpIds: + type: array + items: + type: string + provider: + $ref: '#/components/schemas/IdentityProviderPolicyProvider' + IdentityProviderType: + type: string + enum: + - AgentlessDSSO + - FACEBOOK + - GOOGLE + - IWA + - LINKEDIN + - MICROSOFT + - OIDC + - OKTA + - SAML2 + - X509 + IdpPolicyRuleAction: + type: object + properties: + providers: + items: + $ref: '#/components/schemas/IdpPolicyRuleActionProvider' + type: array + IdpPolicyRuleActionProvider: + type: object + properties: + id: + readOnly: true + type: string + type: + type: string + IframeEmbedScopeAllowedApps: + type: string + enum: + - OKTA_ENDUSER + ImageUploadResponse: + type: object + properties: + url: + readOnly: true + type: string + InactivityPolicyRuleCondition: + type: object + properties: + number: + type: integer + unit: + type: string + InlineHook: + type: object + properties: + channel: + $ref: '#/components/schemas/InlineHookChannel' + created: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + status: + $ref: '#/components/schemas/InlineHookStatus' + type: + $ref: '#/components/schemas/InlineHookType' + version: + type: string + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + InlineHookChannel: + type: object + properties: + config: + $ref: '#/components/schemas/InlineHookChannelConfig' + type: + $ref: '#/components/schemas/InlineHookChannelType' + version: + type: string + discriminator: + propertyName: type + mapping: + HTTP: '#/components/schemas/InlineHookChannelHttp' + InlineHookChannelConfig: + type: object + properties: + authScheme: + $ref: '#/components/schemas/InlineHookChannelConfigAuthScheme' + headers: + type: array + items: + $ref: '#/components/schemas/InlineHookChannelConfigHeaders' + method: + type: string + uri: + type: string + InlineHookChannelConfigAuthScheme: + type: object + properties: + key: + type: string + type: + type: string + value: + type: string + InlineHookChannelConfigHeaders: + type: object + properties: + key: + type: string + value: + type: string + InlineHookChannelHttp: + allOf: + - $ref: '#/components/schemas/InlineHookChannel' + - type: object + properties: + config: + $ref: '#/components/schemas/InlineHookChannelConfig' + InlineHookChannelType: + type: string + enum: + - HTTP + - OAUTH + InlineHookOAuthBasicConfig: + allOf: + - $ref: '#/components/schemas/InlineHookChannelConfig' + type: object + properties: + authType: + type: string + clientId: + type: string + scope: + type: string + tokenUrl: + type: string + InlineHookOAuthChannelConfig: + type: object + properties: + authType: + type: string + discriminator: + propertyName: authType + mapping: + client_secret_post: '#/components/schemas/InlineHookOAuthClientSecretConfig' + private_key_jwt: '#/components/schemas/InlineHookOAuthPrivateKeyJwtConfig' + InlineHookOAuthClientSecretConfig: + allOf: + - $ref: '#/components/schemas/InlineHookOAuthBasicConfig' + type: object + properties: + clientSecret: + type: string + InlineHookOAuthPrivateKeyJwtConfig: + allOf: + - $ref: '#/components/schemas/InlineHookOAuthBasicConfig' + type: object + properties: + hookKeyId: + type: string + InlineHookPayload: + type: object + x-okta-extensible: true + InlineHookResponse: + type: object + properties: + commands: + type: array + items: + $ref: '#/components/schemas/InlineHookResponseCommands' + InlineHookResponseCommandValue: + type: object + properties: + op: + type: string + path: + type: string + value: + type: string + InlineHookResponseCommands: + type: object + properties: + type: + type: string + value: + type: array + items: + $ref: '#/components/schemas/InlineHookResponseCommandValue' + InlineHookStatus: + type: string + enum: + - ACTIVE + - INACTIVE + InlineHookType: + type: string + enum: + - com.okta.import.transform + - com.okta.oauth2.tokens.transform + - com.okta.saml.tokens.transform + - com.okta.user.credential.password.import + - com.okta.user.pre-registration + IssuerMode: + type: string + enum: + - CUSTOM_URL + - DYNAMIC + - ORG_URL + JsonWebKey: + type: object + properties: + alg: + type: string + created: + type: string + format: date-time + e: + type: string + expiresAt: + type: string + format: date-time + key_ops: + type: array + items: + type: string + kid: + type: string + kty: + type: string + lastUpdated: + type: string + format: date-time + 'n': + type: string + status: + type: string + use: + type: string + x5c: + type: array + items: + type: string + x5t: + type: string + x5t#S256: + type: string + x5u: + type: string + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + JwkUse: + type: object + properties: + use: + $ref: '#/components/schemas/JwkUseType' + JwkUseType: + type: string + enum: + - sig + KeyRequest: + type: object + properties: + name: + type: string + KnowledgeConstraint: + allOf: + - $ref: '#/components/schemas/AccessPolicyConstraint' + Language: + description: The language specified as an [IETF BCP 47 language tag](https://datatracker.ietf.org/doc/html/rfc5646). + type: string + LifecycleCreateSettingObject: + type: object + properties: + status: + $ref: '#/components/schemas/EnabledStatus' + LifecycleDeactivateSettingObject: + type: object + properties: + status: + $ref: '#/components/schemas/EnabledStatus' + LifecycleExpirationPolicyRuleCondition: + type: object + properties: + lifecycleStatus: + type: string + number: + type: integer + unit: + type: string + LifecycleStatus: + type: string + enum: + - ACTIVE + - INACTIVE + LinkedObject: + type: object + properties: + associated: + $ref: '#/components/schemas/LinkedObjectDetails' + primary: + $ref: '#/components/schemas/LinkedObjectDetails' + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + LinkedObjectDetails: + type: object + properties: + description: + type: string + name: + type: string + title: + type: string + type: + $ref: '#/components/schemas/LinkedObjectDetailsType' + LinkedObjectDetailsType: + type: string + enum: + - USER + LoadingPageTouchPointVariant: + type: string + enum: + - NONE + - OKTA_DEFAULT + LocationGranularity: + type: string + enum: + - CITY + - COUNTRY + - LAT_LONG + - SUBDIVISION + LogActor: + type: object + properties: + alternateId: + type: string + readOnly: true + detail: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + displayName: + type: string + readOnly: true + id: + type: string + readOnly: true + type: + type: string + readOnly: true + LogAuthenticationContext: + type: object + properties: + authenticationProvider: + $ref: '#/components/schemas/LogAuthenticationProvider' + authenticationStep: + type: integer + readOnly: true + credentialProvider: + $ref: '#/components/schemas/LogCredentialProvider' + credentialType: + $ref: '#/components/schemas/LogCredentialType' + externalSessionId: + type: string + readOnly: true + interface: + type: string + readOnly: true + issuer: + $ref: '#/components/schemas/LogIssuer' + LogAuthenticationProvider: + type: string + enum: + - ACTIVE_DIRECTORY + - FACTOR_PROVIDER + - FEDERATION + - LDAP + - OKTA_AUTHENTICATION_PROVIDER + - SOCIAL + LogClient: + type: object + properties: + device: + type: string + readOnly: true + geographicalContext: + $ref: '#/components/schemas/LogGeographicalContext' + id: + type: string + readOnly: true + ipAddress: + type: string + readOnly: true + userAgent: + $ref: '#/components/schemas/LogUserAgent' + zone: + type: string + readOnly: true + LogCredentialProvider: + type: string + enum: + - DUO + - GOOGLE + - OKTA_AUTHENTICATION_PROVIDER + - OKTA_CREDENTIAL_PROVIDER + - RSA + - SYMANTEC + - YUBIKEY + LogCredentialType: + type: string + enum: + - ASSERTION + - EMAIL + - IWA + - JWT + - OAuth 2.0 + - OTP + - PASSWORD + - SMS + LogDebugContext: + type: object + properties: + debugData: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + LogEvent: + type: object + properties: + actor: + $ref: '#/components/schemas/LogActor' + authenticationContext: + $ref: '#/components/schemas/LogAuthenticationContext' + client: + $ref: '#/components/schemas/LogClient' + debugContext: + $ref: '#/components/schemas/LogDebugContext' + displayMessage: + type: string + readOnly: true + eventType: + type: string + readOnly: true + legacyEventType: + type: string + readOnly: true + outcome: + $ref: '#/components/schemas/LogOutcome' + published: + type: string + format: date-time + readOnly: true + request: + $ref: '#/components/schemas/LogRequest' + securityContext: + $ref: '#/components/schemas/LogSecurityContext' + severity: + $ref: '#/components/schemas/LogSeverity' + target: + type: array + readOnly: true + items: + $ref: '#/components/schemas/LogTarget' + transaction: + $ref: '#/components/schemas/LogTransaction' + uuid: + type: string + readOnly: true + version: + type: string + readOnly: true + LogGeographicalContext: + type: object + properties: + city: + type: string + readOnly: true + country: + type: string + readOnly: true + geolocation: + $ref: '#/components/schemas/LogGeolocation' + postalCode: + type: string + readOnly: true + state: + type: string + readOnly: true + LogGeolocation: + type: object + properties: + lat: + type: number + format: double + readOnly: true + lon: + type: number + format: double + readOnly: true + LogIpAddress: + type: object + properties: + geographicalContext: + $ref: '#/components/schemas/LogGeographicalContext' + ip: + type: string + readOnly: true + source: + type: string + readOnly: true + version: + type: string + readOnly: true + LogIssuer: + type: object + properties: + id: + type: string + readOnly: true + type: + type: string + readOnly: true + LogOutcome: + type: object + properties: + reason: + type: string + readOnly: true + result: + type: string + readOnly: true + LogRequest: + type: object + properties: + ipChain: + type: array + readOnly: true + items: + $ref: '#/components/schemas/LogIpAddress' + LogSecurityContext: + type: object + properties: + asNumber: + type: integer + readOnly: true + asOrg: + type: string + readOnly: true + domain: + type: string + readOnly: true + isp: + type: string + readOnly: true + isProxy: + type: boolean + readOnly: true + LogSeverity: + type: string + enum: + - DEBUG + - ERROR + - INFO + - WARN + LogStream: + type: object + properties: + created: + type: string + format: date-time + description: Timestamp when the Log Stream was created + readOnly: true + id: + type: string + description: Unique key for the Log Stream + readOnly: true + lastUpdated: + type: string + format: date-time + description: Timestamp when the Log Stream was last updated + readOnly: true + name: + type: string + description: Unique name for the Log Stream + status: + $ref: '#/components/schemas/LifecycleStatus' + type: + $ref: '#/components/schemas/LogStreamType' + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + activate: + $ref: '#/components/schemas/HrefObject' + deactivate: + $ref: '#/components/schemas/HrefObject' + readOnly: true + discriminator: + propertyName: type + mapping: + aws_eventbridge: '#/components/schemas/LogStreamAws' + splunk_cloud_logstreaming: '#/components/schemas/LogStreamSplunk' + LogStreamAws: + allOf: + - $ref: '#/components/schemas/LogStream' + - type: object + properties: + settings: + $ref: '#/components/schemas/LogStreamSettingsAws' + LogStreamSchema: + type: object + properties: + $schema: + type: string + readOnly: true + created: + type: string + readOnly: true + errorMessage: + type: object + id: + type: string + readOnly: true + lastUpdated: + type: string + readOnly: true + name: + type: string + readOnly: true + properties: + type: object + required: + type: array + items: + type: string + title: + type: string + type: + type: string + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + LogStreamSettings: + type: object + LogStreamSettingsAws: + allOf: + - $ref: '#/components/schemas/LogStreamSettings' + - description: The AWS EventBridge Settings object specifies the configuration for the `aws_eventbridge` Log Stream type. This can't be modified after creation. + type: object + properties: + accountId: + type: string + description: Your AWS account ID + minLength: 12 + maxLength: 12 + eventSourceName: + type: string + description: An alphanumeric name (no spaces) to identify this event source in AWS EventBridge + pattern: ^[a-zA-Z0-9.\-_]$ + minLength: 1 + maxLength: 75 + region: + $ref: '#/components/schemas/AwsRegion' + LogStreamSettingsSplunk: + allOf: + - $ref: '#/components/schemas/LogStreamSettings' + - description: The Splunk Cloud Settings object specifies the configuration for the `splunk_cloud_logstreaming` Log Stream type. + type: object + properties: + host: + type: string + description: 'The domain name for your Splunk Cloud instance. Don''t include `http` or `https` in the string. For example: `acme.splunkcloud.com`' + minLength: 17 + maxLength: 116 + token: + type: string + description: The HEC token for your Splunk Cloud HTTP Event Collector + pattern: (?i)^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$ + LogStreamSplunk: + allOf: + - $ref: '#/components/schemas/LogStream' + - type: object + properties: + settings: + $ref: '#/components/schemas/LogStreamSettingsSplunk' + LogStreamType: + description: The Log Stream type specifies the streaming provider used. Okta supports [AWS EventBridge](https://aws.amazon.com/eventbridge/) and [Splunk Cloud](https://www.splunk.com/en_us/software/splunk-cloud-platform.html). + type: string + enum: + - aws_eventbridge + - splunk_cloud_logstreaming + LogTarget: + type: object + properties: + alternateId: + type: string + readOnly: true + detailEntry: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + displayName: + type: string + readOnly: true + id: + type: string + readOnly: true + type: + type: string + readOnly: true + LogTransaction: + type: object + properties: + detail: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + id: + type: string + readOnly: true + type: + type: string + readOnly: true + LogUserAgent: + type: object + properties: + browser: + type: string + readOnly: true + os: + type: string + readOnly: true + rawUserAgent: + type: string + readOnly: true + MDMEnrollmentPolicyEnrollment: + type: string + enum: + - ANY_OR_NONE + - OMM + MDMEnrollmentPolicyRuleCondition: + type: object + properties: + blockNonSafeAndroid: + type: boolean + enrollment: + $ref: '#/components/schemas/MDMEnrollmentPolicyEnrollment' + MultifactorEnrollmentPolicy: + allOf: + - $ref: '#/components/schemas/Policy' + - type: object + properties: + conditions: + $ref: '#/components/schemas/PolicyRuleConditions' + settings: + $ref: '#/components/schemas/MultifactorEnrollmentPolicySettings' + MultifactorEnrollmentPolicyAuthenticatorSettings: + type: object + properties: + enroll: + type: object + properties: + self: + $ref: '#/components/schemas/MultifactorEnrollmentPolicyAuthenticatorStatus' + key: + $ref: '#/components/schemas/MultifactorEnrollmentPolicyAuthenticatorType' + MultifactorEnrollmentPolicyAuthenticatorStatus: + type: string + enum: + - NOT_ALLOWED + - OPTIONAL + - REQUIRED + MultifactorEnrollmentPolicyAuthenticatorType: + type: string + enum: + - custom_app + - custom_otp + - duo + - external_idp + - google_otp + - okta_email + - okta_password + - okta_verify + - onprem_mfa + - phone_number + - rsa_token + - security_question + - symantec_vip + - webauthn + - yubikey_token + MultifactorEnrollmentPolicySettings: + type: object + properties: + authenticators: + items: + $ref: '#/components/schemas/MultifactorEnrollmentPolicyAuthenticatorSettings' + type: array + type: + $ref: '#/components/schemas/MultifactorEnrollmentPolicySettingsType' + MultifactorEnrollmentPolicySettingsType: + type: string + enum: + - AUTHENTICATORS + NetworkZone: + type: object + properties: + asns: + type: array + items: + type: string + created: + type: string + format: date-time + readOnly: true + gateways: + type: array + items: + $ref: '#/components/schemas/NetworkZoneAddress' + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + locations: + type: array + items: + $ref: '#/components/schemas/NetworkZoneLocation' + name: + type: string + proxies: + type: array + items: + $ref: '#/components/schemas/NetworkZoneAddress' + proxyType: + type: string + status: + $ref: '#/components/schemas/NetworkZoneStatus' + system: + type: boolean + type: + $ref: '#/components/schemas/NetworkZoneType' + usage: + $ref: '#/components/schemas/NetworkZoneUsage' + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + NetworkZoneAddress: + type: object + properties: + type: + $ref: '#/components/schemas/NetworkZoneAddressType' + value: + type: string + NetworkZoneAddressType: + type: string + enum: + - CIDR + - RANGE + NetworkZoneLocation: + type: object + properties: + country: + type: string + region: + type: string + NetworkZoneStatus: + type: string + enum: + - ACTIVE + - INACTIVE + NetworkZoneType: + type: string + enum: + - DYNAMIC + - IP + NetworkZoneUsage: + type: string + enum: + - BLOCKLIST + - POLICY + NotificationType: + type: string + enum: + - AD_AGENT + - APP_IMPORT + - CONNECTOR_AGENT + - IWA_AGENT + - LDAP_AGENT + - OKTA_ANNOUNCEMENT + - OKTA_ISSUE + - OKTA_UPDATE + - RATELIMIT_NOTIFICATION + - REPORT_SUSPICIOUS_ACTIVITY + - USER_DEPROVISION + - USER_LOCKED_OUT + OAuth2Actor: + type: object + properties: + id: + type: string + readOnly: true + type: + type: string + OAuth2Claim: + type: object + properties: + alwaysIncludeInToken: + type: boolean + claimType: + $ref: '#/components/schemas/OAuth2ClaimType' + conditions: + $ref: '#/components/schemas/OAuth2ClaimConditions' + group_filter_type: + $ref: '#/components/schemas/OAuth2ClaimGroupFilterType' + id: + type: string + readOnly: true + name: + type: string + status: + $ref: '#/components/schemas/LifecycleStatus' + system: + type: boolean + value: + type: string + valueType: + $ref: '#/components/schemas/OAuth2ClaimValueType' + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + OAuth2ClaimConditions: + type: object + properties: + scopes: + type: array + items: + type: string + OAuth2ClaimGroupFilterType: + type: string + enum: + - CONTAINS + - EQUALS + - REGEX + - STARTS_WITH + OAuth2ClaimType: + type: string + enum: + - IDENTITY + - RESOURCE + OAuth2ClaimValueType: + type: string + enum: + - EXPRESSION + - GROUPS + - SYSTEM + OAuth2Client: + type: object + properties: + client_id: + type: string + readOnly: true + client_name: + type: string + readOnly: true + client_uri: + type: string + readOnly: true + logo_uri: + type: string + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + OAuth2RefreshToken: + type: object + properties: + clientId: + type: string + created: + type: string + format: date-time + readOnly: true + createdBy: + $ref: '#/components/schemas/OAuth2Actor' + expiresAt: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + issuer: + type: string + lastUpdated: + type: string + format: date-time + readOnly: true + scopes: + type: array + items: + type: string + status: + $ref: '#/components/schemas/GrantOrTokenStatus' + userId: + type: string + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + OAuth2Scope: + type: object + properties: + consent: + $ref: '#/components/schemas/OAuth2ScopeConsentType' + default: + type: boolean + description: + type: string + displayName: + type: string + id: + type: string + readOnly: true + metadataPublish: + $ref: '#/components/schemas/OAuth2ScopeMetadataPublish' + name: + type: string + system: + type: boolean + OAuth2ScopeConsentGrant: + type: object + properties: + clientId: + type: string + created: + type: string + format: date-time + readOnly: true + createdBy: + $ref: '#/components/schemas/OAuth2Actor' + id: + type: string + readOnly: true + issuer: + type: string + lastUpdated: + type: string + format: date-time + readOnly: true + scopeId: + type: string + source: + $ref: '#/components/schemas/OAuth2ScopeConsentGrantSource' + status: + $ref: '#/components/schemas/GrantOrTokenStatus' + userId: + type: string + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + OAuth2ScopeConsentGrantSource: + type: string + enum: + - ADMIN + - END_USER + OAuth2ScopeConsentType: + type: string + enum: + - ADMIN + - IMPLICIT + - REQUIRED + OAuth2ScopeMetadataPublish: + type: string + enum: + - ALL_CLIENTS + - NO_CLIENTS + OAuth2ScopesMediationPolicyRuleCondition: + type: object + properties: + include: + type: array + items: + type: string + OAuth2Token: + type: object + properties: + clientId: + type: string + created: + type: string + format: date-time + readOnly: true + expiresAt: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + issuer: + type: string + lastUpdated: + type: string + format: date-time + readOnly: true + scopes: + type: array + items: + type: string + status: + $ref: '#/components/schemas/GrantOrTokenStatus' + userId: + type: string + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + OAuthApplicationCredentials: + allOf: + - $ref: '#/components/schemas/ApplicationCredentials' + - type: object + properties: + oauthClient: + $ref: '#/components/schemas/ApplicationCredentialsOAuthClient' + OAuthEndpointAuthenticationMethod: + type: string + enum: + - client_secret_basic + - client_secret_jwt + - client_secret_post + - none + - private_key_jwt + OAuthGrantType: + type: string + enum: + - authorization_code + - client_credentials + - implicit + - interaction_code + - password + - refresh_token + OAuthResponseType: + type: string + enum: + - code + - id_token + - token + OktaSignOnPolicy: + allOf: + - $ref: '#/components/schemas/Policy' + - type: object + properties: + conditions: + $ref: '#/components/schemas/OktaSignOnPolicyConditions' + OktaSignOnPolicyConditions: + allOf: + - $ref: '#/components/schemas/PolicyRuleConditions' + - type: object + properties: + people: + $ref: '#/components/schemas/PolicyPeopleCondition' + OktaSignOnPolicyFactorPromptMode: + type: string + enum: + - ALWAYS + - DEVICE + - SESSION + OktaSignOnPolicyRule: + allOf: + - $ref: '#/components/schemas/PolicyRule' + - type: object + properties: + actions: + $ref: '#/components/schemas/OktaSignOnPolicyRuleActions' + conditions: + $ref: '#/components/schemas/OktaSignOnPolicyRuleConditions' + OktaSignOnPolicyRuleActions: + allOf: + - $ref: '#/components/schemas/PolicyRuleActions' + - type: object + properties: + signon: + $ref: '#/components/schemas/OktaSignOnPolicyRuleSignonActions' + OktaSignOnPolicyRuleConditions: + allOf: + - $ref: '#/components/schemas/PolicyRuleConditions' + - type: object + properties: + authContext: + $ref: '#/components/schemas/PolicyRuleAuthContextCondition' + network: + $ref: '#/components/schemas/PolicyNetworkCondition' + people: + $ref: '#/components/schemas/PolicyPeopleCondition' + OktaSignOnPolicyRuleSignonActions: + type: object + properties: + access: + $ref: '#/components/schemas/PolicyAccess' + factorLifetime: + type: integer + factorPromptMode: + $ref: '#/components/schemas/OktaSignOnPolicyFactorPromptMode' + rememberDeviceByDefault: + type: boolean + default: false + requireFactor: + type: boolean + default: false + session: + $ref: '#/components/schemas/OktaSignOnPolicyRuleSignonSessionActions' + OktaSignOnPolicyRuleSignonSessionActions: + type: object + properties: + maxSessionIdleMinutes: + type: integer + maxSessionLifetimeMinutes: + type: integer + usePersistentCookie: + type: boolean + default: false + OpenIdConnectApplication: + x-okta-defined-as: + name: oidc_client + allOf: + - $ref: '#/components/schemas/Application' + - type: object + properties: + credentials: + $ref: '#/components/schemas/OAuthApplicationCredentials' + name: + type: string + default: oidc_client + settings: + $ref: '#/components/schemas/OpenIdConnectApplicationSettings' + OpenIdConnectApplicationConsentMethod: + type: string + enum: + - REQUIRED + - TRUSTED + OpenIdConnectApplicationIdpInitiatedLogin: + type: object + properties: + default_scope: + type: array + items: + type: string + mode: + type: string + OpenIdConnectApplicationIssuerMode: + type: string + enum: + - CUSTOM_URL + - DYNAMIC + - ORG_URL + OpenIdConnectApplicationSettings: + allOf: + - $ref: '#/components/schemas/ApplicationSettings' + - type: object + properties: + oauthClient: + $ref: '#/components/schemas/OpenIdConnectApplicationSettingsClient' + OpenIdConnectApplicationSettingsClient: + type: object + properties: + application_type: + $ref: '#/components/schemas/OpenIdConnectApplicationType' + client_uri: + type: string + consent_method: + $ref: '#/components/schemas/OpenIdConnectApplicationConsentMethod' + grant_types: + type: array + items: + $ref: '#/components/schemas/OAuthGrantType' + idp_initiated_login: + $ref: '#/components/schemas/OpenIdConnectApplicationIdpInitiatedLogin' + initiate_login_uri: + type: string + issuer_mode: + $ref: '#/components/schemas/OpenIdConnectApplicationIssuerMode' + jwks: + $ref: '#/components/schemas/OpenIdConnectApplicationSettingsClientKeys' + logo_uri: + type: string + policy_uri: + type: string + post_logout_redirect_uris: + type: array + items: + type: string + redirect_uris: + type: array + items: + type: string + refresh_token: + $ref: '#/components/schemas/OpenIdConnectApplicationSettingsRefreshToken' + response_types: + type: array + items: + $ref: '#/components/schemas/OAuthResponseType' + tos_uri: + type: string + wildcard_redirect: + type: string + OpenIdConnectApplicationSettingsClientKeys: + type: object + properties: + keys: + type: array + items: + $ref: '#/components/schemas/JsonWebKey' + OpenIdConnectApplicationSettingsRefreshToken: + type: object + properties: + leeway: + type: integer + rotation_type: + $ref: '#/components/schemas/OpenIdConnectRefreshTokenRotationType' + OpenIdConnectApplicationType: + type: string + enum: + - browser + - native + - service + - web + OpenIdConnectRefreshTokenRotationType: + type: string + enum: + - ROTATE + - STATIC + OperationalStatus: + description: Operational status of a given agent + type: string + enum: + - DEGRADED + - DISRUPTED + - INACTIVE + - OPERATIONAL + OrgContactType: + type: string + enum: + - BILLING + - TECHNICAL + OrgContactTypeObj: + type: object + properties: + contactType: + $ref: '#/components/schemas/OrgContactType' + _links: + additionalProperties: + type: object + OrgContactUser: + type: object + properties: + userId: + type: string + _links: + additionalProperties: + type: object + readOnly: true + type: object + OrgOktaCommunicationSetting: + type: object + properties: + optOutEmailUsers: + type: boolean + readOnly: true + _links: + additionalProperties: + type: object + OrgOktaSupportSetting: + type: string + enum: + - DISABLED + - ENABLED + OrgOktaSupportSettingsObj: + type: object + properties: + expiration: + format: date-time + type: string + readOnly: true + support: + $ref: '#/components/schemas/OrgOktaSupportSetting' + _links: + additionalProperties: + type: object + OrgPreferences: + type: object + properties: + showEndUserFooter: + type: boolean + readOnly: true + _links: + additionalProperties: + type: object + OrgSetting: + type: object + properties: + address1: + type: string + address2: + type: string + city: + type: string + companyName: + type: string + country: + type: string + created: + format: date-time + readOnly: true + type: string + endUserSupportHelpURL: + type: string + expiresAt: + format: date-time + readOnly: true + type: string + id: + readOnly: true + type: string + lastUpdated: + format: date-time + readOnly: true + type: string + phoneNumber: + type: string + postalCode: + type: string + state: + type: string + status: + readOnly: true + type: string + subdomain: + readOnly: true + type: string + supportPhoneNumber: + type: string + website: + type: string + _links: + additionalProperties: + type: object + PageRoot: + type: object + properties: + _embedded: + type: object + properties: + default: + $ref: '#/components/schemas/CustomizablePage' + customized: + $ref: '#/components/schemas/CustomizablePage' + customizedUrl: + type: string + format: uri + preview: + $ref: '#/components/schemas/CustomizablePage' + previewUrl: + type: string + format: uri + readOnly: true + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + default: + $ref: '#/components/schemas/HrefObject' + customized: + $ref: '#/components/schemas/HrefObject' + preview: + $ref: '#/components/schemas/HrefObject' + readOnly: true + PasswordCredential: + type: object + properties: + hash: + $ref: '#/components/schemas/PasswordCredentialHash' + hook: + $ref: '#/components/schemas/PasswordCredentialHook' + value: + type: string + format: password + PasswordCredentialHash: + type: object + properties: + algorithm: + $ref: '#/components/schemas/PasswordCredentialHashAlgorithm' + salt: + type: string + saltOrder: + type: string + value: + type: string + workFactor: + type: integer + PasswordCredentialHashAlgorithm: + type: string + enum: + - BCRYPT + - MD5 + - SHA-1 + - SHA-256 + - SHA-512 + PasswordCredentialHook: + type: object + properties: + type: + type: string + PasswordDictionary: + type: object + properties: + common: + $ref: '#/components/schemas/PasswordDictionaryCommon' + PasswordDictionaryCommon: + type: object + properties: + exclude: + type: boolean + default: false + PasswordExpirationPolicyRuleCondition: + type: object + properties: + number: + type: integer + unit: + type: string + PasswordPolicy: + allOf: + - $ref: '#/components/schemas/Policy' + - type: object + properties: + conditions: + $ref: '#/components/schemas/PasswordPolicyConditions' + settings: + $ref: '#/components/schemas/PasswordPolicySettings' + PasswordPolicyAuthenticationProviderCondition: + type: object + properties: + include: + type: array + items: + type: string + provider: + $ref: '#/components/schemas/PasswordPolicyAuthenticationProviderType' + PasswordPolicyAuthenticationProviderType: + type: string + enum: + - ACTIVE_DIRECTORY + - ANY + - LDAP + - OKTA + PasswordPolicyConditions: + allOf: + - $ref: '#/components/schemas/PolicyRuleConditions' + - type: object + properties: + authProvider: + $ref: '#/components/schemas/PasswordPolicyAuthenticationProviderCondition' + people: + $ref: '#/components/schemas/PolicyPeopleCondition' + PasswordPolicyDelegationSettings: + type: object + properties: + options: + $ref: '#/components/schemas/PasswordPolicyDelegationSettingsOptions' + PasswordPolicyDelegationSettingsOptions: + type: object + properties: + skipUnlock: + type: boolean + PasswordPolicyPasswordSettings: + type: object + properties: + age: + $ref: '#/components/schemas/PasswordPolicyPasswordSettingsAge' + complexity: + $ref: '#/components/schemas/PasswordPolicyPasswordSettingsComplexity' + lockout: + $ref: '#/components/schemas/PasswordPolicyPasswordSettingsLockout' + PasswordPolicyPasswordSettingsAge: + type: object + properties: + expireWarnDays: + type: integer + historyCount: + type: integer + maxAgeDays: + type: integer + minAgeMinutes: + type: integer + PasswordPolicyPasswordSettingsComplexity: + type: object + properties: + dictionary: + $ref: '#/components/schemas/PasswordDictionary' + excludeAttributes: + type: array + items: + type: string + excludeUsername: + type: boolean + default: true + minLength: + type: integer + minLowerCase: + type: integer + minNumber: + type: integer + minSymbol: + type: integer + minUpperCase: + type: integer + PasswordPolicyPasswordSettingsLockout: + type: object + properties: + autoUnlockMinutes: + type: integer + maxAttempts: + type: integer + showLockoutFailures: + type: boolean + userLockoutNotificationChannels: + type: array + items: + type: string + PasswordPolicyRecoveryEmail: + type: object + properties: + properties: + $ref: '#/components/schemas/PasswordPolicyRecoveryEmailProperties' + status: + $ref: '#/components/schemas/LifecycleStatus' + PasswordPolicyRecoveryEmailProperties: + type: object + properties: + recoveryToken: + $ref: '#/components/schemas/PasswordPolicyRecoveryEmailRecoveryToken' + PasswordPolicyRecoveryEmailRecoveryToken: + type: object + properties: + tokenLifetimeMinutes: + type: integer + PasswordPolicyRecoveryFactorSettings: + type: object + properties: + status: + $ref: '#/components/schemas/LifecycleStatus' + PasswordPolicyRecoveryFactors: + type: object + properties: + okta_call: + $ref: '#/components/schemas/PasswordPolicyRecoveryFactorSettings' + okta_email: + $ref: '#/components/schemas/PasswordPolicyRecoveryEmail' + okta_sms: + $ref: '#/components/schemas/PasswordPolicyRecoveryFactorSettings' + recovery_question: + $ref: '#/components/schemas/PasswordPolicyRecoveryQuestion' + PasswordPolicyRecoveryQuestion: + type: object + properties: + properties: + $ref: '#/components/schemas/PasswordPolicyRecoveryQuestionProperties' + status: + $ref: '#/components/schemas/LifecycleStatus' + PasswordPolicyRecoveryQuestionComplexity: + type: object + properties: + minLength: + type: integer + readOnly: true + PasswordPolicyRecoveryQuestionProperties: + type: object + properties: + complexity: + $ref: '#/components/schemas/PasswordPolicyRecoveryQuestionComplexity' + PasswordPolicyRecoverySettings: + type: object + properties: + factors: + $ref: '#/components/schemas/PasswordPolicyRecoveryFactors' + PasswordPolicyRule: + allOf: + - $ref: '#/components/schemas/PolicyRule' + - type: object + properties: + actions: + $ref: '#/components/schemas/PasswordPolicyRuleActions' + conditions: + $ref: '#/components/schemas/PasswordPolicyRuleConditions' + PasswordPolicyRuleAction: + type: object + properties: + access: + $ref: '#/components/schemas/PolicyAccess' + PasswordPolicyRuleActions: + allOf: + - $ref: '#/components/schemas/PolicyRuleActions' + - type: object + properties: + passwordChange: + $ref: '#/components/schemas/PasswordPolicyRuleAction' + selfServicePasswordReset: + $ref: '#/components/schemas/PasswordPolicyRuleAction' + selfServiceUnlock: + $ref: '#/components/schemas/PasswordPolicyRuleAction' + PasswordPolicyRuleConditions: + allOf: + - $ref: '#/components/schemas/PolicyRuleConditions' + - type: object + properties: + network: + $ref: '#/components/schemas/PolicyNetworkCondition' + people: + $ref: '#/components/schemas/PolicyPeopleCondition' + PasswordPolicySettings: + type: object + properties: + delegation: + $ref: '#/components/schemas/PasswordPolicyDelegationSettings' + password: + $ref: '#/components/schemas/PasswordPolicyPasswordSettings' + recovery: + $ref: '#/components/schemas/PasswordPolicyRecoverySettings' + PasswordSettingObject: + type: object + properties: + change: + $ref: '#/components/schemas/ChangeEnum' + seed: + $ref: '#/components/schemas/SeedEnum' + status: + $ref: '#/components/schemas/EnabledStatus' + PerClientRateLimitMode: + type: string + enum: + - DISABLE + - ENFORCE + - PREVIEW + PerClientRateLimitSettings: + title: PerClientRateLimitSettings + description: '' + type: object + properties: + defaultMode: + $ref: '#/components/schemas/PerClientRateLimitMode' + description: The default PerClientRateLimitMode that applies to any use case in the absence of a more specific override + useCaseModeOverrides: + description: A map of Per-Client Rate Limit Use Case to the applicable PerClientRateLimitMode. Overrides the `defaultMode` property for the specified use cases. + type: object + properties: + LOGIN_PAGE: + $ref: '#/components/schemas/PerClientRateLimitMode' + OAUTH2_AUTHORIZE: + $ref: '#/components/schemas/PerClientRateLimitMode' + OIE_APP_INTENT: + $ref: '#/components/schemas/PerClientRateLimitMode' + required: + - defaultMode + Permission: + type: object + properties: + created: + type: string + format: date-time + description: Timestamp when the role was created + readOnly: true + label: + type: string + description: The permission type + readOnly: true + lastUpdated: + type: string + format: date-time + description: Timestamp when the role was last updated + readOnly: true + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + role: + $ref: '#/components/schemas/HrefObject' + readOnly: true + Permissions: + type: object + properties: + permissions: + type: array + items: + $ref: '#/components/schemas/Permission' + PipelineType: + description: The authentication pipeline of the org. `idx` means the org is using the Identity Engine, while `v1` means the org is using the Classic authentication pipeline. + type: string + enum: + - idx + - v1 + Platform: + type: string + enum: + - ANDROID + - IOS + - MACOS + - WINDOWS + PlatformConditionEvaluatorPlatform: + type: object + properties: + os: + $ref: '#/components/schemas/PlatformConditionEvaluatorPlatformOperatingSystem' + type: + $ref: '#/components/schemas/PolicyPlatformType' + PlatformConditionEvaluatorPlatformOperatingSystem: + type: object + properties: + expression: + type: string + type: + $ref: '#/components/schemas/PolicyPlatformOperatingSystemType' + version: + $ref: '#/components/schemas/PlatformConditionEvaluatorPlatformOperatingSystemVersion' + PlatformConditionEvaluatorPlatformOperatingSystemVersion: + type: object + properties: + matchType: + $ref: '#/components/schemas/PlatformConditionOperatingSystemVersionMatchType' + value: + type: string + PlatformConditionOperatingSystemVersionMatchType: + type: string + enum: + - EXPRESSION + - SEMVER + PlatformPolicyRuleCondition: + type: object + properties: + exclude: + type: array + items: + $ref: '#/components/schemas/PlatformConditionEvaluatorPlatform' + include: + type: array + items: + $ref: '#/components/schemas/PlatformConditionEvaluatorPlatform' + Policy: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + description: + type: string + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + priority: + type: integer + status: + $ref: '#/components/schemas/LifecycleStatus' + system: + type: boolean + type: + $ref: '#/components/schemas/PolicyType' + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + discriminator: + propertyName: type + mapping: + ACCESS_POLICY: '#/components/schemas/AccessPolicy' + IDP_DISCOVERY: '#/components/schemas/IdentityProviderPolicy' + MFA_ENROLL: '#/components/schemas/MultifactorEnrollmentPolicy' + OAUTH_AUTHORIZATION_POLICY: '#/components/schemas/AuthorizationServerPolicy' + OKTA_SIGN_ON: '#/components/schemas/OktaSignOnPolicy' + PASSWORD: '#/components/schemas/PasswordPolicy' + PROFILE_ENROLLMENT: '#/components/schemas/ProfileEnrollmentPolicy' + PolicyAccess: + type: string + enum: + - ALLOW + - DENY + PolicyAccountLink: + type: object + properties: + action: + $ref: '#/components/schemas/PolicyAccountLinkAction' + filter: + $ref: '#/components/schemas/PolicyAccountLinkFilter' + PolicyAccountLinkAction: + type: string + enum: + - AUTO + - DISABLED + PolicyAccountLinkFilter: + type: object + properties: + groups: + $ref: '#/components/schemas/PolicyAccountLinkFilterGroups' + PolicyAccountLinkFilterGroups: + type: object + properties: + include: + type: array + items: + type: string + PolicyNetworkCondition: + type: object + properties: + connection: + $ref: '#/components/schemas/PolicyNetworkConnection' + exclude: + type: array + items: + type: string + include: + type: array + items: + type: string + PolicyNetworkConnection: + type: string + enum: + - ANYWHERE + - ZONE + PolicyPeopleCondition: + type: object + properties: + groups: + $ref: '#/components/schemas/GroupCondition' + users: + $ref: '#/components/schemas/UserCondition' + PolicyPlatformOperatingSystemType: + type: string + enum: + - ANDROID + - ANY + - IOS + - OSX + - OTHER + - WINDOWS + PolicyPlatformType: + type: string + enum: + - ANY + - DESKTOP + - MOBILE + - OTHER + PolicyRule: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + nullable: true + id: + type: string + lastUpdated: + type: string + format: date-time + readOnly: true + nullable: true + name: + type: string + priority: + type: integer + status: + $ref: '#/components/schemas/LifecycleStatus' + system: + type: boolean + default: false + type: + $ref: '#/components/schemas/PolicyRuleType' + discriminator: + propertyName: type + mapping: + ACCESS_POLICY: '#/components/schemas/AccessPolicyRule' + PASSWORD: '#/components/schemas/PasswordPolicyRule' + PROFILE_ENROLLMENT: '#/components/schemas/ProfileEnrollmentPolicyRule' + RESOURCE_ACCESS: '#/components/schemas/AuthorizationServerPolicyRule' + SIGN_ON: '#/components/schemas/OktaSignOnPolicyRule' + PolicyRuleActions: + type: object + properties: + enroll: + $ref: '#/components/schemas/PolicyRuleActionsEnroll' + idp: + $ref: '#/components/schemas/IdpPolicyRuleAction' + passwordChange: + $ref: '#/components/schemas/PasswordPolicyRuleAction' + selfServicePasswordReset: + $ref: '#/components/schemas/PasswordPolicyRuleAction' + selfServiceUnlock: + $ref: '#/components/schemas/PasswordPolicyRuleAction' + signon: + $ref: '#/components/schemas/OktaSignOnPolicyRuleSignonActions' + PolicyRuleActionsEnroll: + type: object + properties: + self: + $ref: '#/components/schemas/PolicyRuleActionsEnrollSelf' + PolicyRuleActionsEnrollSelf: + type: string + enum: + - CHALLENGE + - LOGIN + - NEVER + PolicyRuleAuthContextCondition: + type: object + properties: + authType: + $ref: '#/components/schemas/PolicyRuleAuthContextType' + PolicyRuleAuthContextType: + type: string + enum: + - ANY + - RADIUS + PolicyRuleConditions: + type: object + properties: + app: + $ref: '#/components/schemas/AppAndInstancePolicyRuleCondition' + apps: + $ref: '#/components/schemas/AppInstancePolicyRuleCondition' + authContext: + $ref: '#/components/schemas/PolicyRuleAuthContextCondition' + authProvider: + $ref: '#/components/schemas/PasswordPolicyAuthenticationProviderCondition' + beforeScheduledAction: + $ref: '#/components/schemas/BeforeScheduledActionPolicyRuleCondition' + clients: + $ref: '#/components/schemas/ClientPolicyCondition' + context: + $ref: '#/components/schemas/ContextPolicyRuleCondition' + device: + $ref: '#/components/schemas/DevicePolicyRuleCondition' + grantTypes: + $ref: '#/components/schemas/GrantTypePolicyRuleCondition' + groups: + $ref: '#/components/schemas/GroupPolicyRuleCondition' + identityProvider: + $ref: '#/components/schemas/IdentityProviderPolicyRuleCondition' + mdmEnrollment: + $ref: '#/components/schemas/MDMEnrollmentPolicyRuleCondition' + network: + $ref: '#/components/schemas/PolicyNetworkCondition' + people: + $ref: '#/components/schemas/PolicyPeopleCondition' + platform: + $ref: '#/components/schemas/PlatformPolicyRuleCondition' + risk: + $ref: '#/components/schemas/RiskPolicyRuleCondition' + riskScore: + $ref: '#/components/schemas/RiskScorePolicyRuleCondition' + scopes: + $ref: '#/components/schemas/OAuth2ScopesMediationPolicyRuleCondition' + userIdentifier: + $ref: '#/components/schemas/UserIdentifierPolicyRuleCondition' + users: + $ref: '#/components/schemas/UserPolicyRuleCondition' + userStatus: + $ref: '#/components/schemas/UserStatusPolicyRuleCondition' + PolicyRuleType: + type: string + enum: + - ACCESS_POLICY + - IDP_DISCOVERY + - MFA_ENROLL + - PASSWORD + - PROFILE_ENROLLMENT + - RESOURCE_ACCESS + - SIGN_ON + PolicySubject: + type: object + properties: + filter: + type: string + format: + type: array + items: + type: string + matchAttribute: + type: string + matchType: + $ref: '#/components/schemas/PolicySubjectMatchType' + userNameTemplate: + $ref: '#/components/schemas/PolicyUserNameTemplate' + PolicySubjectMatchType: + type: string + enum: + - CUSTOM_ATTRIBUTE + - EMAIL + - USERNAME + - USERNAME_OR_EMAIL + PolicyType: + type: string + enum: + - ACCESS_POLICY + - IDP_DISCOVERY + - MFA_ENROLL + - OAUTH_AUTHORIZATION_POLICY + - OKTA_SIGN_ON + - PASSWORD + - PROFILE_ENROLLMENT + PolicyUserNameTemplate: + type: object + properties: + template: + type: string + PolicyUserStatus: + type: string + enum: + - ACTIVATING + - ACTIVE + - DELETED + - DELETING + - EXPIRED_PASSWORD + - INACTIVE + - PENDING + - SUSPENDED + PossessionConstraint: + allOf: + - $ref: '#/components/schemas/AccessPolicyConstraint' + - type: object + properties: + deviceBound: + type: string + hardwareProtection: + type: string + phishingResistant: + type: string + userPresence: + type: string + PreRegistrationInlineHook: + type: object + properties: + inlineHookId: + type: string + PrincipalRateLimitEntity: + title: PrincipalRateLimitEntity + description: '' + type: object + properties: + createdBy: + type: string + readOnly: true + createdDate: + type: string + format: date-time + readOnly: true + defaultConcurrencyPercentage: + type: integer + readOnly: true + defaultPercentage: + type: integer + readOnly: true + id: + type: string + readOnly: true + lastUpdate: + type: string + format: date-time + readOnly: true + lastUpdatedBy: + type: string + readOnly: true + orgId: + type: string + readOnly: true + principalId: + type: string + principalType: + $ref: '#/components/schemas/PrincipalType' + required: + - principalId + - principalType + PrincipalType: + type: string + enum: + - SSWS_TOKEN + ProfileEnrollmentPolicy: + allOf: + - $ref: '#/components/schemas/Policy' + - type: object + properties: + conditions: + $ref: '#/components/schemas/PolicyRuleConditions' + ProfileEnrollmentPolicyRule: + allOf: + - $ref: '#/components/schemas/PolicyRule' + - type: object + properties: + actions: + $ref: '#/components/schemas/ProfileEnrollmentPolicyRuleActions' + conditions: + $ref: '#/components/schemas/PolicyRuleConditions' + ProfileEnrollmentPolicyRuleAction: + type: object + properties: + access: + type: string + activationRequirements: + $ref: '#/components/schemas/ProfileEnrollmentPolicyRuleActivationRequirement' + preRegistrationInlineHooks: + items: + $ref: '#/components/schemas/PreRegistrationInlineHook' + type: array + profileAttributes: + items: + $ref: '#/components/schemas/ProfileEnrollmentPolicyRuleProfileAttribute' + type: array + targetGroupIds: + items: + type: string + type: array + unknownUserAction: + type: string + ProfileEnrollmentPolicyRuleActions: + allOf: + - $ref: '#/components/schemas/PolicyRuleActions' + - type: object + properties: + profileEnrollment: + $ref: '#/components/schemas/ProfileEnrollmentPolicyRuleAction' + ProfileEnrollmentPolicyRuleActivationRequirement: + type: object + properties: + emailVerification: + type: boolean + ProfileEnrollmentPolicyRuleProfileAttribute: + type: object + properties: + label: + type: string + name: + type: string + required: + type: boolean + ProfileMapping: + type: object + properties: + id: + type: string + readOnly: true + properties: + type: object + additionalProperties: + $ref: '#/components/schemas/ProfileMappingProperty' + readOnly: true + source: + $ref: '#/components/schemas/ProfileMappingSource' + target: + $ref: '#/components/schemas/ProfileMappingSource' + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + ProfileMappingProperty: + type: object + properties: + expression: + type: string + pushStatus: + $ref: '#/components/schemas/ProfileMappingPropertyPushStatus' + ProfileMappingPropertyPushStatus: + type: string + enum: + - DONT_PUSH + - PUSH + ProfileMappingSource: + type: object + properties: + id: + type: string + readOnly: true + name: + type: string + readOnly: true + type: + type: string + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + ProfileSettingObject: + type: object + properties: + status: + $ref: '#/components/schemas/EnabledStatus' + Protocol: + type: object + properties: + algorithms: + $ref: '#/components/schemas/ProtocolAlgorithms' + credentials: + $ref: '#/components/schemas/IdentityProviderCredentials' + endpoints: + $ref: '#/components/schemas/ProtocolEndpoints' + issuer: + $ref: '#/components/schemas/ProtocolEndpoint' + relayState: + $ref: '#/components/schemas/ProtocolRelayState' + scopes: + type: array + items: + type: string + settings: + $ref: '#/components/schemas/ProtocolSettings' + type: + $ref: '#/components/schemas/ProtocolType' + ProtocolAlgorithmType: + type: object + properties: + signature: + $ref: '#/components/schemas/ProtocolAlgorithmTypeSignature' + ProtocolAlgorithmTypeSignature: + type: object + properties: + algorithm: + type: string + scope: + $ref: '#/components/schemas/ProtocolAlgorithmTypeSignatureScope' + ProtocolAlgorithmTypeSignatureScope: + type: string + enum: + - ANY + - NONE + - REQUEST + - RESPONSE + - TOKEN + ProtocolAlgorithms: + type: object + properties: + request: + $ref: '#/components/schemas/ProtocolAlgorithmType' + response: + $ref: '#/components/schemas/ProtocolAlgorithmType' + ProtocolEndpoint: + type: object + properties: + binding: + $ref: '#/components/schemas/ProtocolEndpointBinding' + destination: + type: string + type: + $ref: '#/components/schemas/ProtocolEndpointType' + url: + type: string + ProtocolEndpointBinding: + type: string + enum: + - HTTP-POST + - HTTP-REDIRECT + ProtocolEndpointType: + type: string + enum: + - INSTANCE + - ORG + ProtocolEndpoints: + type: object + properties: + acs: + $ref: '#/components/schemas/ProtocolEndpoint' + authorization: + $ref: '#/components/schemas/ProtocolEndpoint' + jwks: + $ref: '#/components/schemas/ProtocolEndpoint' + metadata: + $ref: '#/components/schemas/ProtocolEndpoint' + slo: + $ref: '#/components/schemas/ProtocolEndpoint' + sso: + $ref: '#/components/schemas/ProtocolEndpoint' + token: + $ref: '#/components/schemas/ProtocolEndpoint' + userInfo: + $ref: '#/components/schemas/ProtocolEndpoint' + ProtocolRelayState: + type: object + properties: + format: + $ref: '#/components/schemas/ProtocolRelayStateFormat' + ProtocolRelayStateFormat: + type: string + enum: + - FROM_URL + - OPAQUE + ProtocolSettings: + type: object + properties: + nameFormat: + type: string + ProtocolType: + type: string + enum: + - MTLS + - OAUTH2 + - OIDC + - SAML2 + ProviderType: + type: string + enum: + - APNS + - FCM + Provisioning: + type: object + properties: + action: + $ref: '#/components/schemas/ProvisioningAction' + conditions: + $ref: '#/components/schemas/ProvisioningConditions' + groups: + $ref: '#/components/schemas/ProvisioningGroups' + profileMaster: + type: boolean + ProvisioningAction: + type: string + enum: + - AUTO + - CALLOUT + - DISABLED + ProvisioningConditions: + type: object + properties: + deprovisioned: + $ref: '#/components/schemas/ProvisioningDeprovisionedCondition' + suspended: + $ref: '#/components/schemas/ProvisioningSuspendedCondition' + ProvisioningConnection: + type: object + properties: + authScheme: + $ref: '#/components/schemas/ProvisioningConnectionAuthScheme' + status: + $ref: '#/components/schemas/ProvisioningConnectionStatus' + _links: + additionalProperties: + type: object + readOnly: true + type: object + ProvisioningConnectionAuthScheme: + type: string + enum: + - TOKEN + - UNKNOWN + ProvisioningConnectionProfile: + type: object + properties: + authScheme: + $ref: '#/components/schemas/ProvisioningConnectionAuthScheme' + token: + type: string + ProvisioningConnectionRequest: + type: object + properties: + profile: + $ref: '#/components/schemas/ProvisioningConnectionProfile' + ProvisioningConnectionStatus: + type: string + enum: + - DISABLED + - ENABLED + - UNKNOWN + ProvisioningDeprovisionedAction: + type: string + enum: + - NONE + - REACTIVATE + ProvisioningDeprovisionedCondition: + type: object + properties: + action: + $ref: '#/components/schemas/ProvisioningDeprovisionedAction' + ProvisioningGroups: + type: object + properties: + action: + $ref: '#/components/schemas/ProvisioningGroupsAction' + assignments: + type: array + items: + type: string + filter: + type: array + items: + type: string + sourceAttributeName: + type: string + ProvisioningGroupsAction: + type: string + enum: + - APPEND + - ASSIGN + - NONE + - SYNC + ProvisioningSuspendedAction: + type: string + enum: + - NONE + - UNSUSPEND + ProvisioningSuspendedCondition: + type: object + properties: + action: + $ref: '#/components/schemas/ProvisioningSuspendedAction' + PushProvider: + title: PushProvider + type: object + properties: + id: + type: string + readOnly: true + lastUpdatedDate: + type: string + readOnly: true + name: + type: string + description: Display name of the push provider + providerType: + $ref: '#/components/schemas/ProviderType' + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + readOnly: true + discriminator: + propertyName: providerType + mapping: + APNS: '#/components/schemas/APNSPushProvider' + FCM: '#/components/schemas/FCMPushProvider' + PushUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + expiresAt: + type: string + format: date-time + factorResult: + $ref: '#/components/schemas/FactorResultType' + profile: + $ref: '#/components/schemas/PushUserFactorProfile' + PushUserFactorProfile: + type: object + properties: + credentialId: + type: string + deviceToken: + type: string + deviceType: + type: string + name: + type: string + platform: + type: string + version: + type: string + RateLimitAdminNotifications: + title: RateLimitAdminNotifications + description: '' + type: object + properties: + notificationsEnabled: + type: boolean + required: + - notificationsEnabled + RecoveryQuestionCredential: + type: object + properties: + answer: + type: string + question: + type: string + ReleaseChannel: + description: Release channel for auto-update + type: string + enum: + - BETA + - EA + - GA + - TEST + RequiredEnum: + type: string + enum: + - ALWAYS + - HIGH_RISK_ONLY + - NEVER + ResetPasswordToken: + type: object + properties: + resetPasswordUrl: + type: string + readOnly: true + ResourceSet: + type: object + properties: + created: + type: string + format: date-time + description: Timestamp when the role was created + readOnly: true + description: + type: string + description: Description of the resource set + id: + type: string + description: Unique key for the role + readOnly: true + label: + type: string + description: Unique label for the resource set + lastUpdated: + type: string + format: date-time + description: Timestamp when the role was last updated + readOnly: true + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + resources: + $ref: '#/components/schemas/HrefObject' + bindings: + $ref: '#/components/schemas/HrefObject' + readOnly: true + ResourceSetBindingAddMembersRequest: + type: object + properties: + additions: + type: array + items: + type: string + ResourceSetBindingCreateRequest: + type: object + properties: + members: + type: array + items: + type: string + role: + type: string + description: Unique key for the role + ResourceSetBindingMember: + type: object + properties: + created: + type: string + format: date-time + description: Timestamp when the role was created + readOnly: true + id: + type: string + description: Unique key for the role + readOnly: true + lastUpdated: + type: string + format: date-time + description: Timestamp when the role was last updated + readOnly: true + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + readOnly: true + ResourceSetBindingMembers: + type: object + properties: + members: + type: array + items: + $ref: '#/components/schemas/ResourceSetBindingMember' + _links: + type: object + properties: + binding: + $ref: '#/components/schemas/HrefObject' + next: + $ref: '#/components/schemas/HrefObject' + readOnly: true + ResourceSetBindingResponse: + type: object + properties: + id: + type: string + description: '`id` of the role' + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + bindings: + $ref: '#/components/schemas/HrefObject' + resource-set: + $ref: '#/components/schemas/HrefObject' + readOnly: true + ResourceSetBindingRole: + type: object + properties: + id: + type: string + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + members: + $ref: '#/components/schemas/HrefObject' + ResourceSetBindings: + type: object + properties: + roles: + type: array + items: + $ref: '#/components/schemas/ResourceSetBindingRole' + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + bindings: + $ref: '#/components/schemas/HrefObject' + resource-set: + $ref: '#/components/schemas/HrefObject' + readOnly: true + ResourceSetResource: + type: object + properties: + created: + type: string + format: date-time + description: Timestamp when the role was created + readOnly: true + description: + type: string + description: Description of the resource set + id: + type: string + description: Unique key for the role + readOnly: true + lastUpdated: + type: string + format: date-time + description: Timestamp when the role was last updated + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + ResourceSetResourcePatchRequest: + type: object + properties: + additions: + type: array + items: + type: string + ResourceSetResources: + type: object + properties: + resources: + type: array + items: + $ref: '#/components/schemas/ResourceSetResource' + _links: + type: object + properties: + next: + $ref: '#/components/schemas/HrefObject' + resource-set: + $ref: '#/components/schemas/HrefObject' + ResourceSets: + type: object + properties: + resource-sets: + type: array + items: + $ref: '#/components/schemas/ResourceSet' + _links: + type: object + properties: + next: + $ref: '#/components/schemas/HrefObject' + readOnly: true + ResponseLinks: + type: object + RiskEvent: + type: object + properties: + expiresAt: + type: string + format: date-time + description: 'Time stamp at which the event expires (Expressed as a UTC time zone using ISO 8601 format: yyyy-MM-dd''T''HH:mm:ss.SSS''Z''). If this optional field is not included, Okta automatically expires the event 24 hours after the event is consumed.' + subjects: + type: array + items: + $ref: '#/components/schemas/RiskEventSubject' + timestamp: + type: string + format: date-time + description: 'Time stamp at which the event is produced (Expressed as a UTC time zone using ISO 8601 format: yyyy-MM-dd''T''HH:mm:ss.SSS''Z'').' + required: + - subjects + RiskEventSubject: + type: object + properties: + ip: + type: string + description: Either an IpV4 or IpV6 address. + message: + type: string + description: Any additional message that the provider can send specifying the reason for the risk level of the IP. + maxLength: 512 + pattern: ^[a-zA-Z0-9.\-_]$ + riskLevel: + $ref: '#/components/schemas/RiskEventSubjectRiskLevel' + required: + - ip + RiskEventSubjectRiskLevel: + type: string + enum: + - HIGH + - LOW + - MEDIUM + RiskPolicyRuleCondition: + type: object + properties: + behaviors: + uniqueItems: true + type: array + items: + type: string + RiskProvider: + type: object + properties: + action: + $ref: '#/components/schemas/RiskProviderAction' + clientId: + type: string + description: The ID of the [OAuth service app](https://developer.okta.com/docs/guides/implement-oauth-for-okta-serviceapp/main/#create-a-service-app-and-grant-scopes) that is used to send risk events to Okta + created: + type: string + format: date-time + description: Timestamp when the risk provider was created + readOnly: true + id: + type: string + description: The ID of the risk provider + readOnly: true + lastUpdated: + type: string + format: date-time + description: Timestamp when the risk provider was last updated + readOnly: true + name: + type: string + description: Name of the risk provider + maxLength: 50 + _links: + type: object + properties: + self: + $ref: '#/components/schemas/HrefObject' + readOnly: true + required: + - name + - clientId + RiskProviderAction: + description: The action taken by Okta during authentication attempts based on the risk events sent by this provider. Logging can be found in the SystemLogs. + default: log_only + type: string + enum: + - enforce_and_log + - log_only + - none + RiskScorePolicyRuleCondition: + type: object + properties: + level: + type: string + Role: + type: object + properties: + assignmentType: + $ref: '#/components/schemas/RoleAssignmentType' + created: + type: string + format: date-time + readOnly: true + description: + type: string + id: + type: string + readOnly: true + label: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + status: + $ref: '#/components/schemas/LifecycleStatus' + type: + $ref: '#/components/schemas/RoleType' + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + RoleAssignmentType: + type: string + enum: + - GROUP + - USER + RolePermissionType: + type: string + enum: + - okta.apps.assignment.manage + - okta.apps.manage + - okta.apps.manageFirstPartyApps + - okta.apps.read + - okta.authzServers.manage + - okta.authzServers.read + - okta.customizations.manage + - okta.customizations.read + - okta.governance.accessCertifications.manage + - okta.governance.accessRequests.manage + - okta.groups.appAssignment.manage + - okta.groups.create + - okta.groups.manage + - okta.groups.members.manage + - okta.groups.read + - okta.profilesources.import.run + - okta.users.appAssignment.manage + - okta.users.create + - okta.users.credentials.expirePassword + - okta.users.credentials.manage + - okta.users.credentials.resetFactors + - okta.users.credentials.resetPassword + - okta.users.groupMembership.manage + - okta.users.lifecycle.activate + - okta.users.lifecycle.clearSessions + - okta.users.lifecycle.deactivate + - okta.users.lifecycle.delete + - okta.users.lifecycle.manage + - okta.users.lifecycle.suspend + - okta.users.lifecycle.unlock + - okta.users.lifecycle.unsuspend + - okta.users.manage + - okta.users.read + - okta.users.userprofile.manage + RoleType: + type: string + enum: + - API_ACCESS_MANAGEMENT_ADMIN + - APP_ADMIN + - GROUP_MEMBERSHIP_ADMIN + - HELP_DESK_ADMIN + - MOBILE_ADMIN + - ORG_ADMIN + - READ_ONLY_ADMIN + - REPORT_ADMIN + - SUPER_ADMIN + - USER_ADMIN + SamlApplication: + allOf: + - $ref: '#/components/schemas/Application' + - type: object + properties: + credentials: + $ref: '#/components/schemas/ApplicationCredentials' + name: + type: string + settings: + $ref: '#/components/schemas/SamlApplicationSettings' + SamlApplicationSettings: + allOf: + - $ref: '#/components/schemas/ApplicationSettings' + - type: object + properties: + app: + $ref: '#/components/schemas/SamlApplicationSettingsApplication' + signOn: + $ref: '#/components/schemas/SamlApplicationSettingsSignOn' + SamlApplicationSettingsApplication: + type: object + properties: + acsUrl: + type: string + audRestriction: + type: string + baseUrl: + type: string + SamlApplicationSettingsSignOn: + type: object + properties: + acsEndpoints: + type: array + items: + $ref: '#/components/schemas/AcsEndpoint' + allowMultipleAcsEndpoints: + type: boolean + assertionSigned: + type: boolean + attributeStatements: + type: array + items: + $ref: '#/components/schemas/SamlAttributeStatement' + audience: + type: string + audienceOverride: + type: string + authnContextClassRef: + type: string + defaultRelayState: + type: string + destination: + type: string + destinationOverride: + type: string + digestAlgorithm: + type: string + honorForceAuthn: + type: boolean + idpIssuer: + type: string + inlineHooks: + items: + $ref: '#/components/schemas/SignOnInlineHook' + type: array + recipient: + type: string + recipientOverride: + type: string + requestCompressed: + type: boolean + responseSigned: + type: boolean + signatureAlgorithm: + type: string + slo: + $ref: '#/components/schemas/SingleLogout' + spCertificate: + $ref: '#/components/schemas/SpCertificate' + spIssuer: + type: string + ssoAcsUrl: + type: string + ssoAcsUrlOverride: + type: string + subjectNameIdFormat: + type: string + subjectNameIdTemplate: + type: string + SamlAttributeStatement: + type: object + properties: + filterType: + type: string + filterValue: + type: string + name: + type: string + namespace: + type: string + type: + type: string + values: + type: array + items: + type: string + ScheduledUserLifecycleAction: + type: object + properties: + status: + $ref: '#/components/schemas/PolicyUserStatus' + SchemeApplicationCredentials: + allOf: + - $ref: '#/components/schemas/ApplicationCredentials' + - type: object + properties: + password: + $ref: '#/components/schemas/PasswordCredential' + revealPassword: + type: boolean + scheme: + $ref: '#/components/schemas/ApplicationCredentialsScheme' + signing: + $ref: '#/components/schemas/ApplicationCredentialsSigning' + userName: + type: string + ScreenLockType: + type: string + enum: + - BIOMETRIC + - PASSCODE + SecurePasswordStoreApplication: + x-okta-defined-as: + name: template_sps + allOf: + - $ref: '#/components/schemas/Application' + - type: object + properties: + credentials: + $ref: '#/components/schemas/SchemeApplicationCredentials' + name: + type: string + default: template_sps + settings: + $ref: '#/components/schemas/SecurePasswordStoreApplicationSettings' + SecurePasswordStoreApplicationSettings: + allOf: + - $ref: '#/components/schemas/ApplicationSettings' + - type: object + properties: + app: + $ref: '#/components/schemas/SecurePasswordStoreApplicationSettingsApplication' + SecurePasswordStoreApplicationSettingsApplication: + type: object + properties: + optionalField1: + type: string + optionalField1Value: + type: string + optionalField2: + type: string + optionalField2Value: + type: string + optionalField3: + type: string + optionalField3Value: + type: string + passwordField: + type: string + url: + type: string + usernameField: + type: string + SecurityQuestion: + type: object + properties: + answer: + type: string + question: + type: string + questionText: + type: string + SecurityQuestionUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/SecurityQuestionUserFactorProfile' + SecurityQuestionUserFactorProfile: + type: object + properties: + answer: + type: string + question: + type: string + questionText: + type: string + SeedEnum: + type: string + enum: + - OKTA + - RANDOM + Session: + type: object + properties: + amr: + type: array + readOnly: true + items: + $ref: '#/components/schemas/SessionAuthenticationMethod' + createdAt: + type: string + format: date-time + readOnly: true + expiresAt: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + idp: + $ref: '#/components/schemas/SessionIdentityProvider' + lastFactorVerification: + type: string + format: date-time + readOnly: true + lastPasswordVerification: + type: string + format: date-time + readOnly: true + login: + type: string + readOnly: true + status: + $ref: '#/components/schemas/SessionStatus' + userId: + type: string + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + SessionAuthenticationMethod: + type: string + enum: + - fpt + - geo + - hwk + - kba + - mca + - mfa + - otp + - pwd + - sc + - sms + - swk + - tel + SessionIdentityProvider: + type: object + properties: + id: + type: string + readOnly: true + type: + $ref: '#/components/schemas/SessionIdentityProviderType' + SessionIdentityProviderType: + type: string + enum: + - ACTIVE_DIRECTORY + - FEDERATION + - LDAP + - OKTA + - SOCIAL + SessionStatus: + type: string + enum: + - ACTIVE + - MFA_ENROLL + - MFA_REQUIRED + SignInPage: + allOf: + - $ref: '#/components/schemas/CustomizablePage' + - type: object + properties: + widgetCustomizations: + type: object + properties: + signInLabel: + type: string + usernameLabel: + type: string + usernameInfoTip: + type: string + passwordLabel: + type: string + passwordInfoTip: + type: string + showPasswordVisibilityToggle: + type: boolean + showUserIdentifier: + type: boolean + forgotPasswordLabel: + type: string + forgotPasswordUrl: + type: string + unlockAccountLabel: + type: string + unlockAccountUrl: + type: string + helpLabel: + type: string + helpUrl: + type: string + customLink1Label: + type: string + customLink1Url: + type: string + customLink2Label: + type: string + customLink2Url: + type: string + authenticatorPageCustomLinkLabel: + type: string + authenticatorPageCustomLinkUrl: + type: string + classicRecoveryFlowEmailOrUsernameLabel: + type: string + widgetVersion: + $ref: '#/components/schemas/Version' + SignInPageTouchPointVariant: + type: string + enum: + - BACKGROUND_IMAGE + - BACKGROUND_SECONDARY_COLOR + - OKTA_DEFAULT + SignOnInlineHook: + properties: + id: + type: string + readOnly: false + SingleLogout: + type: object + properties: + enabled: + type: boolean + issuer: + type: string + logoutUrl: + type: string + SmsTemplate: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + name: + type: string + template: + type: string + translations: + $ref: '#/components/schemas/SmsTemplateTranslations' + type: + $ref: '#/components/schemas/SmsTemplateType' + SmsTemplateTranslations: + type: object + x-okta-extensible: true + SmsTemplateType: + type: string + enum: + - SMS_VERIFY_CODE + SmsUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/SmsUserFactorProfile' + SmsUserFactorProfile: + type: object + properties: + phoneNumber: + type: string + SocialAuthToken: + type: object + properties: + expiresAt: + type: string + format: date-time + readOnly: true + id: + type: string + readOnly: true + scopes: + type: array + items: + type: string + token: + type: string + tokenAuthScheme: + type: string + tokenType: + type: string + SpCertificate: + type: object + properties: + x5c: + type: array + items: + type: string + Subscription: + type: object + properties: + channels: + items: + type: string + type: array + notificationType: + $ref: '#/components/schemas/NotificationType' + status: + $ref: '#/components/schemas/SubscriptionStatus' + _links: + additionalProperties: + type: object + readOnly: true + type: object + SubscriptionStatus: + type: string + enum: + - subscribed + - unsubscribed + SwaApplicationSettings: + allOf: + - $ref: '#/components/schemas/ApplicationSettings' + - type: object + properties: + app: + $ref: '#/components/schemas/SwaApplicationSettingsApplication' + SwaApplicationSettingsApplication: + type: object + properties: + buttonField: + type: string + buttonSelector: + type: string + checkbox: + type: string + extraFieldSelector: + type: string + extraFieldValue: + type: string + loginUrlRegex: + type: string + passwordField: + type: string + passwordSelector: + type: string + redirectUrl: + type: string + targetURL: + type: string + url: + type: string + usernameField: + type: string + userNameSelector: + type: string + TempPassword: + type: object + properties: + tempPassword: + type: string + readOnly: true + Theme: + type: object + properties: + backgroundImage: + readOnly: true + type: string + emailTemplateTouchPointVariant: + $ref: '#/components/schemas/EmailTemplateTouchPointVariant' + endUserDashboardTouchPointVariant: + $ref: '#/components/schemas/EndUserDashboardTouchPointVariant' + errorPageTouchPointVariant: + $ref: '#/components/schemas/ErrorPageTouchPointVariant' + loadingPageTouchPointVariant: + $ref: '#/components/schemas/LoadingPageTouchPointVariant' + primaryColorContrastHex: + type: string + primaryColorHex: + type: string + secondaryColorContrastHex: + type: string + secondaryColorHex: + type: string + signInPageTouchPointVariant: + $ref: '#/components/schemas/SignInPageTouchPointVariant' + _links: + additionalProperties: + type: object + readOnly: true + type: object + ThemeResponse: + type: object + properties: + backgroundImage: + readOnly: true + type: string + emailTemplateTouchPointVariant: + $ref: '#/components/schemas/EmailTemplateTouchPointVariant' + endUserDashboardTouchPointVariant: + $ref: '#/components/schemas/EndUserDashboardTouchPointVariant' + errorPageTouchPointVariant: + $ref: '#/components/schemas/ErrorPageTouchPointVariant' + favicon: + readOnly: true + type: string + id: + readOnly: true + type: string + loadingPageTouchPointVariant: + $ref: '#/components/schemas/LoadingPageTouchPointVariant' + logo: + readOnly: true + type: string + primaryColorContrastHex: + type: string + primaryColorHex: + type: string + secondaryColorContrastHex: + type: string + secondaryColorHex: + type: string + signInPageTouchPointVariant: + $ref: '#/components/schemas/SignInPageTouchPointVariant' + _links: + additionalProperties: + type: object + readOnly: true + type: object + ThreatInsightConfiguration: + type: object + properties: + action: + type: string + created: + type: string + format: date-time + readOnly: true + excludeZones: + type: array + items: + type: string + lastUpdated: + type: string + format: date-time + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + TimeDuration: + description: A time duration specified as an [ISO-8601 duration](https://en.wikipedia.org/wiki/ISO_8601#Durations). + type: string + pattern: ^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$ + TokenAuthorizationServerPolicyRuleAction: + type: object + properties: + accessTokenLifetimeMinutes: + type: integer + inlineHook: + $ref: '#/components/schemas/TokenAuthorizationServerPolicyRuleActionInlineHook' + refreshTokenLifetimeMinutes: + type: integer + refreshTokenWindowMinutes: + type: integer + TokenAuthorizationServerPolicyRuleActionInlineHook: + type: object + properties: + id: + type: string + readOnly: false + TokenUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/TokenUserFactorProfile' + TokenUserFactorProfile: + type: object + properties: + credentialId: + type: string + TotpUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/TotpUserFactorProfile' + TotpUserFactorProfile: + type: object + properties: + credentialId: + type: string + TrustedOrigin: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + createdBy: + type: string + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + lastUpdatedBy: + type: string + name: + type: string + origin: + type: string + scopes: + type: array + items: + $ref: '#/components/schemas/TrustedOriginScope' + status: + type: string + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + TrustedOriginScope: + type: object + properties: + allowedOktaApps: + type: array + items: + $ref: '#/components/schemas/IframeEmbedScopeAllowedApps' + type: + $ref: '#/components/schemas/TrustedOriginScopeType' + TrustedOriginScopeType: + type: string + enum: + - CORS + - IFRAME_EMBED + - REDIRECT + U2fUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/U2fUserFactorProfile' + U2fUserFactorProfile: + type: object + properties: + credentialId: + type: string + UpdateDomain: + type: object + properties: + brandId: + type: string + UpdateEmailDomain: + allOf: + - $ref: '#/components/schemas/BaseEmailDomain' + UpdateUserRequest: + type: object + properties: + credentials: + $ref: '#/components/schemas/UserCredentials' + profile: + $ref: '#/components/schemas/UserProfile' + User: + type: object + properties: + activated: + type: string + format: date-time + readOnly: true + nullable: true + created: + type: string + format: date-time + readOnly: true + credentials: + $ref: '#/components/schemas/UserCredentials' + id: + type: string + readOnly: true + lastLogin: + type: string + format: date-time + readOnly: true + nullable: true + lastUpdated: + type: string + format: date-time + readOnly: true + passwordChanged: + type: string + format: date-time + readOnly: true + nullable: true + profile: + $ref: '#/components/schemas/UserProfile' + status: + $ref: '#/components/schemas/UserStatus' + statusChanged: + type: string + format: date-time + readOnly: true + nullable: true + transitioningToStatus: + $ref: '#/components/schemas/UserStatus' + type: + $ref: '#/components/schemas/UserType' + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + UserActivationToken: + type: object + properties: + activationToken: + type: string + readOnly: true + activationUrl: + type: string + readOnly: true + UserCondition: + type: object + properties: + exclude: + type: array + items: + type: string + include: + type: array + items: + type: string + UserCredentials: + type: object + properties: + password: + $ref: '#/components/schemas/PasswordCredential' + provider: + $ref: '#/components/schemas/AuthenticationProvider' + recovery_question: + $ref: '#/components/schemas/RecoveryQuestionCredential' + UserFactor: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + factorType: + $ref: '#/components/schemas/FactorType' + id: + type: string + readOnly: true + lastUpdated: + type: string + format: date-time + readOnly: true + provider: + $ref: '#/components/schemas/FactorProvider' + status: + $ref: '#/components/schemas/FactorStatus' + verify: + $ref: '#/components/schemas/VerifyFactorRequest' + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + discriminator: + propertyName: factorType + mapping: + call: '#/components/schemas/CallUserFactor' + email: '#/components/schemas/EmailUserFactor' + push: '#/components/schemas/PushUserFactor' + question: '#/components/schemas/SecurityQuestionUserFactor' + sms: '#/components/schemas/SmsUserFactor' + token: '#/components/schemas/TokenUserFactor' + token:hardware: '#/components/schemas/HardwareUserFactor' + token:hotp: '#/components/schemas/CustomHotpUserFactor' + token:software:totp: '#/components/schemas/TotpUserFactor' + u2f: '#/components/schemas/U2fUserFactor' + web: '#/components/schemas/WebUserFactor' + webauthn: '#/components/schemas/WebAuthnUserFactor' + hotp: '#/components/schemas/CustomHotpUserFactor' + UserIdentifierConditionEvaluatorPattern: + type: object + properties: + matchType: + $ref: '#/components/schemas/UserIdentifierMatchType' + value: + type: string + UserIdentifierMatchType: + type: string + enum: + - CONTAINS + - EQUALS + - EXPRESSION + - STARTS_WITH + - SUFFIX + UserIdentifierPolicyRuleCondition: + type: object + properties: + attribute: + type: string + patterns: + type: array + items: + $ref: '#/components/schemas/UserIdentifierConditionEvaluatorPattern' + type: + $ref: '#/components/schemas/UserIdentifierType' + UserIdentifierType: + type: string + enum: + - ATTRIBUTE + - IDENTIFIER + UserIdentityProviderLinkRequest: + type: object + properties: + externalId: + type: string + UserLifecycleAttributePolicyRuleCondition: + type: object + properties: + attributeName: + type: string + matchingValue: + type: string + UserNextLogin: + type: string + enum: + - changePassword + UserPolicyRuleCondition: + type: object + properties: + exclude: + type: array + items: + type: string + inactivity: + $ref: '#/components/schemas/InactivityPolicyRuleCondition' + include: + type: array + items: + type: string + lifecycleExpiration: + $ref: '#/components/schemas/LifecycleExpirationPolicyRuleCondition' + passwordExpiration: + $ref: '#/components/schemas/PasswordExpirationPolicyRuleCondition' + userLifecycleAttribute: + $ref: '#/components/schemas/UserLifecycleAttributePolicyRuleCondition' + UserProfile: + additionalProperties: true + type: object + properties: + city: + type: string + maxLength: 128 + nullable: true + costCenter: + type: string + countryCode: + type: string + maxLength: 2 + nullable: true + department: + type: string + displayName: + type: string + division: + type: string + email: + type: string + format: email + minLength: 5 + maxLength: 100 + employeeNumber: + type: string + firstName: + type: string + minLength: 1 + maxLength: 50 + nullable: true + honorificPrefix: + type: string + honorificSuffix: + type: string + lastName: + type: string + minLength: 1 + maxLength: 50 + nullable: true + locale: + $ref: '#/components/schemas/Language' + login: + type: string + maxLength: 100 + manager: + type: string + managerId: + type: string + middleName: + type: string + mobilePhone: + type: string + maxLength: 100 + nullable: true + nickName: + type: string + organization: + type: string + postalAddress: + type: string + maxLength: 4096 + nullable: true + preferredLanguage: + type: string + primaryPhone: + type: string + maxLength: 100 + nullable: true + profileUrl: + type: string + secondEmail: + type: string + format: email + minLength: 5 + maxLength: 100 + nullable: true + state: + type: string + maxLength: 128 + nullable: true + streetAddress: + type: string + maxLength: 1024 + nullable: true + timezone: + type: string + title: + type: string + userType: + type: string + zipCode: + type: string + maxLength: 50 + nullable: true + UserSchema: + type: object + properties: + $schema: + type: string + readOnly: true + created: + type: string + readOnly: true + definitions: + $ref: '#/components/schemas/UserSchemaDefinitions' + id: + type: string + readOnly: true + lastUpdated: + type: string + readOnly: true + name: + type: string + readOnly: true + properties: + $ref: '#/components/schemas/UserSchemaProperties' + title: + type: string + type: + type: string + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + UserSchemaAttribute: + type: object + properties: + description: + type: string + enum: + type: array + items: + type: string + externalName: + type: string + externalNamespace: + type: string + items: + $ref: '#/components/schemas/UserSchemaAttributeItems' + master: + $ref: '#/components/schemas/UserSchemaAttributeMaster' + maxLength: + type: integer + minLength: + type: integer + mutability: + type: string + oneOf: + type: array + items: + $ref: '#/components/schemas/UserSchemaAttributeEnum' + pattern: + type: string + permissions: + type: array + items: + $ref: '#/components/schemas/UserSchemaAttributePermission' + required: + type: boolean + scope: + $ref: '#/components/schemas/UserSchemaAttributeScope' + title: + type: string + type: + $ref: '#/components/schemas/UserSchemaAttributeType' + union: + $ref: '#/components/schemas/UserSchemaAttributeUnion' + unique: + type: string + x-okta-allow-null-property-value-for-updates: true + UserSchemaAttributeEnum: + type: object + properties: + const: + type: string + title: + type: string + UserSchemaAttributeItems: + type: object + properties: + enum: + type: array + items: + type: string + oneOf: + type: array + items: + $ref: '#/components/schemas/UserSchemaAttributeEnum' + type: + type: string + UserSchemaAttributeMaster: + type: object + properties: + priority: + type: array + items: + $ref: '#/components/schemas/UserSchemaAttributeMasterPriority' + type: + $ref: '#/components/schemas/UserSchemaAttributeMasterType' + UserSchemaAttributeMasterPriority: + type: object + properties: + type: + type: string + value: + type: string + UserSchemaAttributeMasterType: + type: string + enum: + - OKTA + - OVERRIDE + - PROFILE_MASTER + UserSchemaAttributePermission: + type: object + properties: + action: + type: string + principal: + type: string + UserSchemaAttributeScope: + type: string + enum: + - NONE + - SELF + UserSchemaAttributeType: + type: string + enum: + - array + - boolean + - integer + - number + - string + UserSchemaAttributeUnion: + type: string + enum: + - DISABLE + - ENABLE + UserSchemaBase: + type: object + properties: + id: + type: string + properties: + $ref: '#/components/schemas/UserSchemaBaseProperties' + required: + type: array + items: + type: string + type: + type: string + UserSchemaBaseProperties: + type: object + properties: + city: + $ref: '#/components/schemas/UserSchemaAttribute' + costCenter: + $ref: '#/components/schemas/UserSchemaAttribute' + countryCode: + $ref: '#/components/schemas/UserSchemaAttribute' + department: + $ref: '#/components/schemas/UserSchemaAttribute' + displayName: + $ref: '#/components/schemas/UserSchemaAttribute' + division: + $ref: '#/components/schemas/UserSchemaAttribute' + email: + $ref: '#/components/schemas/UserSchemaAttribute' + employeeNumber: + $ref: '#/components/schemas/UserSchemaAttribute' + firstName: + $ref: '#/components/schemas/UserSchemaAttribute' + honorificPrefix: + $ref: '#/components/schemas/UserSchemaAttribute' + honorificSuffix: + $ref: '#/components/schemas/UserSchemaAttribute' + lastName: + $ref: '#/components/schemas/UserSchemaAttribute' + locale: + $ref: '#/components/schemas/UserSchemaAttribute' + login: + $ref: '#/components/schemas/UserSchemaAttribute' + manager: + $ref: '#/components/schemas/UserSchemaAttribute' + managerId: + $ref: '#/components/schemas/UserSchemaAttribute' + middleName: + $ref: '#/components/schemas/UserSchemaAttribute' + mobilePhone: + $ref: '#/components/schemas/UserSchemaAttribute' + nickName: + $ref: '#/components/schemas/UserSchemaAttribute' + organization: + $ref: '#/components/schemas/UserSchemaAttribute' + postalAddress: + $ref: '#/components/schemas/UserSchemaAttribute' + preferredLanguage: + $ref: '#/components/schemas/UserSchemaAttribute' + primaryPhone: + $ref: '#/components/schemas/UserSchemaAttribute' + profileUrl: + $ref: '#/components/schemas/UserSchemaAttribute' + secondEmail: + $ref: '#/components/schemas/UserSchemaAttribute' + state: + $ref: '#/components/schemas/UserSchemaAttribute' + streetAddress: + $ref: '#/components/schemas/UserSchemaAttribute' + timezone: + $ref: '#/components/schemas/UserSchemaAttribute' + title: + $ref: '#/components/schemas/UserSchemaAttribute' + userType: + $ref: '#/components/schemas/UserSchemaAttribute' + zipCode: + $ref: '#/components/schemas/UserSchemaAttribute' + UserSchemaDefinitions: + type: object + properties: + base: + $ref: '#/components/schemas/UserSchemaBase' + custom: + $ref: '#/components/schemas/UserSchemaPublic' + UserSchemaProperties: + type: object + properties: + profile: + $ref: '#/components/schemas/UserSchemaPropertiesProfile' + UserSchemaPropertiesProfile: + type: object + properties: + allOf: + type: array + items: + $ref: '#/components/schemas/UserSchemaPropertiesProfileItem' + UserSchemaPropertiesProfileItem: + type: object + properties: + $ref: + type: string + UserSchemaPublic: + type: object + properties: + id: + type: string + properties: + type: object + additionalProperties: + $ref: '#/components/schemas/UserSchemaAttribute' + required: + type: array + items: + type: string + type: + type: string + UserStatus: + type: string + enum: + - ACTIVE + - DEPROVISIONED + - LOCKED_OUT + - PASSWORD_EXPIRED + - PROVISIONED + - RECOVERY + - STAGED + - SUSPENDED + UserStatusPolicyRuleCondition: + type: object + properties: + value: + $ref: '#/components/schemas/PolicyUserStatus' + UserType: + type: object + properties: + created: + type: string + format: date-time + readOnly: true + createdBy: + type: string + readOnly: true + default: + type: boolean + readOnly: true + description: + type: string + displayName: + type: string + id: + type: string + lastUpdated: + type: string + format: date-time + readOnly: true + lastUpdatedBy: + type: string + readOnly: true + name: + type: string + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + UserTypeCondition: + properties: + exclude: + items: + type: string + type: array + include: + items: + type: string + type: array + UserVerificationEnum: + type: string + enum: + - PREFERRED + - REQUIRED + VerificationMethod: + type: object + properties: + constraints: + items: + $ref: '#/components/schemas/AccessPolicyConstraints' + type: array + factorMode: + type: string + reauthenticateIn: + type: string + type: + type: string + VerifyFactorRequest: + type: object + properties: + activationToken: + type: string + answer: + type: string + attestation: + type: string + clientData: + type: string + nextPassCode: + type: string + passCode: + type: string + registrationData: + type: string + stateToken: + type: string + VerifyUserFactorResponse: + type: object + properties: + expiresAt: + type: string + format: date-time + readOnly: true + factorResult: + $ref: '#/components/schemas/VerifyUserFactorResult' + factorResultMessage: + type: string + _embedded: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + _links: + type: object + additionalProperties: + type: object + properties: {} + readOnly: true + VerifyUserFactorResult: + type: string + enum: + - CHALLENGE + - ERROR + - EXPIRED + - FAILED + - PASSCODE_REPLAYED + - REJECTED + - SUCCESS + - TIMEOUT + - TIME_WINDOW_EXCEEDED + - WAITING + Version: + description: The version specified as a [Semantic Version](https://semver.org/). + type: string + pattern: ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ + VersionObject: + type: object + properties: + minimum: + type: string + WebAuthnUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/WebAuthnUserFactorProfile' + WebAuthnUserFactorProfile: + type: object + properties: + authenticatorName: + type: string + credentialId: + type: string + WebUserFactor: + allOf: + - $ref: '#/components/schemas/UserFactor' + - type: object + properties: + profile: + $ref: '#/components/schemas/WebUserFactorProfile' + WebUserFactorProfile: + type: object + properties: + credentialId: + type: string + WellKnownOrgMetadata: + type: object + properties: + id: + type: string + description: The unique identifier of the Org + pipeline: + $ref: '#/components/schemas/PipelineType' + settings: + $ref: '#/components/schemas/WellKnownOrgMetadataSettings' + _links: + type: object + properties: + alternate: + $ref: '#/components/schemas/HrefObject' + organization: + $ref: '#/components/schemas/HrefObject' + WellKnownOrgMetadataSettings: + type: object + properties: + analyticsCollectionEnabled: + type: boolean + bugReportingEnabled: + type: boolean + omEnabled: + type: boolean + description: Whether the legacy Okta Mobile application is enabled for the org + WsFederationApplication: + x-okta-defined-as: + name: template_wsfed + allOf: + - $ref: '#/components/schemas/Application' + - type: object + properties: + name: + type: string + default: template_wsfed + settings: + $ref: '#/components/schemas/WsFederationApplicationSettings' + WsFederationApplicationSettings: + allOf: + - $ref: '#/components/schemas/ApplicationSettings' + - type: object + properties: + app: + $ref: '#/components/schemas/WsFederationApplicationSettingsApplication' + WsFederationApplicationSettingsApplication: + type: object + properties: + attributeStatements: + type: string + audienceRestriction: + type: string + authnContextClassRef: + type: string + groupFilter: + type: string + groupName: + type: string + groupValueFormat: + type: string + nameIDFormat: + type: string + realm: + type: string + siteURL: + type: string + usernameAttribute: + type: string + wReplyOverride: + type: boolean + wReplyURL: + type: string + responses: + ErrorApiValidationFailed400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + API Validation Failed: + $ref: '#/components/examples/ErrorApiValidationFailed' + ErrorAccessDenied403: + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Access Denied: + $ref: '#/components/examples/ErrorAccessDenied' + ErrorResourceNotFound404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Resource Not Found: + $ref: '#/components/examples/ErrorResourceNotFound' + ErrorTooManyRequests429: + description: Too Many Requests + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + examples: + Resource Not Found: + $ref: '#/components/examples/ErrorTooManyRequests' + AuthenticatorResponse: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Authenticator' + examples: + Duo: + $ref: '#/components/examples/AuthenticatorResponseDuo' + Email: + $ref: '#/components/examples/AuthenticatorResponseEmail' + Password: + $ref: '#/components/examples/AuthenticatorResponsePassword' + Phone: + $ref: '#/components/examples/AuthenticatorResponsePhone' + WebAuthn: + $ref: '#/components/examples/AuthenticatorResponseWebAuthn' + Security Question: + $ref: '#/components/examples/AuthenticatorResponseSecurityQuestion' + requestBodies: + AuthenticatorRequestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Authenticator' + examples: + Duo: + $ref: '#/components/examples/AuthenticatorRequestDuo' + required: true diff --git a/swagger-templates/pom.xml b/swagger-templates/pom.xml deleted file mode 100644 index 233c2baedb8..00000000000 --- a/swagger-templates/pom.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - 4.0.0 - - - com.okta.sdk - okta-sdk-root - 8.2.3-SNAPSHOT - - - okta-api-swagger-templates - Okta Java SDK :: Swagger Templates - - - 2.2.3 - - - - - io.swagger - swagger-codegen - ${swagger-version} - - - commons-logging - commons-logging - - - - com.google.guava - guava - - - org.slf4j - slf4j-ext - - - org.apache.httpcomponents - httpclient - - - - - com.google.guava - guava - 30.0-jre - runtime - - - org.slf4j - jcl-over-slf4j - - - org.yaml - snakeyaml - - - diff --git a/swagger-templates/src/main/java/com/okta/swagger/codegen/AbstractOktaJavaClientCodegen.java b/swagger-templates/src/main/java/com/okta/swagger/codegen/AbstractOktaJavaClientCodegen.java deleted file mode 100644 index 1b78e9c0462..00000000000 --- a/swagger-templates/src/main/java/com/okta/swagger/codegen/AbstractOktaJavaClientCodegen.java +++ /dev/null @@ -1,1150 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.swagger.codegen; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.samskivert.mustache.Mustache; -import io.swagger.codegen.CodegenModel; -import io.swagger.codegen.CodegenOperation; -import io.swagger.codegen.CodegenParameter; -import io.swagger.codegen.CodegenProperty; -import io.swagger.codegen.CodegenType; -import io.swagger.codegen.languages.AbstractJavaCodegen; -import io.swagger.models.HttpMethod; -import io.swagger.models.Model; -import io.swagger.models.ModelImpl; -import io.swagger.models.Operation; -import io.swagger.models.Path; -import io.swagger.models.RefModel; -import io.swagger.models.Response; -import io.swagger.models.Swagger; -import io.swagger.models.parameters.BodyParameter; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.Property; -import io.swagger.models.properties.RefProperty; -import io.swagger.parser.SwaggerException; -import io.swagger.util.Json; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.text.WordUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.constructor.SafeConstructor; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.stream.Collectors; - -public abstract class AbstractOktaJavaClientCodegen extends AbstractJavaCodegen { - - private final String codeGenName; - - public static final String API_FILE_KEY = "apiFile"; - private static final String NON_OPTIONAL_PRAMS = "nonOptionalParams"; - static final String X_OPENAPI_V3_SCHEMA_REF = "x-openapi-v3-schema-ref"; - - @SuppressWarnings("hiding") - private final Logger log = LoggerFactory.getLogger(AbstractOktaJavaClientCodegen.class); - - protected Map modelTagMap = new HashMap<>(); - protected Set enumList = new HashSet<>(); - protected Map discriminatorMap = new HashMap<>(); - protected Map reverseDiscriminatorMap = new HashMap<>(); - protected Set topLevelResources = new HashSet<>(); - protected Map rawSwaggerConfig; - - public AbstractOktaJavaClientCodegen(String codeGenName, String relativeTemplateDir, String modelPackage) { - super(); - this.codeGenName = codeGenName; - this.dateLibrary = "legacy"; - - outputFolder = "generated-code" + File.separator + codeGenName; - embeddedTemplateDir = templateDir = relativeTemplateDir; - - artifactId = "not_used"; - - this.modelPackage = modelPackage; - // TODO: these are hard coded for now, calling Maven Plugin does NOT set the packages correctly. - invokerPackage = "com.okta.sdk.invoker"; - apiPackage = "com.okta.sdk.client"; - - apiTemplateFiles.clear(); - modelTemplateFiles.clear(); - } - - @Override - public void preprocessSwagger(Swagger swagger) { - - // make sure we have the apiFile location - String apiFile = (String) additionalProperties.get(API_FILE_KEY); - if (apiFile == null || apiFile.isEmpty()) { - throw new SwaggerException("'additionalProperties."+API_FILE_KEY +" property is required. This must be " + - "set to the same file that Swagger is using."); - } - - try (Reader reader = new InputStreamReader(new FileInputStream(apiFile), StandardCharsets.UTF_8.toString())) { - rawSwaggerConfig = new Yaml(new SafeConstructor()).load(reader); - } catch (IOException e) { - throw new IllegalStateException("Failed to parse apiFile: "+ apiFile, e); - } - - vendorExtensions.put("basePath", swagger.getBasePath()); - super.preprocessSwagger(swagger); - tagEnums(swagger); - buildTopLevelResourceList(swagger); - addListModels(swagger); - buildModelTagMap(swagger); - removeListAfterAndLimit(swagger); - moveOperationsToSingleClient(swagger); - handleOktaLinkedOperations(swagger); - buildDiscriminationMap(swagger); - buildGraalVMReflectionConfig(swagger); - } - - /** - * Figure out which models are top level models (directly returned from a endpoint). - * @param swagger The instance of swagger. - */ - protected void buildTopLevelResourceList(Swagger swagger) { - - Set resources = new HashSet<>(); - - // Loop through all of the operations looking for the models that are used as the response and body params - swagger.getPaths().forEach((pathName, path) -> - path.getOperations().forEach(operation -> { - // find all body params - operation.getParameters().forEach(parameter -> { - if (parameter instanceof BodyParameter) { - resources.add(((RefModel) ((BodyParameter)parameter).getSchema()).getSimpleRef()); - } - }); - - // response objects are a more complicated, start with filter for only the 200 responses - operation.getResponses().entrySet().stream() - .filter(entry -> "200".equals(entry.getKey())) - .forEach(entry -> { - // this schema could be a ref or an array property containing a ref (or null) - Property rawSchema = entry.getValue().getSchema(); - - if (rawSchema != null) { - RefProperty refProperty; - // detect array properties - if (rawSchema instanceof ArrayProperty) { - Property innerProp = ((ArrayProperty) rawSchema).getItems(); - if (innerProp instanceof RefProperty) { - refProperty = (RefProperty) innerProp; - } else { - // invalid swagger config file - throw new SwaggerException("Expected 'schema.items.$ref' to exist."); - } - } else if (rawSchema instanceof RefProperty) { - // non array, standard ref property typically in the format of '#/Definitions/MyModel' - refProperty = (RefProperty) rawSchema; - } else { - throw new SwaggerException("Expected 'schema' to be of type 'ArrayProperty' or 'RefProperty'."); - } - - // get the simple name 'MyModel' instead of '#/Definitions/MyModel' - resources.add(refProperty.getSimpleRef()); - } - }); - }) - ); - - // find any children of these resources - swagger.getDefinitions().forEach((name, model) -> { - String parent = (String) model.getVendorExtensions().get("x-okta-parent"); - if (parent != null) { - parent = parent.replaceAll(".*/", ""); - - if (resources.contains(parent)) { - resources.add(parent); - } - } - }); - - // mark each model with a 'top-level' vendorExtension - resources.stream() - .map(resourceName -> swagger.getDefinitions().get(resourceName)) - .forEach(model -> { - model.getVendorExtensions().put("top-level", true); - }); - - this.topLevelResources = resources; - } - - protected void buildDiscriminationMap(Swagger swagger) { - swagger.getDefinitions().forEach((name, model) -> { - ObjectNode discriminatorMapExtension = - (ObjectNode) model.getVendorExtensions().get("x-openapi-v3-discriminator"); - if (discriminatorMapExtension != null) { - String propertyName = discriminatorMapExtension.get("propertyName").asText(); - ObjectNode mapping = (ObjectNode) discriminatorMapExtension.get("mapping"); - ObjectMapper mapper = new ObjectMapper(); - Map result = mapper.convertValue(mapping, Map.class); - result = result.entrySet().stream() - .collect( - Collectors.toMap( - e -> e.getValue().substring(e.getValue().lastIndexOf('/') + 1), - e -> e.getKey(), - (oldValue, newValue) -> newValue - ) - ); - result.forEach((key, value) -> reverseDiscriminatorMap.put(key, name)); - discriminatorMap.put(name, new Discriminator(name, propertyName, result)); - } - }); - } - - protected void buildGraalVMReflectionConfig(Swagger swagger) { - - try { - List> reflectionConfig = swagger.getDefinitions().keySet().stream() - .filter(it -> !enumList.contains(it)) // ignore enums - .map(this::fqcn) - .map(this::reflectionConfig) - .collect(Collectors.toList()); - - // this is slightly error prone, but this project only has `api` and `impl` - File projectDir = new File(outputFolder(), "../../..").getCanonicalFile(); - String projectName = projectDir.getName(); - - File reflectionConfigFile = new File(projectDir, "target/classes/META-INF/native-image/com.okta.sdk/okta-sdk-" + projectName + "/generated-reflection-config.json"); - if (!(reflectionConfigFile.getParentFile().exists() || reflectionConfigFile.getParentFile().mkdirs())) { - throw new IllegalStateException("Failed to create directory: "+ reflectionConfigFile.getParent()); - } - new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(reflectionConfigFile, reflectionConfig); - } catch (IOException e) { - throw new IllegalStateException("Failed to write generated-reflection-config.json file", e); - } - } - - protected Map reflectionConfig(String fqcn) { - return Collections.singletonMap("name", fqcn); - } - - protected void tagEnums(Swagger swagger) { - swagger.getDefinitions().forEach((name, model) -> { - - if (model instanceof ModelImpl && ((ModelImpl) model).getEnum() != null) { - enumList.add(name); - } - }); - } - - protected void buildModelTagMap(Swagger swagger) { - - swagger.getDefinitions().forEach((key, definition) -> { - Object tags = definition.getVendorExtensions().get("x-okta-tags"); - if (tags != null) { - // if tags is NOT null, then assume it is an array - if (tags instanceof List) { - if (!((List) tags).isEmpty()) { - String packageName = tagToPackageName(((List) tags).get(0).toString()); - addToModelTagMap(key, packageName); - definition.getVendorExtensions().put("x-okta-package", packageName); - } - } - else { - throw new SwaggerException("Model: "+ key + " contains 'x-okta-tags' that is NOT a List."); - } - } - }); - } - - protected void addToModelTagMap(String modelName, String packageName) { - modelTagMap.put(modelName, packageName); - } - - protected String tagToPackageName(String tag) { - return tag.replaceAll("(.)(\\p{Upper})", "$1.$2").toLowerCase(Locale.ENGLISH); - } - - public void removeListAfterAndLimit(Swagger swagger) { - swagger.getPaths().forEach((pathName, path) -> - path.getOperations().forEach(operation -> - operation.getParameters().removeIf(param -> - !param.getRequired() && - ("limit".equals(param.getName()) || - "after".equals(param.getName()))) - ) - ); - } - - private void addAllIfNotNull(List destList, List srcList) { - if (srcList != null) { - destList.addAll(srcList); - } - } - - private void handleOktaLinkedOperations(Swagger swagger) { - // we want to move any operations defined by the 'x-okta-operations' or 'x-okta-crud' - // or 'x-okta-multi-operation' vendor extension to the model - Map modelMap = swagger.getDefinitions().entrySet().stream() - .filter(e -> e.getValue().getVendorExtensions().containsKey("x-okta-operations") - || e.getValue().getVendorExtensions().containsKey("x-okta-crud") - || e.getValue().getVendorExtensions().containsKey("x-okta-multi-operation")) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - - modelMap.forEach((k, model) -> { - List linkNodes = new ArrayList<>(); - - addAllIfNotNull(linkNodes, (List) model.getVendorExtensions().get("x-okta-operations")); - addAllIfNotNull(linkNodes, (List) model.getVendorExtensions().get("x-okta-crud")); - addAllIfNotNull(linkNodes, (List) model.getVendorExtensions().get("x-okta-multi-operation")); - - Map operationMap = new HashMap<>(); - - linkNodes.forEach(n -> { - String operationId = n.get("operationId").textValue(); - - // find the swagger path operation - swagger.getPaths().forEach((pathName, path) -> { - Optional> operationEntry = - path.getOperationMap().entrySet().stream().filter( - oper -> { - //Looking for an operationId in paths:path:operationId - if (oper.getValue().getOperationId() != null - && oper.getValue().getOperationId().equals(operationId)) { - return true; - } - //Looking for an operationId in paths:path:method:x-okta-multi-operation:operationId - List xOktaMultiOperation = getOktaMultiOperationObject(oper.getValue()); - if (xOktaMultiOperation != null && - xOktaMultiOperation - .stream() - .anyMatch(multiOper -> multiOper.getOperationId().equals(operationId)) - ) { - return true; - } - return false; - } - ).findFirst(); - - if (operationEntry.isPresent()) { - - Operation operation = operationEntry.get().getValue(); - - //Trying to get an Operation from x-okta-multi-operation - Operation xOktaMultiOperation = produceOperationFromXOktaMultiOperation(operation, operationId); - - CodegenOperation cgOperation = fromOperation( - pathName, - operationEntry.get().getKey().name().toLowerCase(), - xOktaMultiOperation != null ? xOktaMultiOperation : operation, - swagger.getDefinitions(), - swagger); - - boolean canLinkMethod = true; - - JsonNode aliasNode = n.get("alias"); - String alias = null; - if (aliasNode != null) { - alias = aliasNode.textValue(); - cgOperation.vendorExtensions.put("alias", alias); - - if ("update".equals(alias)) { - model.getVendorExtensions().put("saveable", true); - } else if ("delete".equals(alias)) { - model.getVendorExtensions().put("deletable", true); - cgOperation.vendorExtensions.put("selfDelete", true); - } - else if ("read".equals(alias) || "create".equals(alias)) { - canLinkMethod = false; - } - } - - // we do NOT link read or create methods, those need to be on the parent object - if (canLinkMethod) { - - // now any params that match the models we need to use the model value directly - // for example if the path contained {id} we would call getId() instead - - Map argMap = createArgMap(n); - - List cgOtherPathParamList = new ArrayList<>(); - List cgParamAllList = new ArrayList<>(); - List cgParamModelList = new ArrayList<>(); - - cgOperation.pathParams.forEach(param -> { - - if (argMap.containsKey(param.paramName)) { - - String paramName = argMap.get(param.paramName); - cgParamModelList.add(param); - - if (model.getProperties() != null) { - CodegenProperty cgProperty = fromProperty(paramName, model.getProperties().get(paramName)); - if(cgProperty == null && cgOperation.operationId.equals("deleteLinkedObjectDefinition")) { - cgProperty = new CodegenProperty(); - cgProperty.getter = "getPrimary().getName"; - } - param.vendorExtensions.put("fromModel", cgProperty); - } else { - System.err.println("Model '" + model.getTitle() + "' has no properties"); - } - - } else { - cgOtherPathParamList.add(param); - } - }); - - // remove the body param if the body is the object itself - for (Iterator iter = cgOperation.bodyParams.iterator(); iter.hasNext(); ) { - CodegenParameter bodyParam = iter.next(); - if (argMap.containsKey(bodyParam.paramName)) { - cgOperation.vendorExtensions.put("bodyIsSelf", true); - iter.remove(); - } - } - - // do not add the parrent path params to the list (they will be parsed from the href) - SortedSet pathParents = parentPathParams(n); - cgOtherPathParamList.forEach(param -> { - if (!pathParents.contains(param.paramName)) { - cgParamAllList.add(param); - } - }); - - //do not implement interface Deletable when delete method has some arguments - if(alias.equals("delete") && cgParamAllList.size() > 0) { - model.getVendorExtensions().put("deletable", false); - } - - if (!pathParents.isEmpty()) { - cgOperation.vendorExtensions.put("hasPathParents", true); - cgOperation.vendorExtensions.put("pathParents", pathParents); - } - - cgParamAllList.addAll(cgOperation.bodyParams); - cgParamAllList.addAll(cgOperation.queryParams); - cgParamAllList.addAll(cgOperation.headerParams); - - if(cgOperation.formParams.stream().anyMatch(x -> x.isFile)) { - cgOperation.vendorExtensions.put("fileUpload", true); - cgOperation.vendorExtensions.put("fileFormDataName", cgOperation.formParams.get(0).paramName); - cgParamAllList.addAll(cgOperation.formParams); - } - - // set all params to have more - cgParamAllList.forEach(param -> param.hasMore = true); - - // then grab the last one and mark it as the last - if (!cgParamAllList.isEmpty()) { - CodegenParameter param = cgParamAllList.get(cgParamAllList.size() - 1); - param.hasMore = false; - } - - cgOperation.vendorExtensions.put("allParams", cgParamAllList); - cgOperation.vendorExtensions.put("fromModelPathParams", cgParamModelList); - - addOptionalExtensionAndBackwardCompatibleArgs(cgOperation, cgParamAllList); - - operationMap.put(cgOperation.operationId, cgOperation); - - // mark the operation as moved so we do NOT add it to the client - operation.getVendorExtensions().put("moved", true); - - if ("VerifyUserFactorResponse".equals(cgOperation.returnType)) { - cgOperation.vendorExtensions.put("isUserFactor", true); - } - } - } - }); - }); - - model.getVendorExtensions().put("operations", operationMap.values()); - }); - } - - private List getOktaMultiOperationObject(Operation operation) { - Object multiOperationObject = operation.getVendorExtensions().get("x-okta-multi-operation"); - List xOktaMultiOperationList = new ArrayList<>(); - if (multiOperationObject instanceof List) { - for(Object node : (List)multiOperationObject) { - Operation multiOperation = Json.mapper().convertValue(node, Operation.class); - xOktaMultiOperationList.add(multiOperation); - } - return xOktaMultiOperationList; - } - return null; - } - - private Operation produceOperationFromXOktaMultiOperation(Operation operation, String operationId) { - - Operation xOktaMultiOperation = null; - - List xOktaMultiOperationList = getOktaMultiOperationObject(operation); - if (xOktaMultiOperationList != null) { - Optional operationFromXOktaMultiOperation = xOktaMultiOperationList.stream() - .filter(multiOper -> multiOper.getOperationId().equals(operationId)).findFirst(); - - if (operationFromXOktaMultiOperation.isPresent()) { - Operation xOktaMultiOperationTmp = operationFromXOktaMultiOperation.get(); - xOktaMultiOperation = new Operation(); - - // VendorExtensions deep copy - Map vendorExtensions = new LinkedHashMap<>(operation.getVendorExtensions()); - xOktaMultiOperation.setVendorExtensions(vendorExtensions); - - // Tags deep copy - List tags = new ArrayList<>(operation.getTags()); - xOktaMultiOperation.setTags(tags); - - xOktaMultiOperation.setSummary(operation.getSummary()); - xOktaMultiOperation.setDescription(xOktaMultiOperationTmp.getDescription()); - xOktaMultiOperation.setOperationId(xOktaMultiOperationTmp.getOperationId()); - - // Consumes deep copy - List consumes = new ArrayList<>(operation.getConsumes()); - xOktaMultiOperation.setConsumes(consumes); - - // Produces deep copy - List produces = new ArrayList<>(operation.getProduces()); - xOktaMultiOperation.setProduces(produces); - - // Parameters deep copy - List parameters = new ArrayList<>(operation.getParameters()); - xOktaMultiOperation.setParameters(parameters); - - // Responses deep copy - Map responses = new LinkedHashMap<>(operation.getResponses()); - xOktaMultiOperation.setResponses(responses); - - // Security deep copy - List>> security = new ArrayList<>(operation.getSecurity()); - xOktaMultiOperation.setSecurity(security); - - //Add params defined in x-okta-multi-operation - for(Parameter p: xOktaMultiOperationTmp.getParameters()) { - if (p instanceof BodyParameter && ((BodyParameter) p).getSchema() != null) { - xOktaMultiOperation.getParameters().add(p); - } else if (!(p instanceof BodyParameter)) { - xOktaMultiOperation.getParameters().add(p); - } - } - } - } - return xOktaMultiOperation; - } - - private Map createArgMap(ObjectNode n) { - - Map argMap = new LinkedHashMap<>(); - ArrayNode argNodeList = (ArrayNode) n.get("arguments"); - - if (argNodeList != null) { - for (Iterator argNodeIter = argNodeList.iterator(); argNodeIter.hasNext(); ) { - JsonNode argNode = (JsonNode) argNodeIter.next(); - - if (argNode.has("src")) { - String src = argNode.get("src").textValue(); - String dest = argNode.get("dest").textValue(); - if (src != null) { - argMap.put(dest, src); // reverse lookup - } - } - - if (argNode.has("self")) { - String dest = argNode.get("dest").textValue(); - argMap.put(dest, "this"); // reverse lookup - } - } - } - return argMap; - } - - private SortedSet parentPathParams(ObjectNode n) { - - SortedSet result = new TreeSet<>(); - ArrayNode argNodeList = (ArrayNode) n.get("arguments"); - - if (argNodeList != null) { - for (JsonNode argNode : argNodeList) { - if (argNode.has("parentSrc")) { - String src = argNode.get("parentSrc").textValue(); - String dest = argNode.get("dest").textValue(); - if (src != null) { - result.add(dest); - } - } - } - } - return result; - } - - private void moveOperationsToSingleClient(Swagger swagger) { - swagger.getPaths().values().forEach(path -> - path.getOperations().forEach(operation -> - operation.setTags(Collections.singletonList("client")) - ) - ); - } - - @Override - public String apiFileFolder() { - return outputFolder + "/" + apiPackage().replace('.', File.separatorChar); - } - - @Override - public String modelFileFolder() { - return outputFolder + "/" + modelPackage().replace('.', File.separatorChar); - } - - @Override - public CodegenType getTag() { - return CodegenType.CLIENT; - } - - @Override - public String getName() { - return codeGenName; - } - - @Override - public String getHelp() { - return "Generates a Java client library."; - } - - @Override - public String toModelFilename(String name) { - if (modelTagMap.containsKey(name)) { - String tag = modelTagMap.get(name); - return tag.replaceAll("\\.","/") +"/"+ super.toModelFilename(name); - } - return super.toModelFilename(name); - } - - @Override - public String toModelImport(String name) { - if (languageSpecificPrimitives.contains(name)) { - throw new IllegalStateException("Cannot import primitives: "+ name); - } - if (modelTagMap.containsKey(name)) { - return modelPackage() +"."+ modelTagMap.get(name) +"."+ name; - } - return super.toModelImport(name); - } - - protected String fqcn(String name) { - String className = toApiName(name); - if (modelTagMap.containsKey(className)) { - return modelPackage() +"."+ modelTagMap.get(className) +"."+ className; - } - return super.toModelImport(className); - } - - @Override - public CodegenModel fromModel(String name, Model model, Map allDefinitions) { - CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); - // super add these imports, and we don't want that dependency - codegenModel.imports.remove("ApiModel"); - - if (model.getVendorExtensions().containsKey("x-baseType")) { - String baseType = (String) model.getVendorExtensions().get("x-baseType"); - codegenModel.vendorExtensions.put("baseType", toModelName(baseType)); - codegenModel.imports.add(toModelName(baseType)); - } - - Collection operations = (Collection) codegenModel.vendorExtensions.get("operations"); - if (operations != null) { - operations.forEach(op -> { - if (op.returnType != null) { - codegenModel.imports.add(op.returnType); - } - if (op.allParams != null) { - op.allParams.stream() - .filter(param -> needToImport(param.dataType)) - .forEach(param -> codegenModel.imports.add(param.dataType)); - } - }); - } - - // force alias == false (likely only relevant for Lists, but something changed in swagger 2.2.3 to require this) - codegenModel.isAlias = false; - - String parent = (String) model.getVendorExtensions().get("x-okta-parent"); - if (StringUtils.isNotEmpty(parent)) { - codegenModel.parent = toApiName(parent.substring(parent.lastIndexOf("/"))); - - // figure out the resourceClass if this model has a parent - String discriminatorRoot = getRootDiscriminator(name); - if (discriminatorRoot != null) { - model.getVendorExtensions().put("discriminatorRoot", discriminatorRoot); - } - - } - - // We use '$ref' attributes with siblings, which isn't valid JSON schema (or swagger), so we need process - // additional attributes from the raw schema - Map modelDef = getRawSwaggerDefinition(name); - codegenModel.vars.forEach(codegenProperty -> { - Map rawPropertyMap = getRawSwaggerProperty(modelDef, codegenProperty.baseName); - codegenProperty.isReadOnly = Boolean.TRUE.equals(rawPropertyMap.get("readOnly")); - }); - - return codegenModel; - } - - private List sortOperations(Collection operations) { - - return operations.stream() - .sorted(Comparator.comparing(o -> ((CodegenOperation) o).path) - .thenComparing(o -> ((CodegenOperation) o).httpMethod)) - .collect(Collectors.toList()); - } - - private String getRootDiscriminator(String name) { - String result = reverseDiscriminatorMap.get(name); - - if (result != null) { - String parentResult = getRootDiscriminator(result); - if (parentResult != null) { - result = parentResult; - } - } - return result; - } - - @Override - public Map postProcessOperations(Map objs) { - - Map resultMap = super.postProcessOperations(objs); - - List> imports = (List>) objs.get("imports"); - Map operations = (Map) objs.get("operations"); - List codegenOperations = (List) operations.get("operation"); - - // find all of the list return values - Set importsToAdd = new HashSet<>(); - codegenOperations.stream() - .filter(cgOp -> cgOp.returnType != null) - .filter(cgOp -> cgOp.returnType.matches(".+List$")) - .forEach(cgOp -> importsToAdd.add(toModelImport(cgOp.returnType))); - - // the params might have imports too - codegenOperations.stream() - .filter(cgOp -> cgOp.allParams != null) - .forEach(cgOp -> cgOp.allParams.stream() - .filter(cgParam -> cgParam.isEnum) - .filter(cgParam -> needToImport(cgParam.dataType)) - .forEach(cgParam -> importsToAdd.add(toModelImport(cgParam.dataType)))); - - // add each one as an import - importsToAdd.forEach(className -> { - Map listImport = new LinkedHashMap<>(); - listImport.put("import", className); - imports.add(listImport); - }); - - operations.put("operation", sortOperations(codegenOperations)); - return resultMap; - } - - - @Override - public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - super.postProcessModelProperty(model, property); - if(!BooleanUtils.toBoolean(model.isEnum)) { - - //Do not use JsonWebKeyList because it's based on Map but API require a simple List - if(model.name.equals("OpenIdConnectApplicationSettingsClientKeys")) { - property.datatypeWithEnum = property.baseType + "<" + property.complexType + ">"; - } - - if (property.vendorExtensions.containsKey("x-okta-known-values")) { - String name = WordUtils.capitalizeFully(property.name); - property.vendorExtensions.put("x-okta-known-values-exists", true); - property.vendorExtensions.put("x-okta-known-values-class-name", name + "Values"); - property.datatypeWithEnum = property.baseType; - property.isEnum = false; - } - - String datatype = property.datatype; - if (datatype != null - && datatype.matches(".+List$") - && needToImport(datatype)) { - model.imports.add(datatype); - } - - String type = property.complexType; - if (type == null) { - type = property.baseType; - } - - if (needToImport(type)) { - model.imports.add(type); - } - - // super add these imports, and we don't want that dependency - model.imports.remove("ApiModelProperty"); - model.imports.remove("ApiModel"); - - //final String lib = getLibrary(); - //Needed imports for Jackson based libraries - if(additionalProperties.containsKey("jackson")) { - model.imports.add("JsonProperty"); - } - if(additionalProperties.containsKey("gson")) { - model.imports.add("SerializedName"); - } - } else { // enum class - //Needed imports for Jackson's JsonCreator - if(additionalProperties.containsKey("jackson")) { - model.imports.add("JsonCreator"); - } - } - - model.vendorExtensions.put("optionalClassnamePartial", (Mustache.Lambda) (frag, out) -> { - String templateResource = "/" + templateDir + "/" + model.classname + ".mustache"; - URL optionalClassnameTemplate = getClass().getResource(templateResource); - - Mustache.Compiler compiler = Mustache.compiler().withLoader((name) -> { - if (optionalClassnameTemplate != null) { - return new InputStreamReader(getClass().getResourceAsStream(templateResource), StandardCharsets.UTF_8); - } - return new StringReader(""); - }); - processCompiler(compiler).compile("{{> " + model.classname + "}}").execute(frag.context(), out); - }); - } - - @Override - public Map postProcessModelsEnum(Map objs) { - objs = super.postProcessModelsEnum(objs); - //Needed import for Gson based libraries - if (additionalProperties.containsKey("gson")) { - List> imports = (List>)objs.get("imports"); - List models = (List) objs.get("models"); - for (Object _mo : models) { - Map mo = (Map) _mo; - CodegenModel cm = (CodegenModel) mo.get("model"); - // for enum model - if (Boolean.TRUE.equals(cm.isEnum) && cm.allowableValues != null) { - cm.imports.add(importMapping.get("SerializedName")); - Map item = new HashMap(); - item.put("import", importMapping.get("SerializedName")); - imports.add(item); - } - } - } - return objs; - } - - @Override - public CodegenOperation fromOperation(String path, - String httpMethod, - Operation operation, - Map definitions, - Swagger swagger) { - CodegenOperation co = super.fromOperation(path, - httpMethod, - operation, - definitions, - swagger); - - // Deep copy for vendorExtensions Map - Map vendorExtensions = new LinkedHashMap<>(); - co.vendorExtensions.forEach(vendorExtensions::put); - co.vendorExtensions = vendorExtensions; - - // scan params for X_OPENAPI_V3_SCHEMA_REF, and _correct_ the param - co.allParams.forEach(param -> { - if (param.vendorExtensions.containsKey(X_OPENAPI_V3_SCHEMA_REF)) { - String enumDef = param.vendorExtensions.get(X_OPENAPI_V3_SCHEMA_REF).toString().replaceFirst(".*/",""); - param.isEnum = true; - param.enumName = enumDef; - param.dataType = enumDef; - } - }); - - // mark the operation as having optional params, so we can take advantage of it in the template - addOptionalExtensionAndBackwardCompatibleArgs(co, co.allParams); - - // if the body and the return type are the same mark the body param - co.bodyParams.forEach(bodyParam -> { - if (bodyParam.dataType.equals(co.returnType)) { - co.vendorExtensions.put("updateBody", true); - } - }); - - return co; - } - - private void addOptionalExtensionAndBackwardCompatibleArgs(CodegenOperation co, List params) { - addOptionalArgs(co, params); - addBackwardCompatibleArgs(co, params); - } - - private void addOptionalArgs(CodegenOperation co, List params) { - if (params.parallelStream().anyMatch(param -> !param.required)) { - co.vendorExtensions.put("hasOptional", true); - - List nonOptionalParams = params.stream() - .filter(param -> param.required) - .map(CodegenParameter::copy) - .collect(Collectors.toList()); - - if (!nonOptionalParams.isEmpty()) { - CodegenParameter param = nonOptionalParams.get(nonOptionalParams.size() - 1); - param.hasMore = false; - co.vendorExtensions.put(NON_OPTIONAL_PRAMS, nonOptionalParams); - } - - // remove the nonOptionalParams if we have trimmed down the list. - if (co.vendorExtensions.get(NON_OPTIONAL_PRAMS) != null && nonOptionalParams.isEmpty()) { - co.vendorExtensions.remove(NON_OPTIONAL_PRAMS); - } - - // remove the body parameter if it was optional - if (co.bodyParam != null && !co.bodyParam.required) { - co.vendorExtensions.put("optionalBody", true); - } - } - } - - private void addBackwardCompatibleArgs(CodegenOperation co, List params) { - // add backward compatible args only for major revisions greater than 1 - if (params.parallelStream().anyMatch(param -> param.vendorExtensions.containsKey("x-okta-added-version") && - Integer.parseInt(param.vendorExtensions.get("x-okta-added-version").toString().substring(0, 1)) > 1)) { - - // capture the backward compat params - Map> versionedParamsMap = new LinkedHashMap<>(); - - // loop through first and build the keys - List paramVersions = params.stream() - .filter(param -> param.vendorExtensions.containsKey("x-okta-added-version")) - .map(param -> param.vendorExtensions.get("x-okta-added-version").toString()) - .collect(Collectors.toList()); - Collections.reverse(paramVersions); - paramVersions.add("preversion"); // anything without 'x-okta-added-version' - - paramVersions.forEach(version -> versionedParamsMap.put(version, new ArrayList<>())); - - // now loop through again and figure out which buckets each param goes into - params.forEach(param -> { - String version = param.vendorExtensions.getOrDefault("x-okta-added-version", "preversion").toString(); - for (Map.Entry> entry : versionedParamsMap.entrySet()) { - - String versionKey = entry.getKey(); - List versionedParams = entry.getValue(); - - // add the param, the break if we are adding to the final version - versionedParams.add(param.copy()); - if (version.equals(versionKey)) { - break; - } - } - }); - - // remove the latest version as this is equivalent to the expected swagger flow - String latestVersion = paramVersions.get(0); - versionedParamsMap.remove(latestVersion); - - // also remove any versions that are empty - Map> resultVersionedParamsMap = versionedParamsMap.entrySet().stream() - .filter(entry -> - !entry.getValue().isEmpty() // not empty - && entry.getValue().stream().anyMatch(param -> param.isQueryParam || param.isHeaderParam)) // has query or header params - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - if (resultVersionedParamsMap.size() > 0) { - - // mark the last parm on each versioned param list - resultVersionedParamsMap.values().forEach(versionedParams -> { - if (!versionedParams.isEmpty()) { - CodegenParameter lastItem = versionedParams.get(versionedParams.size() - 1); - lastItem.hasMore = false; - } - }); - - // it'd be nice if we could just add new CodegenOperations, but the swagger lib does NOT support this - // instead we will add them as a vendorExtension and process them in a template - co.vendorExtensions.put("hasBackwardsCompatibleParams", true); - co.vendorExtensions.put("backwardsCompatibleParamsEntrySet", resultVersionedParamsMap.entrySet()); - } - } - } - - @Override - public String toVarName(String name) { - String originalResult = super.toVarName(name); - if (originalResult.contains("oauth")) { - originalResult = originalResult.replaceAll("oauth", "oAuth"); - } - return originalResult; - } - - @Override - public String toApiName(String name) { - if (name.length() == 0) { - return "Client"; - } - - name = sanitizeName(name); - return camelize(name); - } - - private Property getArrayPropertyFromOperation(Operation operation) { - - - if (operation != null && operation.getResponses() != null) { - Response response = operation.getResponses().get("200"); - if (response != null) { - return response.getSchema(); - } - } - return null; - } - - public void addListModels(Swagger swagger) { - - Map listModels = new LinkedHashMap<>(); - - // lists in paths - for (Path path : swagger.getPaths().values()) { - - List properties = new ArrayList<>(); - properties.add(getArrayPropertyFromOperation(path.getGet())); - properties.add(getArrayPropertyFromOperation(path.getPost())); - properties.add(getArrayPropertyFromOperation(path.getPatch())); - properties.add(getArrayPropertyFromOperation(path.getPut())); - - listModels.putAll(processListsFromProperties(properties, null, swagger)); - } - - swagger.getDefinitions() - .entrySet().stream() - .filter(entry -> topLevelResources.contains(entry.getKey())) - .forEach(entry -> { - Model model = entry.getValue(); - if (model != null && model.getProperties() != null) { - listModels.putAll(processListsFromProperties(model.getProperties().values(), model, swagger)); - } - }); - - listModels.forEach(swagger::addDefinition); - - } - - private Map processListsFromProperties(Collection properties, Model baseModel, Swagger swagger) { - - Map result = new LinkedHashMap<>(); - - for (Property p : properties) { - if (p != null && "array".equals(p.getType())) { - - ArrayProperty arrayProperty = (ArrayProperty) p; - if ( arrayProperty.getItems() instanceof RefProperty) { - RefProperty ref = (RefProperty) arrayProperty.getItems(); - - String baseName = ref.getSimpleRef(); - - // Do not generate List wrappers for primitives (or strings) - if (!languageSpecificPrimitives.contains(baseName) && topLevelResources.contains(baseName)) { - - String modelName = baseName + "List"; - - ModelImpl model = new ModelImpl(); - model.setName(modelName); - model.setAllowEmptyValue(false); - model.setDescription("Collection List for " + baseName); - - if (baseModel == null) { - baseModel = swagger.getDefinitions().get(baseName); - } - - // only add the tags from the base model - if (baseModel.getVendorExtensions().containsKey("x-okta-tags")) { - model.setVendorExtension("x-okta-tags", baseModel.getVendorExtensions().get("x-okta-tags")); - } - - model.setVendorExtension("x-isResourceList", true); - model.setVendorExtension("x-baseType", baseName); - model.setType(modelName); - - result.put(modelName, model); - } - } - } - } - - return result; - } - - @Override - public String getTypeDeclaration(Property p) { - - if ("password".equals(p.getFormat())) { - return "char[]"; - } - - if (p instanceof ArrayProperty) { - ArrayProperty ap = (ArrayProperty) p; - Property inner = ap.getItems(); - if (inner == null) { - // mimic super behavior - log.warn("{} (array property) does not have a proper inner type defined", ap.getName()); - return null; - } - - String type = super.getTypeDeclaration(inner); - if (!languageSpecificPrimitives.contains(type) && topLevelResources.contains(type)) { - return type + "List"; - } - } - return super.getTypeDeclaration(p); - } - - private Map castToMap(Object object) { - return (Map) object; - } - - protected Map getRawSwaggerDefinition(String name) { - return castToMap(castToMap(rawSwaggerConfig.get("definitions")).get(name)); - } - - protected Map getRawSwaggerProperty(Map definition, String propertyName) { - return castToMap(castToMap(definition.get("properties")).get(propertyName)); - } -} diff --git a/swagger-templates/src/main/java/com/okta/swagger/codegen/Discriminator.java b/swagger-templates/src/main/java/com/okta/swagger/codegen/Discriminator.java deleted file mode 100644 index 18a350ed780..00000000000 --- a/swagger-templates/src/main/java/com/okta/swagger/codegen/Discriminator.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.swagger.codegen; - -import java.util.Map; - -public class Discriminator { - - private final String parentDefName; - - private final String fieldName; - - private final Map valueDefMap; - - public Discriminator(String parentDefName, String fieldName, Map valueDefMap) { - this.parentDefName = parentDefName; - this.fieldName = fieldName; - this.valueDefMap = valueDefMap; - } - - public String getParentDefName() { - return parentDefName; - } - - public String getFieldName() { - return fieldName; - } - - public Map getValueDefMap() { - return valueDefMap; - } - - public String getDefaultFieldValue(String key) { - return valueDefMap.get(key); - } -} diff --git a/swagger-templates/src/main/java/com/okta/swagger/codegen/KeyValuePair.java b/swagger-templates/src/main/java/com/okta/swagger/codegen/KeyValuePair.java deleted file mode 100644 index e72fb9cdc3d..00000000000 --- a/swagger-templates/src/main/java/com/okta/swagger/codegen/KeyValuePair.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.swagger.codegen; - -/** - * Simple key/value pair to make things easier with swagger templates. - */ -public class KeyValuePair { - - public final String key; - public final String value; - - public KeyValuePair(String key, String value) { - this.key = key; - this.value = value; - } -} diff --git a/swagger-templates/src/main/java/com/okta/swagger/codegen/OktaJavaClientApiCodegen.java b/swagger-templates/src/main/java/com/okta/swagger/codegen/OktaJavaClientApiCodegen.java deleted file mode 100644 index bdc99511738..00000000000 --- a/swagger-templates/src/main/java/com/okta/swagger/codegen/OktaJavaClientApiCodegen.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.swagger.codegen; - -public class OktaJavaClientApiCodegen extends AbstractOktaJavaClientCodegen -{ - - public OktaJavaClientApiCodegen() { - super("okta_java", "OktaJava", "com.okta.sdk.resource"); - - modelTemplateFiles.put("model.mustache", ".java"); - - apiTemplateFiles.put("api.mustache", ".java"); - } -} diff --git a/swagger-templates/src/main/java/com/okta/swagger/codegen/OktaJavaClientImplCodegen.java b/swagger-templates/src/main/java/com/okta/swagger/codegen/OktaJavaClientImplCodegen.java deleted file mode 100644 index 475cbdf317f..00000000000 --- a/swagger-templates/src/main/java/com/okta/swagger/codegen/OktaJavaClientImplCodegen.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright 2017 Okta - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.okta.swagger.codegen; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.swagger.codegen.CodegenModel; -import io.swagger.codegen.CodegenOperation; -import io.swagger.codegen.CodegenProperty; -import io.swagger.models.Model; -import io.swagger.models.Operation; -import io.swagger.models.Swagger; -import org.apache.commons.lang3.BooleanUtils; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class OktaJavaClientImplCodegen extends AbstractOktaJavaClientCodegen -{ - private static final String CREATE_NESTED_KEY = "x-oktaInstantiateNested"; - - private final String overrideModelPackage; - - public OktaJavaClientImplCodegen() { - super("okta_java_impl", "OktaJavaImpl", "com.okta.sdk.impl.resource"); - - modelTemplateFiles.put("model.mustache", ".java"); - overrideModelPackage = "com.okta.sdk.resource"; - apiPackage = "com.okta.sdk.impl.client"; - vendorExtensions().put("overrideModelPackage", overrideModelPackage); - vendorExtensions().put("overrideApiPackage", "com.okta.sdk.client"); - - apiTemplateFiles.put("api.mustache", ".java"); - } - - @Override - public void preprocessSwagger(Swagger swagger) { - super.preprocessSwagger(swagger); - // Enum based definitions are created by OktaJavaClientApiCodegen, so they need to be removed here - enumList.forEach(enumEntry -> swagger.getDefinitions().remove(enumEntry)); - } - - @Override - public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { - super.postProcessModelProperty(model, property); - if (!BooleanUtils.toBoolean(model.isEnum)) { - - String propertyType; - String propertyTypeMethod; - boolean forceCast = false; - - if(property.isListContainer) { - if (property.items.baseType.equals("String")) { - propertyType = "ListProperty"; - propertyTypeMethod = "getListProperty"; - } else if(enumList.contains(property.items.baseType)) { - propertyType = "EnumListProperty"; - propertyTypeMethod = "getEnumListProperty"; - property.vendorExtensions.put("itemType", property.items.datatypeWithEnum); - property.vendorExtensions.put("constructorTypeExtra", ", " + property.items.datatypeWithEnum + ".class"); - property.vendorExtensions.put("typeClassExtra", Boolean.TRUE); - } else { - propertyType = "ResourceListProperty"; - propertyTypeMethod = "getResourceListProperty"; - property.vendorExtensions.put("itemType", property.items.datatypeWithEnum); - property.vendorExtensions.put("constructorTypeExtra", ", " + property.items.datatypeWithEnum + ".class"); - property.vendorExtensions.put("typeClassExtra", Boolean.TRUE); - } - forceCast = true; - } else if (property.isEnum || enumList.contains(property.datatype)) { - propertyType = "EnumProperty"; - propertyTypeMethod = "getEnumProperty"; - property.vendorExtensions.put("itemType", property.datatypeWithEnum); - property.vendorExtensions.put("constructorTypeExtra", ", " + property.datatypeWithEnum + ".class"); - property.vendorExtensions.put("typeClassExtra", Boolean.TRUE); - } else if(property.isMapContainer || "Object".equals(property.datatype)) { - propertyType = "MapProperty"; - propertyTypeMethod = "getMap"; - } - else { - - switch (property.baseType) { - case "String": - if ("password".equals(property.dataFormat)) { - propertyType = "CharacterArrayProperty"; - propertyTypeMethod = "getCharArray"; - } else { - propertyType = "StringProperty"; - propertyTypeMethod = "getString"; - } - break; - case "Boolean": - propertyType = "BooleanProperty"; - propertyTypeMethod = "getBoolean"; - break; - case "Integer": - propertyType = "IntegerProperty"; - propertyTypeMethod = "getIntProperty"; - break; - case "Date": - propertyType = "DateProperty"; - propertyTypeMethod = "getDateProperty"; - break; - case "Double": - propertyType = "DoubleProperty"; - propertyTypeMethod = "getDoubleProperty"; - break; - default: - propertyType = "ResourceReference"; - propertyTypeMethod = "getResourceProperty"; - property.vendorExtensions.put("itemType", property.datatype); - property.vendorExtensions.put("constructorTypeExtra", buildConstructorTypeExtra(property)); - property.vendorExtensions.put("typeClassExtra", Boolean.TRUE); - } - } - - property.vendorExtensions.put("forceCast", forceCast); - property.vendorExtensions.put("propertyType", propertyType); - property.vendorExtensions.put("propertyTypeMethod", propertyTypeMethod); - - } - } - - private String buildConstructorTypeExtra(CodegenProperty property) { - Collection autoCreateParams = Collections.singleton("profile"); - boolean createNested = property.vendorExtensions.containsKey(CREATE_NESTED_KEY) || autoCreateParams.contains(property.name); - return ", " + property.datatype + ".class, "+ createNested; - } - - @Override - public CodegenModel fromModel(String name, Model model, Map allDefinitions) { - CodegenModel codegenModel = super.fromModel(name, model, allDefinitions); - codegenModel.imports.add(toModelName(codegenModel.classname)); // The 'Default' gets added in the template - - Map defaultValuesMap = new LinkedHashMap<>(); - - ObjectNode rawDefaultValues = (ObjectNode) codegenModel.vendorExtensions.get("x-okta-defined-as"); - if (rawDefaultValues != null) { - rawDefaultValues.fields().forEachRemaining(entry -> { - defaultValuesMap.put(entry.getKey(), entry.getValue().textValue()); - }); - } - - // if the parent is set, we need to check for discrimination - String parent = (String) codegenModel.vendorExtensions.get("x-okta-parent"); - if (parent != null) { - parent = parent.substring(parent.lastIndexOf('/') + 1); - if (discriminatorMap.containsKey(parent)) { - Discriminator discriminator = discriminatorMap.get(parent); - - String fieldName = discriminator.getFieldName(); - String defaultValue = discriminator.getDefaultFieldValue(name); - - defaultValuesMap.put(fieldName, defaultValue); - } - } - - List defaultTypeSetter = defaultValuesMap.entrySet().stream() - .map(entry -> new KeyValuePair(entry.getKey(), entry.getValue())) - .collect(Collectors.toList()); - - codegenModel.vendorExtensions.put("defaultSetter", defaultTypeSetter); - - return codegenModel; - } - - public CodegenOperation fromOperation(String path, - String httpMethod, - Operation operation, - Map definitions, - Swagger swagger) { - CodegenOperation co = super.fromOperation(path, - httpMethod, - operation, - definitions, - swagger); - - co.vendorExtensions.put("resourceReturnType", co.returnType); - - if ("put".equals(httpMethod) ) { - - co.vendorExtensions.put("dsMethod", "create"); - co.vendorExtensions.put("isPut", true); - - if (co.bodyParam == null) { - co.vendorExtensions.put("resourceReturnType", "VoidResource"); - } - else { - co.vendorExtensions.put("dsMethod", "save"); - } - if ("updateBrandTheme".equals(operation.getOperationId()) || - "updateFeatureForApplication".equals(operation.getOperationId()) || - "updateEmailTemplateCustomization".equals(operation.getOperationId())) { - co.vendorExtensions.put("forceToCreateObject", "true"); - } - } else if ("post".equals(httpMethod) ) { - - co.vendorExtensions.put("dsMethod", "create"); - co.vendorExtensions.put("isPost", true); - } else if ("get".equals(httpMethod)) { - co.vendorExtensions.put("dsMethod", "getResource"); - co.vendorExtensions.put("isGet", true); - } else if ("delete".equals(httpMethod)) { - co.vendorExtensions.put("dsMethod", "delete"); - co.vendorExtensions.put("isDelete", true); - } - - // pre interpolate the resource href - co.vendorExtensions.put("hrefFiltered", co.path - .replaceAll("\\{", "\" + ") - .replaceAll("\\}", " + \"")); - - return co; - } - - @Override - protected void addToModelTagMap(String modelName, String packageName) { - modelTagMap.put(modelName, packageName); - modelTagMap.put("Default" + modelName, packageName); // Also add the 'Default' impl - } - - @Override - public String toApiName(String name) { - return "Default" + super.toApiName(name); - } - - @Override - public String toModelFilename(String name) { - return super.toModelFilename("Default" + name); - } - - @Override - public Map postProcessOperations(Map objs) { - - objs.entrySet().stream() - .filter(e -> "operations".equals(e.getKey()) && e.getValue() instanceof Map) - .filter(e -> ((Map) e.getValue()).containsKey("classname")) - .forEach(e -> { - Map ops = (Map) e.getValue(); - String interfaceClassname = ops.get("classname").toString().replaceFirst("^Default", ""); - ops.put("interfaceClassname", interfaceClassname); - }); - - return super.postProcessOperations(objs); - } - - public String toModelImport(String name) { - - if ("".equals(modelPackage())) { - return name; - } - - if (modelTagMap.containsKey(name)) { - return overrideModelPackage +"."+ modelTagMap.get(name) +"."+ name; - } - - return overrideModelPackage + "." + name; - } - - @Override - protected void buildDiscriminationMap(Swagger swagger) { - super.buildDiscriminationMap(swagger); - - Map rootConfigMap = new HashMap<>(); - Map destMap = new HashMap<>(); - rootConfigMap.put("config", destMap); - discriminatorMap.values().forEach(disc -> { - String fqn = toModelImport(disc.getParentDefName()); - String fieldName = disc.getFieldName(); - Map valueMap = disc.getValueDefMap().entrySet().stream() - .collect(Collectors.toMap(e -> e.getValue(), e -> toModelImport(e.getKey()))); - Map entries = new HashMap<>(); - entries.put("fieldName", fieldName); - entries.put("values", valueMap); - destMap.put(fqn, entries); - }); - - // now dump this to yaml - // cheat a little here because we are assuming we are using maven, replace the LAST index of /target/ (the - // release process will have two 'target' directories in the path - String mavenTargetDir = outputFolder().substring(0, outputFolder.lastIndexOf("/target/") + 8); - File destDir = new File(mavenTargetDir, "generated-resources/swagger/" + overrideModelPackage.replace('.', '/')); - - boolean folderCreated = destDir.mkdirs(); - if (!folderCreated && !destDir.exists()) { - throw new RuntimeException("Directory does not exist and could not be created: " + destDir); - } - - File destFileJson = new File(destDir, "/discrimination.json"); - try (OutputStream outputStream = new FileOutputStream(destFileJson)) { - new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(outputStream, rootConfigMap); - } catch (IOException e) { - throw new RuntimeException("Failed to write discrimination map to json: "+ destFileJson.getAbsolutePath(), e); - } - } - - @Override - protected Map reflectionConfig(String fqcn) { - Map data = new HashMap<>(super.reflectionConfig(fqcn)); - data.put("allDeclaredConstructors", true); - return data; - } -} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/swagger-templates/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig deleted file mode 100644 index e7aa10689fa..00000000000 --- a/swagger-templates/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ /dev/null @@ -1,2 +0,0 @@ -com.okta.swagger.codegen.OktaJavaClientApiCodegen -com.okta.swagger.codegen.OktaJavaClientImplCodegen \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJava/api.mustache b/swagger-templates/src/main/resources/OktaJava/api.mustache deleted file mode 100644 index 89aa87bf7c0..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/api.mustache +++ /dev/null @@ -1,114 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{>licenseInfo}} -package {{package}}; - -{{#imports}}import {{import}}; -{{/imports}} - -import java.util.LinkedHashMap; -import com.okta.sdk.ds.DataStore; - -{{#operations}} -/** -* The {@code Client} is the main entry point to the Okta Java SDK. A JVM project wishing to -* communicate with the Okta REST API service must build a {@code Client} instance. After obtaining -* a {@code Client instance}, the REST API may be used by making simple Java calls on objects returned from -* the Client (or any children objects obtained therein). -*

    -* For example: -*

    -* Client client = Clients.builder().build();
    -*
    -* client.getUser(userId)
    -* 
    -* @see Communicating with Okta: Get your API Token -* @see DataStore -* @since 0.5.0 -*/ -@javax.annotation.Generated(value = "{{generatorClass}}", - date = "{{generatedDate}}") -public interface {{classname}} extends DataStore { - - /** - * Returns the internal {@link DataStore} of the client. It is typically not necessary to invoke this method as - * the Client implements the {@link DataStore} API and will delegate to this instance automatically. - * - * @return the client's internal {@link DataStore}. - */ - DataStore getDataStore(); - -{{#operation}} -{{^vendorExtensions.moved}} - /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/allParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); - - {{#vendorExtensions.hasOptional}} - /** - * {{summary}} - * {{notes}} - {{#vendorExtensions.nonOptionalParams}} - * @param {{paramName}} {{description}} (required) - {{/vendorExtensions.nonOptionalParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#vendorExtensions.nonOptionalParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/vendorExtensions.nonOptionalParams}}); - {{/vendorExtensions.hasOptional}} - -{{#vendorExtensions.hasBackwardsCompatibleParams}} -{{#vendorExtensions.backwardsCompatibleParamsEntrySet}} - /** - * {{summary}} - * {{notes}} - {{#value}} - * @param {{paramName}} {{description}} (required) - {{/value}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#value}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/value}}); - -{{/vendorExtensions.backwardsCompatibleParamsEntrySet}} -{{/vendorExtensions.hasBackwardsCompatibleParams}} - -{{/vendorExtensions.moved}} -{{/operation}} -} -{{/operations}} diff --git a/swagger-templates/src/main/resources/OktaJava/generatedAnnotation.mustache b/swagger-templates/src/main/resources/OktaJava/generatedAnnotation.mustache deleted file mode 100644 index 04d0c0e0c4e..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/generatedAnnotation.mustache +++ /dev/null @@ -1,16 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{^hideGenerationTimestamp}}@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJava/licenseInfo.mustache b/swagger-templates/src/main/resources/OktaJava/licenseInfo.mustache deleted file mode 100644 index ff43812357d..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/licenseInfo.mustache +++ /dev/null @@ -1,26 +0,0 @@ -{{! - Copyright 2017-Present Okta, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -/* - * {{{appName}}} - * {{{appDescription}}} - * - * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} - * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} - * - * NOTE: This class is auto generated by the swagger code generator program. - * https://github.com/swagger-api/swagger-codegen.git - * Do not edit the class manually. - */ diff --git a/swagger-templates/src/main/resources/OktaJava/manifest.mustache b/swagger-templates/src/main/resources/OktaJava/manifest.mustache deleted file mode 100644 index abbe36ce05f..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/manifest.mustache +++ /dev/null @@ -1,18 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - - - diff --git a/swagger-templates/src/main/resources/OktaJava/model.mustache b/swagger-templates/src/main/resources/OktaJava/model.mustache deleted file mode 100644 index c0aabc1b43c..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/model.mustache +++ /dev/null @@ -1,30 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{>licenseInfo}} - -{{! this is a hack to get sub package name generations working with swagger }} -package {{package}}{{#models}}{{#model}}{{#vendorExtensions.x-okta-package}}.{{vendorExtensions.x-okta-package}}{{/vendorExtensions.x-okta-package}}{{/model}}{{/models}}; - -{{#imports}} -import {{import}}; -{{/imports}} - -{{#models}} -{{#model}} -{{#vendorExtensions.x-isResourceList}}{{>modelListResourceInterface}}{{/vendorExtensions.x-isResourceList}}{{^vendorExtensions.x-isResourceList}} -{{#isEnum}}{{>modelEnum}}{{/isEnum}}{{^isEnum}}{{>modelInterface}}{{/isEnum}}{{/vendorExtensions.x-isResourceList}} -{{/model}} -{{/models}} diff --git a/swagger-templates/src/main/resources/OktaJava/modelEnum.mustache b/swagger-templates/src/main/resources/OktaJava/modelEnum.mustache deleted file mode 100644 index e0182b4cc34..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/modelEnum.mustache +++ /dev/null @@ -1,39 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - -/** - * {{^description}}Enum {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} - */ -public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { - - {{#allowableValues}}{{#enumVars}} - {{{name}}}({{{value}}}), - {{/enumVars}} - - SDK_UNKNOWN("SDK_UNKNOWN"); - {{/allowableValues}} - - private {{{dataType}}} value; - - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { - this.value = value; - } - - @Override - public String toString() { - return String.valueOf(value); - } -} diff --git a/swagger-templates/src/main/resources/OktaJava/modelInnerEnum.mustache b/swagger-templates/src/main/resources/OktaJava/modelInnerEnum.mustache deleted file mode 100644 index e839583b5b0..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/modelInnerEnum.mustache +++ /dev/null @@ -1,48 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - /** - * {{^description}}Enum {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} - */ - public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} { - {{#gson}} - {{#allowableValues}} - {{#enumVars}} - @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) - {{{name}}}({{{value}}}){{^-last}}, - {{/-last}}{{#-last}};{{/-last}} - {{/enumVars}} - {{/allowableValues}} - {{/gson}} - {{^gson}} - {{#allowableValues}} - {{#enumVars}} - {{{name}}}({{{value}}}){{^-last}}, - {{/-last}}{{#-last}};{{/-last}} - {{/enumVars}} - {{/allowableValues}} - {{/gson}} - - private {{{datatype}}} value; - - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}({{{datatype}}} value) { - this.value = value; - } - - @Override - public String toString() { - return String.valueOf(value); - } - } diff --git a/swagger-templates/src/main/resources/OktaJava/modelInterface.mustache b/swagger-templates/src/main/resources/OktaJava/modelInterface.mustache deleted file mode 100644 index b8bfef9e63f..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/modelInterface.mustache +++ /dev/null @@ -1,112 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -import java.util.Map; -import com.okta.sdk.resource.ExtensibleResource; -import com.okta.sdk.resource.Deletable; -import com.okta.sdk.resource.Saveable; -{{#vendorExtensions.x-okta-extensible}}import com.okta.sdk.resource.PropertyRetriever;{{/vendorExtensions.x-okta-extensible}} -{{#models}}{{#model}} -/** - * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} - */ -{{>generatedAnnotation}} -public interface {{classname}} extends ExtensibleResource{{#parent}}, {{.}}{{/parent}}{{#vendorExtensions.x-okta-extensible}}, PropertyRetriever, Map{{/vendorExtensions.x-okta-extensible}}{{#vendorExtensions.deletable}}, Deletable{{/vendorExtensions.deletable}} { - -{{#vars}} - {{#vendorExtensions.extraAnnotation}} - {{{vendorExtensions.extraAnnotation}}} - {{/vendorExtensions.extraAnnotation}} - {{{datatypeWithEnum}}} {{getter}}(); -{{^isReadOnly}} - - {{classname}} {{setter}}({{{datatypeWithEnum}}} {{name}}); -{{/isReadOnly}} - -{{#vendorExtensions.x-okta-known-values-exists}} - {{>modelKnownValues}} -{{/vendorExtensions.x-okta-known-values-exists}} -{{#isEnum}} - {{^isContainer}} -{{>modelInnerEnum}} - {{/isContainer}} -{{/isEnum}} -{{#items.isEnum}} - {{#items}} - {{^isContainer}} -{{>modelInnerEnum}} - {{/isContainer}} - {{/items}} -{{/items.isEnum}} -{{/vars}} -{{#vendorExtensions.operations}}{{#.}} - /** - * {{summary}} - * {{notes}} - {{#vendorExtensions.allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/vendorExtensions.allParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{#vendorExtensions.alias}}{{vendorExtensions.alias}}{{/vendorExtensions.alias}}{{^vendorExtensions.alias}}{{operationId}}{{/vendorExtensions.alias}}({{#vendorExtensions.allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/vendorExtensions.allParams}}); - -{{#vendorExtensions.hasOptional}} - /** - * {{summary}} - * {{notes}} - {{#vendorExtensions.nonOptionalParams}} - * @param {{paramName}} {{description}} (required) - {{/vendorExtensions.nonOptionalParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{#vendorExtensions.alias}}{{vendorExtensions.alias}}{{/vendorExtensions.alias}}{{^vendorExtensions.alias}}{{operationId}}{{/vendorExtensions.alias}}({{#vendorExtensions.nonOptionalParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/vendorExtensions.nonOptionalParams}}); -{{/vendorExtensions.hasOptional}} -{{#vendorExtensions.hasBackwardsCompatibleParams}} -{{#vendorExtensions.backwardsCompatibleParamsEntrySet}} - /** - * {{summary}} - * {{notes}} - {{#value}} - * @param {{paramName}} {{description}} (required) - {{/value}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - // backwardsCompatible spec v{{key}} - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{vendorExtensions.alias}}({{#value}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/value}}); -{{/vendorExtensions.backwardsCompatibleParamsEntrySet}} -{{/vendorExtensions.hasBackwardsCompatibleParams}} -{{/.}} -{{/vendorExtensions.operations}} -{{#vendorExtensions.optionalClassnamePartial}}// optional class specific partial{{/vendorExtensions.optionalClassnamePartial}} -} -{{/model}}{{/models}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJava/modelKnownValues.mustache b/swagger-templates/src/main/resources/OktaJava/modelKnownValues.mustache deleted file mode 100644 index 90d0daf0f8f..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/modelKnownValues.mustache +++ /dev/null @@ -1,21 +0,0 @@ -{{! - Copyright 2021, Okta Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - - public static class {{#vendorExtensions.x-okta-known-values-class-name}}{{{.}}}{{/vendorExtensions.x-okta-known-values-class-name}} { - {{#vendorExtensions.x-okta-known-values}} - public static final String {{{.}}} = "{{{.}}}"; - {{/vendorExtensions.x-okta-known-values}} - } \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJava/modelListResourceInterface.mustache b/swagger-templates/src/main/resources/OktaJava/modelListResourceInterface.mustache deleted file mode 100644 index ddf38b1cbf0..00000000000 --- a/swagger-templates/src/main/resources/OktaJava/modelListResourceInterface.mustache +++ /dev/null @@ -1,23 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - -import com.okta.sdk.resource.CollectionResource; - -/** -* {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} -*/ -{{>generatedAnnotation}} -public interface {{classname}} extends CollectionResource<{{vendorExtensions.baseType}}> {} diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/api.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/api.mustache deleted file mode 100644 index b53f64aa8b8..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/api.mustache +++ /dev/null @@ -1,182 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{>licenseInfo}} -package {{package}}; - -import com.okta.commons.http.RequestExecutor; -import com.okta.sdk.cache.CacheManager; -import com.okta.sdk.client.AuthenticationScheme; -import com.okta.commons.http.config.Proxy; -import com.okta.commons.http.QueryString; -import com.okta.commons.http.HttpHeaders; -import com.okta.sdk.impl.config.ClientConfiguration; - -import {{vendorExtensions.overrideApiPackage}}.*; - -{{#imports}}import {{import}}; -{{/imports}} -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.impl.resource.DefaultVoidResource; - -import java.util.LinkedHashMap; -{{^fullJavaUtil}} -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -{{/fullJavaUtil}} - -import static com.okta.commons.lang.Assert.notNull; -import static com.okta.commons.lang.Assert.hasText; - -{{#operations}} -@javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}") -@SuppressWarnings("deprecation") -public class {{classname}} extends com.okta.sdk.impl.client.BaseClient implements com.okta.sdk.client.Client { - - /** - * Instantiates a new Client instance that will communicate with the Okta REST API. See the class-level - * JavaDoc for a usage example. - * - * @param clientConfiguration the {@link ClientConfiguration} containing the connection information - * @param cacheManager the {@link CacheManager} that should be used to cache - */ - public {{classname}}(ClientConfiguration clientConfiguration, CacheManager cacheManager) { - super(clientConfiguration, cacheManager); - } - - /** - * Instantiates a new Client instance that will communicate with the Okta REST API. See the class-level - * JavaDoc for a usage example. - * - * @param clientConfiguration the {@link ClientConfiguration} containing the connection information - * @param cacheManager the {@link CacheManager} that should be used to cache - * @param requestExecutor the {@link RequestExecutor} that should be used to execute requests - */ - public {{classname}}(ClientConfiguration clientConfiguration, CacheManager cacheManager, RequestExecutor requestExecutor) { - super(clientConfiguration, cacheManager, requestExecutor); - } - -{{#operation}}{{^vendorExtensions.moved}} - /** - * {{summary}} - * {{notes}} - {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/allParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @Override - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { -{{>paramPartial}} -{{#vendorExtensions.isGet}} -{{>apiMethodGet}} -{{/vendorExtensions.isGet}} -{{#vendorExtensions.isPut}} -{{>apiMethodPut}} -{{/vendorExtensions.isPut}} -{{#vendorExtensions.isPost}} -{{>apiMethodPostClient}} -{{/vendorExtensions.isPost}} -{{#vendorExtensions.isDelete}} -{{>apiMethodDelete}} -{{/vendorExtensions.isDelete}} - } - -{{#vendorExtensions.hasOptional}} - /** - * {{summary}} - * {{notes}} - {{#vendorExtensions.nonOptionalParams}} - * @param {{paramName}} {{description}} (required) - {{/vendorExtensions.nonOptionalParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @Override - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#vendorExtensions.nonOptionalParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/vendorExtensions.nonOptionalParams}}) { -{{>paramPartialOnlyRequired}} -{{#vendorExtensions.isGet}} -{{>apiMethodGet}} -{{/vendorExtensions.isGet}} -{{#vendorExtensions.isPut}} -{{>apiMethodPut}} -{{/vendorExtensions.isPut}} -{{#vendorExtensions.isPost}} -{{#vendorExtensions.optionalBody}} -{{>apiMethodPostNoBody}} -{{/vendorExtensions.optionalBody}} -{{^vendorExtensions.optionalBody}} -{{>apiMethodPostClient}} -{{/vendorExtensions.optionalBody}} -{{/vendorExtensions.isPost}} -{{#vendorExtensions.isDelete}} -{{>apiMethodDelete}} -{{/vendorExtensions.isDelete}} - } -{{/vendorExtensions.hasOptional}} - -{{#vendorExtensions.hasBackwardsCompatibleParams}} -{{#vendorExtensions.backwardsCompatibleParamsEntrySet}} - /** - * {{summary}} - * {{notes}} - {{#value}} - * @param {{paramName}} {{description}} (required) - {{/value}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @Override - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#value}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/value}}) { -{{>paramPartialBackwardsCompat}} -{{#vendorExtensions.isGet}} -{{>apiMethodGet}} -{{/vendorExtensions.isGet}} -{{#vendorExtensions.isPut}} -{{>apiMethodPut}} -{{/vendorExtensions.isPut}} -{{#vendorExtensions.isPost}} -{{>apiMethodPostClient}} -{{/vendorExtensions.isPost}} -{{#vendorExtensions.isDelete}} -{{>apiMethodDelete}} -{{/vendorExtensions.isDelete}} - } -{{/vendorExtensions.backwardsCompatibleParamsEntrySet}} -{{/vendorExtensions.hasBackwardsCompatibleParams}} -{{/vendorExtensions.moved}} -{{/operation}} -} -{{/operations}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodDelete.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodDelete.mustache deleted file mode 100644 index d1454d14346..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodDelete.mustache +++ /dev/null @@ -1,25 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - getDataStore().delete( -{{#vendorExtensions.selfDelete}} - "{{{vendorExtensions.hrefFiltered}}}", - (Resource) this, -{{/vendorExtensions.selfDelete}} -{{^vendorExtensions.selfDelete}} - "{{{vendorExtensions.hrefFiltered}}}", -{{/vendorExtensions.selfDelete}} - queryArgs, - headers); \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodGet.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodGet.mustache deleted file mode 100644 index b701c18043b..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodGet.mustache +++ /dev/null @@ -1,20 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - {{#returnType}}return {{/returnType}}getDataStore().getResource( - "{{{vendorExtensions.hrefFiltered}}}", - {{#returnType}}{{{returnType}}}.class{{/returnType}}{{^returnType}}VoidResource.class{{/returnType}}, - queryArgs, - headers); \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPost.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPost.mustache deleted file mode 100644 index b8077c6497e..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPost.mustache +++ /dev/null @@ -1,41 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{#returnType}}{{#vendorExtensions.updateBody}}{{#vendorExtensions.bodyIsSelf}} - {{returnType}} {{bodyParam.paramName}} = this; -{{/vendorExtensions.bodyIsSelf}}{{/vendorExtensions.updateBody}} -{{/returnType}} -{{#returnType}}{{^vendorExtensions.updateBody}} - return {{/vendorExtensions.updateBody}}{{/returnType}}getDataStore().create( - "{{{vendorExtensions.hrefFiltered}}}", -{{#vendorExtensions.bodyIsSelf}} - this -{{/vendorExtensions.bodyIsSelf}} -{{^vendorExtensions.bodyIsSelf}} - {{bodyParam.paramName}}, -{{/vendorExtensions.bodyIsSelf}} -{{^bodyParam}} - new DefaultVoidResource(getDataStore()){{/bodyParam}}, -{{#returnType}} -{{#vendorExtensions.updateBody}} - {{bodyParam.paramName}}.getClass(){{/vendorExtensions.updateBody}} -{{^vendorExtensions.updateBody}} - {{returnType}}.class{{/vendorExtensions.updateBody}} -{{/returnType}} - queryArgs, - headers); -{{#returnType}} -{{#vendorExtensions.updateBody}} return {{bodyParam.paramName}};{{/vendorExtensions.updateBody}} -{{/returnType}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostClient.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostClient.mustache deleted file mode 100644 index bdbdf6473fc..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostClient.mustache +++ /dev/null @@ -1,51 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{#returnType}} - {{#vendorExtensions.updateBody}} - {{#vendorExtensions.bodyIsSelf}} - {{returnType}} {{bodyParam.paramName}} = this; - {{/vendorExtensions.bodyIsSelf}} - {{/vendorExtensions.updateBody}} -{{/returnType}} - {{#returnType}}{{^vendorExtensions.updateBody}}return {{/vendorExtensions.updateBody}}{{/returnType}}getDataStore().create( - "{{{vendorExtensions.hrefFiltered}}}", -{{#vendorExtensions.bodyIsSelf}} - this, -{{/vendorExtensions.bodyIsSelf}} -{{^vendorExtensions.bodyIsSelf}} -{{#bodyParam}} - {{bodyParam.paramName}}, -{{/bodyParam}} -{{/vendorExtensions.bodyIsSelf}} -{{^bodyParam}} - new DefaultVoidResource(getDataStore()), -{{/bodyParam}} - null, -{{#returnType}} -{{#vendorExtensions.updateBody}} - {{bodyParam.dataType}}.class, -{{/vendorExtensions.updateBody}} -{{^vendorExtensions.updateBody}} - {{returnType}}.class, -{{/vendorExtensions.updateBody}} -{{/returnType}} - queryArgs, - headers); -{{#returnType}} - {{#vendorExtensions.updateBody}} - return {{bodyParam.paramName}}; - {{/vendorExtensions.updateBody}} -{{/returnType}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostFileResource.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostFileResource.mustache deleted file mode 100644 index c765f7a71f1..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostFileResource.mustache +++ /dev/null @@ -1,37 +0,0 @@ -{{! - Copyright 2021-Present Okta, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - {{#returnType}}{{^vendorExtensions.updateBody}}return {{/vendorExtensions.updateBody}}{{/returnType}}getDataStore().create( - "{{{vendorExtensions.hrefFiltered}}}", - new DefaultFileResource(getDataStore(), file.getAbsoluteFile().toPath(), "{{vendorExtensions.fileFormDataName}}"), - null, -{{^returnType}} - VoidResource.class, -{{/returnType}} -{{#returnType}} - {{#vendorExtensions.updateBody}} - {{bodyParam.dataType}}.class, - {{/vendorExtensions.updateBody}} - {{^vendorExtensions.updateBody}} - {{returnType}}.class, - {{/vendorExtensions.updateBody}} -{{/returnType}} - queryArgs, - headers); -{{#returnType}} - {{#vendorExtensions.updateBody}} - return {{bodyParam.paramName}}; - {{/vendorExtensions.updateBody}} -{{/returnType}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostNoBody.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostNoBody.mustache deleted file mode 100644 index 9ae72d57ff2..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostNoBody.mustache +++ /dev/null @@ -1,27 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - {{#returnType}}return {{/returnType}}getDataStore().create( - "{{{vendorExtensions.hrefFiltered}}}", -{{#vendorExtensions.bodyIsSelf}} - this, -{{/vendorExtensions.bodyIsSelf}} -{{^vendorExtensions.bodyIsSelf}} - {{#vendorExtensions.isUserFactor}}getVerify() != null ? getVerify() : {{/vendorExtensions.isUserFactor}}new DefaultVoidResource(getDataStore()), -{{/vendorExtensions.bodyIsSelf}} - null, - {{#returnType}}{{returnType}}.class,{{/returnType}} - queryArgs, - headers); \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostResource.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostResource.mustache deleted file mode 100644 index 5b4bf14abf6..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPostResource.mustache +++ /dev/null @@ -1,59 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{#returnType}} - {{#vendorExtensions.updateBody}} - {{#vendorExtensions.bodyIsSelf}} - {{returnType}} {{bodyParam.paramName}} = this; - {{/vendorExtensions.bodyIsSelf}} - {{/vendorExtensions.updateBody}} -{{/returnType}} - {{#returnType}}{{^vendorExtensions.updateBody}}return {{/vendorExtensions.updateBody}}{{/returnType}}getDataStore().create( - "{{{vendorExtensions.hrefFiltered}}}", -{{#vendorExtensions.bodyIsSelf}} - this, -{{/vendorExtensions.bodyIsSelf}} -{{^vendorExtensions.bodyIsSelf}} -{{#bodyParam}} -{{#bodyParam.required}} - {{bodyParam.paramName}}, -{{/bodyParam.required}} -{{^bodyParam.required}} - ({{bodyParam.paramName}} != null) ? {{bodyParam.paramName}} : getDataStore().instantiate(VoidResource.class), -{{/bodyParam.required}} -{{/bodyParam}} -{{/vendorExtensions.bodyIsSelf}} -{{^bodyParam}} - new DefaultVoidResource(getDataStore()), -{{/bodyParam}} - this, -{{^returnType}} - VoidResource.class, -{{/returnType}} -{{#returnType}} -{{#vendorExtensions.updateBody}} - {{bodyParam.dataType}}.class, -{{/vendorExtensions.updateBody}} -{{^vendorExtensions.updateBody}} - {{returnType}}.class, -{{/vendorExtensions.updateBody}} -{{/returnType}} - queryArgs, - headers); -{{#returnType}} - {{#vendorExtensions.updateBody}} - return {{bodyParam.paramName}}; - {{/vendorExtensions.updateBody}} -{{/returnType}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPut.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPut.mustache deleted file mode 100644 index 62232d865ce..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPut.mustache +++ /dev/null @@ -1,40 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - - String href = "{{{vendorExtensions.hrefFiltered}}}"; -{{#vendorExtensions.bodyIsSelf}} - getDataStore().save(href, this, null, queryArgs, headers); - {{#returnType}} - return this; - {{/returnType}} -{{/vendorExtensions.bodyIsSelf}} -{{^vendorExtensions.bodyIsSelf}} - {{#vendorExtensions.forceToCreateObject}} - return getDataStore().save(href, {{bodyParam.paramName}}, {{{vendorExtensions.resourceReturnType}}}.class, false); - {{/vendorExtensions.forceToCreateObject}} - {{^vendorExtensions.forceToCreateObject}} - {{#bodyParam}} - getDataStore().save(href, {{bodyParam.paramName}}, this, queryArgs, headers); - {{#returnType}}return {{/returnType}} {{bodyParam.paramName}}; - {{/bodyParam}} - {{^bodyParam}} - getDataStore().save(href, new DefaultVoidResource(getDataStore()), this, queryArgs, headers); - {{#returnType}} - return this; - {{/returnType}} - {{/bodyParam}} - {{/vendorExtensions.forceToCreateObject}} -{{/vendorExtensions.bodyIsSelf}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPutNoBody.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPutNoBody.mustache deleted file mode 100644 index b87373917f4..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/apiMethodPutNoBody.mustache +++ /dev/null @@ -1,38 +0,0 @@ -{{! - Copyright 2020-Present Okta, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - - String href = "{{{vendorExtensions.hrefFiltered}}}"; -{{#vendorExtensions.bodyIsSelf}} - getDataStore().save(href, this, null, queryArgs, headers); - {{#returnType}} - return this; - {{/returnType}} -{{/vendorExtensions.bodyIsSelf}} -{{^vendorExtensions.bodyIsSelf}} - {{#bodyParam}} - {{^bodyParam.required}} - ApplicationGroupAssignment applicationGroupAssignment = new DefaultApplicationGroupAssignment(getDataStore()); - {{/bodyParam.required}} - getDataStore().save(href, {{bodyParam.paramName}}, this, queryArgs, headers); - {{#returnType}}return {{/returnType}} {{bodyParam.paramName}}; - {{/bodyParam}} - {{^bodyParam}} - getDataStore().save(href, new DefaultVoidResource(getDataStore()), this, queryArgs, headers); - {{#returnType}} - return this; - {{/returnType}} - {{/bodyParam}} -{{/vendorExtensions.bodyIsSelf}} diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/generatedAnnotation.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/generatedAnnotation.mustache deleted file mode 100644 index 04d0c0e0c4e..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/generatedAnnotation.mustache +++ /dev/null @@ -1,16 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{^hideGenerationTimestamp}}@javax.annotation.Generated(value = "{{generatorClass}}", date = "{{generatedDate}}"){{/hideGenerationTimestamp}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/licenseInfo.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/licenseInfo.mustache deleted file mode 100644 index ff43812357d..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/licenseInfo.mustache +++ /dev/null @@ -1,26 +0,0 @@ -{{! - Copyright 2017-Present Okta, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -/* - * {{{appName}}} - * {{{appDescription}}} - * - * {{#version}}OpenAPI spec version: {{{version}}}{{/version}} - * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} - * - * NOTE: This class is auto generated by the swagger code generator program. - * https://github.com/swagger-api/swagger-codegen.git - * Do not edit the class manually. - */ diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/manifest.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/manifest.mustache deleted file mode 100644 index abbe36ce05f..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/manifest.mustache +++ /dev/null @@ -1,18 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - - - diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/model.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/model.mustache deleted file mode 100644 index 6d87126946f..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/model.mustache +++ /dev/null @@ -1,38 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{>licenseInfo}} - -{{! this is a hack to get sub package name generations working with swagger }} -package {{package}}{{#models}}{{#model}}{{#vendorExtensions.x-okta-package}}.{{vendorExtensions.x-okta-package}}{{/vendorExtensions.x-okta-package}}{{/model}}{{/models}}; - -{{#imports}} -import {{import}}; -{{/imports}} - -{{#serializableModel}} -import java.io.Serializable; -{{/serializableModel}} - -{{#models}} - {{#model}} - {{#vendorExtensions.x-isResourceList}} -{{>modelListResourceImpl}} - {{/vendorExtensions.x-isResourceList}} - {{^vendorExtensions.x-isResourceList}} -{{>modelImpl}} - {{/vendorExtensions.x-isResourceList}} - {{/model}} -{{/models}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/modelEnum.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/modelEnum.mustache deleted file mode 100644 index 0fdc848c205..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/modelEnum.mustache +++ /dev/null @@ -1,58 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{#jackson}} -import com.fasterxml.jackson.annotation.JsonCreator; -{{/jackson}} - -/** - * {{^description}}Enum {{{name}}}{{/description}}{{#description}}{{{description}}}{{/description}} - */ -public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} { - {{#gson}} - {{#allowableValues}}{{#enumVars}} - @SerializedName({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) - {{{name}}}({{{value}}}){{^-last}}, - {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} - {{/gson}} - {{^gson}} - {{#allowableValues}}{{#enumVars}} - {{{name}}}({{{value}}}){{^-last}}, - {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} - {{/gson}} - - private {{{dataType}}} value; - - {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}({{{dataType}}} value) { - this.value = value; - } - - @Override - public String toString() { - return String.valueOf(value); - } -{{#jackson}} - - @JsonCreator - public static {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} fromValue(String text) { - for ({{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} b : {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.values()) { - if (String.valueOf(b.value).equals(text)) { - return b; - } - } - return null; - } -{{/jackson}} -} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/modelImpl.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/modelImpl.mustache deleted file mode 100644 index a6458d09a2d..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/modelImpl.mustache +++ /dev/null @@ -1,241 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -import com.okta.sdk.impl.resource.AbstractInstanceResource; -import com.okta.sdk.impl.resource.AbstractResource; -import com.okta.sdk.impl.resource.Property; -import com.okta.sdk.impl.resource.ResourceReference; -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.commons.http.QueryString; -import com.okta.commons.http.HttpHeaders; - -{{! TODO: add these programatically when needed }} -import com.okta.sdk.impl.resource.BooleanProperty; -import com.okta.sdk.impl.resource.IntegerProperty; -import com.okta.sdk.impl.resource.DoubleProperty; -import com.okta.sdk.impl.resource.StringProperty; -import com.okta.sdk.impl.resource.CharacterArrayProperty; -import com.okta.sdk.impl.resource.ListProperty; -import com.okta.sdk.impl.resource.EnumListProperty; -import com.okta.sdk.impl.resource.ResourceListProperty; -import com.okta.sdk.impl.resource.DateProperty; -import com.okta.sdk.impl.resource.EnumProperty; -import com.okta.sdk.impl.resource.MapProperty; -import com.okta.sdk.impl.resource.DefaultVoidResource; -import com.okta.sdk.impl.resource.DefaultFileResource; -import com.okta.sdk.resource.VoidResource; -{{#vendorExtensions.top-level}} -import com.okta.sdk.resource.Resource; -{{/vendorExtensions.top-level}} -import java.util.Map; -import java.util.HashMap; - -import static com.okta.commons.lang.Assert.notNull; -import static com.okta.commons.lang.Assert.hasText; - -{{#models}}{{#model}} -/** - * {{#description}}{{.}}{{/description}}{{^description}}{{classname}}{{/description}} - */ -@javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}") -public class Default{{classname}} extends {{#parent}}{{.}}{{/parent}}{{^parent}}{{#vendorExtensions.top-level}}AbstractInstanceResource<{{classname}}>{{/vendorExtensions.top-level}}{{^vendorExtensions.top-level}}AbstractResource{{/vendorExtensions.top-level}}{{/parent}} implements {{classname}} { - -{{#vars}} - private final static {{vendorExtensions.propertyType}}{{#vendorExtensions.itemType}}<{{{vendorExtensions.itemType}}}>{{/vendorExtensions.itemType}} {{name}}Property = new {{vendorExtensions.propertyType}}("{{baseName}}"{{{vendorExtensions.constructorTypeExtra}}}); -{{/vars}} - - private final static Map PROPERTY_DESCRIPTORS = createPropertyDescriptorMap({{#vars}}{{name}}Property{{^-last}}, {{/-last}}{{/vars}}); - - public Default{{classname}}(InternalDataStore dataStore) { - super(dataStore);{{#vendorExtensions.defaultSetter}} - setProperty("{{key}}", "{{value}}");{{/vendorExtensions.defaultSetter}} - } - - public Default{{classname}}(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - @Override - public Map getPropertyDescriptors() { - return PROPERTY_DESCRIPTORS; - } - -{{#vendorExtensions.top-level}} - @Override - public Class getResourceClass() { - return {{#vendorExtensions.discriminatorRoot}}{{.}}{{/vendorExtensions.discriminatorRoot}}{{^vendorExtensions.discriminatorRoot}}{{classname}}{{/vendorExtensions.discriminatorRoot}}.class; - } -{{/vendorExtensions.top-level}} -{{#vars}} - - public {{{datatypeWithEnum}}} {{getter}}() { - return {{#vendorExtensions.forceCast}}({{{datatypeWithEnum}}}){{/vendorExtensions.forceCast}} {{vendorExtensions.propertyTypeMethod}}({{name}}Property); - } - {{^isReadOnly}} - - public {{classname}} {{setter}}({{{datatypeWithEnum}}} {{name}}) { - setProperty({{name}}Property, {{name}}); - return this; - } - {{/isReadOnly}} -{{/vars}} -{{#vendorExtensions.operations}}{{#.}} - - /** - * {{summary}} - * {{notes}} - {{#vendorExtensions.allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}} - {{/vendorExtensions.allParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @Override - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{#vendorExtensions.alias}}{{vendorExtensions.alias}}{{/vendorExtensions.alias}}{{^vendorExtensions.alias}}{{operationId}}{{/vendorExtensions.alias}}({{#vendorExtensions.allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/vendorExtensions.allParams}}) { - -{{#vendorExtensions.fromModelPathParams}}{{#.}} {{{dataType}}} {{paramName}} = {{vendorExtensions.fromModel.getter}}();{{/.}}{{/vendorExtensions.fromModelPathParams}} -{{#vendorExtensions.hasPathParents}} - Map pathArgs = getParamsFromHref("{{path}}"); -{{#vendorExtensions.pathParents}} - String {{.}} = pathArgs.get("{{.}}"); -{{/vendorExtensions.pathParents}} -{{/vendorExtensions.hasPathParents}} -{{>paramPartial}} -{{#vendorExtensions.isGet}} -{{>apiMethodGet}} -{{/vendorExtensions.isGet}} -{{#vendorExtensions.isPut}} -{{>apiMethodPut}} -{{/vendorExtensions.isPut}} -{{#vendorExtensions.isPost}} -{{#vendorExtensions.fileUpload}} -{{>apiMethodPostFileResource}} -{{/vendorExtensions.fileUpload}} -{{^vendorExtensions.fileUpload}} -{{>apiMethodPostResource}} -{{/vendorExtensions.fileUpload}} -{{/vendorExtensions.isPost}} -{{#vendorExtensions.isDelete}} -{{>apiMethodDelete}} -{{/vendorExtensions.isDelete}} - } -{{#vendorExtensions.hasOptional}} - - /** - * {{summary}} - * {{notes}} - {{#vendorExtensions.nonOptionalParams}} - * @param {{paramName}} {{description}} (required) - {{/vendorExtensions.nonOptionalParams}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @Override - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{#vendorExtensions.alias}}{{vendorExtensions.alias}}{{/vendorExtensions.alias}}{{^vendorExtensions.alias}}{{operationId}}{{/vendorExtensions.alias}}({{#vendorExtensions.nonOptionalParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/vendorExtensions.nonOptionalParams}}) { - -{{#vendorExtensions.fromModelPathParams}}{{#.}} {{{dataType}}} {{paramName}} = {{vendorExtensions.fromModel.getter}}();{{/.}}{{/vendorExtensions.fromModelPathParams}} -{{#vendorExtensions.hasPathParents}} - Map pathArgs = getParamsFromHref("{{path}}"); -{{#vendorExtensions.pathParents}} - String {{.}} = pathArgs.get("{{.}}"); -{{/vendorExtensions.pathParents}} -{{/vendorExtensions.hasPathParents}} -{{>paramPartialOnlyRequired}} -{{#vendorExtensions.isGet}} -{{>apiMethodGet}} -{{/vendorExtensions.isGet}} -{{#vendorExtensions.isPut}} - {{#vendorExtensions.optionalBody}} - {{>apiMethodPutNoBody}} - {{/vendorExtensions.optionalBody}} - {{^vendorExtensions.optionalBody}} - {{>apiMethodPut}} - {{/vendorExtensions.optionalBody}} -{{/vendorExtensions.isPut}} -{{#vendorExtensions.isPost}} - {{#vendorExtensions.optionalBody}} -{{>apiMethodPostNoBody}} - {{/vendorExtensions.optionalBody}} - {{^vendorExtensions.optionalBody}} -{{>apiMethodPostResource}} - {{/vendorExtensions.optionalBody}} -{{/vendorExtensions.isPost}} -{{#vendorExtensions.isDelete}} -{{>apiMethodDelete}} -{{/vendorExtensions.isDelete}} - } -{{/vendorExtensions.hasOptional}} - -{{#vendorExtensions.hasBackwardsCompatibleParams}} -{{#vendorExtensions.backwardsCompatibleParamsEntrySet}} - /** - * {{summary}} - * {{notes}} - {{#value}} - * @param {{paramName}} {{description}} (required) - {{/value}} - {{#returnType}} - * @return {{returnType}} - {{/returnType}} - */ - @Override - @javax.annotation.Generated( - value = "{{generatorClass}}", - date = "{{generatedDate}}", - comments = "{{httpMethod}} - {{path}}") - public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{#vendorExtensions.alias}}{{vendorExtensions.alias}}{{/vendorExtensions.alias}}{{^vendorExtensions.alias}}{{operationId}}{{/vendorExtensions.alias}}({{#value}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/value}}) { - -{{#vendorExtensions.fromModelPathParams}}{{#.}} {{{dataType}}} {{paramName}} = {{vendorExtensions.fromModel.getter}}();{{/.}}{{/vendorExtensions.fromModelPathParams}} -{{#vendorExtensions.hasPathParents}} - Map pathArgs = getParamsFromHref("{{path}}"); -{{#vendorExtensions.pathParents}} - String {{.}} = pathArgs.get("{{.}}"); -{{/vendorExtensions.pathParents}} -{{/vendorExtensions.hasPathParents}} -{{>paramPartialBackwardsCompat}} -{{#vendorExtensions.isGet}} -{{>apiMethodGet}} -{{/vendorExtensions.isGet}} -{{#vendorExtensions.isPut}} -{{>apiMethodPut}} -{{/vendorExtensions.isPut}} -{{#vendorExtensions.isPost}} -{{>apiMethodPostClient}} -{{/vendorExtensions.isPost}} -{{#vendorExtensions.isDelete}} -{{>apiMethodDelete}} -{{/vendorExtensions.isDelete}} - } -{{/vendorExtensions.backwardsCompatibleParamsEntrySet}} -{{/vendorExtensions.hasBackwardsCompatibleParams}} - -{{/.}} -{{/vendorExtensions.operations}} -{{#vendorExtensions.optionalClassnamePartial}}// optional class specific partial{{/vendorExtensions.optionalClassnamePartial}} -{{/model}} -{{/models}} -} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/modelListResourceImpl.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/modelListResourceImpl.mustache deleted file mode 100644 index eb9f44e2a9e..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/modelListResourceImpl.mustache +++ /dev/null @@ -1,51 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} - -import com.okta.sdk.impl.ds.InternalDataStore; -import com.okta.sdk.impl.resource.AbstractCollectionResource; -import com.okta.sdk.impl.resource.Property; -import com.okta.sdk.impl.resource.ArrayProperty; - -import java.util.Collections; -import java.util.Map; - -public class Default{{classname}} extends AbstractCollectionResource<{{vendorExtensions.baseType}}> implements {{classname}} { - - private static final ArrayProperty<{{vendorExtensions.baseType}}> ITEMS = new ArrayProperty<>("items", {{vendorExtensions.baseType}}.class); - private static final Map PROPERTY_DESCRIPTORS = createPropertyDescriptorMap(ITEMS); - - public Default{{classname}}(InternalDataStore dataStore) { - super(dataStore); - } - - public Default{{classname}}(InternalDataStore dataStore, Map properties) { - super(dataStore, properties); - } - - public Default{{classname}}(InternalDataStore dataStore, Map properties, Map queryParams) { - super(dataStore, properties, queryParams); - } - - @Override - public Map getPropertyDescriptors() { - return PROPERTY_DESCRIPTORS; - } - - @Override - protected Class<{{vendorExtensions.baseType}}> getItemType() { - return {{vendorExtensions.baseType}}.class; - } -} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/paramPartial.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/paramPartial.mustache deleted file mode 100644 index aa2370f3ae8..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/paramPartial.mustache +++ /dev/null @@ -1,25 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{>paramValidatePartial}} - - Map queryArgs = new HashMap<>();{{#queryParams}} - if ({{paramName}} != null) queryArgs.put("{{baseName}}", {{paramName}});{{/queryParams}} - - HttpHeaders headers = new HttpHeaders();{{#headerParams}} - if ({{paramName}} != null) headers.add("{{baseName}}", {{paramName}});{{/headerParams}} - {{#vendorExtensions.fileUpload}} - headers.add("x-contentType", "{{{vendorExtensions.x-contentType}}}"); - {{/vendorExtensions.fileUpload}} \ No newline at end of file diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/paramPartialBackwardsCompat.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/paramPartialBackwardsCompat.mustache deleted file mode 100644 index 86edd761cf7..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/paramPartialBackwardsCompat.mustache +++ /dev/null @@ -1,22 +0,0 @@ -{{! - Copyright 2017-Present Okta, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{>paramValidatePartial}} - - Map queryArgs = new HashMap<>(); - HttpHeaders headers = new HttpHeaders(); -{{#value}}{{#isQueryParam}} - if ({{paramName}} != null) queryArgs.put("{{baseName}}", {{paramName}});{{/isQueryParam}}{{#isHeaderParam}} - if ({{paramName}} != null) headers.add("{{baseName}}", {{paramName}});{{/isHeaderParam}}{{/value}} diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/paramPartialOnlyRequired.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/paramPartialOnlyRequired.mustache deleted file mode 100644 index e8018cc2cb1..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/paramPartialOnlyRequired.mustache +++ /dev/null @@ -1,22 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{>paramValidatePartial}} - - Map queryArgs = new HashMap<>();{{#queryParams}}{{#required}} - queryArgs.put("{{baseName}}", {{paramName}});{{/required}}{{/queryParams}} - - HttpHeaders headers = new HttpHeaders();{{#headerParams}}{{#required}} - headers.add("{{baseName}}", {{paramName}});{{/required}}{{/headerParams}} diff --git a/swagger-templates/src/main/resources/OktaJavaImpl/paramValidatePartial.mustache b/swagger-templates/src/main/resources/OktaJavaImpl/paramValidatePartial.mustache deleted file mode 100644 index b99a0c4e32e..00000000000 --- a/swagger-templates/src/main/resources/OktaJavaImpl/paramValidatePartial.mustache +++ /dev/null @@ -1,20 +0,0 @@ -{{! - Copyright 2017 Okta - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -}} -{{#queryParams}}{{#required}} - notNull({{paramName}}, "'{{paramName}}' is required and cannot be null.");{{/required}}{{/queryParams}}{{#headerParams}}{{#required}} - notNull({{paramName}}, "'{{paramName}}' is required and cannot be null.");{{/required}}{{/headerParams}}{{^vendorExtensions.bodyIsSelf}}{{#bodyParam}}{{! required body param }}{{#required}} - notNull({{bodyParam.paramName}}, "'{{paramName}}' is required and cannot be null.");{{/required}}{{/bodyParam}}{{/vendorExtensions.bodyIsSelf}}{{#pathParams}} - hasText({{paramName}}, "'{{paramName}}' is required and cannot be null or empty.");{{/pathParams}} \ No newline at end of file