Finish MFA v1 and refactor all tokens into separate TokenService with modified collection

This commit is contained in:
Tuan Dang
2023-01-23 22:10:15 +07:00
parent 00fee63ff3
commit 5cadb9e2f9
25 changed files with 692 additions and 98 deletions
+3 -3
View File
@@ -10,7 +10,7 @@ import MembershipOrg, { IMembershipOrg } from './membershipOrg';
import Organization, { IOrganization } from './organization';
import Secret, { ISecret } from './secret';
import ServiceToken, { IServiceToken } from './serviceToken';
import Token, { IToken } from './token';
import TokenData, { ITokenData } from './tokenData';
import User, { IUser } from './user';
import UserAction, { IUserAction } from './userAction';
import Workspace, { IWorkspace } from './workspace';
@@ -42,8 +42,8 @@ export {
ISecret,
ServiceToken,
IServiceToken,
Token,
IToken,
TokenData,
ITokenData,
User,
IUser,
UserAction,
-33
View File
@@ -1,33 +0,0 @@
import { Schema, model } from 'mongoose';
import { EMAIL_TOKEN_LIFETIME } from '../config';
export interface IToken {
email: string;
token: string;
createdAt: Date;
}
const tokenSchema = new Schema<IToken>({
email: {
type: String,
required: true
},
token: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now
}
});
tokenSchema.index({
createdAt: 1
}, {
expireAfterSeconds: parseInt(EMAIL_TOKEN_LIFETIME)
});
const Token = model<IToken>('Token', tokenSchema);
export default Token;
+57
View File
@@ -0,0 +1,57 @@
import { Schema, Types, model } from 'mongoose';
export interface ITokenData {
type: string;
email?: string;
phoneNumber?: string;
organization?: Types.ObjectId;
tokenHash: string;
expiresAt: Date;
createdAt: Date;
updatedAt: Date;
}
const tokenDataSchema = new Schema<ITokenData>({
type: {
type: String,
enum: [
'emailConfirmation',
'emailMfa',
'organizationInvitation',
'passwordReset'
],
required: true
},
email: {
type: String
},
phoneNumber: {
type: String
},
organization: { // organizationInvitation-specific field
type: Schema.Types.ObjectId,
ref: 'Organization'
},
tokenHash: {
type: String,
select: false,
required: true
},
expiresAt: {
type: Date,
expires: 0,
required: true
}
}, {
timestamps: true
});
tokenDataSchema.index({
expiresAt: 1
}, {
expireAfterSeconds: 0
});
const TokenData = model<ITokenData>('TokenData', tokenDataSchema);
export default TokenData;
+6
View File
@@ -1,4 +1,5 @@
import { Schema, model, Types } from 'mongoose';
import { MFA_METHOD_EMAIL } from '../variables';
export interface IUser {
_id: Types.ObjectId;
@@ -12,6 +13,7 @@ export interface IUser {
salt?: string;
verifier?: string;
refreshVersion?: number;
isMfaEnabled: boolean;
}
const userSchema = new Schema<IUser>(
@@ -54,6 +56,10 @@ const userSchema = new Schema<IUser>(
type: Number,
default: 0,
select: false
},
isMfaEnabled: {
type: Boolean,
default: false
}
},
{