82 lines
2.3 KiB
TypeScript
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>;
|