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 { EmptyResponseError } from "../errors/EmptyResponseError";
|
||||||
import { JsonParseError } from "../errors/JsonParseError";
|
import { JsonParseError } from "../errors/JsonParseError";
|
||||||
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
||||||
|
import { handleRcError } from "./common/endpoint";
|
||||||
import { Context } from "./Context";
|
import { Context } from "./Context";
|
||||||
|
|
||||||
type ApiEndpointMethod = (
|
type ApiEndpointMethod = (
|
||||||
|
@ -41,6 +42,7 @@ export abstract class ScimEndpoint extends ApiEndpoint {
|
||||||
public post: ApiEndpointMethod | undefined;
|
public post: ApiEndpointMethod | undefined;
|
||||||
public put: ApiEndpointMethod | undefined;
|
public put: ApiEndpointMethod | undefined;
|
||||||
public delete: ApiEndpointMethod | undefined;
|
public delete: ApiEndpointMethod | undefined;
|
||||||
|
protected handleError = handleRcError;
|
||||||
|
|
||||||
constructor(app: IApp) {
|
constructor(app: IApp) {
|
||||||
super(app);
|
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 {
|
private wrapMethod(name: string): ApiEndpointMethod | undefined {
|
||||||
const method = this[`_${name}`];
|
const method = this[`_${name}`];
|
||||||
if (method === undefined || typeof method !== "function") {
|
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 { IApiResponse } from "@rocket.chat/apps-engine/definition/api";
|
||||||
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
||||||
import { SCIMUser } from "../scim/User";
|
import { SCIMUser } from "../scim/User";
|
||||||
|
import { findOrCreateRole } from "./common/user";
|
||||||
import { Context } from "./Context";
|
import { Context } from "./Context";
|
||||||
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
|
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ export class UserEndpoint extends ScimEndpoint implements IScimEndpoint {
|
||||||
u.roles.push({ value: "admin" });
|
u.roles.push({ value: "admin" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const roles = await findOrCreateRole(ctx, u);
|
||||||
const o = await ctx.rc.user.update({
|
const o = await ctx.rc.user.update({
|
||||||
userId: ctx.id(),
|
userId: ctx.id(),
|
||||||
data: {
|
data: {
|
||||||
|
@ -35,7 +37,7 @@ export class UserEndpoint extends ScimEndpoint implements IScimEndpoint {
|
||||||
username: u.userName,
|
username: u.userName,
|
||||||
active: u.active,
|
active: u.active,
|
||||||
verified: true,
|
verified: true,
|
||||||
roles: u.roles.map((x) => x.value),
|
roles,
|
||||||
customFields: {
|
customFields: {
|
||||||
scimExternalId: u.externalId,
|
scimExternalId: u.externalId,
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { IApiResponse } from "@rocket.chat/apps-engine/definition/api";
|
||||||
import crypto = require("crypto");
|
import crypto = require("crypto");
|
||||||
import { SCIMListResponse } from "../scim/ListResponse";
|
import { SCIMListResponse } from "../scim/ListResponse";
|
||||||
import { SCIMUser } from "../scim/User";
|
import { SCIMUser } from "../scim/User";
|
||||||
|
import { findOrCreateRole } from "./common/user";
|
||||||
import { Context } from "./Context";
|
import { Context } from "./Context";
|
||||||
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
|
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
|
||||||
|
|
||||||
|
@ -28,12 +29,13 @@ export class UsersEndpoint extends ScimEndpoint implements IScimEndpoint {
|
||||||
|
|
||||||
public async _post(ctx: Context): Promise<IApiResponse> {
|
public async _post(ctx: Context): Promise<IApiResponse> {
|
||||||
const u = SCIMUser.fromPlain(ctx.content());
|
const u = SCIMUser.fromPlain(ctx.content());
|
||||||
|
const roles = await findOrCreateRole(ctx, u);
|
||||||
const o = await ctx.rc.user.create({
|
const o = await ctx.rc.user.create({
|
||||||
email: u.getEmail(),
|
email: u.getEmail(),
|
||||||
name: u.displayName || u.userName,
|
name: u.displayName || u.userName,
|
||||||
username: u.userName,
|
username: u.userName,
|
||||||
password: crypto.randomBytes(64).toString("base64").slice(0, 64),
|
password: crypto.randomBytes(64).toString("base64").slice(0, 64),
|
||||||
roles: u.roles.map((x) => x.value),
|
roles,
|
||||||
verified: true,
|
verified: true,
|
||||||
customFields: {
|
customFields: {
|
||||||
scimExternalId: u.externalId,
|
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";
|
} from "@rocket.chat/apps-engine/definition/accessors";
|
||||||
import { EmptyResponseError } from "../errors/EmptyResponseError";
|
import { EmptyResponseError } from "../errors/EmptyResponseError";
|
||||||
import { JsonParseError } from "../errors/JsonParseError";
|
import { JsonParseError } from "../errors/JsonParseError";
|
||||||
|
import { RcSdkRole } from "./RcSdkRole";
|
||||||
import { RcSdkTeam } from "./RcSdkTeam";
|
import { RcSdkTeam } from "./RcSdkTeam";
|
||||||
import { RcSdkUser } from "./RcSdkUser";
|
import { RcSdkUser } from "./RcSdkUser";
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@ type RequestCallback = (
|
||||||
export class RcSdk {
|
export class RcSdk {
|
||||||
public user: RcSdkUser;
|
public user: RcSdkUser;
|
||||||
public team: RcSdkTeam;
|
public team: RcSdkTeam;
|
||||||
|
public role: RcSdkRole;
|
||||||
private readonly baseUrl = "http://localhost:3000/api/v1";
|
private readonly baseUrl = "http://localhost:3000/api/v1";
|
||||||
private readonly http: IHttp;
|
private readonly http: IHttp;
|
||||||
private readonly read: IRead;
|
private readonly read: IRead;
|
||||||
|
@ -29,10 +31,11 @@ export class RcSdk {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.user = new RcSdkUser(this);
|
this.user = new RcSdkUser(this);
|
||||||
this.team = new RcSdkTeam(this);
|
this.team = new RcSdkTeam(this);
|
||||||
|
this.role = new RcSdkRole(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get(url: string, content?: any): Promise<any> {
|
public get(url: string, content?: any): Promise<any> {
|
||||||
return this.request(this.http.get, url, content);
|
return this.request(this.http.get, url, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public post(url: string, content?: any): Promise<any> {
|
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