mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 05:05:53 +00:00
Convert the frontend to the async/await pattern
We have to drop bluebird to be able to do this.
This commit is contained in:
parent
51740308a2
commit
8d6c2dfa00
@ -21,7 +21,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/body-parser": "^1.16.8",
|
"@types/body-parser": "^1.16.8",
|
||||||
"@types/node": "^8.9.5",
|
"@types/node": "^8.9.5",
|
||||||
"bluebird": "^3.5.1",
|
|
||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
"config": "^1.30.0",
|
"config": "^1.30.0",
|
||||||
"dns-then": "^0.1.0",
|
"dns-then": "^0.1.0",
|
||||||
|
@ -2,8 +2,9 @@ export class ApiError {
|
|||||||
|
|
||||||
public statusCode: number;
|
public statusCode: number;
|
||||||
public jsonResponse: any;
|
public jsonResponse: any;
|
||||||
|
public errorCode: string;
|
||||||
|
|
||||||
constructor(statusCode: number, json: any) {
|
constructor(statusCode: number, json: any, errCode = "D_UNKNOWN") {
|
||||||
// Because typescript is just plain dumb
|
// Because typescript is just plain dumb
|
||||||
// https://stackoverflow.com/questions/31626231/custom-error-class-in-typescript
|
// https://stackoverflow.com/questions/31626231/custom-error-class-in-typescript
|
||||||
Error.apply(this, ["ApiError"]);
|
Error.apply(this, ["ApiError"]);
|
||||||
@ -11,5 +12,6 @@ export class ApiError {
|
|||||||
if (typeof(json) === "string") json = {message: json};
|
if (typeof(json) === "string") json = {message: json};
|
||||||
this.jsonResponse = json;
|
this.jsonResponse = json;
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
|
this.errorCode = errCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
import { GET, Path, QueryParam } from "typescript-rest";
|
import { GET, Path, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { ScalarService } from "../scalar/ScalarService";
|
import { ScalarService } from "../scalar/ScalarService";
|
||||||
import config from "../../config";
|
import config from "../../config";
|
||||||
import { ApiError } from "../ApiError";
|
import { ApiError } from "../ApiError";
|
||||||
@ -27,51 +26,41 @@ export class DimensionAdminService {
|
|||||||
return config.admins.indexOf(userId) >= 0;
|
return config.admins.indexOf(userId) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static validateAndGetAdminTokenOwner(scalarToken: string): Promise<string> {
|
public static async validateAndGetAdminTokenOwner(scalarToken: string): Promise<string> {
|
||||||
return ScalarService.getTokenOwner(scalarToken, true).then(userId => {
|
const userId = await ScalarService.getTokenOwner(scalarToken, true);
|
||||||
if (!DimensionAdminService.isAdmin(userId))
|
if (!DimensionAdminService.isAdmin(userId))
|
||||||
throw new ApiError(401, {message: "You must be an administrator to use this API"});
|
throw new ApiError(401, "You must be an administrator to use this API");
|
||||||
else return userId;
|
return userId;
|
||||||
}, ScalarService.invalidTokenErrorHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("check")
|
@Path("check")
|
||||||
public checkIfAdmin(@QueryParam("scalar_token") scalarToken: string): Promise<{}> {
|
public async checkIfAdmin(@QueryParam("scalar_token") scalarToken: string): Promise<{}> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return {}; // A 200 OK essentially means "you're an admin".
|
return {}; // A 200 OK essentially means "you're an admin".
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("version")
|
@Path("version")
|
||||||
public getVersion(@QueryParam("scalar_token") scalarToken: string): Promise<DimensionVersionResponse> {
|
public async getVersion(@QueryParam("scalar_token") scalarToken: string): Promise<DimensionVersionResponse> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return {version: CURRENT_VERSION};
|
return {version: CURRENT_VERSION};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("config")
|
@Path("config")
|
||||||
public getConfig(@QueryParam("scalar_token") scalarToken: string): Promise<DimensionConfigResponse> {
|
public async getConfig(@QueryParam("scalar_token") scalarToken: string): Promise<DimensionConfigResponse> {
|
||||||
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
|
|
||||||
const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken);
|
const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken);
|
||||||
const response: DimensionConfigResponse = {
|
return {
|
||||||
admins: config.admins,
|
admins: config.admins,
|
||||||
widgetBlacklist: config.widgetBlacklist,
|
widgetBlacklist: config.widgetBlacklist,
|
||||||
homeserver: {
|
homeserver: {
|
||||||
name: config.homeserver.name,
|
name: config.homeserver.name,
|
||||||
userId: "", // populated below
|
userId: await client.whoAmI(),
|
||||||
federationUrl: "", // populated below
|
federationUrl: await client.getFederationUrl(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
|
||||||
return client.whoAmI();
|
|
||||||
}).then(userId => {
|
|
||||||
response.homeserver.userId = userId;
|
|
||||||
return client.getFederationUrl();
|
|
||||||
}).then(url => {
|
|
||||||
response.homeserver.federationUrl = url;
|
|
||||||
}).then(() => response);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { DimensionAdminService } from "./DimensionAdminService";
|
import { DimensionAdminService } from "./DimensionAdminService";
|
||||||
import AppService from "../../db/models/AppService";
|
import AppService from "../../db/models/AppService";
|
||||||
import { AppserviceStore } from "../../db/AppserviceStore";
|
import { AppserviceStore } from "../../db/AppserviceStore";
|
||||||
@ -33,49 +32,44 @@ export class DimensionAppserviceAdminService {
|
|||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("all")
|
@Path("all")
|
||||||
public getAppservices(@QueryParam("scalar_token") scalarToken: string): Promise<AppserviceResponse[]> {
|
public async getAppservices(@QueryParam("scalar_token") scalarToken: string): Promise<AppserviceResponse[]> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return AppService.findAll();
|
return (await AppService.findAll()).map(a => this.mapAppservice(a));
|
||||||
}).then(appservices => {
|
|
||||||
return appservices.map(this.mapAppservice);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("new")
|
@Path("new")
|
||||||
public createAppservice(@QueryParam("scalar_token") scalarToken: string, request: AppserviceCreateRequest): Promise<AppserviceResponse> {
|
public async createAppservice(@QueryParam("scalar_token") scalarToken: string, request: AppserviceCreateRequest): Promise<AppserviceResponse> {
|
||||||
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
|
|
||||||
// Trim off the @ sign if it's on the prefix
|
// Trim off the @ sign if it's on the prefix
|
||||||
if (request.userPrefix[0] === "@") {
|
if (request.userPrefix[0] === "@") {
|
||||||
request.userPrefix = request.userPrefix.substring(1);
|
request.userPrefix = request.userPrefix.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
const appservices = await AppserviceStore.getAllByUserPrefix(request.userPrefix);
|
||||||
return AppserviceStore.getAllByUserPrefix(request.userPrefix);
|
|
||||||
}).then(appservices => {
|
|
||||||
if (appservices && appservices.length > 0) {
|
if (appservices && appservices.length > 0) {
|
||||||
throw new ApiError(400, "User prefix is already in use");
|
throw new ApiError(400, "User prefix is already in use");
|
||||||
}
|
}
|
||||||
|
|
||||||
return AppserviceStore.create(AppserviceStore.getSafeUserId(request.userPrefix));
|
const appservice = await AppserviceStore.create(AppserviceStore.getSafeUserId(request.userPrefix));
|
||||||
}).then(this.mapAppservice);
|
return this.mapAppservice(appservice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path(":appserviceId/users")
|
@Path(":appserviceId/users")
|
||||||
public getUsers(@QueryParam("scalar_token") scalarToken: string, @PathParam("appserviceId") asId: string): Promise<UserResponse[]> {
|
public async getUsers(@QueryParam("scalar_token") scalarToken: string, @PathParam("appserviceId") asId: string): Promise<UserResponse[]> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return AppserviceStore.getUsers(asId);
|
return (await AppserviceStore.getUsers(asId)).map(u => this.mapUser(u));
|
||||||
}).then(users => {
|
|
||||||
return users.map(this.mapUser);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path(":appserviceId/users/register")
|
@Path(":appserviceId/users/register")
|
||||||
public registerUser(@QueryParam("scalar_token") scalarToken: string, @PathParam("appserviceId") asId: string, request: NewUserRequest): Promise<UserResponse> {
|
public async registerUser(@QueryParam("scalar_token") scalarToken: string, @PathParam("appserviceId") asId: string, request: NewUserRequest): Promise<UserResponse> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return AppserviceStore.registerUser(asId, request.userId);
|
|
||||||
}).then(this.mapUser);
|
const user = await AppserviceStore.registerUser(asId, request.userId);
|
||||||
|
return this.mapUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
private mapAppservice(as: AppService): AppserviceResponse {
|
private mapAppservice(as: AppService): AppserviceResponse {
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { ApiError } from "../ApiError";
|
import { ApiError } from "../ApiError";
|
||||||
import { DimensionAdminService } from "./DimensionAdminService";
|
import { DimensionAdminService } from "./DimensionAdminService";
|
||||||
import { DimensionIntegrationsService, IntegrationsResponse } from "./DimensionIntegrationsService";
|
import { DimensionIntegrationsService, IntegrationsResponse } from "./DimensionIntegrationsService";
|
||||||
import { WidgetStore } from "../../db/WidgetStore";
|
import { WidgetStore } from "../../db/WidgetStore";
|
||||||
import { CACHE_INTEGRATIONS, Cache } from "../../MemoryCache";
|
import { Cache, CACHE_INTEGRATIONS } from "../../MemoryCache";
|
||||||
|
|
||||||
interface SetEnabledRequest {
|
interface SetEnabledRequest {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@ -19,29 +18,33 @@ export class DimensionIntegrationsAdminService {
|
|||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path(":category/:type/options")
|
@Path(":category/:type/options")
|
||||||
public setOptions(@QueryParam("scalar_token") scalarToken: string, @PathParam("category") category: string, @PathParam("type") type: string, body: SetOptionsRequest): Promise<any> {
|
public async setOptions(@QueryParam("scalar_token") scalarToken: string, @PathParam("category") category: string, @PathParam("type") type: string, body: SetOptionsRequest): Promise<any> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
if (category === "widget") {
|
|
||||||
return WidgetStore.setOptions(type, body.options);
|
if (category === "widget") await WidgetStore.setOptions(type, body.options);
|
||||||
} else throw new ApiError(400, "Unrecongized category");
|
else throw new ApiError(400, "Unrecognized category");
|
||||||
}).then(() => Cache.for(CACHE_INTEGRATIONS).clear());
|
|
||||||
|
Cache.for(CACHE_INTEGRATIONS).clear();
|
||||||
|
return {}; // 200 OK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path(":category/:type/enabled")
|
@Path(":category/:type/enabled")
|
||||||
public setEnabled(@QueryParam("scalar_token") scalarToken: string, @PathParam("category") category: string, @PathParam("type") type: string, body: SetEnabledRequest): Promise<any> {
|
public async setEnabled(@QueryParam("scalar_token") scalarToken: string, @PathParam("category") category: string, @PathParam("type") type: string, body: SetEnabledRequest): Promise<any> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
if (category === "widget") {
|
|
||||||
return WidgetStore.setEnabled(type, body.enabled);
|
if (category === "widget") await WidgetStore.setEnabled(type, body.enabled);
|
||||||
} else throw new ApiError(400, "Unrecongized category");
|
else throw new ApiError(400, "Unrecognized category");
|
||||||
}).then(() => Cache.for(CACHE_INTEGRATIONS).clear());
|
|
||||||
|
Cache.for(CACHE_INTEGRATIONS).clear();
|
||||||
|
return {}; // 200 OK
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("all")
|
@Path("all")
|
||||||
public getAllIntegrations(@QueryParam("scalar_token") scalarToken: string): Promise<IntegrationsResponse> {
|
public async getAllIntegrations(@QueryParam("scalar_token") scalarToken: string): Promise<IntegrationsResponse> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return DimensionIntegrationsService.getIntegrations(null);
|
return DimensionIntegrationsService.getIntegrations(null);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,7 @@
|
|||||||
import { GET, Path, PathParam, QueryParam } from "typescript-rest";
|
import { GET, Path, PathParam, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { ScalarService } from "../scalar/ScalarService";
|
import { ScalarService } from "../scalar/ScalarService";
|
||||||
import { Widget } from "../../integrations/Widget";
|
import { Widget } from "../../integrations/Widget";
|
||||||
import { CACHE_INTEGRATIONS, Cache } from "../../MemoryCache";
|
import { Cache, CACHE_INTEGRATIONS } from "../../MemoryCache";
|
||||||
import { Integration } from "../../integrations/Integration";
|
import { Integration } from "../../integrations/Integration";
|
||||||
import { ApiError } from "../ApiError";
|
import { ApiError } from "../ApiError";
|
||||||
import { WidgetStore } from "../../db/WidgetStore";
|
import { WidgetStore } from "../../db/WidgetStore";
|
||||||
@ -14,34 +13,27 @@ export interface IntegrationsResponse {
|
|||||||
@Path("/api/v1/dimension/integrations")
|
@Path("/api/v1/dimension/integrations")
|
||||||
export class DimensionIntegrationsService {
|
export class DimensionIntegrationsService {
|
||||||
|
|
||||||
public static getIntegrations(isEnabledCheck?: boolean): Promise<IntegrationsResponse> {
|
public static async getIntegrations(isEnabledCheck?: boolean): Promise<IntegrationsResponse> {
|
||||||
const cachedResponse = Cache.for(CACHE_INTEGRATIONS).get("integrations_" + isEnabledCheck);
|
const cachedWidgets = Cache.for(CACHE_INTEGRATIONS).get("integrations_" + isEnabledCheck);
|
||||||
if (cachedResponse) {
|
if (cachedWidgets) {
|
||||||
return cachedResponse;
|
return {widgets: cachedWidgets};
|
||||||
}
|
}
|
||||||
const response = <IntegrationsResponse>{
|
|
||||||
widgets: [],
|
|
||||||
};
|
|
||||||
return Promise.resolve()
|
|
||||||
.then(() => WidgetStore.listAll(isEnabledCheck))
|
|
||||||
.then(widgets => response.widgets = widgets)
|
|
||||||
|
|
||||||
// Cache and return response
|
const widgets = await WidgetStore.listAll(isEnabledCheck);
|
||||||
.then(() => Cache.for(CACHE_INTEGRATIONS).put("integrations_" + isEnabledCheck, response))
|
Cache.for(CACHE_INTEGRATIONS).put("integrations_" + isEnabledCheck, widgets);
|
||||||
.then(() => response);
|
return {widgets: widgets};
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("enabled")
|
@Path("enabled")
|
||||||
public getEnabledIntegrations(@QueryParam("scalar_token") scalarToken: string): Promise<IntegrationsResponse> {
|
public async getEnabledIntegrations(@QueryParam("scalar_token") scalarToken: string): Promise<IntegrationsResponse> {
|
||||||
return ScalarService.getTokenOwner(scalarToken).then(_userId => {
|
await ScalarService.getTokenOwner(scalarToken);
|
||||||
return DimensionIntegrationsService.getIntegrations(true);
|
return DimensionIntegrationsService.getIntegrations(true);
|
||||||
}, ScalarService.invalidTokenErrorHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("room/:roomId")
|
@Path("room/:roomId")
|
||||||
public getIntegrationsInRoom(@QueryParam("scalar_token") scalarToken: string, @PathParam("roomId") roomId: string): Promise<IntegrationsResponse> {
|
public async getIntegrationsInRoom(@QueryParam("scalar_token") scalarToken: string, @PathParam("roomId") roomId: string): Promise<IntegrationsResponse> {
|
||||||
console.log(roomId);
|
console.log(roomId);
|
||||||
// TODO: Other integrations
|
// TODO: Other integrations
|
||||||
return this.getEnabledIntegrations(scalarToken);
|
return this.getEnabledIntegrations(scalarToken);
|
||||||
@ -49,18 +41,15 @@ export class DimensionIntegrationsService {
|
|||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path(":category/:type")
|
@Path(":category/:type")
|
||||||
public getIntegration(@PathParam("category") category: string, @PathParam("type") type: string): Promise<Integration> {
|
public async getIntegration(@PathParam("category") category: string, @PathParam("type") type: string): Promise<Integration> {
|
||||||
// This is intentionally an unauthed endpoint to ensure we can use it in widgets
|
// This is intentionally an unauthed endpoint to ensure we can use it in widgets
|
||||||
return DimensionIntegrationsService.getIntegrations(true).then(response => {
|
const integrationsResponse = await DimensionIntegrationsService.getIntegrations(true);
|
||||||
for (const key of Object.keys(response)) {
|
for (const key in integrationsResponse) {
|
||||||
for (const integration of <Integration[]>response[key]) {
|
for (const integration of integrationsResponse[key]) {
|
||||||
if (integration.category === category && integration.type === type) {
|
if (integration.category === category && integration.type === type) return integration;
|
||||||
return integration;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ApiError(404, "Integration not found");
|
throw new ApiError(404, "Integration not found");
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { DimensionAdminService } from "./DimensionAdminService";
|
import { DimensionAdminService } from "./DimensionAdminService";
|
||||||
import { Cache, CACHE_NEB } from "../../MemoryCache";
|
import { Cache, CACHE_NEB } from "../../MemoryCache";
|
||||||
import { NebStore } from "../../db/NebStore";
|
import { NebStore } from "../../db/NebStore";
|
||||||
@ -26,66 +25,66 @@ export class DimensionNebAdminService {
|
|||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("all")
|
@Path("all")
|
||||||
public getNebConfigs(@QueryParam("scalar_token") scalarToken: string): Promise<NebConfig[]> {
|
public async getNebConfigs(@QueryParam("scalar_token") scalarToken: string): Promise<NebConfig[]> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
|
|
||||||
const cachedConfigs = Cache.for(CACHE_NEB).get("configurations");
|
const cachedConfigs = Cache.for(CACHE_NEB).get("configurations");
|
||||||
if (cachedConfigs) return cachedConfigs;
|
if (cachedConfigs) return cachedConfigs;
|
||||||
|
|
||||||
return NebStore.getAllConfigs().then(configs => {
|
const configs = await NebStore.getAllConfigs();
|
||||||
Cache.for(CACHE_NEB).put("configurations", configs);
|
Cache.for(CACHE_NEB).put("configurations", configs);
|
||||||
return configs;
|
return configs;
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path(":id/config")
|
@Path(":id/config")
|
||||||
public getNebConfig(@QueryParam("scalar_token") scalarToken: string, @PathParam("id") nebId: number): Promise<NebConfig> {
|
public async getNebConfig(@QueryParam("scalar_token") scalarToken: string, @PathParam("id") nebId: number): Promise<NebConfig> {
|
||||||
return this.getNebConfigs(scalarToken).then(configs => {
|
const configs = await this.getNebConfigs(scalarToken); // does auth for us
|
||||||
for (const config of configs) {
|
const firstConfig = configs.filter(c => c.id === nebId)[0];
|
||||||
if (config.id === nebId) return config;
|
if (!firstConfig) throw new ApiError(404, "Configuration not found");
|
||||||
}
|
return firstConfig;
|
||||||
|
|
||||||
throw new ApiError(404, "Configuration not found");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path(":id/integration/:type/enabled")
|
@Path(":id/integration/:type/enabled")
|
||||||
public setIntegrationEnabled(@QueryParam("scalar_token") scalarToken: string, @PathParam("id") nebId: number, @PathParam("type") integrationType: string, request: SetEnabledRequest): Promise<any> {
|
public async setIntegrationEnabled(@QueryParam("scalar_token") scalarToken: string, @PathParam("id") nebId: number, @PathParam("type") integrationType: string, request: SetEnabledRequest): Promise<any> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return NebStore.getOrCreateIntegration(nebId, integrationType);
|
|
||||||
}).then(integration => {
|
const integration = await NebStore.getOrCreateIntegration(nebId, integrationType);
|
||||||
integration.isEnabled = request.enabled;
|
integration.isEnabled = request.enabled;
|
||||||
return integration.save();
|
await integration.save();
|
||||||
}).then(() => Cache.for(CACHE_NEB).clear());
|
Cache.for(CACHE_NEB).clear();
|
||||||
|
|
||||||
|
return {}; // 200 OK
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("new/upstream")
|
@Path("new/upstream")
|
||||||
public newConfigForUpstream(@QueryParam("scalar_token") scalarToken: string, request: CreateWithUpstream): Promise<NebConfig> {
|
public async newConfigForUpstream(@QueryParam("scalar_token") scalarToken: string, request: CreateWithUpstream): Promise<NebConfig> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return NebStore.createForUpstream(request.upstreamId).catch(err => {
|
|
||||||
|
try {
|
||||||
|
const neb = await NebStore.createForUpstream(request.upstreamId);
|
||||||
|
Cache.for(CACHE_NEB).clear();
|
||||||
|
return neb;
|
||||||
|
} catch (err) {
|
||||||
LogService.error("DimensionNebAdminService", err);
|
LogService.error("DimensionNebAdminService", err);
|
||||||
throw new ApiError(500, "Error creating go-neb instance");
|
throw new ApiError(500, "Error creating go-neb instance");
|
||||||
});
|
}
|
||||||
}).then(config => {
|
|
||||||
Cache.for(CACHE_NEB).clear();
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("new/appservice")
|
@Path("new/appservice")
|
||||||
public newConfigForAppservice(@QueryParam("scalar_token") scalarToken: string, request: CreateWithAppservice): Promise<NebConfig> {
|
public async newConfigForAppservice(@QueryParam("scalar_token") scalarToken: string, request: CreateWithAppservice): Promise<NebConfig> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return NebStore.createForAppservice(request.appserviceId, request.adminUrl).catch(err => {
|
|
||||||
|
try {
|
||||||
|
const neb = await NebStore.createForAppservice(request.appserviceId, request.adminUrl);
|
||||||
|
Cache.for(CACHE_NEB).clear();
|
||||||
|
return neb;
|
||||||
|
} catch (err) {
|
||||||
LogService.error("DimensionNebAdminService", err);
|
LogService.error("DimensionNebAdminService", err);
|
||||||
throw new ApiError(500, "Error creating go-neb instance");
|
throw new ApiError(500, "Error creating go-neb instance");
|
||||||
});
|
}
|
||||||
}).then(config => {
|
|
||||||
Cache.for(CACHE_NEB).clear();
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
import { GET, Path, POST, QueryParam } from "typescript-rest";
|
import { GET, Path, POST, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { DimensionAdminService } from "./DimensionAdminService";
|
import { DimensionAdminService } from "./DimensionAdminService";
|
||||||
import { Cache, CACHE_UPSTREAM } from "../../MemoryCache";
|
import { Cache, CACHE_UPSTREAM } from "../../MemoryCache";
|
||||||
import Upstream from "../../db/models/Upstream";
|
import Upstream from "../../db/models/Upstream";
|
||||||
@ -24,33 +23,32 @@ export class DimensionUpstreamAdminService {
|
|||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("all")
|
@Path("all")
|
||||||
public getUpstreams(@QueryParam("scalar_token") scalarToken: string): Promise<UpstreamRepsonse[]> {
|
public async getUpstreams(@QueryParam("scalar_token") scalarToken: string): Promise<UpstreamRepsonse[]> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
|
|
||||||
const cachedUpstreams = Cache.for(CACHE_UPSTREAM).get("upstreams");
|
const cachedUpstreams = Cache.for(CACHE_UPSTREAM).get("upstreams");
|
||||||
if (cachedUpstreams) return cachedUpstreams;
|
if (cachedUpstreams) return cachedUpstreams;
|
||||||
return Upstream.findAll().then(upstreams => {
|
|
||||||
const mapped = upstreams.map(this.mapUpstream);
|
|
||||||
Cache.for(CACHE_UPSTREAM).put("upstreams", mapped);
|
|
||||||
|
|
||||||
|
const upstreams = await Upstream.findAll();
|
||||||
|
const mapped = upstreams.map(u => this.mapUpstream(u));
|
||||||
|
Cache.for(CACHE_UPSTREAM).put("upstreams", mapped);
|
||||||
return mapped;
|
return mapped;
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("new")
|
@Path("new")
|
||||||
public createUpstream(@QueryParam("scalar_token") scalarToken: string, request: NewUpstreamRequest): Promise<UpstreamRepsonse> {
|
public async createUpstream(@QueryParam("scalar_token") scalarToken: string, request: NewUpstreamRequest): Promise<UpstreamRepsonse> {
|
||||||
return DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken).then(_userId => {
|
await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return Upstream.create({
|
|
||||||
|
const upstream = await Upstream.create({
|
||||||
name: request.name,
|
name: request.name,
|
||||||
type: request.type,
|
type: request.type,
|
||||||
scalarUrl: request.scalarUrl,
|
scalarUrl: request.scalarUrl,
|
||||||
apiUrl: request.apiUrl,
|
apiUrl: request.apiUrl,
|
||||||
});
|
});
|
||||||
}).then(upstream => {
|
|
||||||
Cache.for(CACHE_UPSTREAM).clear();
|
Cache.for(CACHE_UPSTREAM).clear();
|
||||||
return this.mapUpstream(upstream);
|
return this.mapUpstream(upstream);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private mapUpstream(upstream: Upstream): UpstreamRepsonse {
|
private mapUpstream(upstream: Upstream): UpstreamRepsonse {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { GET, Path, PathParam, PUT, QueryParam } from "typescript-rest";
|
import { GET, Path, PathParam, PUT, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { ApiError } from "../ApiError";
|
import { ApiError } from "../ApiError";
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import { SimplifiedMatrixEvent } from "../../models/MatrixEvent";
|
import { SimplifiedMatrixEvent } from "../../models/MatrixEvent";
|
||||||
@ -18,48 +17,58 @@ export class MatrixAppServiceApiService {
|
|||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/transactions/:txnId")
|
@Path("/transactions/:txnId")
|
||||||
public onTransaction(@QueryParam("access_token") homeserverToken: string, @PathParam("txnId") txnId: string, _txn: AppServiceTransaction): Promise<any> {
|
public async onTransaction(@QueryParam("access_token") homeserverToken: string, @PathParam("txnId") txnId: string, _txn: AppServiceTransaction): Promise<any> {
|
||||||
return AppserviceStore.getByHomeserverToken(homeserverToken).then(appservice => {
|
try {
|
||||||
|
const appservice = await AppserviceStore.getByHomeserverToken(homeserverToken);
|
||||||
|
|
||||||
// We don't handle the transaction at all - we just don't want the homeserver to consider us down
|
// We don't handle the transaction at all - we just don't want the homeserver to consider us down
|
||||||
LogService.verbose("MatrixAppServiceApiService", "Accepting transaction " + txnId + " for appservice " + appservice.id + " blindly");
|
LogService.verbose("MatrixAppServiceApiService", "Accepting transaction " + txnId + " for appservice " + appservice.id + " blindly");
|
||||||
return {}; // 200 OK
|
return {}; // 200 OK
|
||||||
}, err => {
|
} catch (err) {
|
||||||
LogService.error("MatrixAppServiceApiService", err);
|
LogService.error("MatrixAppServiceApiService", err);
|
||||||
throw new ApiError(403, {errcode: "M_FORBIDDEN"});
|
throw new ApiError(403, {errcode: "M_FORBIDDEN"});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/room/:alias")
|
@Path("/room/:alias")
|
||||||
public getRoom(@QueryParam("access_token") homeserverToken: string, @PathParam("alias") roomAlias: string): Promise<any> {
|
public async getRoom(@QueryParam("access_token") homeserverToken: string, @PathParam("alias") roomAlias: string): Promise<any> {
|
||||||
return AppserviceStore.getByHomeserverToken(homeserverToken).then(appservice => {
|
try {
|
||||||
|
const appservice = await AppserviceStore.getByHomeserverToken(homeserverToken);
|
||||||
|
|
||||||
// We don't support room lookups
|
// We don't support room lookups
|
||||||
LogService.verbose("MatrixAppServiceApiService", "404ing request for room " + roomAlias + " at appservice " + appservice.id);
|
LogService.verbose("MatrixAppServiceApiService", "404ing request for room " + roomAlias + " at appservice " + appservice.id);
|
||||||
throw new ApiError(404, {errcode: "IO.T2BOT.DIMENSION.ROOMS_NOT_SUPPORTED"});
|
throw new ApiError(404, {errcode: "IO.T2BOT.DIMENSION.ROOMS_NOT_SUPPORTED"});
|
||||||
}, err => {
|
} catch (err) {
|
||||||
|
if (err instanceof ApiError) throw err;
|
||||||
LogService.error("MatrixAppServiceApiService", err);
|
LogService.error("MatrixAppServiceApiService", err);
|
||||||
throw new ApiError(403, {errcode: "M_FORBIDDEN"});
|
throw new ApiError(403, {errcode: "M_FORBIDDEN"});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/user/:userId")
|
@Path("/user/:userId")
|
||||||
public getUser(@QueryParam("access_token") homeserverToken: string, @PathParam("userId") userId: string): Promise<any> {
|
public async getUser(@QueryParam("access_token") homeserverToken: string, @PathParam("userId") userId: string): Promise<any> {
|
||||||
return AppserviceStore.getByHomeserverToken(homeserverToken).then(appservice => {
|
try {
|
||||||
return AppserviceStore.getUser(appservice.id, userId).catch(err => {
|
const appservice = await AppserviceStore.getByHomeserverToken(homeserverToken);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await AppserviceStore.getUser(appservice.id, userId);
|
||||||
|
return {
|
||||||
|
userId: user.id,
|
||||||
|
displayName: user.displayName,
|
||||||
|
avatarUrl: user.avatarUrl,
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
LogService.error("MatrixAppServiceApiService", err);
|
LogService.error("MatrixAppServiceApiService", err);
|
||||||
throw new ApiError(404, {errcode: "IO.T2BOT.DIMENSION.USER_NOT_FOUND"});
|
throw new ApiError(404, {errcode: "IO.T2BOT.DIMENSION.USER_NOT_FOUND"});
|
||||||
});
|
}
|
||||||
}, err => {
|
} catch (err) {
|
||||||
|
if (err instanceof ApiError) throw err;
|
||||||
|
|
||||||
LogService.error("MatrixAppServiceApiService", err);
|
LogService.error("MatrixAppServiceApiService", err);
|
||||||
throw new ApiError(403, {errcode: "M_FORBIDDEN"});
|
throw new ApiError(403, {errcode: "M_FORBIDDEN"});
|
||||||
}).then(appserviceUser => {
|
}
|
||||||
return {
|
|
||||||
userId: appserviceUser.id,
|
|
||||||
displayName: appserviceUser.displayName,
|
|
||||||
avatarUrl: appserviceUser.avatarUrl,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
import { GET, Path, POST, QueryParam } from "typescript-rest";
|
import { GET, Path, POST, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { MatrixOpenIdClient } from "../../matrix/MatrixOpenIdClient";
|
import { MatrixOpenIdClient } from "../../matrix/MatrixOpenIdClient";
|
||||||
import Upstream from "../../db/models/Upstream";
|
import Upstream from "../../db/models/Upstream";
|
||||||
import { ScalarClient } from "../../scalar/ScalarClient";
|
import { ScalarClient } from "../../scalar/ScalarClient";
|
||||||
@ -23,80 +22,62 @@ interface RegisterRequest {
|
|||||||
@Path("/api/v1/scalar")
|
@Path("/api/v1/scalar")
|
||||||
export class ScalarService {
|
export class ScalarService {
|
||||||
|
|
||||||
public static getTokenOwner(scalarToken: string, ignoreUpstreams?: boolean): Promise<string> {
|
public static async getTokenOwner(scalarToken: string, ignoreUpstreams?: boolean): Promise<string> {
|
||||||
const cachedUserId = Cache.for(CACHE_SCALAR_ACCOUNTS).get(scalarToken);
|
const cachedUserId = Cache.for(CACHE_SCALAR_ACCOUNTS).get(scalarToken);
|
||||||
if (cachedUserId) return Promise.resolve(cachedUserId);
|
if (cachedUserId) return cachedUserId;
|
||||||
|
|
||||||
|
const user = await ScalarStore.getTokenOwner(scalarToken, ignoreUpstreams);
|
||||||
|
if (!user) throw new ApiError(401, "Invalid token");
|
||||||
|
|
||||||
return ScalarStore.getTokenOwner(scalarToken, ignoreUpstreams).then(user => {
|
|
||||||
if (!user) return Promise.reject("Invalid token");
|
|
||||||
Cache.for(CACHE_SCALAR_ACCOUNTS).put(scalarToken, user.userId, 30 * 60 * 1000); // 30 minutes
|
Cache.for(CACHE_SCALAR_ACCOUNTS).put(scalarToken, user.userId, 30 * 60 * 1000); // 30 minutes
|
||||||
return Promise.resolve(user.userId);
|
return user.userId;
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static invalidTokenErrorHandler(error: any): any {
|
|
||||||
if (error !== "Invalid token") {
|
|
||||||
LogService.error("ScalarWidgetService", "Error processing request");
|
|
||||||
LogService.error("ScalarWidgetService", error);
|
|
||||||
}
|
|
||||||
throw new ApiError(401, {message: "Invalid token"});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("register")
|
@Path("register")
|
||||||
public register(request: RegisterRequest): Promise<ScalarRegisterResponse> {
|
public async register(request: RegisterRequest): Promise<ScalarRegisterResponse> {
|
||||||
let userId = null;
|
|
||||||
const mxClient = new MatrixOpenIdClient(<OpenId>request);
|
const mxClient = new MatrixOpenIdClient(<OpenId>request);
|
||||||
return mxClient.getUserId().then(mxUserId => {
|
const mxUserId = await mxClient.getUserId();
|
||||||
userId = mxUserId;
|
|
||||||
return User.findByPrimary(userId).then(user => {
|
const user = await User.findByPrimary(mxUserId);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
// There's a small chance we'll get a validation error because of:
|
// There's a small chance we'll get a validation error because of:
|
||||||
// https://github.com/vector-im/riot-web/issues/5846
|
// https://github.com/vector-im/riot-web/issues/5846
|
||||||
LogService.verbose("ScalarService", "User " + userId + " never seen before - creating");
|
LogService.verbose("ScalarService", "User " + mxUserId + " never seen before - creating");
|
||||||
return User.create({userId: userId});
|
await User.create({userId: mxUserId});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}).then(() => {
|
const upstreams = await Upstream.findAll();
|
||||||
return Upstream.findAll();
|
await Promise.all(upstreams.map(async upstream => {
|
||||||
}).then(upstreams => {
|
const tokens = await UserScalarToken.findAll({where: {userId: mxUserId, upstreamId: upstream.id}});
|
||||||
return Promise.all(upstreams.map(u => {
|
|
||||||
return UserScalarToken.findAll({where: {userId: userId, upstreamId: u.id}}).then(tokens => {
|
|
||||||
if (!tokens || tokens.length === 0) {
|
if (!tokens || tokens.length === 0) {
|
||||||
LogService.info("ScalarService", "Registering " + userId + " for token at upstream " + u.id + " (" + u.name + ")");
|
LogService.info("ScalarService", "Registering " + mxUserId + " for a token at upstream " + upstream.id + " (" + upstream.name + ")");
|
||||||
const client = new ScalarClient(u);
|
const client = new ScalarClient(upstream);
|
||||||
return client.register(<OpenId>request).then(registerResponse => {
|
const response = await client.register(<OpenId>request);
|
||||||
return UserScalarToken.create({
|
return UserScalarToken.create({
|
||||||
userId: userId,
|
userId: mxUserId,
|
||||||
scalarToken: registerResponse.scalar_token,
|
scalarToken: response.scalar_token,
|
||||||
isDimensionToken: false,
|
isDimensionToken: false,
|
||||||
upstreamId: u.id,
|
upstreamId: upstream.id,
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
}).then(() => {
|
|
||||||
const dimensionToken = randomString({length: 25});
|
const dimensionToken = randomString({length: 25});
|
||||||
return UserScalarToken.create({
|
const dimensionScalarToken = await UserScalarToken.create({
|
||||||
userId: userId,
|
userId: mxUserId,
|
||||||
scalarToken: dimensionToken,
|
scalarToken: dimensionToken,
|
||||||
isDimensionToken: true,
|
isDimensionToken: true,
|
||||||
});
|
});
|
||||||
}).then(userToken => {
|
|
||||||
return {scalar_token: userToken.scalarToken};
|
return {scalar_token: dimensionScalarToken.scalarToken};
|
||||||
}).catch(err => {
|
|
||||||
LogService.error("ScalarService", err);
|
|
||||||
throw new ApiError(401, {message: "Failed to authenticate user"});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("account")
|
@Path("account")
|
||||||
public getAccount(@QueryParam("scalar_token") scalarToken: string): Promise<ScalarAccountResponse> {
|
public async getAccount(@QueryParam("scalar_token") scalarToken: string): Promise<ScalarAccountResponse> {
|
||||||
return ScalarService.getTokenOwner(scalarToken).then(userId => {
|
const userId = await ScalarService.getTokenOwner(scalarToken);
|
||||||
return {user_id: userId};
|
return {user_id: userId};
|
||||||
}, ScalarService.invalidTokenErrorHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
import { GET, Path, QueryParam } from "typescript-rest";
|
import { GET, Path, QueryParam } from "typescript-rest";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import { CACHE_WIDGET_TITLES, Cache } from "../../MemoryCache";
|
import { Cache, CACHE_WIDGET_TITLES } from "../../MemoryCache";
|
||||||
import { MatrixLiteClient } from "../../matrix/MatrixLiteClient";
|
import { MatrixLiteClient } from "../../matrix/MatrixLiteClient";
|
||||||
import config from "../../config";
|
import config from "../../config";
|
||||||
import { ScalarService } from "./ScalarService";
|
import { ScalarService } from "./ScalarService";
|
||||||
@ -22,15 +21,21 @@ interface UrlPreviewResponse {
|
|||||||
@Path("/api/v1/scalar/widgets")
|
@Path("/api/v1/scalar/widgets")
|
||||||
export class ScalarWidgetService {
|
export class ScalarWidgetService {
|
||||||
|
|
||||||
private static getUrlTitle(url: string): Promise<UrlPreviewResponse> {
|
@GET
|
||||||
|
@Path("title_lookup")
|
||||||
|
public async titleLookup(@QueryParam("scalar_token") scalarToken: string, @QueryParam("curl") url: string): Promise<UrlPreviewResponse> {
|
||||||
|
await ScalarService.getTokenOwner(scalarToken);
|
||||||
|
|
||||||
const cachedResult = Cache.for(CACHE_WIDGET_TITLES).get(url);
|
const cachedResult = Cache.for(CACHE_WIDGET_TITLES).get(url);
|
||||||
if (cachedResult) {
|
if (cachedResult) {
|
||||||
cachedResult.cached_response = true;
|
cachedResult.cached_response = true;
|
||||||
return Promise.resolve(cachedResult);
|
return cachedResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken);
|
const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken);
|
||||||
return client.getUrlPreview(url).then(preview => {
|
|
||||||
|
try {
|
||||||
|
const preview = await client.getUrlPreview(url);
|
||||||
const expirationTime = 60 * 80 * 1000; // 1 hour
|
const expirationTime = 60 * 80 * 1000; // 1 hour
|
||||||
const expirationAsString = moment().add(expirationTime, "milliseconds").toISOString();
|
const expirationAsString = moment().add(expirationTime, "milliseconds").toISOString();
|
||||||
const cachedItem = {
|
const cachedItem = {
|
||||||
@ -44,7 +49,7 @@ export class ScalarWidgetService {
|
|||||||
};
|
};
|
||||||
Cache.for(CACHE_WIDGET_TITLES).put(url, cachedItem, expirationTime);
|
Cache.for(CACHE_WIDGET_TITLES).put(url, cachedItem, expirationTime);
|
||||||
return cachedItem;
|
return cachedItem;
|
||||||
}).catch(err => {
|
} catch (err) {
|
||||||
LogService.error("ScalarWidgetService", "Error getting URL preview");
|
LogService.error("ScalarWidgetService", "Error getting URL preview");
|
||||||
LogService.error("ScalarWidgetService", err);
|
LogService.error("ScalarWidgetService", err);
|
||||||
return <UrlPreviewResponse>{
|
return <UrlPreviewResponse>{
|
||||||
@ -53,20 +58,12 @@ export class ScalarWidgetService {
|
|||||||
page_title_cache_item: {
|
page_title_cache_item: {
|
||||||
expires: null,
|
expires: null,
|
||||||
cached_response_err: "Failed to get URL preview",
|
cached_response_err: "Failed to get URL preview",
|
||||||
cached_title: null
|
cached_title: null,
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
message: "Failed to get URL preview",
|
message: "Failed to get URL preview",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("title_lookup")
|
|
||||||
public titleLookup(@QueryParam("scalar_token") scalarToken: string, @QueryParam("curl") url: string): Promise<UrlPreviewResponse> {
|
|
||||||
return ScalarService.getTokenOwner(scalarToken).then(_userId => {
|
|
||||||
return ScalarWidgetService.getUrlTitle(url);
|
|
||||||
}, ScalarService.invalidTokenErrorHandler);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,13 @@
|
|||||||
import AppService from "./models/AppService";
|
import AppService from "./models/AppService";
|
||||||
import AppServiceUser from "./models/AppServiceUser";
|
import AppServiceUser from "./models/AppServiceUser";
|
||||||
import * as randomString from "random-string";
|
import * as randomString from "random-string";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { MatrixAppserviceClient } from "../matrix/MatrixAppserviceClient";
|
import { MatrixAppserviceClient } from "../matrix/MatrixAppserviceClient";
|
||||||
import { resolveIfExists } from "./DimensionStore";
|
import { resolveIfExists } from "./DimensionStore";
|
||||||
import config from "../config";
|
import config from "../config";
|
||||||
|
|
||||||
export class AppserviceStore {
|
export class AppserviceStore {
|
||||||
|
|
||||||
public static create(userPrefix: string): Promise<AppService> {
|
public static async create(userPrefix: string): Promise<AppService> {
|
||||||
const id = "dimension-" + randomString({length: 25});
|
const id = "dimension-" + randomString({length: 25});
|
||||||
const asToken = randomString({length: 100});
|
const asToken = randomString({length: 100});
|
||||||
const hsToken = randomString({length: 100});
|
const hsToken = randomString({length: 100});
|
||||||
@ -21,15 +20,15 @@ export class AppserviceStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getUser(appserviceId: string, userId: string): Promise<AppServiceUser> {
|
public static async getUser(appserviceId: string, userId: string): Promise<AppServiceUser> {
|
||||||
return AppServiceUser.findOne({where: {appserviceId: appserviceId, id: userId}}).then(resolveIfExists);
|
return AppServiceUser.findOne({where: {appserviceId: appserviceId, id: userId}}).then(resolveIfExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getByHomeserverToken(hsToken: string): Promise<AppService> {
|
public static async getByHomeserverToken(hsToken: string): Promise<AppService> {
|
||||||
return AppService.findOne({where: {hsToken: hsToken}}).then(resolveIfExists);
|
return AppService.findOne({where: {hsToken: hsToken}}).then(resolveIfExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getAllByUserPrefix(userPrefix: string): Promise<AppService[]> {
|
public static async getAllByUserPrefix(userPrefix: string): Promise<AppService[]> {
|
||||||
return AppService.findAll({where: {userPrefix: userPrefix}});
|
return AppService.findAll({where: {userPrefix: userPrefix}});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,11 +38,11 @@ export class AppserviceStore {
|
|||||||
return userIdOrPrefix.toLowerCase().replace(/[^a-z0-9._\-=]/g, '.');
|
return userIdOrPrefix.toLowerCase().replace(/[^a-z0-9._\-=]/g, '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getUsers(appserviceId: string): Promise<AppServiceUser[]> {
|
public static async getUsers(appserviceId: string): Promise<AppServiceUser[]> {
|
||||||
return AppServiceUser.findAll({where: {appserviceId: appserviceId}});
|
return AppServiceUser.findAll({where: {appserviceId: appserviceId}});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static registerUser(appserviceId: string, userId: string): Promise<AppServiceUser> {
|
public static async registerUser(appserviceId: string, userId: string): Promise<AppServiceUser> {
|
||||||
userId = AppserviceStore.getSafeUserId(userId);
|
userId = AppserviceStore.getSafeUserId(userId);
|
||||||
return AppService.findOne({where: {id: appserviceId}}).then(resolveIfExists).then(appservice => {
|
return AppService.findOne({where: {id: appserviceId}}).then(resolveIfExists).then(appservice => {
|
||||||
const client = new MatrixAppserviceClient(config.homeserver.name, appservice);
|
const client = new MatrixAppserviceClient(config.homeserver.name, appservice);
|
||||||
|
@ -4,7 +4,6 @@ import { LogService } from "matrix-js-snippets";
|
|||||||
import User from "./models/User";
|
import User from "./models/User";
|
||||||
import UserScalarToken from "./models/UserScalarToken";
|
import UserScalarToken from "./models/UserScalarToken";
|
||||||
import Upstream from "./models/Upstream";
|
import Upstream from "./models/Upstream";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import WidgetRecord from "./models/WidgetRecord";
|
import WidgetRecord from "./models/WidgetRecord";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as Umzug from "umzug";
|
import * as Umzug from "umzug";
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as Promise from "bluebird";
|
|
||||||
import { resolveIfExists } from "./DimensionStore";
|
import { resolveIfExists } from "./DimensionStore";
|
||||||
import { NebConfig } from "../models/neb";
|
import { NebConfig } from "../models/neb";
|
||||||
import NebConfiguration from "./models/NebConfiguration";
|
import NebConfiguration from "./models/NebConfiguration";
|
||||||
@ -77,13 +76,13 @@ export class NebStore {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
public static getAllConfigs(): Promise<NebConfig[]> {
|
public static async getAllConfigs(): Promise<NebConfig[]> {
|
||||||
return NebConfiguration.findAll().then(configs => {
|
return NebConfiguration.findAll().then(configs => {
|
||||||
return Promise.all((configs || []).map(c => NebStore.getConfig(c.id)));
|
return Promise.all((configs || []).map(c => NebStore.getConfig(c.id)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getConfig(id: number): Promise<NebConfig> {
|
public static async getConfig(id: number): Promise<NebConfig> {
|
||||||
let nebConfig: NebConfiguration;
|
let nebConfig: NebConfiguration;
|
||||||
return NebConfiguration.findByPrimary(id).then(resolveIfExists).then(conf => {
|
return NebConfiguration.findByPrimary(id).then(resolveIfExists).then(conf => {
|
||||||
nebConfig = conf;
|
nebConfig = conf;
|
||||||
@ -95,7 +94,7 @@ export class NebStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createForUpstream(upstreamId: number): Promise<NebConfig> {
|
public static async createForUpstream(upstreamId: number): Promise<NebConfig> {
|
||||||
return Upstream.findByPrimary(upstreamId).then(resolveIfExists).then(upstream => {
|
return Upstream.findByPrimary(upstreamId).then(resolveIfExists).then(upstream => {
|
||||||
return NebConfiguration.create({
|
return NebConfiguration.create({
|
||||||
upstreamId: upstream.id,
|
upstreamId: upstream.id,
|
||||||
@ -105,7 +104,7 @@ export class NebStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createForAppservice(appserviceId: string, adminUrl: string): Promise<NebConfig> {
|
public static async createForAppservice(appserviceId: string, adminUrl: string): Promise<NebConfig> {
|
||||||
return AppService.findByPrimary(appserviceId).then(resolveIfExists).then(appservice => {
|
return AppService.findByPrimary(appserviceId).then(resolveIfExists).then(appservice => {
|
||||||
return NebConfiguration.create({
|
return NebConfiguration.create({
|
||||||
appserviceId: appservice.id,
|
appserviceId: appservice.id,
|
||||||
@ -116,7 +115,7 @@ export class NebStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getOrCreateIntegration(configurationId: number, integrationType: string): Promise<NebIntegration> {
|
public static async getOrCreateIntegration(configurationId: number, integrationType: string): Promise<NebIntegration> {
|
||||||
if (!NebStore.INTEGRATIONS[integrationType]) return Promise.reject(new Error("Integration not supported"));
|
if (!NebStore.INTEGRATIONS[integrationType]) return Promise.reject(new Error("Integration not supported"));
|
||||||
|
|
||||||
return NebConfiguration.findByPrimary(configurationId).then(resolveIfExists).then(config => {
|
return NebConfiguration.findByPrimary(configurationId).then(resolveIfExists).then(config => {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as Promise from "bluebird";
|
|
||||||
import UserScalarToken from "./models/UserScalarToken";
|
import UserScalarToken from "./models/UserScalarToken";
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import Upstream from "./models/Upstream";
|
import Upstream from "./models/Upstream";
|
||||||
@ -6,7 +5,7 @@ import User from "./models/User";
|
|||||||
|
|
||||||
export class ScalarStore {
|
export class ScalarStore {
|
||||||
|
|
||||||
public static doesUserHaveTokensForAllUpstreams(userId: string): Promise<boolean> {
|
public static async doesUserHaveTokensForAllUpstreams(userId: string): Promise<boolean> {
|
||||||
let upstreamTokenIds: number[] = [];
|
let upstreamTokenIds: number[] = [];
|
||||||
let hasDimensionToken = false;
|
let hasDimensionToken = false;
|
||||||
return UserScalarToken.findAll({where: {userId: userId}}).then(results => {
|
return UserScalarToken.findAll({where: {userId: userId}}).then(results => {
|
||||||
@ -30,7 +29,7 @@ export class ScalarStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getTokenOwner(scalarToken: string, ignoreUpstreams?: boolean): Promise<User> {
|
public static async getTokenOwner(scalarToken: string, ignoreUpstreams?: boolean): Promise<User> {
|
||||||
let user: User = null;
|
let user: User = null;
|
||||||
return UserScalarToken.findAll({
|
return UserScalarToken.findAll({
|
||||||
where: {isDimensionToken: true, scalarToken: scalarToken},
|
where: {isDimensionToken: true, scalarToken: scalarToken},
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
import * as Promise from "bluebird";
|
|
||||||
import WidgetRecord from "./models/WidgetRecord";
|
import WidgetRecord from "./models/WidgetRecord";
|
||||||
import { Widget } from "../integrations/Widget";
|
import { Widget } from "../integrations/Widget";
|
||||||
import { resolveIfExists } from "./DimensionStore";
|
import { resolveIfExists } from "./DimensionStore";
|
||||||
|
|
||||||
export class WidgetStore {
|
export class WidgetStore {
|
||||||
|
|
||||||
public static listAll(isEnabled?: boolean): Promise<Widget[]> {
|
public static async listAll(isEnabled?: boolean): Promise<Widget[]> {
|
||||||
let conditions = {};
|
let conditions = {};
|
||||||
if (isEnabled === true || isEnabled === false) conditions = {where: {isEnabled: isEnabled}};
|
if (isEnabled === true || isEnabled === false) conditions = {where: {isEnabled: isEnabled}};
|
||||||
return WidgetRecord.findAll(conditions).then(widgets => widgets.map(w => new Widget(w)));
|
return WidgetRecord.findAll(conditions).then(widgets => widgets.map(w => new Widget(w)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static setEnabled(type: string, isEnabled: boolean): Promise<any> {
|
public static async setEnabled(type: string, isEnabled: boolean): Promise<any> {
|
||||||
return WidgetRecord.findOne({where: {type: type}}).then(resolveIfExists).then(widget => {
|
return WidgetRecord.findOne({where: {type: type}}).then(resolveIfExists).then(widget => {
|
||||||
widget.isEnabled = isEnabled;
|
widget.isEnabled = isEnabled;
|
||||||
return widget.save();
|
return widget.save();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static setOptions(type: string, options: any): Promise<any> {
|
public static async setOptions(type: string, options: any): Promise<any> {
|
||||||
const optionsJson = JSON.stringify(options);
|
const optionsJson = JSON.stringify(options);
|
||||||
return WidgetRecord.findOne({where: {type: type}}).then(resolveIfExists).then(widget => {
|
return WidgetRecord.findOne({where: {type: type}}).then(resolveIfExists).then(widget => {
|
||||||
widget.optionsJson = optionsJson;
|
widget.optionsJson = optionsJson;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { QueryInterface } from "sequelize";
|
import { QueryInterface } from "sequelize";
|
||||||
import { DataType } from "sequelize-typescript";
|
import { DataType } from "sequelize-typescript";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
up: (queryInterface: QueryInterface) => {
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { QueryInterface } from "sequelize";
|
import { QueryInterface } from "sequelize";
|
||||||
import { DataType } from "sequelize-typescript";
|
import { DataType } from "sequelize-typescript";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
up: (queryInterface: QueryInterface) => {
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { QueryInterface } from "sequelize";
|
import { QueryInterface } from "sequelize";
|
||||||
import { DataType } from "sequelize-typescript";
|
import { DataType } from "sequelize-typescript";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
up: (queryInterface: QueryInterface) => {
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { QueryInterface } from "sequelize";
|
import { QueryInterface } from "sequelize";
|
||||||
import { DataType } from "sequelize-typescript";
|
import { DataType } from "sequelize-typescript";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
up: (queryInterface: QueryInterface) => {
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { QueryInterface } from "sequelize";
|
import { QueryInterface } from "sequelize";
|
||||||
import { DataType } from "sequelize-typescript";
|
import { DataType } from "sequelize-typescript";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
up: (queryInterface: QueryInterface) => {
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as Promise from "bluebird";
|
|
||||||
import { doFederatedApiCall } from "./helpers";
|
import { doFederatedApiCall } from "./helpers";
|
||||||
import AppService from "../db/models/AppService";
|
import AppService from "../db/models/AppService";
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as Promise from "bluebird";
|
|
||||||
import { doFederatedApiCall, getFederationUrl as getFedUrl } from "./helpers";
|
import { doFederatedApiCall, getFederationUrl as getFedUrl } from "./helpers";
|
||||||
|
|
||||||
export interface MatrixUrlPreview {
|
export interface MatrixUrlPreview {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as Promise from "bluebird";
|
|
||||||
import { doFederatedApiCall } from "./helpers";
|
import { doFederatedApiCall } from "./helpers";
|
||||||
import { OpenId } from "../models/OpenId";
|
import { OpenId } from "../models/OpenId";
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import * as dns from "dns-then";
|
import * as dns from "dns-then";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import { Cache, CACHE_FEDERATION } from "../MemoryCache";
|
import { Cache, CACHE_FEDERATION } from "../MemoryCache";
|
||||||
import * as request from "request";
|
import * as request from "request";
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { OpenId } from "../models/OpenId";
|
import { OpenId } from "../models/OpenId";
|
||||||
import { ScalarRegisterResponse } from "../models/ScalarResponses";
|
import { ScalarRegisterResponse } from "../models/ScalarResponses";
|
||||||
import * as Promise from "bluebird";
|
|
||||||
import * as request from "request";
|
import * as request from "request";
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import Upstream from "../db/models/Upstream";
|
import Upstream from "../db/models/Upstream";
|
||||||
|
Loading…
Reference in New Issue
Block a user