store externalId

This commit is contained in:
Hugo Renard 2022-02-15 15:53:18 +01:00
parent 60f9cc8b2c
commit d29fd81317
Signed by: hougo
GPG key ID: 3A285FD470209C59
7 changed files with 138 additions and 4 deletions

View file

@ -10,9 +10,11 @@ import {
} from "@rocket.chat/apps-engine/definition/api"; } from "@rocket.chat/apps-engine/definition/api";
import { EmptyRequestError } from "../errors/EmptyRequestError"; import { EmptyRequestError } from "../errors/EmptyRequestError";
import { RcSdk } from "../rc-sdk/RcSdk"; import { RcSdk } from "../rc-sdk/RcSdk";
import { Store } from "../store/Store";
export class Context { export class Context {
public readonly rc: RcSdk; public readonly rc: RcSdk;
public readonly store: Store;
public readonly request: IApiRequest; public readonly request: IApiRequest;
public readonly endpoint: IApiEndpointInfo; public readonly endpoint: IApiEndpointInfo;
public readonly read: IRead; public readonly read: IRead;
@ -28,6 +30,7 @@ export class Context {
persis: IPersistence, persis: IPersistence,
) { ) {
this.rc = new RcSdk(http, read); this.rc = new RcSdk(http, read);
this.store = new Store(read, persis);
this.request = request; this.request = request;
this.endpoint = endpoint; this.endpoint = endpoint;
this.read = read; this.read = read;

View file

@ -22,6 +22,10 @@ export class GroupEndpoint extends ScimEndpoint implements IScimEndpoint {
const teamArgs = await Promise.all([getTeamInfo(), getTeamMembers()]); const teamArgs = await Promise.all([getTeamInfo(), getTeamMembers()]);
const group = SCIMGroup.fromRC(...teamArgs); const group = SCIMGroup.fromRC(...teamArgs);
const meta = await ctx.store.getGroup(group.id);
if (meta) {
group.externalId = meta.externalId;
}
return this.success(group); return this.success(group);
} }
@ -73,6 +77,7 @@ export class GroupEndpoint extends ScimEndpoint implements IScimEndpoint {
public async _delete(ctx: Context): Promise<IApiResponse> { public async _delete(ctx: Context): Promise<IApiResponse> {
const o = await ctx.rc.team.delete({ teamId: ctx.id() }); const o = await ctx.rc.team.delete({ teamId: ctx.id() });
this.handleError(o); this.handleError(o);
await ctx.store.deleteGroup(ctx.id());
return this.response({ return this.response({
status: HttpStatusCode.NO_CONTENT, status: HttpStatusCode.NO_CONTENT,
}); });

View file

@ -14,7 +14,12 @@ export class GroupsEndpoint extends ScimEndpoint implements IScimEndpoint {
const groups = teamsRaw.teams.map(async (team) => { const groups = teamsRaw.teams.map(async (team) => {
const membersRaw = await ctx.rc.team.members(team._id); const membersRaw = await ctx.rc.team.members(team._id);
this.handleError(membersRaw); this.handleError(membersRaw);
return SCIMGroup.fromRC(team, membersRaw.members); const group = SCIMGroup.fromRC(team, membersRaw.members);
const meta = await ctx.store.getGroup(group.id);
if (meta) {
group.externalId = meta.externalId;
}
return group;
}); });
const list = new SCIMListResponse(); const list = new SCIMListResponse();
list.Resources = await Promise.all(groups); list.Resources = await Promise.all(groups);
@ -32,6 +37,8 @@ export class GroupsEndpoint extends ScimEndpoint implements IScimEndpoint {
this.handleError(o); this.handleError(o);
const m = await ctx.rc.team.members(o.team._id); const m = await ctx.rc.team.members(o.team._id);
const group = SCIMGroup.fromRC(o.team, m.members); const group = SCIMGroup.fromRC(o.team, m.members);
group.externalId = u.externalId;
await ctx.store.saveGroup(group.id, { externalId: group.externalId });
return this.response({ return this.response({
status: HttpStatusCode.CREATED, status: HttpStatusCode.CREATED,
content: group, content: group,

View file

@ -1,5 +1,9 @@
import { HttpStatusCode } from "@rocket.chat/apps-engine/definition/accessors"; 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 {
RocketChatAssociationModel,
RocketChatAssociationRecord,
} from "@rocket.chat/apps-engine/definition/metadata";
import { SCIMUser } from "../scim/User"; import { SCIMUser } from "../scim/User";
import { Context } from "./Context"; import { Context } from "./Context";
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint"; import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
@ -11,6 +15,10 @@ export class UserEndpoint extends ScimEndpoint implements IScimEndpoint {
const o = await ctx.rc.user.info(ctx.id()); const o = await ctx.rc.user.info(ctx.id());
this.handleError(o); this.handleError(o);
const user = SCIMUser.fromRC(o.user); const user = SCIMUser.fromRC(o.user);
const m = await ctx.store.getUser(ctx.id());
if (m) {
user.externalId = m.externalId;
}
return this.success(user); return this.success(user);
} }
@ -29,9 +37,10 @@ export class UserEndpoint extends ScimEndpoint implements IScimEndpoint {
}, },
}, },
}); });
this.handleError(o); this.handleError(o);
await ctx.store.saveUser(ctx.id(), { externalId: u.externalId });
const user = SCIMUser.fromRC(o.user); const user = SCIMUser.fromRC(o.user);
user.externalId = u.externalId;
return this.success(user); return this.success(user);
} }
@ -41,6 +50,7 @@ export class UserEndpoint extends ScimEndpoint implements IScimEndpoint {
confirmRelinquish: true, confirmRelinquish: true,
}); });
this.handleError(o); this.handleError(o);
await ctx.store.deleteUser(ctx.id());
return this.response({ return this.response({
status: HttpStatusCode.NO_CONTENT, status: HttpStatusCode.NO_CONTENT,
}); });

View file

@ -1,5 +1,9 @@
import { HttpStatusCode } from "@rocket.chat/apps-engine/definition/accessors"; 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 {
RocketChatAssociationModel,
RocketChatAssociationRecord,
} from "@rocket.chat/apps-engine/definition/metadata";
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";
@ -13,7 +17,15 @@ export class UsersEndpoint extends ScimEndpoint implements IScimEndpoint {
const o = await ctx.rc.user.list(); const o = await ctx.rc.user.list();
this.handleError(o); this.handleError(o);
const list = new SCIMListResponse(); const list = new SCIMListResponse();
list.Resources = o.users.map(SCIMUser.fromRC); list.Resources = await Promise.all(
o.users.map(SCIMUser.fromRC).map(async (x) => {
const meta = await ctx.store.getUser(x.id);
if (meta) {
x.externalId = meta.externalId;
}
return x;
}),
);
list.totalResults = o.total; list.totalResults = o.total;
return this.success(list); return this.success(list);
} }
@ -35,6 +47,8 @@ export class UsersEndpoint extends ScimEndpoint implements IScimEndpoint {
}); });
this.handleError(o); this.handleError(o);
const user = SCIMUser.fromRC(o.user); const user = SCIMUser.fromRC(o.user);
user.externalId = u.externalId;
await ctx.store.saveUser(user.id, { externalId: user.externalId });
return this.response({ return this.response({
status: HttpStatusCode.CREATED, status: HttpStatusCode.CREATED,
content: user, content: user,

View file

@ -90,7 +90,7 @@ export class RcSdkUser {
} }
public async delete(body: IUserDelete): Promise<IUserDeleteResponse> { public async delete(body: IUserDelete): Promise<IUserDeleteResponse> {
const response = await this.sdk.post(`users.delete`); const response = await this.sdk.post(`users.delete`, body);
return this.sdk.parseResponse(response); return this.sdk.parseResponse(response);
} }

95
src/store/Store.ts Normal file
View file

@ -0,0 +1,95 @@
import {
IPersistence,
IRead,
} from "@rocket.chat/apps-engine/definition/accessors";
import {
RocketChatAssociationModel,
RocketChatAssociationRecord,
} from "@rocket.chat/apps-engine/definition/metadata";
interface IUserMeta {
externalId: string;
}
interface IGroupMeta {
externalId: string;
}
export class Store {
private read: IRead;
private persis: IPersistence;
constructor(read: IRead, persis: IPersistence) {
this.read = read;
this.persis = persis;
}
public deleteUser(id: string) {
return this.persis.removeByAssociation(
new RocketChatAssociationRecord(
RocketChatAssociationModel.USER,
id,
),
);
}
public saveUser(id: string, meta: IUserMeta) {
return this.persis.updateByAssociation(
new RocketChatAssociationRecord(
RocketChatAssociationModel.USER,
id,
),
meta,
true,
);
}
public async getUser(id: string): Promise<IUserMeta | undefined> {
const list = await this.read
.getPersistenceReader()
.readByAssociation(
new RocketChatAssociationRecord(
RocketChatAssociationModel.USER,
id,
),
);
if (list.length > 0) {
return list[0] as IUserMeta;
}
return;
}
public deleteGroup(id: string) {
return this.persis.removeByAssociation(
new RocketChatAssociationRecord(
RocketChatAssociationModel.ROOM,
id,
),
);
}
public saveGroup(id: string, meta: IGroupMeta) {
return this.persis.updateByAssociation(
new RocketChatAssociationRecord(
RocketChatAssociationModel.ROOM,
id,
),
meta,
true,
);
}
public async getGroup(id: string): Promise<IGroupMeta | undefined> {
const list = await this.read
.getPersistenceReader()
.readByAssociation(
new RocketChatAssociationRecord(
RocketChatAssociationModel.ROOM,
id,
),
);
if (list.length > 0) {
return list[0] as IGroupMeta;
}
return;
}
}