Skip to content

Commit

Permalink
feat: add option to update the mappers of an IDP (#1222)
Browse files Browse the repository at this point in the history
  • Loading branch information
JivusAyrus authored Sep 27, 2024
1 parent 7c3781f commit 00c7b2e
Show file tree
Hide file tree
Showing 14 changed files with 4,401 additions and 3,533 deletions.
7,041 changes: 3,598 additions & 3,443 deletions connect-go/gen/proto/wg/cosmo/platform/v1/platform.pb.go

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion connect/src/wg/cosmo/platform/v1/platform_connect.ts

Large diffs are not rendered by default.

80 changes: 80 additions & 0 deletions connect/src/wg/cosmo/platform/v1/platform_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11680,6 +11680,11 @@ export class GetOIDCProviderResponse extends Message<GetOIDCProviderResponse> {
*/
signOutRedirectURL = "";

/**
* @generated from field: repeated wg.cosmo.platform.v1.GroupMapper mappers = 7;
*/
mappers: GroupMapper[] = [];

constructor(data?: PartialMessage<GetOIDCProviderResponse>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -11694,6 +11699,7 @@ export class GetOIDCProviderResponse extends Message<GetOIDCProviderResponse> {
{ no: 4, name: "loginURL", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 5, name: "signInRedirectURL", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 6, name: "signOutRedirectURL", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 7, name: "mappers", kind: "message", T: GroupMapper, repeated: true },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetOIDCProviderResponse {
Expand Down Expand Up @@ -11781,6 +11787,80 @@ export class DeleteOIDCProviderResponse extends Message<DeleteOIDCProviderRespon
}
}

/**
* @generated from message wg.cosmo.platform.v1.UpdateIDPMappersRequest
*/
export class UpdateIDPMappersRequest extends Message<UpdateIDPMappersRequest> {
/**
* @generated from field: repeated wg.cosmo.platform.v1.GroupMapper mappers = 1;
*/
mappers: GroupMapper[] = [];

constructor(data?: PartialMessage<UpdateIDPMappersRequest>) {
super();
proto3.util.initPartial(data, this);
}

static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "wg.cosmo.platform.v1.UpdateIDPMappersRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "mappers", kind: "message", T: GroupMapper, repeated: true },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): UpdateIDPMappersRequest {
return new UpdateIDPMappersRequest().fromBinary(bytes, options);
}

static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): UpdateIDPMappersRequest {
return new UpdateIDPMappersRequest().fromJson(jsonValue, options);
}

static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): UpdateIDPMappersRequest {
return new UpdateIDPMappersRequest().fromJsonString(jsonString, options);
}

static equals(a: UpdateIDPMappersRequest | PlainMessage<UpdateIDPMappersRequest> | undefined, b: UpdateIDPMappersRequest | PlainMessage<UpdateIDPMappersRequest> | undefined): boolean {
return proto3.util.equals(UpdateIDPMappersRequest, a, b);
}
}

/**
* @generated from message wg.cosmo.platform.v1.UpdateIDPMappersResponse
*/
export class UpdateIDPMappersResponse extends Message<UpdateIDPMappersResponse> {
/**
* @generated from field: wg.cosmo.platform.v1.Response response = 1;
*/
response?: Response;

constructor(data?: PartialMessage<UpdateIDPMappersResponse>) {
super();
proto3.util.initPartial(data, this);
}

static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "wg.cosmo.platform.v1.UpdateIDPMappersResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "response", kind: "message", T: Response },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): UpdateIDPMappersResponse {
return new UpdateIDPMappersResponse().fromBinary(bytes, options);
}

static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): UpdateIDPMappersResponse {
return new UpdateIDPMappersResponse().fromJson(jsonValue, options);
}

static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): UpdateIDPMappersResponse {
return new UpdateIDPMappersResponse().fromJsonString(jsonString, options);
}

static equals(a: UpdateIDPMappersResponse | PlainMessage<UpdateIDPMappersResponse> | undefined, b: UpdateIDPMappersResponse | PlainMessage<UpdateIDPMappersResponse> | undefined): boolean {
return proto3.util.equals(UpdateIDPMappersResponse, a, b);
}
}

/**
* @generated from message wg.cosmo.platform.v1.GetOrganizationRequestsCountRequest
*/
Expand Down
5 changes: 5 additions & 0 deletions controlplane/src/core/bufservices/PlatformService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ import { inviteUser } from './user/inviteUser.js';
import { removeInvitation } from './user/removeInvitation.js';
import { removeOrganizationMember } from './user/removeOrganizationMember.js';
import { updateOrgMemberRole } from './user/updateOrgMemberRole.js';
import { updateIDPMappers } from './sso/updateIDPMappers.js';

export default function (opts: RouterOptions): Partial<ServiceImpl<typeof PlatformService>> {
return {
Expand Down Expand Up @@ -697,5 +698,9 @@ export default function (opts: RouterOptions): Partial<ServiceImpl<typeof Platfo
redeliverWebhook: (req, ctx) => {
return redeliverWebhook(opts, req, ctx);
},

updateIDPMappers: (req, ctx) => {
return updateIDPMappers(opts, req, ctx);
},
};
}
9 changes: 9 additions & 0 deletions controlplane/src/core/bufservices/sso/getOIDCProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { OidcRepository } from '../../repositories/OidcRepository.js';
import type { RouterOptions } from '../../routes.js';
import { enrichLogger, getLogger, handleError } from '../../util.js';
import OidcProvider from '../../services/OidcProvider.js';

export function getOIDCProvider(
opts: RouterOptions,
Expand All @@ -21,6 +22,7 @@ export function getOIDCProvider(
logger = enrichLogger(ctx, logger, authContext);

const oidcRepo = new OidcRepository(opts.db);
const oidcProvider = new OidcProvider();

await opts.keycloakClient.authenticateClient();

Expand All @@ -35,8 +37,14 @@ export function getOIDCProvider(
loginURL: '',
signInRedirectURL: '',
signOutRedirectURL: '',
mappers: [],
};
}
const mappers = await oidcProvider.fetchIDPMappers({
alias: provider.alias,
kcRealm: opts.keycloakRealm,
kcClient: opts.keycloakClient,
});

return {
response: {
Expand All @@ -53,6 +61,7 @@ export function getOIDCProvider(
`/realms/${opts.keycloakRealm}/broker/${provider.alias}/endpoint/logout_response`,
opts.keycloakApiUrl,
).toString(),
mappers,
};
});
}
71 changes: 71 additions & 0 deletions controlplane/src/core/bufservices/sso/updateIDPMappers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { PlainMessage } from '@bufbuild/protobuf';
import { HandlerContext } from '@connectrpc/connect';
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
import {
GetOIDCProviderRequest,
GetOIDCProviderResponse,
UpdateIDPMappersRequest,
UpdateIDPMappersResponse,
} from '@wundergraph/cosmo-connect/dist/platform/v1/platform_pb';
import { OidcRepository } from '../../repositories/OidcRepository.js';
import type { RouterOptions } from '../../routes.js';
import { enrichLogger, getLogger, handleError } from '../../util.js';
import OidcProvider from '../../services/OidcProvider.js';

export function updateIDPMappers(
opts: RouterOptions,
req: UpdateIDPMappersRequest,
ctx: HandlerContext,
): Promise<PlainMessage<UpdateIDPMappersResponse>> {
let logger = getLogger(ctx, opts.logger);

return handleError<PlainMessage<UpdateIDPMappersResponse>>(ctx, logger, async () => {
const authContext = await opts.authenticator.authenticate(ctx.requestHeader);
logger = enrichLogger(ctx, logger, authContext);

if (!authContext.isAdmin) {
return {
response: {
code: EnumStatusCode.ERR,
details: `The user doesnt have the permissions to perform this operation`,
},
};
}

const oidcProvider = new OidcProvider();
const oidcRepo = new OidcRepository(opts.db);

await opts.keycloakClient.authenticateClient();

const provider = await oidcRepo.getOidcProvider({ organizationId: authContext.organizationId });
if (!provider) {
return {
response: {
code: EnumStatusCode.ERR_NOT_FOUND,
details: `OIDC Provider not found`,
},
};
}

await oidcProvider.deleteIDPMappers({
alias: provider.alias,
kcClient: opts.keycloakClient,
kcRealm: opts.keycloakRealm,
});

await oidcProvider.addIDPMappers({
kcClient: opts.keycloakClient,
kcRealm: opts.keycloakRealm,
mappers: req.mappers,
organizationSlug: authContext.organizationSlug,
endpoint: provider.endpoint,
alias: provider.alias,
});

return {
response: {
code: EnumStatusCode.OK,
},
};
});
}
1 change: 1 addition & 0 deletions controlplane/src/core/services/Keycloak.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import KeycloakAdminClient from '@keycloak/keycloak-admin-client';
import { RequiredActionAlias } from '@keycloak/keycloak-admin-client/lib/defs/requiredActionProviderRepresentation.js';
import { uid } from 'uid';
import { GroupMapper } from '@wundergraph/cosmo-connect/dist/platform/v1/platform_pb';
import { MemberRole } from '../../db/models.js';

export default class Keycloak {
Expand Down
Loading

0 comments on commit 00c7b2e

Please sign in to comment.