-
Notifications
You must be signed in to change notification settings - Fork 53
fix!: rename portal to adminPortal
#1562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,33 @@ | ||||||||||||||||||||||||||
| // This file is auto-generated by oagen. Do not edit. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import type { WorkOS } from '../workos'; | ||||||||||||||||||||||||||
| import type { | ||||||||||||||||||||||||||
| PortalLinkResponse, | ||||||||||||||||||||||||||
| PortalLinkResponseWire, | ||||||||||||||||||||||||||
| } from './interfaces/portal-link-response.interface'; | ||||||||||||||||||||||||||
| import type { GenerateLink } from './interfaces/generate-link.interface'; | ||||||||||||||||||||||||||
| import { deserializePortalLinkResponse } from './serializers/portal-link-response.serializer'; | ||||||||||||||||||||||||||
| import { serializeGenerateLink } from './serializers/generate-link.serializer'; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| export class AdminPortal { | ||||||||||||||||||||||||||
| constructor(private readonly workos: WorkOS) {} | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||
| * Generate a Portal Link | ||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||
| * Generate a Portal Link scoped to an Organization. | ||||||||||||||||||||||||||
| * @param payload - Object containing organization. | ||||||||||||||||||||||||||
| * @returns {Promise<PortalLinkResponse>} | ||||||||||||||||||||||||||
| * @throws {BadRequestException} 400 | ||||||||||||||||||||||||||
| * @throws {AuthorizationException} 403 | ||||||||||||||||||||||||||
| * @throws {NotFoundException} 404 | ||||||||||||||||||||||||||
| * @throws {UnprocessableEntityException} 422 | ||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update JSDoc to match current payload and error behavior. Line 19 still says “Object containing organization,” but 📝 Suggested doc fix- * `@param` payload - Object containing organization.
+ * `@param` payload - Admin Portal link generation parameters.
...
- * `@throws` {AuthorizationException} 403
+ * `@throws` {OauthException | GenericServerException} 403📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||
| async generateLink(payload: GenerateLink): Promise<PortalLinkResponse> { | ||||||||||||||||||||||||||
| const { data } = await this.workos.post<PortalLinkResponseWire>( | ||||||||||||||||||||||||||
| '/portal/generate_link', | ||||||||||||||||||||||||||
| serializeGenerateLink(payload), | ||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| return deserializePortalLinkResponse(data); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "return_url": "https://example.com/admin-portal/return", | ||
| "success_url": "https://example.com/admin-portal/success", | ||
| "organization": "org_01EHZNVPK3SFK441A1RGBFSHRT", | ||
| "intent": "sso", | ||
| "intent_options": { | ||
| "sso": { | ||
| "bookmark_slug": "chatgpt", | ||
| "provider_type": "GoogleSAML" | ||
| } | ||
| }, | ||
| "admin_emails": ["admin@example.com"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "sso": { | ||
| "bookmark_slug": "chatgpt", | ||
| "provider_type": "GoogleSAML" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,3 @@ | ||||||
| { | ||||||
| "link": "https://setup.workos.com?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace secret-like token in fixture to avoid leak-scanner failures. Line 2 uses a JWT-looking token string. Even in test fixtures, this pattern can be treated as exposed credentials and fail security checks. Use an obviously fake token value instead. Suggested change- "link": "https://setup.workos.com?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
+ "link": "https://setup.workos.com?token=test_admin_portal_token"📝 Committable suggestion
Suggested change
🧰 Tools🪛 Betterleaks (1.1.2)[high] 2-2: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key) 🤖 Prompt for AI Agents |
||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "bookmark_slug": "chatgpt", | ||
| "provider_type": "GoogleSAML" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| import type { | ||
| IntentOptions, | ||
| IntentOptionsResponse, | ||
| } from './intent-options.interface'; | ||
| import type { GenerateLinkIntent } from '../../common/interfaces/generate-link-intent.interface'; | ||
|
|
||
| export interface GenerateLink { | ||
| /** The URL to go to when an admin clicks on your logo in the Admin Portal. If not specified, the return URL configured on the [Redirects](https://dashboard.workos.com/redirects) page will be used. */ | ||
| returnUrl?: string; | ||
| /** The URL to redirect the admin to when they finish setup. If not specified, the success URL configured on the [Redirects](https://dashboard.workos.com/redirects) page will be used. */ | ||
| successUrl?: string; | ||
| /** An [Organization](https://workos.com/docs/reference/organization) identifier. */ | ||
| organization: string; | ||
| /** | ||
| * | ||
| * The intent of the Admin Portal. | ||
| * - `sso` - Launch Admin Portal for creating SSO connections | ||
| * - `dsync` - Launch Admin Portal for creating Directory Sync connections | ||
| * - `audit_logs` - Launch Admin Portal for viewing Audit Logs | ||
| * - `log_streams` - Launch Admin Portal for creating Log Streams | ||
| * - `domain_verification` - Launch Admin Portal for Domain Verification | ||
| * - `certificate_renewal` - Launch Admin Portal for renewing SAML Certificates | ||
| * - `bring_your_own_key` - Launch Admin Portal for configuring Bring Your Own Key | ||
| */ | ||
| intent?: GenerateLinkIntent; | ||
| /** Options to configure the Admin Portal based on the intent. */ | ||
| intentOptions?: IntentOptions; | ||
| /** The email addresses of the IT admins to grant access to the Admin Portal for the given organization. Accepts up to 20 emails. */ | ||
| adminEmails?: string[]; | ||
| } | ||
|
|
||
| export interface GenerateLinkResponse { | ||
| return_url?: string; | ||
| success_url?: string; | ||
| organization: string; | ||
| intent?: GenerateLinkIntent; | ||
| intent_options?: IntentOptionsResponse; | ||
| admin_emails?: string[]; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| export * from './generate-link.interface'; | ||
| export * from './intent-options.interface'; | ||
| export * from './portal-link-response.interface'; | ||
| export * from './sso-intent-options.interface'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| import type { | ||
| SSOIntentOptions, | ||
| SSOIntentOptionsResponse, | ||
| } from './sso-intent-options.interface'; | ||
|
|
||
| export interface IntentOptions { | ||
| /** SSO-specific options for the Admin Portal. */ | ||
| sso: SSOIntentOptions; | ||
| } | ||
|
|
||
| export interface IntentOptionsResponse { | ||
| sso: SSOIntentOptionsResponse; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| export interface PortalLinkResponse { | ||
| /** An ephemeral link to initiate the Admin Portal. */ | ||
| link: string; | ||
| } | ||
|
|
||
| export interface PortalLinkResponseWire { | ||
| link: string; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| export interface SSOIntentOptions { | ||
| /** The bookmark slug to use for SSO. */ | ||
| bookmarkSlug?: string; | ||
| /** The SSO provider type to configure. */ | ||
| providerType?: 'GoogleSAML'; | ||
| } | ||
|
|
||
| export interface SSOIntentOptionsResponse { | ||
| bookmark_slug?: string; | ||
| provider_type?: 'GoogleSAML'; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| import { | ||
| deserializeSSOIntentOptions, | ||
| serializeSSOIntentOptions, | ||
| } from './serializers/sso-intent-options.serializer'; | ||
| import { | ||
| deserializeIntentOptions, | ||
| serializeIntentOptions, | ||
| } from './serializers/intent-options.serializer'; | ||
| import { | ||
| deserializeGenerateLink, | ||
| serializeGenerateLink, | ||
| } from './serializers/generate-link.serializer'; | ||
| import { | ||
| deserializePortalLinkResponse, | ||
| serializePortalLinkResponse, | ||
| } from './serializers/portal-link-response.serializer'; | ||
| import type { SSOIntentOptionsResponse } from './interfaces/sso-intent-options.interface'; | ||
| import type { IntentOptionsResponse } from './interfaces/intent-options.interface'; | ||
| import type { GenerateLinkResponse } from './interfaces/generate-link.interface'; | ||
| import type { PortalLinkResponseWire } from './interfaces/portal-link-response.interface'; | ||
| import sSOIntentOptionsFixture from './fixtures/sso-intent-options.fixture.json'; | ||
| import intentOptionsFixture from './fixtures/intent-options.fixture.json'; | ||
| import generateLinkFixture from './fixtures/generate-link.fixture.json'; | ||
| import portalLinkResponseFixture from './fixtures/portal-link-response.fixture.json'; | ||
|
|
||
| describe('SSOIntentOptionsSerializer', () => { | ||
| it('round-trips through serialize/deserialize', () => { | ||
| const fixture = sSOIntentOptionsFixture as SSOIntentOptionsResponse; | ||
| const deserialized = deserializeSSOIntentOptions(fixture); | ||
| const reserialized = serializeSSOIntentOptions(deserialized); | ||
| expect(reserialized).toEqual(expect.objectContaining(fixture)); | ||
| }); | ||
| }); | ||
|
|
||
| describe('IntentOptionsSerializer', () => { | ||
| it('round-trips through serialize/deserialize', () => { | ||
| const fixture = intentOptionsFixture as IntentOptionsResponse; | ||
| const deserialized = deserializeIntentOptions(fixture); | ||
| const reserialized = serializeIntentOptions(deserialized); | ||
| expect(reserialized).toEqual(expect.objectContaining(fixture)); | ||
| }); | ||
| }); | ||
|
|
||
| describe('GenerateLinkSerializer', () => { | ||
| it('round-trips through serialize/deserialize', () => { | ||
| const fixture = generateLinkFixture as GenerateLinkResponse; | ||
| const deserialized = deserializeGenerateLink(fixture); | ||
| const reserialized = serializeGenerateLink(deserialized); | ||
| expect(reserialized).toEqual(expect.objectContaining(fixture)); | ||
| }); | ||
| }); | ||
|
|
||
| describe('PortalLinkResponseSerializer', () => { | ||
| it('round-trips through serialize/deserialize', () => { | ||
| const fixture = portalLinkResponseFixture as PortalLinkResponseWire; | ||
| const deserialized = deserializePortalLinkResponse(fixture); | ||
| const reserialized = serializePortalLinkResponse(deserialized); | ||
| expect(reserialized).toEqual(expect.objectContaining(fixture)); | ||
| }); | ||
| }); | ||
|
Comment on lines
+1
to
+62
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The deleted
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 24b982b — added
Comment on lines
+28
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Consider table-driven tests to reduce duplication. Current coverage is good; a parameterized pattern would make adding serializer cases simpler and keep this file smaller. ♻️ Optional refactor+type RoundTripCase<T> = {
+ name: string;
+ fixture: T;
+ deserialize: (input: T) => any;
+ serialize: (input: any) => T;
+};
+
+const cases: RoundTripCase<any>[] = [
+ {
+ name: 'SSOIntentOptionsSerializer',
+ fixture: sSOIntentOptionsFixture as SSOIntentOptionsResponse,
+ deserialize: deserializeSSOIntentOptions,
+ serialize: serializeSSOIntentOptions,
+ },
+ {
+ name: 'IntentOptionsSerializer',
+ fixture: intentOptionsFixture as IntentOptionsResponse,
+ deserialize: deserializeIntentOptions,
+ serialize: serializeIntentOptions,
+ },
+ {
+ name: 'GenerateLinkSerializer',
+ fixture: generateLinkFixture as GenerateLinkResponse,
+ deserialize: deserializeGenerateLink,
+ serialize: serializeGenerateLink,
+ },
+ {
+ name: 'PortalLinkResponseSerializer',
+ fixture: portalLinkResponseFixture as PortalLinkResponseWire,
+ deserialize: deserializePortalLinkResponse,
+ serialize: serializePortalLinkResponse,
+ },
+];
+
+describe.each(cases)('$name', ({ fixture, deserialize, serialize }) => {
+ it('round-trips through serialize/deserialize', () => {
+ const deserialized = deserialize(fixture);
+ const reserialized = serialize(deserialized);
+ expect(reserialized).toEqual(expect.objectContaining(fixture));
+ });
+});
-
-describe('SSOIntentOptionsSerializer', () => {
- it('round-trips through serialize/deserialize', () => {
- const fixture = sSOIntentOptionsFixture as SSOIntentOptionsResponse;
- const deserialized = deserializeSSOIntentOptions(fixture);
- const reserialized = serializeSSOIntentOptions(deserialized);
- expect(reserialized).toEqual(expect.objectContaining(fixture));
- });
-});
-
-... repeated blocks ...🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| import type { | ||
| GenerateLink, | ||
| GenerateLinkResponse, | ||
| } from '../interfaces/generate-link.interface'; | ||
| import { | ||
| deserializeIntentOptions, | ||
| serializeIntentOptions, | ||
| } from './intent-options.serializer'; | ||
|
|
||
| export const deserializeGenerateLink = ( | ||
| response: GenerateLinkResponse, | ||
| ): GenerateLink => ({ | ||
| returnUrl: response.return_url, | ||
| successUrl: response.success_url, | ||
| organization: response.organization, | ||
| intent: response.intent, | ||
| intentOptions: | ||
| response.intent_options != null | ||
| ? deserializeIntentOptions(response.intent_options) | ||
| : undefined, | ||
| adminEmails: response.admin_emails, | ||
| }); | ||
|
|
||
| export const serializeGenerateLink = ( | ||
| model: GenerateLink, | ||
| ): GenerateLinkResponse => ({ | ||
| return_url: model.returnUrl, | ||
| success_url: model.successUrl, | ||
| organization: model.organization, | ||
| intent: model.intent, | ||
| intent_options: | ||
| model.intentOptions != null | ||
| ? serializeIntentOptions(model.intentOptions) | ||
| : undefined, | ||
| admin_emails: model.adminEmails, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| import type { | ||
| IntentOptions, | ||
| IntentOptionsResponse, | ||
| } from '../interfaces/intent-options.interface'; | ||
| import { | ||
| deserializeSSOIntentOptions, | ||
| serializeSSOIntentOptions, | ||
| } from './sso-intent-options.serializer'; | ||
|
|
||
| export const deserializeIntentOptions = ( | ||
| response: IntentOptionsResponse, | ||
| ): IntentOptions => ({ | ||
| sso: deserializeSSOIntentOptions(response.sso), | ||
| }); | ||
|
|
||
| export const serializeIntentOptions = ( | ||
| model: IntentOptions, | ||
| ): IntentOptionsResponse => ({ | ||
| sso: serializeSSOIntentOptions(model.sso), | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| import type { | ||
| PortalLinkResponse, | ||
| PortalLinkResponseWire, | ||
| } from '../interfaces/portal-link-response.interface'; | ||
|
|
||
| export const deserializePortalLinkResponse = ( | ||
| response: PortalLinkResponseWire, | ||
| ): PortalLinkResponse => ({ | ||
| link: response.link, | ||
| }); | ||
|
|
||
| export const serializePortalLinkResponse = ( | ||
| model: PortalLinkResponse, | ||
| ): PortalLinkResponseWire => ({ | ||
| link: model.link, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| import type { | ||
| SSOIntentOptions, | ||
| SSOIntentOptionsResponse, | ||
| } from '../interfaces/sso-intent-options.interface'; | ||
|
|
||
| export const deserializeSSOIntentOptions = ( | ||
| response: SSOIntentOptionsResponse, | ||
| ): SSOIntentOptions => ({ | ||
| bookmarkSlug: response.bookmark_slug, | ||
| providerType: response.provider_type, | ||
| }); | ||
|
|
||
| export const serializeSSOIntentOptions = ( | ||
| model: SSOIntentOptions, | ||
| ): SSOIntentOptionsResponse => ({ | ||
| bookmark_slug: model.bookmarkSlug, | ||
| provider_type: model.providerType, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // This file is auto-generated by oagen. Do not edit. | ||
|
|
||
| export type GenerateLinkIntent = | ||
| | 'sso' | ||
| | 'dsync' | ||
| | 'audit_logs' | ||
| | 'log_streams' | ||
| | 'domain_verification' | ||
| | 'certificate_renewal' | ||
| | 'bring_your_own_key'; | ||
|
devin-ai-integration[bot] marked this conversation as resolved.
|
||
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.