This repository has been archived by the owner on Feb 10, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
SmsVerificationServiceImpl.ts
124 lines (110 loc) · 3.83 KB
/
SmsVerificationServiceImpl.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright (c) 2021-2023. Heusala Group Oy <info@heusalagroup.fi>. All rights reserved.
import { randomInt } from 'crypto';
import { find } from "../core/functions/find";
import { forEach } from "../core/functions/forEach";
import { remove } from "../core/functions/remove";
import { LogService } from "../core/LogService";
import { clearTimeout } from "timers";
import { Disposable } from "../core/types/Disposable";
import { LogLevel } from "../core/types/LogLevel";
import { SmsVerificationService } from "../core/auth/SmsVerificationService";
const DEFAULT_VERIFICATION_TIMEOUT : number = 5*60*1000;
interface InternalSmsCode {
readonly code : string;
readonly sms : string;
timer : any | undefined;
}
const LOG = LogService.createLogger('SmsVerificationServiceImpl');
export class SmsVerificationServiceImpl
implements Disposable, SmsVerificationService {
public static setLogLevel (level: LogLevel) {
LOG.setLogLevel(level);
}
private _codes : InternalSmsCode[];
private readonly _verificationTimeout : number;
protected constructor (
verificationTimeout : number = DEFAULT_VERIFICATION_TIMEOUT
) {
this._codes = [];
this._verificationTimeout = verificationTimeout;
}
public static create (
verificationTimeout : number = DEFAULT_VERIFICATION_TIMEOUT
) : SmsVerificationServiceImpl {
return new SmsVerificationServiceImpl(
verificationTimeout
);
}
public destroy () {
forEach(
this._codes,
(item: InternalSmsCode) => {
try {
const timer = item?.timer;
if (timer !== undefined) {
clearTimeout(timer);
item.timer = undefined;
}
} catch (err) {
LOG.error(`Could not remove timer: `, err);
}
}
);
this._codes = [];
}
public verifyCode (
sms : string,
code : string
) : boolean {
LOG.debug(`verifyCode: "${code}" for sms "${sms}" `);
if (!sms) return false;
if (!code) return false;
const itemMatcher = (item : InternalSmsCode) => {
return item?.sms === sms && item?.code === code;
};
const item : InternalSmsCode | undefined = find(this._codes, itemMatcher);
if (!item) return false;
if (item?.timer) {
clearTimeout(item.timer);
item.timer = undefined;
}
remove(this._codes, itemMatcher);
LOG.debug(`Verified & removed "${code}" for sms "${sms}"`);
return true;
}
public removeVerificationCode (
sms : string,
code : string
) {
if (!sms) throw new TypeError('sms is required');
if (!code) throw new TypeError('code is required');
const itemMatcher = (item : InternalSmsCode) => {
return item.sms === sms && item.code === code;
};
const item : InternalSmsCode | undefined = find(this._codes, itemMatcher);
if (item) {
if (item?.timer) {
clearTimeout(item.timer);
item.timer = undefined;
}
remove(this._codes, itemMatcher);
LOG.debug(`Removed "${code}" for sms "${sms}"`);
}
}
public createVerificationCode (
sms: string
) : string {
const code = `${randomInt(0, 9999)}`.padStart(4, "0");
const timer = setTimeout(() => {
this.removeVerificationCode(sms, code);
}, this._verificationTimeout);
remove(this._codes, (item: InternalSmsCode) => item.sms === sms);
this._codes.push({
sms,
code,
timer
});
LOG.debug(`Added "${code}" for sms "${sms}"`)
return code;
}
}