mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-09-02 15:11:58 +00:00
Very simple terms of service auth requirement
This commit is contained in:
parent
4ae49702bd
commit
d9637b1d3d
35
src/api/controllers/TermsController.ts
Normal file
35
src/api/controllers/TermsController.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { AutoWired } from "typescript-ioc/es6";
|
||||
import { IMSCUser } from "../security/MSCSecurity";
|
||||
|
||||
export interface ILanguagePolicy {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface IPolicy {
|
||||
version: string;
|
||||
|
||||
// a string value is not allowed here, but TypeScript is angry otherwise.
|
||||
[language: string]: string | ILanguagePolicy;
|
||||
}
|
||||
|
||||
export interface ITermsNotSignedResponse {
|
||||
policies: { [policyName: string]: IPolicy };
|
||||
}
|
||||
|
||||
/**
|
||||
* API controller for terms of service management
|
||||
*/
|
||||
@AutoWired
|
||||
export default class TermsController {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public async doesUserNeedToSignTerms(user: IMSCUser): Promise<boolean> {
|
||||
return Object.keys((await this.getMissingTermsForUser(user)).policies).length > 0;
|
||||
}
|
||||
|
||||
public async getMissingTermsForUser(_user: IMSCUser): Promise<ITermsNotSignedResponse> {
|
||||
return {policies: {}};
|
||||
}
|
||||
}
|
25
src/api/msc/MSCTermsService.ts
Normal file
25
src/api/msc/MSCTermsService.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Context, GET, Path, Security, ServiceContext } from "typescript-rest";
|
||||
import { AutoWired, Inject } from "typescript-ioc/es6";
|
||||
import { ROLE_MSC_USER } from "../security/MSCSecurity";
|
||||
import TermsController, { ITermsNotSignedResponse } from "../controllers/TermsController";
|
||||
|
||||
/**
|
||||
* API for account management
|
||||
*/
|
||||
@Path("/_matrix/integrations/v1/terms")
|
||||
@AutoWired
|
||||
export class MSCTermsService {
|
||||
|
||||
@Inject
|
||||
private termsController: TermsController;
|
||||
|
||||
@Context
|
||||
private context: ServiceContext;
|
||||
|
||||
@GET
|
||||
@Path("")
|
||||
@Security(ROLE_MSC_USER)
|
||||
public async needsSignatures(): Promise<ITermsNotSignedResponse> {
|
||||
return this.termsController.getMissingTermsForUser(this.context.request.user);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import { Request, RequestHandler, Response, Router } from "express";
|
||||
import { ApiError } from "../ApiError";
|
||||
import { LogService } from "matrix-js-snippets";
|
||||
import AccountController from "../controllers/AccountController";
|
||||
import TermsController from "../controllers/TermsController";
|
||||
|
||||
export interface IMSCUser {
|
||||
userId: string;
|
||||
@ -10,18 +11,25 @@ export interface IMSCUser {
|
||||
}
|
||||
|
||||
export const ROLE_MSC_USER = "ROLE_MSC_USER";
|
||||
export const ROLE_MSC_TERMS_SIGNED = "ROLE_MSC_TERMS_SIGNED";
|
||||
|
||||
const TERMS_IGNORED_ROUTES = [
|
||||
{method: "GET", path: "/_matrix/integrations/v1/terms"},
|
||||
{method: "POST", path: "/_matrix/integrations/v1/terms"},
|
||||
{method: "POST", path: "/_matrix/integrations/v1/register"},
|
||||
{method: "POST", path: "/_matrix/integrations/v1/logout"},
|
||||
];
|
||||
|
||||
export default class MSCSecurity implements ServiceAuthenticator {
|
||||
|
||||
private accountController = new AccountController();
|
||||
private termsController = new TermsController();
|
||||
|
||||
public getRoles(req: Request): string[] {
|
||||
if (req.user) return [ROLE_MSC_USER];
|
||||
return [];
|
||||
}
|
||||
|
||||
getMiddleware(): RequestHandler {
|
||||
public getMiddleware(): RequestHandler {
|
||||
return (async (req: Request, res: Response, next: () => void) => {
|
||||
try {
|
||||
let token = null;
|
||||
@ -41,6 +49,27 @@ export default class MSCSecurity implements ServiceAuthenticator {
|
||||
userId: await this.accountController.getTokenOwner(token),
|
||||
token: token,
|
||||
};
|
||||
|
||||
let needTerms = true;
|
||||
if (req.method !== "OPTIONS") {
|
||||
for (const route of TERMS_IGNORED_ROUTES) {
|
||||
if (route.method === req.method && route.path === req.path) {
|
||||
needTerms = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else needTerms = false;
|
||||
|
||||
if (needTerms) {
|
||||
const signatureNeeded = await this.termsController.doesUserNeedToSignTerms(req.user);
|
||||
if (signatureNeeded) {
|
||||
return res.status(403).json({
|
||||
errcode: "M_TERMS_NOT_SIGNED",
|
||||
error: "The user has not accepted all terms of service for this integration manager",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return next();
|
||||
} else {
|
||||
return res.status(401).json({errcode: "M_INVALID_TOKEN", error: "Invalid token"});
|
||||
@ -57,7 +86,7 @@ export default class MSCSecurity implements ServiceAuthenticator {
|
||||
});
|
||||
}
|
||||
|
||||
initialize(_router: Router): void {
|
||||
public initialize(_router: Router): void {
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user