mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Simple implementation of listing and accepting policies
This commit is contained in:
parent
6c6ae5c5ed
commit
147d8a18ae
@ -2,6 +2,8 @@ import { AutoWired } from "typescript-ioc/es6";
|
||||
import { IMSCUser } from "../security/MSCSecurity";
|
||||
import TermsRecord from "../../db/models/TermsRecord";
|
||||
import TermsTextRecord from "../../db/models/TermsTextRecord";
|
||||
import TermsSignedRecord from "../../db/models/TermsSignedRecord";
|
||||
import { Op } from "sequelize";
|
||||
|
||||
export interface ILanguagePolicy {
|
||||
name: string;
|
||||
@ -45,9 +47,53 @@ export default class TermsController {
|
||||
return Object.keys((await this.getMissingTermsForUser(user)).policies).length > 0;
|
||||
}
|
||||
|
||||
public async getMissingTermsForUser(_user: IMSCUser): Promise<ITermsNotSignedResponse> {
|
||||
public async getMissingTermsForUser(user: IMSCUser): Promise<ITermsNotSignedResponse> {
|
||||
// TODO: Abuse a cache for non-draft policies
|
||||
return {policies: {}};
|
||||
// TODO: Upstream policies
|
||||
|
||||
const notDrafts = await TermsRecord.findAll({
|
||||
where: {version: {[Op.ne]: VERSION_DRAFT}},
|
||||
include: [TermsTextRecord],
|
||||
});
|
||||
const signed = await TermsSignedRecord.findAll({where: {userId: user.userId}});
|
||||
|
||||
const latest: { [shortcode: string]: TermsRecord } = {};
|
||||
for (const record of notDrafts) {
|
||||
if (!latest[record.shortcode]) {
|
||||
latest[record.shortcode] = record;
|
||||
}
|
||||
if (latest[record.shortcode].id < record.id) {
|
||||
latest[record.shortcode] = record;
|
||||
}
|
||||
}
|
||||
|
||||
const missing = Object.values(latest).filter(d => !signed.find(s => s.termsId === d.id));
|
||||
const policies: ITermsNotSignedResponse = {policies: {}};
|
||||
|
||||
for (const missingPolicy of missing) {
|
||||
policies.policies[missingPolicy.shortcode] = {
|
||||
version: missingPolicy.version,
|
||||
};
|
||||
|
||||
for (const text of missingPolicy.texts) {
|
||||
policies.policies[missingPolicy.shortcode][text.language] = {
|
||||
name: text.name,
|
||||
url: text.url,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return policies;
|
||||
}
|
||||
|
||||
public async signTermsMatching(user: IMSCUser, urls: string[]): Promise<any> {
|
||||
const terms = await TermsTextRecord.findAll({where: {url: {[Op.in]: urls}}});
|
||||
const signed = await TermsSignedRecord.findAll({where: {userId: user.userId}});
|
||||
|
||||
const toAdd = terms.filter(t => !signed.find(s => s.termsId === t.termsId));
|
||||
for (const termsToSign of toAdd) {
|
||||
await TermsSignedRecord.create({termsId: termsToSign.id, userId: user.userId});
|
||||
}
|
||||
}
|
||||
|
||||
public async getPoliciesForAdmin(): Promise<ITerms[]> {
|
||||
|
@ -1,8 +1,12 @@
|
||||
import { Context, GET, Path, Security, ServiceContext } from "typescript-rest";
|
||||
import { Context, GET, Path, POST, 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";
|
||||
|
||||
interface SignTermsRequest {
|
||||
user_accepts: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* API for account management
|
||||
*/
|
||||
@ -22,4 +26,12 @@ export class MSCTermsService {
|
||||
public async needsSignatures(): Promise<ITermsNotSignedResponse> {
|
||||
return this.termsController.getMissingTermsForUser(this.context.request.user);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("")
|
||||
@Security(ROLE_MSC_USER)
|
||||
public async signTerms(request: SignTermsRequest): Promise<any> {
|
||||
await this.termsController.signTermsMatching(this.context.request.user, request.user_accepts);
|
||||
return {};
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ import CustomSimpleBotRecord from "./models/CustomSimpleBotRecord";
|
||||
import SlackBridgeRecord from "./models/SlackBridgeRecord";
|
||||
import TermsRecord from "./models/TermsRecord";
|
||||
import TermsTextRecord from "./models/TermsTextRecord";
|
||||
import TermsSignedRecord from "./models/TermsSignedRecord";
|
||||
|
||||
class _DimensionStore {
|
||||
private sequelize: Sequelize;
|
||||
@ -67,6 +68,7 @@ class _DimensionStore {
|
||||
SlackBridgeRecord,
|
||||
TermsRecord,
|
||||
TermsTextRecord,
|
||||
TermsSignedRecord,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ export default {
|
||||
.then(() => queryInterface.createTable("dimension_terms_text", {
|
||||
"id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false},
|
||||
"termsId": {
|
||||
type: DataType.INTEGER, allowNull: true,
|
||||
type: DataType.INTEGER, allowNull: false,
|
||||
references: {model: "dimension_terms", key: "id"},
|
||||
onUpdate: "cascade", onDelete: "cascade",
|
||||
},
|
||||
|
25
src/db/migrations/20190706154345-AddUserSignedTerms.ts
Normal file
25
src/db/migrations/20190706154345-AddUserSignedTerms.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { QueryInterface } from "sequelize";
|
||||
import { DataType } from "sequelize-typescript";
|
||||
|
||||
export default {
|
||||
up: (queryInterface: QueryInterface) => {
|
||||
return Promise.resolve()
|
||||
.then(() => queryInterface.createTable("dimension_terms_signed", {
|
||||
"id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false},
|
||||
"termsId": {
|
||||
type: DataType.INTEGER, allowNull: false,
|
||||
references: {model: "dimension_terms", key: "id"},
|
||||
onUpdate: "cascade", onDelete: "cascade",
|
||||
},
|
||||
"userId": {
|
||||
type: DataType.STRING, allowNull: false,
|
||||
references: {model: "dimension_users", key: "userId"},
|
||||
onUpdate: "cascade", onDelete: "cascade",
|
||||
},
|
||||
}));
|
||||
},
|
||||
down: (queryInterface: QueryInterface) => {
|
||||
return Promise.resolve()
|
||||
.then(() => queryInterface.dropTable("dimension_terms_signed"));
|
||||
}
|
||||
}
|
25
src/db/models/TermsSignedRecord.ts
Normal file
25
src/db/models/TermsSignedRecord.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { AllowNull, AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript";
|
||||
import User from "./User";
|
||||
import TermsRecord from "./TermsRecord";
|
||||
|
||||
@Table({
|
||||
tableName: "dimension_terms_signed",
|
||||
underscored: false,
|
||||
timestamps: false,
|
||||
})
|
||||
export default class TermsSignedRecord extends Model<TermsSignedRecord> {
|
||||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column
|
||||
id: number;
|
||||
|
||||
@AllowNull
|
||||
@Column
|
||||
@ForeignKey(() => TermsRecord)
|
||||
termsId?: number;
|
||||
|
||||
@AllowNull
|
||||
@Column
|
||||
@ForeignKey(() => User)
|
||||
userId?: string;
|
||||
}
|
Loading…
Reference in New Issue
Block a user