mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04: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 { ApiError } from "../ApiError";
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import AccountController from "../controllers/AccountController";
|
import AccountController from "../controllers/AccountController";
|
||||||
|
import TermsController from "../controllers/TermsController";
|
||||||
|
|
||||||
export interface IMSCUser {
|
export interface IMSCUser {
|
||||||
userId: string;
|
userId: string;
|
||||||
@ -10,18 +11,25 @@ export interface IMSCUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ROLE_MSC_USER = "ROLE_MSC_USER";
|
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 {
|
export default class MSCSecurity implements ServiceAuthenticator {
|
||||||
|
|
||||||
private accountController = new AccountController();
|
private accountController = new AccountController();
|
||||||
|
private termsController = new TermsController();
|
||||||
|
|
||||||
public getRoles(req: Request): string[] {
|
public getRoles(req: Request): string[] {
|
||||||
if (req.user) return [ROLE_MSC_USER];
|
if (req.user) return [ROLE_MSC_USER];
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
getMiddleware(): RequestHandler {
|
public getMiddleware(): RequestHandler {
|
||||||
return (async (req: Request, res: Response, next: () => void) => {
|
return (async (req: Request, res: Response, next: () => void) => {
|
||||||
try {
|
try {
|
||||||
let token = null;
|
let token = null;
|
||||||
@ -41,6 +49,27 @@ export default class MSCSecurity implements ServiceAuthenticator {
|
|||||||
userId: await this.accountController.getTokenOwner(token),
|
userId: await this.accountController.getTokenOwner(token),
|
||||||
token: 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();
|
return next();
|
||||||
} else {
|
} else {
|
||||||
return res.status(401).json({errcode: "M_INVALID_TOKEN", error: "Invalid token"});
|
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