Files
auth-db/lib/schema/strategy.ts

82 lines
2.3 KiB
TypeScript

import { Document, InferSchemaType, Model, Schema, StringSchemaDefinition, Types } from 'mongoose';
import { STRATEGIES } from '../constants/strategies';
import { encrypt } from '../utils/password';
import { COLL_AUTH } from '../constants/db';
import { AuthDocument } from './auth';
import { Strategy } from '..';
export interface Strategy {
method: STRATEGIES;
parent: StringSchemaDefinition | AuthDocument;
externalId?: string;
key: string;
profile?: { [key: string]: string | boolean | number };
forceReset?: boolean;
}
interface StrategyBaseDocument extends Strategy, Document {
getAuthRecord(): Promise<AuthDocument>;
getPopulatedStrategy(): Promise<StrategyPopulatedDocument>;
}
export interface StrategyDocument extends StrategyBaseDocument {
parent: StringSchemaDefinition;
}
export interface StrategyPopulatedDocument extends StrategyBaseDocument {
parent: AuthDocument;
}
export type StrategyModel = Model<StrategyDocument>;
export const StrategySchema = new Schema<StrategyDocument, StrategyModel>(
{
method: {
type: Number,
enum: STRATEGIES,
index: true,
},
externalId: { type: String, index: true },
forceReset: { type: Boolean },
key: { type: String, required: true, trim: true },
parent: {
type: Types.ObjectId,
ref: COLL_AUTH,
required: true,
},
profile: {},
},
{
minimize: true,
timestamps: true,
},
);
StrategySchema.methods.getPopulatedStrategy = async function (this: StrategyModel) {
return this.populate<StrategyPopulatedDocument>('parent');
};
StrategySchema.methods.getAuthRecord = async function (this: StrategyModel) {
return (await this.getPopulatedStrategy()).parent;
};
StrategySchema.pre('save', async function save(next) {
if (typeof this.method === 'undefined') {
return next(new Error(`Strategy requires a method.`));
}
if (await Strategy.findOne({ method: this.method, parent: this.parent })) {
return next(new Error(`${this.method} strategy already exists for this user.`));
}
if (this.method !== STRATEGIES.LOCAL || !this.isModified('key')) {
return next();
}
this.key = encrypt(this.key);
return next();
});
export type StrategySchema = InferSchemaType<typeof StrategySchema>;