DTP Base provides a scalable and secure Node.js application development harness ready for production service.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

84 lines
2.1 KiB

// auth-token.js
// Copyright (C) 2024 DTP Technologies, LLC
// All Rights Reserved
'use strict';
import mongoose from 'mongoose';
const AuthToken = mongoose.model('AuthToken');
import { v4 as uuidv4 } from 'uuid';
import { SiteService, SiteError } from '../../lib/site-lib.js';
export default class AuthTokenService extends SiteService {
static get slug () { return 'authToken'; }
static get name ( ) { return 'AuthTokenService'; }
constructor (dtp) {
super(dtp, AuthTokenService);
}
async create (purpose, data) {
const NOW = new Date();
const passwordResetToken = new AuthToken();
passwordResetToken.created = NOW;
passwordResetToken.purpose = purpose;
passwordResetToken.token = uuidv4();
if (data) {
passwordResetToken.data = data;
}
await passwordResetToken.save();
return passwordResetToken.toObject();
}
async getByValue (tokenValue) {
if (!tokenValue) {
throw new SiteError(400, 'Must include an authentication token');
}
if ((typeof tokenValue !== 'string') || (tokenValue.length !== 36)) {
throw new SiteError(400, 'The authentication token is invalid');
}
const token = await AuthToken
.findOne({ token: tokenValue })
.lean();
if (!token) {
throw new SiteError(400, 'Auth token not found');
}
if (token.claimed) {
throw new SiteError(403, 'Auth token already used');
}
return token;
}
async claim (tokenValue) {
const token = await this.getByValue(tokenValue);
if (!token) {
throw new SiteError(403, 'The authentication token has expired');
}
if (token.claimed) {
throw new SiteError(403, 'This authentication token has already been claimed');
}
token.claimed = new Date();
await AuthToken.updateOne({ _id: token._id }, { $set: { claimed: token.claimed } });
return token; // with claimed date
}
async removeForUser (user) {
await AuthToken.deleteMany({ user: user._id });
}
async remove (token) {
if (!token || !token._id) {
throw new SiteError(400, 'Must include auth token');
}
await AuthToken.deleteOne({ _id: token._id });
}
}