Renewal Token Update
This commit is contained in:
parent
d8ebe48a76
commit
be4d6d9392
|
|
@ -5,4 +5,5 @@ export class Token
|
|||
id:string;
|
||||
expires:ISOTimeStamp;
|
||||
hashedIP:string;
|
||||
renewalToken:string;
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { DateHelper } from "../../browser/date/DateHelper";
|
||||
import { DateMath } from "../../browser/date/DateMath";
|
||||
import { ISOTimeStamp } from "../../browser/date/ISOTimeStamp";
|
||||
import { Message } from "../../browser/messages/Message";
|
||||
import { CryptIO } from "../crypt/CryptIO";
|
||||
import { Token } from "./Token";
|
||||
import { UserManagementServer } from "./UserManagementServer";
|
||||
|
|
@ -28,6 +29,7 @@ export class TokenDB
|
|||
|
||||
let token = new Token();
|
||||
token.id = CryptIO.createUUID();
|
||||
token.renewalToken = CryptIO.createUUID();
|
||||
token.hashedIP = await CryptIO.hash( ip );
|
||||
token.expires = ISOTimeStamp.fromDate( DateMath.fromNowAddMinutes( expireDurationInMinutes ) );
|
||||
|
||||
|
|
@ -36,15 +38,20 @@ export class TokenDB
|
|||
return Promise.resolve( token );
|
||||
}
|
||||
|
||||
async validate( token:Token, ip:string ):Promise<boolean>
|
||||
|
||||
|
||||
async validate( token:Token, ip:string, debugMesssges:Message[] = undefined ):Promise<boolean>
|
||||
{
|
||||
if ( this._tokens.get( token.id ) != token )
|
||||
{
|
||||
debugMesssges?.push( Message.Error( "Token doesn't exist" ) );
|
||||
|
||||
return Promise.resolve( false );
|
||||
}
|
||||
|
||||
if ( DateMath.isExpired( ISOTimeStamp.toDate( token.expires ) ) )
|
||||
{
|
||||
debugMesssges?.push( Message.Error( "Token is out of date" ) );
|
||||
return Promise.resolve( false );
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +62,8 @@ export class TokenDB
|
|||
return true;
|
||||
}
|
||||
|
||||
debugMesssges?.push( Message.Error( "Ip mismatch" ) );
|
||||
|
||||
return Promise.resolve( false );
|
||||
}
|
||||
}
|
||||
|
|
@ -156,6 +156,24 @@ export class UserDB
|
|||
return Promise.resolve( isValid );
|
||||
}
|
||||
|
||||
async renew( oldToken:string, renewal:string, ip:string ):Promise<Token>
|
||||
{
|
||||
let session = this._ums._sessions.get( oldToken );
|
||||
let tokenData = this._ums._tokenDB._tokens.get( session.token );
|
||||
|
||||
if ( tokenData.renewalToken !== renewal )
|
||||
{
|
||||
return Promise.resolve( null );
|
||||
}
|
||||
|
||||
let hour = 60;
|
||||
let day = hour * 24;
|
||||
let week = day * 7;
|
||||
|
||||
let token = await this._ums.tokenDB.create( ip, week );
|
||||
|
||||
return Promise.resolve( token );
|
||||
}
|
||||
|
||||
async login( email:string, password:string, ip:string ):Promise<Token>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export class UserLoginData
|
|||
timeStamp:ISOTimeStamp;
|
||||
location:LocationData;
|
||||
userAgent:string;
|
||||
renewal:boolean
|
||||
}
|
||||
|
||||
export class UserData
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ export class ReminderApp extends UserApp<ReminderData> implements iTaskScheduler
|
|||
( me )=>
|
||||
{
|
||||
let date = DateHelper.parseDateExpression( me.date );
|
||||
date = DateMath.addMinutes( date, me.utcOffsetMinutes );
|
||||
|
||||
if ( DateMath.isBefore( date, maxDate ) )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { ReminderEntry, ReminderEntryType } from "./ReminderEntry";
|
|||
export class MailEntry extends ReminderEntry
|
||||
{
|
||||
date:string;
|
||||
utcOffsetMinutes:number;
|
||||
subject:string;
|
||||
message:string;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { ConfirmSignUpHandler } from "./_/confirm-signup";
|
|||
import { InfoHandler } from "./_/info";
|
||||
import { LoginHandler } from "./_/login";
|
||||
import { LogoutHandler } from "./_/logout";
|
||||
import { RenewHandler } from "./_/renew";
|
||||
import { RequestPasswordChangeHandler } from "./_/request-password-change";
|
||||
import { SignUpHandler } from "./_/signup";
|
||||
import { AppsCanUseHandler } from "./apps/can-use";
|
||||
|
|
@ -21,6 +22,7 @@ export class HandlerGroups
|
|||
new ConfirmSignUpHandler(),
|
||||
|
||||
new LoginHandler(),
|
||||
new RenewHandler(),
|
||||
new LogoutHandler(),
|
||||
new InfoHandler(),
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ export class LoginHandler extends RequestHandler
|
|||
loginData.timeStamp = ISOTimeStamp.now();
|
||||
loginData.location = await this.getLocation();
|
||||
loginData.userAgent = this.userAgent;
|
||||
loginData.renewal = false;
|
||||
|
||||
user.lastLogins = user.lastLogins || [];
|
||||
user.lastLogins.push( loginData );
|
||||
|
|
@ -56,7 +57,7 @@ export class LoginHandler extends RequestHandler
|
|||
await this.ums.saveSessionData();
|
||||
|
||||
|
||||
return this.sendDataInfo( "Login successfull", { token: session.token } );
|
||||
return this.sendDataInfo( "Login successfull", { token: session.token, renewal: loginToken.renewalToken } );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
import { RegExpUtility } from "../../../../browser/text/RegExpUtitlity";
|
||||
import { CryptIO } from "../../../crypt/CryptIO";
|
||||
import { RJLog } from "../../../log/RJLog";
|
||||
import { RequestHandler, RequestType } from "../../RequestHandler";
|
||||
import { FastifyRequest, FastifyReply } from 'fastify';
|
||||
import { VariableReplacer, Variables } from "../../../../browser/text/replacing/VariableReplacer";
|
||||
import { ConfirmSignUpHandler } from "./confirm-signup";
|
||||
import { Session } from "../../Session";
|
||||
import { UserLoginData } from "../../UserData";
|
||||
import { ISOTimeStamp } from "../../../../browser/date/ISOTimeStamp";
|
||||
import { Arrays } from "../../../../browser/tools/Arrays";
|
||||
|
||||
export class RenewHandler extends RequestHandler
|
||||
{
|
||||
static url = "/renew";
|
||||
constructor(){ super( RequestType.POST, RenewHandler.url ); }
|
||||
|
||||
async _handle( request:FastifyRequest, reply:FastifyReply )
|
||||
{
|
||||
let requestBody = request.body;
|
||||
let { token, renewal } = requestBody as { token: string; renewal: string };
|
||||
|
||||
if ( ! token || ! renewal )
|
||||
{
|
||||
return this.sendError( "Missing token or renewal:" + `"${requestBody}"` );
|
||||
}
|
||||
|
||||
let session = this._ums._sessions.get( token );
|
||||
|
||||
if ( ! session )
|
||||
{
|
||||
return this.sendError( "Invalid token" );
|
||||
}
|
||||
|
||||
let user = await this._ums.userDB.byID( session.userID );
|
||||
|
||||
let renewToken = await this.userDB.renew( token, renewal, this.ip );
|
||||
|
||||
if ( ! renewToken )
|
||||
{
|
||||
return this.sendError( "Renewal failed" );
|
||||
}
|
||||
|
||||
let loginData = new UserLoginData();
|
||||
loginData.timeStamp = ISOTimeStamp.now();
|
||||
loginData.location = await this.getLocation();
|
||||
loginData.userAgent = this.userAgent;
|
||||
loginData.renewal = true;
|
||||
|
||||
user.lastLogins = user.lastLogins || [];
|
||||
user.lastLogins.push( loginData );
|
||||
|
||||
Arrays.shiftToSize( user.lastLogins, this._ums._settings.maxLogins );
|
||||
|
||||
this._ums._sessions.delete( session.token );
|
||||
|
||||
session.token = renewToken.id;
|
||||
|
||||
this._ums._sessions.set( session.token, session );
|
||||
|
||||
await this.userDB.save();
|
||||
|
||||
await this.ums.saveSessionData();
|
||||
|
||||
|
||||
return this.sendDataInfo( "Renewal successfull", { token: session.token, renewal: renewToken.renewalToken } );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -22,16 +22,18 @@ export class UserIsLoggedIn extends RequestRequirement
|
|||
|
||||
if ( ! session )
|
||||
{
|
||||
return this.sendError( "No session for token:" + tokenID );
|
||||
return this.sendError( "No session for token: " + tokenID );
|
||||
}
|
||||
|
||||
let token = this.ums.tokenDB._tokens.get( tokenID );
|
||||
|
||||
let isValid = await this.ums.tokenDB.validate( token, request.ip );
|
||||
let messages = [];
|
||||
let isValid = await this.ums.tokenDB.validate( token, request.ip, messages );
|
||||
|
||||
if ( ! isValid )
|
||||
{
|
||||
return this.sendError( "Invalid token" + tokenID );
|
||||
let message = messages.length > 0 ? ( " " + messages.join( ", " ) ) : "";
|
||||
return this.sendError( "Invalid token: " + tokenID + message );
|
||||
}
|
||||
|
||||
return this.giveOK();
|
||||
|
|
|
|||
|
|
@ -56,13 +56,13 @@ export class Scheduler
|
|||
scheduleTasks( tasks:Task[] )
|
||||
{
|
||||
let maxDate = DateMath.fromNowAddDays( this._maxScheduleDurationDays );
|
||||
tasks = tasks.filter( t => ! this._scheduledTasks.has( t.id ) && ! DateMath.isAfter( t.date, maxDate ) );
|
||||
tasks = tasks.filter( t => ! this._scheduledTasks.has( t.id ) && ! DateMath.isAfter( t.utcDate, maxDate ) );
|
||||
|
||||
|
||||
this._queue = this._queue.concat( tasks );
|
||||
tasks.forEach( t => this._scheduledTasks.add( t.id ) );
|
||||
|
||||
this._queue.sort( ( a, b ) => { return a.date.getTime() - b.date.getTime() } );
|
||||
this._queue.sort( ( a, b ) => { return a.utcDate.getTime() - b.utcDate.getTime() } );
|
||||
|
||||
let newNextTask = this._queue[ 0 ];
|
||||
|
||||
|
|
@ -98,9 +98,9 @@ export class Scheduler
|
|||
let task = this._queue[ 0 ];
|
||||
this._nextTaskID = task.id;
|
||||
|
||||
let delay = Math.max( 0, task.date.getTime() - Date.now() );
|
||||
let delay = Math.max( 0, task.utcDate.getTime() - Date.now() );
|
||||
|
||||
RJLog.log( task.id, DateFormatter.HMS( task.date ), "delaying:", Duration.fromMilliSeconds( delay ) + " sec" );
|
||||
RJLog.log( task.id, DateFormatter.HMS( task.utcDate ), "delaying:", Duration.fromMilliSeconds( delay ) + " sec" );
|
||||
|
||||
this._taskTimerCallback = setTimeout(
|
||||
() =>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export class Task
|
|||
id:string;
|
||||
userID:string;
|
||||
appID:string;
|
||||
date:Date;
|
||||
utcDate:Date;
|
||||
action:()=>void;
|
||||
|
||||
setUserContext( appID:string, userID:string )
|
||||
|
|
@ -25,13 +25,13 @@ export class Task
|
|||
return Task.createAt( id, date, action );
|
||||
}
|
||||
|
||||
static createAt( id:string, date:Date, action:()=>void )
|
||||
static createAt( id:string, utcDate:Date, action:()=>void )
|
||||
{
|
||||
let task = new Task();
|
||||
|
||||
task.id = id;
|
||||
task.action = action;
|
||||
task.date = date;
|
||||
task.utcDate = utcDate;
|
||||
|
||||
return task;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue