fix role mapping + create role if doesn't exit
This commit is contained in:
parent
c957b152b7
commit
4cc01ed771
7 changed files with 96 additions and 17 deletions
|
@ -18,6 +18,7 @@ import { EmptyRequestError } from "../errors/EmptyRequestError";
|
|||
import { EmptyResponseError } from "../errors/EmptyResponseError";
|
||||
import { JsonParseError } from "../errors/JsonParseError";
|
||||
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
||||
import { handleRcError } from "./common/endpoint";
|
||||
import { Context } from "./Context";
|
||||
|
||||
type ApiEndpointMethod = (
|
||||
|
@ -41,6 +42,7 @@ export abstract class ScimEndpoint extends ApiEndpoint {
|
|||
public post: ApiEndpointMethod | undefined;
|
||||
public put: ApiEndpointMethod | undefined;
|
||||
public delete: ApiEndpointMethod | undefined;
|
||||
protected handleError = handleRcError;
|
||||
|
||||
constructor(app: IApp) {
|
||||
super(app);
|
||||
|
@ -91,19 +93,6 @@ export abstract class ScimEndpoint extends ApiEndpoint {
|
|||
}
|
||||
}
|
||||
|
||||
protected handleError(o: any) {
|
||||
if (!o.success) {
|
||||
if (o.error?.includes("already in use")) {
|
||||
throw new ConflictError(
|
||||
o.error.includes("@") ? "email" : "username",
|
||||
);
|
||||
}
|
||||
if (o.error?.includes("not found")) {
|
||||
}
|
||||
throw new Error(o.error);
|
||||
}
|
||||
}
|
||||
|
||||
private wrapMethod(name: string): ApiEndpointMethod | undefined {
|
||||
const method = this[`_${name}`];
|
||||
if (method === undefined || typeof method !== "function") {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { HttpStatusCode } from "@rocket.chat/apps-engine/definition/accessors";
|
|||
import { IApiResponse } from "@rocket.chat/apps-engine/definition/api";
|
||||
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
||||
import { SCIMUser } from "../scim/User";
|
||||
import { findOrCreateRole } from "./common/user";
|
||||
import { Context } from "./Context";
|
||||
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
|
||||
|
||||
|
@ -27,6 +28,7 @@ export class UserEndpoint extends ScimEndpoint implements IScimEndpoint {
|
|||
u.roles.push({ value: "admin" });
|
||||
}
|
||||
}
|
||||
const roles = await findOrCreateRole(ctx, u);
|
||||
const o = await ctx.rc.user.update({
|
||||
userId: ctx.id(),
|
||||
data: {
|
||||
|
@ -35,7 +37,7 @@ export class UserEndpoint extends ScimEndpoint implements IScimEndpoint {
|
|||
username: u.userName,
|
||||
active: u.active,
|
||||
verified: true,
|
||||
roles: u.roles.map((x) => x.value),
|
||||
roles,
|
||||
customFields: {
|
||||
scimExternalId: u.externalId,
|
||||
},
|
||||
|
|
|
@ -3,6 +3,7 @@ import { IApiResponse } from "@rocket.chat/apps-engine/definition/api";
|
|||
import crypto = require("crypto");
|
||||
import { SCIMListResponse } from "../scim/ListResponse";
|
||||
import { SCIMUser } from "../scim/User";
|
||||
import { findOrCreateRole } from "./common/user";
|
||||
import { Context } from "./Context";
|
||||
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
|
||||
|
||||
|
@ -28,12 +29,13 @@ export class UsersEndpoint extends ScimEndpoint implements IScimEndpoint {
|
|||
|
||||
public async _post(ctx: Context): Promise<IApiResponse> {
|
||||
const u = SCIMUser.fromPlain(ctx.content());
|
||||
const roles = await findOrCreateRole(ctx, u);
|
||||
const o = await ctx.rc.user.create({
|
||||
email: u.getEmail(),
|
||||
name: u.displayName || u.userName,
|
||||
username: u.userName,
|
||||
password: crypto.randomBytes(64).toString("base64").slice(0, 64),
|
||||
roles: u.roles.map((x) => x.value),
|
||||
roles,
|
||||
verified: true,
|
||||
customFields: {
|
||||
scimExternalId: u.externalId,
|
||||
|
|
14
src/endpoints/common/endpoint.ts
Normal file
14
src/endpoints/common/endpoint.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { ConflictError } from "../../errors/ConflictError";
|
||||
|
||||
export function handleRcError(o: any) {
|
||||
if (!o.success) {
|
||||
if (o.error?.includes("already in use")) {
|
||||
throw new ConflictError(
|
||||
o.error.includes("@") ? "email" : "username",
|
||||
);
|
||||
}
|
||||
if (o.error?.includes("not found")) {
|
||||
}
|
||||
throw new Error(o.error);
|
||||
}
|
||||
}
|
25
src/endpoints/common/user.ts
Normal file
25
src/endpoints/common/user.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { SCIMUser } from "../../scim/User";
|
||||
import { Context } from "../Context";
|
||||
import { handleRcError } from "./endpoint";
|
||||
|
||||
export async function findOrCreateRole(
|
||||
ctx: Context,
|
||||
user: SCIMUser,
|
||||
): Promise<Array<string>> {
|
||||
const listResp = await ctx.rc.role.list();
|
||||
handleRcError(listResp);
|
||||
const rcRoles = listResp.roles;
|
||||
const roles = await Promise.all(
|
||||
user.roles.map(async ({ value }) => {
|
||||
let rcRole = rcRoles.find((x) => x.name === value);
|
||||
if (!rcRole) {
|
||||
const r = await ctx.rc.role.create({ name: value });
|
||||
handleRcError(r);
|
||||
rcRoles.push(r.role);
|
||||
rcRole = r.role;
|
||||
}
|
||||
return rcRole._id;
|
||||
}),
|
||||
);
|
||||
return roles;
|
||||
}
|
|
@ -7,6 +7,7 @@ import {
|
|||
} from "@rocket.chat/apps-engine/definition/accessors";
|
||||
import { EmptyResponseError } from "../errors/EmptyResponseError";
|
||||
import { JsonParseError } from "../errors/JsonParseError";
|
||||
import { RcSdkRole } from "./RcSdkRole";
|
||||
import { RcSdkTeam } from "./RcSdkTeam";
|
||||
import { RcSdkUser } from "./RcSdkUser";
|
||||
|
||||
|
@ -18,6 +19,7 @@ type RequestCallback = (
|
|||
export class RcSdk {
|
||||
public user: RcSdkUser;
|
||||
public team: RcSdkTeam;
|
||||
public role: RcSdkRole;
|
||||
private readonly baseUrl = "http://localhost:3000/api/v1";
|
||||
private readonly http: IHttp;
|
||||
private readonly read: IRead;
|
||||
|
@ -29,10 +31,11 @@ export class RcSdk {
|
|||
this.logger = logger;
|
||||
this.user = new RcSdkUser(this);
|
||||
this.team = new RcSdkTeam(this);
|
||||
this.role = new RcSdkRole(this);
|
||||
}
|
||||
|
||||
public get(url: string, content?: any): Promise<any> {
|
||||
return this.request(this.http.get, url, content);
|
||||
public get(url: string, content?: any): Promise<any> {
|
||||
return this.request(this.http.get, url, content);
|
||||
}
|
||||
|
||||
public post(url: string, content?: any): Promise<any> {
|
||||
|
|
44
src/rc-sdk/RcSdkRole.ts
Normal file
44
src/rc-sdk/RcSdkRole.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { RcSdk } from "./RcSdk";
|
||||
|
||||
interface IRoleCreate {
|
||||
name: string;
|
||||
scope?: string;
|
||||
description?: boolean;
|
||||
}
|
||||
|
||||
export interface IRole {
|
||||
_id: string;
|
||||
name: string;
|
||||
scope?: string;
|
||||
description?: boolean;
|
||||
createdAt: string;
|
||||
_updatedAt?: string;
|
||||
}
|
||||
|
||||
interface IRoleListResponse {
|
||||
roles: Array<IRole>;
|
||||
count: number;
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
interface IRoleResponse {
|
||||
role: IRole;
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export class RcSdkRole {
|
||||
private sdk: RcSdk;
|
||||
constructor(sdk: RcSdk) {
|
||||
this.sdk = sdk;
|
||||
}
|
||||
|
||||
public list(): Promise<IRoleListResponse> {
|
||||
return this.sdk.get(`roles.list`);
|
||||
}
|
||||
|
||||
public create(body: IRoleCreate): Promise<IRoleResponse> {
|
||||
return this.sdk.post(`roles.create`, body);
|
||||
}
|
||||
}
|
Reference in a new issue