diff --git a/package.json b/package.json index 4a4b387..70b7098 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "scripts": { "start:web": "webpack-dev-server --inline --progress --port 8080 --host 0.0.0.0", "start:app": "npm run-script build && node build/app/index.js", - "build": "rimraf build && npm run-script build:web && npm run-script build:app", - "build:web": "webpack --progress --profile --bail", - "build:app": "tsc -p tsconfig-app.json", + "build": "npm run-script build:web && npm run-script build:app", + "build:web": "rimraf build/web && webpack --progress --profile --bail", + "build:app": "rimraf build/app && tsc -p tsconfig-app.json", "lint": "npm run-script lint:app && npm run-script lint:web", "lint:app": "tslint --project ./tsconfig-app.json -t stylish", "lint:web": "tslint --project ./tsconfig.json -t stylish" diff --git a/src/api/Webserver.ts b/src/api/Webserver.ts index 814a3f0..61729fd 100644 --- a/src/api/Webserver.ts +++ b/src/api/Webserver.ts @@ -20,7 +20,7 @@ export default class Webserver { } private loadRoutes() { - const apis = ["scalar", "dimension", "matrix"].map(a => path.join(__dirname, a, "*.js")); + const apis = ["scalar", "dimension", "admin", "matrix"].map(a => path.join(__dirname, a, "*.js")); const router = express.Router(); apis.forEach(a => Server.loadServices(router, [a])); const routes = _.uniq(router.stack.map(r => r.route.path)); diff --git a/src/api/dimension/DimensionAppserviceAdminService.ts b/src/api/admin/AdminAppserviceService.ts similarity index 86% rename from src/api/dimension/DimensionAppserviceAdminService.ts rename to src/api/admin/AdminAppserviceService.ts index 4467234..9a124da 100644 --- a/src/api/dimension/DimensionAppserviceAdminService.ts +++ b/src/api/admin/AdminAppserviceService.ts @@ -1,5 +1,5 @@ import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest"; -import { DimensionAdminService } from "./DimensionAdminService"; +import { AdminService } from "./AdminService"; import AppService from "../../db/models/AppService"; import { AppserviceStore } from "../../db/AppserviceStore"; import { ApiError } from "../ApiError"; @@ -28,19 +28,19 @@ interface AppserviceCreateRequest { } @Path("/api/v1/dimension/admin/appservices") -export class DimensionAppserviceAdminService { +export class AdminAppserviceService { @GET @Path("all") public async getAppservices(@QueryParam("scalar_token") scalarToken: string): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); return (await AppService.findAll()).map(a => this.mapAppservice(a)); } @POST @Path("new") public async createAppservice(@QueryParam("scalar_token") scalarToken: string, request: AppserviceCreateRequest): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); // Trim off the @ sign if it's on the prefix if (request.userPrefix[0] === "@") { @@ -59,14 +59,14 @@ export class DimensionAppserviceAdminService { @GET @Path(":appserviceId/users") public async getUsers(@QueryParam("scalar_token") scalarToken: string, @PathParam("appserviceId") asId: string): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); return (await AppserviceStore.getUsers(asId)).map(u => this.mapUser(u)); } @POST @Path(":appserviceId/users/register") public async registerUser(@QueryParam("scalar_token") scalarToken: string, @PathParam("appserviceId") asId: string, request: NewUserRequest): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); const user = await AppserviceStore.registerUser(asId, request.userId); return this.mapUser(user); diff --git a/src/api/dimension/DimensionIntegrationsAdminService.ts b/src/api/admin/AdminIntegrationsService.ts similarity index 80% rename from src/api/dimension/DimensionIntegrationsAdminService.ts rename to src/api/admin/AdminIntegrationsService.ts index 3ed77eb..5509734 100644 --- a/src/api/dimension/DimensionIntegrationsAdminService.ts +++ b/src/api/admin/AdminIntegrationsService.ts @@ -1,7 +1,7 @@ import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest"; import { ApiError } from "../ApiError"; -import { DimensionAdminService } from "./DimensionAdminService"; -import { DimensionIntegrationsService, IntegrationsResponse } from "./DimensionIntegrationsService"; +import { AdminService } from "./AdminService"; +import { DimensionIntegrationsService, IntegrationsResponse } from "../dimension/DimensionIntegrationsService"; import { WidgetStore } from "../../db/WidgetStore"; import { Cache, CACHE_INTEGRATIONS } from "../../MemoryCache"; @@ -14,12 +14,12 @@ interface SetOptionsRequest { } @Path("/api/v1/dimension/admin/integrations") -export class DimensionIntegrationsAdminService { +export class AdminIntegrationsService { @POST @Path(":category/:type/options") public async setOptions(@QueryParam("scalar_token") scalarToken: string, @PathParam("category") category: string, @PathParam("type") type: string, body: SetOptionsRequest): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); if (category === "widget") await WidgetStore.setOptions(type, body.options); else throw new ApiError(400, "Unrecognized category"); @@ -32,7 +32,7 @@ export class DimensionIntegrationsAdminService { @POST @Path(":category/:type/enabled") public async setEnabled(@QueryParam("scalar_token") scalarToken: string, @PathParam("category") category: string, @PathParam("type") type: string, body: SetEnabledRequest): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); if (category === "widget") await WidgetStore.setEnabled(type, body.enabled); else throw new ApiError(400, "Unrecognized category"); @@ -44,7 +44,7 @@ export class DimensionIntegrationsAdminService { @GET @Path("all") public async getAllIntegrations(@QueryParam("scalar_token") scalarToken: string): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); return DimensionIntegrationsService.getIntegrations(null); } } \ No newline at end of file diff --git a/src/api/dimension/DimensionNebAdminService.ts b/src/api/admin/AdminNebService.ts similarity index 87% rename from src/api/dimension/DimensionNebAdminService.ts rename to src/api/admin/AdminNebService.ts index aefa6e1..b4e79e5 100644 --- a/src/api/dimension/DimensionNebAdminService.ts +++ b/src/api/admin/AdminNebService.ts @@ -1,5 +1,5 @@ import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest"; -import { DimensionAdminService } from "./DimensionAdminService"; +import { AdminService } from "./AdminService"; import { Cache, CACHE_NEB } from "../../MemoryCache"; import { NebStore } from "../../db/NebStore"; import { NebConfig } from "../../models/neb"; @@ -21,12 +21,12 @@ interface SetEnabledRequest { @Path("/api/v1/dimension/admin/neb") -export class DimensionNebAdminService { +export class AdminNebService { @GET @Path("all") public async getNebConfigs(@QueryParam("scalar_token") scalarToken: string): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); const cachedConfigs = Cache.for(CACHE_NEB).get("configurations"); if (cachedConfigs) return cachedConfigs; @@ -48,7 +48,7 @@ export class DimensionNebAdminService { @POST @Path(":id/integration/:type/enabled") public async setIntegrationEnabled(@QueryParam("scalar_token") scalarToken: string, @PathParam("id") nebId: number, @PathParam("type") integrationType: string, request: SetEnabledRequest): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); const integration = await NebStore.getOrCreateIntegration(nebId, integrationType); integration.isEnabled = request.enabled; @@ -61,7 +61,7 @@ export class DimensionNebAdminService { @POST @Path("new/upstream") public async newConfigForUpstream(@QueryParam("scalar_token") scalarToken: string, request: CreateWithUpstream): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); try { const neb = await NebStore.createForUpstream(request.upstreamId); @@ -76,7 +76,7 @@ export class DimensionNebAdminService { @POST @Path("new/appservice") public async newConfigForAppservice(@QueryParam("scalar_token") scalarToken: string, request: CreateWithAppservice): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); try { const neb = await NebStore.createForAppservice(request.appserviceId, request.adminUrl); diff --git a/src/api/dimension/DimensionAdminService.ts b/src/api/admin/AdminService.ts similarity index 85% rename from src/api/dimension/DimensionAdminService.ts rename to src/api/admin/AdminService.ts index 6b84905..661e141 100644 --- a/src/api/dimension/DimensionAdminService.ts +++ b/src/api/admin/AdminService.ts @@ -20,7 +20,7 @@ interface DimensionConfigResponse { } @Path("/api/v1/dimension/admin") -export class DimensionAdminService { +export class AdminService { public static isAdmin(userId: string) { return config.admins.indexOf(userId) >= 0; @@ -28,7 +28,7 @@ export class DimensionAdminService { public static async validateAndGetAdminTokenOwner(scalarToken: string): Promise { const userId = await ScalarService.getTokenOwner(scalarToken, true); - if (!DimensionAdminService.isAdmin(userId)) + if (!AdminService.isAdmin(userId)) throw new ApiError(401, "You must be an administrator to use this API"); return userId; } @@ -36,21 +36,21 @@ export class DimensionAdminService { @GET @Path("check") public async checkIfAdmin(@QueryParam("scalar_token") scalarToken: string): Promise<{}> { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); return {}; // A 200 OK essentially means "you're an admin". } @GET @Path("version") public async getVersion(@QueryParam("scalar_token") scalarToken: string): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); return {version: CURRENT_VERSION}; } @GET @Path("config") public async getConfig(@QueryParam("scalar_token") scalarToken: string): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); const client = new MatrixLiteClient(config.homeserver.name, config.homeserver.accessToken); return { diff --git a/src/api/dimension/DimensionUpstreamAdminService.ts b/src/api/admin/AdminUpstreamService.ts similarity index 86% rename from src/api/dimension/DimensionUpstreamAdminService.ts rename to src/api/admin/AdminUpstreamService.ts index 74408ca..ea9ca6e 100644 --- a/src/api/dimension/DimensionUpstreamAdminService.ts +++ b/src/api/admin/AdminUpstreamService.ts @@ -1,5 +1,5 @@ import { GET, Path, POST, QueryParam } from "typescript-rest"; -import { DimensionAdminService } from "./DimensionAdminService"; +import { AdminService } from "./AdminService"; import { Cache, CACHE_UPSTREAM } from "../../MemoryCache"; import Upstream from "../../db/models/Upstream"; @@ -19,12 +19,12 @@ interface NewUpstreamRequest { } @Path("/api/v1/dimension/admin/upstreams") -export class DimensionUpstreamAdminService { +export class AdminUpstreamService { @GET @Path("all") public async getUpstreams(@QueryParam("scalar_token") scalarToken: string): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); const cachedUpstreams = Cache.for(CACHE_UPSTREAM).get("upstreams"); if (cachedUpstreams) return cachedUpstreams; @@ -38,7 +38,7 @@ export class DimensionUpstreamAdminService { @POST @Path("new") public async createUpstream(@QueryParam("scalar_token") scalarToken: string, request: NewUpstreamRequest): Promise { - await DimensionAdminService.validateAndGetAdminTokenOwner(scalarToken); + await AdminService.validateAndGetAdminTokenOwner(scalarToken); const upstream = await Upstream.create({ name: request.name,