scim errors
This commit is contained in:
parent
9cc58730dd
commit
835c2aa53c
11 changed files with 398 additions and 220 deletions
3
.prettierrc
Normal file
3
.prettierrc
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"trailingComma": "all"
|
||||
}
|
76
RcHttp.ts
Normal file
76
RcHttp.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
import {
|
||||
IHttp,
|
||||
IHttpRequest,
|
||||
IHttpResponse,
|
||||
IRead,
|
||||
} from "@rocket.chat/apps-engine/definition/accessors";
|
||||
|
||||
export class RcHttp implements IHttp {
|
||||
private readonly baseUrl = "http://localhost:3000/api/v1";
|
||||
private readonly http: IHttp;
|
||||
private readonly read: IRead;
|
||||
|
||||
constructor(http: IHttp, read: IRead) {
|
||||
this.http = http;
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
public async get(url: string, content?: any): Promise<IHttpResponse> {
|
||||
return this.http.get(
|
||||
this.buildUrl(url),
|
||||
await this.buildOptions(content)
|
||||
);
|
||||
}
|
||||
|
||||
public async post(url: string, content?: any): Promise<IHttpResponse> {
|
||||
return this.http.post(
|
||||
this.buildUrl(url),
|
||||
await this.buildOptions(content)
|
||||
);
|
||||
}
|
||||
|
||||
public async put(url: string, content?: any): Promise<IHttpResponse> {
|
||||
return this.http.put(
|
||||
this.buildUrl(url),
|
||||
await this.buildOptions(content)
|
||||
);
|
||||
}
|
||||
|
||||
public async del(url: string, content?: any): Promise<IHttpResponse> {
|
||||
return this.http.del(
|
||||
this.buildUrl(url),
|
||||
await this.buildOptions(content)
|
||||
);
|
||||
}
|
||||
|
||||
public async patch(url: string, content?: any): Promise<IHttpResponse> {
|
||||
return this.http.patch(
|
||||
this.buildUrl(url),
|
||||
await this.buildOptions(content)
|
||||
);
|
||||
}
|
||||
|
||||
private buildUrl(url: string): string {
|
||||
return `${this.baseUrl}/${url}`;
|
||||
}
|
||||
|
||||
private async buildOptions(content?: any): Promise<IHttpRequest> {
|
||||
const options: IHttpRequest = {
|
||||
headers: {
|
||||
"X-User-Id": await this.read
|
||||
.getEnvironmentReader()
|
||||
.getSettings()
|
||||
.getValueById("rc-user-id"),
|
||||
"X-Auth-Token": await this.read
|
||||
.getEnvironmentReader()
|
||||
.getSettings()
|
||||
.getValueById("rc-token"),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
};
|
||||
if (content !== undefined) {
|
||||
options.content = JSON.stringify(content);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
}
|
171
ScimEndpoint.ts
Normal file
171
ScimEndpoint.ts
Normal file
|
@ -0,0 +1,171 @@
|
|||
import {
|
||||
HttpStatusCode,
|
||||
IHttp,
|
||||
IHttpResponse,
|
||||
IModify,
|
||||
IPersistence,
|
||||
IRead,
|
||||
} from "@rocket.chat/apps-engine/definition/accessors";
|
||||
import {
|
||||
ApiEndpoint,
|
||||
IApiEndpointInfo,
|
||||
IApiRequest,
|
||||
IApiResponse,
|
||||
} from "@rocket.chat/apps-engine/definition/api";
|
||||
import { IApp } from "@rocket.chat/apps-engine/definition/IApp";
|
||||
import { ConflictError } from "./errors/ConflictError";
|
||||
import { EmptyRequestError } from "./errors/EmptyRequestError";
|
||||
import { EmptyResponseError } from "./errors/EmptyResponseError";
|
||||
import { JsonParseError } from "./errors/JsonParseError";
|
||||
import { SCIMError, SCIMErrorType } from "./scim/Error";
|
||||
|
||||
type ApiEndpointMethod = (
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence,
|
||||
) => Promise<IApiResponse>;
|
||||
|
||||
export interface IScimEndpoint {
|
||||
_get?(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse>;
|
||||
_post?(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse>;
|
||||
_put?(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse>;
|
||||
_delete?(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse>;
|
||||
}
|
||||
|
||||
export abstract class ScimEndpoint extends ApiEndpoint {
|
||||
public get: ApiEndpointMethod | undefined;
|
||||
public post: ApiEndpointMethod | undefined;
|
||||
public put: ApiEndpointMethod | undefined;
|
||||
public delete: ApiEndpointMethod | undefined;
|
||||
|
||||
constructor(app: IApp) {
|
||||
super(app);
|
||||
this.get = this.wrapMethod("get");
|
||||
this.post = this.wrapMethod("post");
|
||||
this.put = this.wrapMethod("put");
|
||||
this.delete = this.wrapMethod("delete");
|
||||
}
|
||||
|
||||
protected success(content?: any): IApiResponse {
|
||||
return this.response({
|
||||
status: HttpStatusCode.OK,
|
||||
content,
|
||||
});
|
||||
}
|
||||
|
||||
protected response(response: IApiResponse): IApiResponse {
|
||||
if (response.headers === undefined) {
|
||||
response.headers = {};
|
||||
}
|
||||
response.headers["Content-Type"] = "application/scim+json";
|
||||
return response;
|
||||
}
|
||||
|
||||
protected error(error: SCIMError): IApiResponse {
|
||||
return this.response({
|
||||
status: parseInt(error.status, 10),
|
||||
content: error,
|
||||
});
|
||||
}
|
||||
|
||||
protected parseResponse(response: IHttpResponse): any {
|
||||
if (!response.content) {
|
||||
throw new EmptyResponseError();
|
||||
}
|
||||
let content: any;
|
||||
try {
|
||||
content = JSON.parse(response.content);
|
||||
} catch (e) {
|
||||
throw new JsonParseError();
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
protected hasContent(request: IApiRequest) {
|
||||
if (!request.content || Object.keys(request.content).length === 0) {
|
||||
throw new EmptyRequestError();
|
||||
}
|
||||
}
|
||||
|
||||
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") {
|
||||
return undefined;
|
||||
}
|
||||
return async (
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse> => {
|
||||
try {
|
||||
return await method.bind(this)(
|
||||
request,
|
||||
endpoint,
|
||||
read,
|
||||
modify,
|
||||
http,
|
||||
persis,
|
||||
);
|
||||
} catch (e) {
|
||||
let err: SCIMError;
|
||||
if (e.toSCIMError && typeof e.toSCIMError === "function") {
|
||||
err = e.toSCIMError();
|
||||
} else {
|
||||
err = new SCIMError()
|
||||
.setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR)
|
||||
.setScimType(SCIMErrorType.INVALID_VALUE)
|
||||
.setDetail(e.message);
|
||||
}
|
||||
|
||||
return this.error(err);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
155
UserEndpoint.ts
155
UserEndpoint.ts
|
@ -6,161 +6,74 @@ import {
|
|||
IRead,
|
||||
} from "@rocket.chat/apps-engine/definition/accessors";
|
||||
import {
|
||||
ApiEndpoint,
|
||||
IApiEndpointInfo,
|
||||
IApiRequest,
|
||||
IApiResponse,
|
||||
} from "@rocket.chat/apps-engine/definition/api";
|
||||
import { RcHttp } from "./RcHttp";
|
||||
import { SCIMUser } from "./scim/User";
|
||||
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
|
||||
|
||||
export class UserEndpoint extends ApiEndpoint {
|
||||
export class UserEndpoint extends ScimEndpoint implements IScimEndpoint {
|
||||
public path = "Users/:id";
|
||||
|
||||
public async get(
|
||||
public async _get(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse> {
|
||||
let user: SCIMUser;
|
||||
try {
|
||||
const response = await http.get(
|
||||
`http://localhost:3000/api/v1/users.info?userId=` +
|
||||
request.params.id,
|
||||
{
|
||||
headers: {
|
||||
...(await this.getAuthHeaders(read)),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.content) throw new Error("Empty response");
|
||||
const o = JSON.parse(response.content);
|
||||
if (!o.success) throw new Error(o.error);
|
||||
user = SCIMUser.fromRC(o.user);
|
||||
} catch (e) {
|
||||
return {
|
||||
headers: {
|
||||
"Content-Type": "application/scim+json",
|
||||
},
|
||||
status: HttpStatusCode.BAD_REQUEST,
|
||||
content: { message: e.message },
|
||||
};
|
||||
}
|
||||
return {
|
||||
headers: {
|
||||
"Content-Type": "application/scim+json",
|
||||
},
|
||||
status: HttpStatusCode.OK,
|
||||
content: user,
|
||||
};
|
||||
const response = await new RcHttp(http, read).get(
|
||||
`users.info?userId=${request.params.id}`,
|
||||
);
|
||||
const o = this.parseResponse(response);
|
||||
this.handleError(o);
|
||||
const user = SCIMUser.fromRC(o.user);
|
||||
return this.success(user);
|
||||
}
|
||||
|
||||
public async put(
|
||||
public async _put(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse> {
|
||||
let user: SCIMUser;
|
||||
try {
|
||||
const response = await http.post(
|
||||
"http://localhost:3000/api/v1/users.update",
|
||||
{
|
||||
headers: {
|
||||
...(await this.getAuthHeaders(read)),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
content: JSON.stringify(
|
||||
this.scimToUserUpdate(
|
||||
request.params.id,
|
||||
SCIMUser.fromPlain(request.content)
|
||||
)
|
||||
),
|
||||
}
|
||||
);
|
||||
if (!response.content) throw new Error("Empty response");
|
||||
const o = JSON.parse(response.content);
|
||||
if (!o.success) throw new Error(o.error);
|
||||
user = SCIMUser.fromRC(o.user);
|
||||
} catch (e) {
|
||||
return {
|
||||
headers: {
|
||||
"Content-Type": "application/scim+json",
|
||||
},
|
||||
status: HttpStatusCode.BAD_REQUEST,
|
||||
content: { message: e.message },
|
||||
};
|
||||
}
|
||||
return {
|
||||
headers: {
|
||||
"Content-Type": "application/scim+json",
|
||||
},
|
||||
status: HttpStatusCode.OK,
|
||||
content: user,
|
||||
};
|
||||
this.hasContent(request);
|
||||
const response = await new RcHttp(http, read).post(
|
||||
"users.update",
|
||||
this.scimToUserUpdate(
|
||||
request.params.id,
|
||||
SCIMUser.fromPlain(request.content),
|
||||
),
|
||||
);
|
||||
const o = this.parseResponse(response);
|
||||
this.handleError(o);
|
||||
const user = SCIMUser.fromRC(o.user);
|
||||
return this.success(user);
|
||||
}
|
||||
|
||||
public async delete(
|
||||
public async _delete(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse> {
|
||||
let d: IUserDelete = {
|
||||
const d: IUserDelete = {
|
||||
userId: request.params.id,
|
||||
confirmRelinquish: true,
|
||||
};
|
||||
try {
|
||||
const response = await http.post(
|
||||
"http://localhost:3000/api/v1/users.delete",
|
||||
{
|
||||
headers: {
|
||||
...(await this.getAuthHeaders(read)),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
content: JSON.stringify(d),
|
||||
}
|
||||
);
|
||||
if (!response.content) throw new Error("Empty response");
|
||||
const o = JSON.parse(response.content);
|
||||
if (!o.success) throw new Error(o.error);
|
||||
} catch (e) {
|
||||
return {
|
||||
headers: {
|
||||
"Content-Type": "application/scim+json",
|
||||
},
|
||||
status: HttpStatusCode.BAD_REQUEST,
|
||||
content: { message: e.message },
|
||||
};
|
||||
}
|
||||
return {
|
||||
headers: {
|
||||
"Content-Type": "application/scim+json",
|
||||
},
|
||||
const response = await new RcHttp(http, read).post("users.delete", d);
|
||||
const o = this.parseResponse(response);
|
||||
this.handleError(o);
|
||||
return this.response({
|
||||
status: HttpStatusCode.NO_CONTENT,
|
||||
};
|
||||
}
|
||||
|
||||
private async getAuthHeaders(
|
||||
read: IRead
|
||||
): Promise<{ [key: string]: string }> {
|
||||
return {
|
||||
"X-User-Id": await read
|
||||
.getEnvironmentReader()
|
||||
.getSettings()
|
||||
.getValueById("rc-user-id"),
|
||||
"X-Auth-Token": await read
|
||||
.getEnvironmentReader()
|
||||
.getSettings()
|
||||
.getValueById("rc-token"),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private scimToUserUpdate(userId: string, user: SCIMUser): IUserUpdate {
|
||||
|
|
121
UsersEndpoint.ts
121
UsersEndpoint.ts
|
@ -6,128 +6,67 @@ import {
|
|||
IRead,
|
||||
} from "@rocket.chat/apps-engine/definition/accessors";
|
||||
import {
|
||||
ApiEndpoint,
|
||||
IApiEndpointInfo,
|
||||
IApiRequest,
|
||||
IApiResponse,
|
||||
} from "@rocket.chat/apps-engine/definition/api";
|
||||
import crypto = require("crypto");
|
||||
import { SCIMError, SCIMErrorType } from "./scim/Error";
|
||||
import { RcHttp } from "./RcHttp";
|
||||
import { SCIMListResponse } from "./scim/ListResponse";
|
||||
import { SCIMUser } from "./scim/User";
|
||||
import { IScimEndpoint, ScimEndpoint } from "./ScimEndpoint";
|
||||
|
||||
export class UsersEndpoint extends ApiEndpoint {
|
||||
export class UsersEndpoint extends ScimEndpoint implements IScimEndpoint {
|
||||
public path = "Users";
|
||||
|
||||
public async get(
|
||||
public async _get(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse> {
|
||||
const response = await new RcHttp(http, read).get(
|
||||
`users.list?query={"type":{"$eq":"user"}}&fields={"createdAt":1}`,
|
||||
);
|
||||
const o = this.parseResponse(response);
|
||||
this.handleError(o);
|
||||
const list = new SCIMListResponse();
|
||||
try {
|
||||
const response = await http.get(
|
||||
`http://localhost:3000/api/v1/users.list?query={"type":{"$eq":"user"}}&fields={"createdAt":1}`,
|
||||
{
|
||||
headers: {
|
||||
...(await this.getAuthHeaders(read)),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
if (!response.content) {
|
||||
throw new Error("Empty response");
|
||||
}
|
||||
const o = JSON.parse(response.content);
|
||||
if (!o.success) {
|
||||
throw new Error(o.error);
|
||||
}
|
||||
list.Resources = o.users.map(SCIMUser.fromRC);
|
||||
list.totalResults = o.total;
|
||||
} catch (e) {
|
||||
const err = new SCIMError();
|
||||
err.scimType = SCIMErrorType.INVALID_VALUE;
|
||||
err.detail = e.message;
|
||||
err.status = "400";
|
||||
return err.toApiResponse();
|
||||
}
|
||||
return {
|
||||
headers: {
|
||||
"Content-Type": "application/scim+json",
|
||||
},
|
||||
status: HttpStatusCode.OK,
|
||||
content: list,
|
||||
};
|
||||
list.Resources = o.users.map(SCIMUser.fromRC);
|
||||
list.totalResults = o.total;
|
||||
return this.success(list);
|
||||
}
|
||||
|
||||
public async post(
|
||||
public async _post(
|
||||
request: IApiRequest,
|
||||
endpoint: IApiEndpointInfo,
|
||||
read: IRead,
|
||||
modify: IModify,
|
||||
http: IHttp,
|
||||
persis: IPersistence
|
||||
persis: IPersistence,
|
||||
): Promise<IApiResponse> {
|
||||
let user = request.content;
|
||||
try {
|
||||
const response = await http.post(
|
||||
`http://localhost:3000/api/v1/users.create`,
|
||||
{
|
||||
headers: {
|
||||
...(await this.getAuthHeaders(read)),
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
content: JSON.stringify(
|
||||
this.scimToUserCreate(SCIMUser.fromPlain(user))
|
||||
),
|
||||
}
|
||||
);
|
||||
if (!response.content) {
|
||||
throw new Error("Empty response");
|
||||
}
|
||||
const o = JSON.parse(response.content);
|
||||
if (!o.success) {
|
||||
throw new Error(o.error);
|
||||
}
|
||||
user = SCIMUser.fromRC(o.user);
|
||||
} catch (e) {
|
||||
const err = new SCIMError();
|
||||
err.scimType = SCIMErrorType.INVALID_VALUE;
|
||||
err.detail = e.message;
|
||||
err.status = "400";
|
||||
return err.toApiResponse();
|
||||
}
|
||||
return {
|
||||
headers: {
|
||||
"Content-Type": "application/scim+json",
|
||||
},
|
||||
this.hasContent(request);
|
||||
const response = await new RcHttp(http, read).post(
|
||||
`users.create`,
|
||||
this.scimToUserCreate(SCIMUser.fromPlain(request.content)),
|
||||
);
|
||||
const o = this.parseResponse(response);
|
||||
this.handleError(o);
|
||||
const user = SCIMUser.fromRC(o.user);
|
||||
return this.response({
|
||||
status: HttpStatusCode.CREATED,
|
||||
content: user,
|
||||
};
|
||||
}
|
||||
|
||||
private async getAuthHeaders(
|
||||
read: IRead
|
||||
): Promise<{ [key: string]: string }> {
|
||||
return {
|
||||
"X-User-Id": await read
|
||||
.getEnvironmentReader()
|
||||
.getSettings()
|
||||
.getValueById("rc-user-id"),
|
||||
"X-Auth-Token": await read
|
||||
.getEnvironmentReader()
|
||||
.getSettings()
|
||||
.getValueById("rc-token"),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private scimToUserCreate(user: SCIMUser): IUserCreate {
|
||||
return {
|
||||
email: user.emails[0].value,
|
||||
name: user.displayName,
|
||||
email: user.getEmail(),
|
||||
name:
|
||||
user.displayName ||
|
||||
`${user.name.givenName} ${user.name.familyName}` ||
|
||||
user.userName,
|
||||
username: user.userName,
|
||||
password: crypto.randomBytes(64).toString("base64").slice(0, 64),
|
||||
verified: true,
|
||||
|
|
6
errors/BaseError.ts
Normal file
6
errors/BaseError.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { SCIMError } from "../scim/Error";
|
||||
|
||||
export abstract class BaseError extends Error {
|
||||
public readonly isBaseError = true;
|
||||
public abstract toSCIMError(): SCIMError;
|
||||
}
|
22
errors/ConflictError.ts
Normal file
22
errors/ConflictError.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { HttpStatusCode } from "@rocket.chat/apps-engine/definition/accessors";
|
||||
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
||||
import { BaseError } from "./BaseError";
|
||||
|
||||
export class ConflictError extends BaseError {
|
||||
public get message() {
|
||||
return `This ${this.type} already exists`;
|
||||
}
|
||||
private type = "";
|
||||
|
||||
constructor(type: string) {
|
||||
super();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public toSCIMError(): SCIMError {
|
||||
return new SCIMError()
|
||||
.setStatus(HttpStatusCode.CONFLICT)
|
||||
.setScimType(SCIMErrorType.INVALID_VALUE)
|
||||
.setDetail(this.message);
|
||||
}
|
||||
}
|
13
errors/EmptyRequestError.ts
Normal file
13
errors/EmptyRequestError.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { HttpStatusCode } from "@rocket.chat/apps-engine/definition/accessors";
|
||||
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
||||
import { BaseError } from "./BaseError";
|
||||
|
||||
export class EmptyRequestError extends BaseError {
|
||||
public message = "Request body is empty or content type is unsupported";
|
||||
public toSCIMError(): SCIMError {
|
||||
return new SCIMError()
|
||||
.setStatus(HttpStatusCode.BAD_REQUEST)
|
||||
.setScimType(SCIMErrorType.INVALID_VALUE)
|
||||
.setDetail(this.message);
|
||||
}
|
||||
}
|
13
errors/EmptyResponseError.ts
Normal file
13
errors/EmptyResponseError.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { HttpStatusCode } from "@rocket.chat/apps-engine/definition/accessors";
|
||||
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
||||
import { BaseError } from "./BaseError";
|
||||
|
||||
export class EmptyResponseError extends BaseError {
|
||||
public message = "Rocket.Chat API returned an empty response";
|
||||
public toSCIMError(): SCIMError {
|
||||
return new SCIMError()
|
||||
.setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR)
|
||||
.setScimType(SCIMErrorType.INVALID_VALUE)
|
||||
.setDetail(this.message);
|
||||
}
|
||||
}
|
13
errors/JsonParseError.ts
Normal file
13
errors/JsonParseError.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { HttpStatusCode } from "@rocket.chat/apps-engine/definition/accessors";
|
||||
import { SCIMError, SCIMErrorType } from "../scim/Error";
|
||||
import { BaseError } from "./BaseError";
|
||||
|
||||
export class JsonParseError extends BaseError {
|
||||
public message = "Failed to parse Rocket.Chat API response content";
|
||||
public toSCIMError(): SCIMError {
|
||||
return new SCIMError()
|
||||
.setStatus(HttpStatusCode.INTERNAL_SERVER_ERROR)
|
||||
.setScimType(SCIMErrorType.INVALID_VALUE)
|
||||
.setDetail(this.message);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { IApiResponse } from "@rocket.chat/apps-engine/definition/api";
|
||||
import { HttpStatusCode } from "@rocket.chat/apps-engine/definition/accessors";
|
||||
|
||||
export enum SCIMErrorType {
|
||||
INVALID_FILTER = "invalidFilter",
|
||||
|
@ -27,15 +27,24 @@ export enum SCIMErrorDetail {
|
|||
NOT_IMPLEMENTED = "Service provider does not support the request operation.",
|
||||
}
|
||||
|
||||
export class SCIMError {
|
||||
export class SCIMError {
|
||||
public readonly schemas: ["urn:ietf:params:scim:api:messages:2.0:Error"];
|
||||
public scimType: SCIMErrorType;
|
||||
public detail: SCIMErrorDetail | string;
|
||||
public status: string;
|
||||
public toApiResponse(): IApiResponse {
|
||||
return {
|
||||
status: parseInt(this.status, 10),
|
||||
content: this,
|
||||
};
|
||||
|
||||
public setScimType(scimType: SCIMErrorType): SCIMError {
|
||||
this.scimType = scimType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public setStatus(status: HttpStatusCode): SCIMError {
|
||||
this.status = `${status}`;
|
||||
return this;
|
||||
}
|
||||
|
||||
public setDetail(detail: SCIMErrorDetail | string): SCIMError {
|
||||
this.detail = detail;
|
||||
return this;
|
||||
}
|
||||
}
|
Reference in a new issue