auth-verify 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/auth-verify.js ADDED
@@ -0,0 +1,182 @@
1
+ const sqlite3 = require("sqlite3").verbose();
2
+ const nodemailer = require('nodemailer')
3
+ const crypto = require('crypto');
4
+ const { request } = require("http");
5
+
6
+ class Verifier {
7
+ constructor(sender = {}){
8
+ this.otpLen = sender.otp?.leng || 6;
9
+ this.expMin = sender.otp?.expMin || 3;
10
+ this.limit = sender.otp?.limit || 5;
11
+ this.cooldown = sender.otp?.cooldown || 60;
12
+ // Setup SMTP
13
+ this.transport = nodemailer.createTransport({
14
+ service: `${sender.serv}`,
15
+ auth: {
16
+ user: `${sender.sender}`,
17
+ pass: sender.pass
18
+ }
19
+ });
20
+
21
+ this.sender = `${sender.smtp?.sender}`
22
+
23
+ //making a db for saving otp codes
24
+ this.db = new sqlite3.Database('./authverify.db');
25
+ this.db.serialize(()=>{
26
+ // creating a table
27
+ this.db.run(`
28
+ CREATE TABLE IF NOT EXISTS verifications (
29
+ email TEXT PRIMARY KEY,
30
+ code TEXT,
31
+ expiresAt TEXT,
32
+ requests INTEGER DEFAULT 0,
33
+ lastRequest TEXT
34
+ )
35
+ `);
36
+ });
37
+
38
+ }
39
+
40
+ // Generate OTP securely
41
+ generateOTP() {
42
+ const buffer = crypto.randomBytes(this.otpLen);
43
+ const number = parseInt(buffer.toString('hex'), 16)
44
+ .toString()
45
+ .slice(0, this.otpLen);
46
+ return number.padStart(this.otpLen, '0');
47
+ }
48
+
49
+ html(html){
50
+ this.htmlContent = html;
51
+ return this;
52
+ }
53
+
54
+ subject(subject){
55
+ this.mailSubject = subject;
56
+ return this;
57
+ }
58
+
59
+ text(text){
60
+ this.mailText = text;
61
+ return this;
62
+ }
63
+
64
+ sendTo(email, callback){
65
+
66
+ this.recieverEmail = email;
67
+ const code = this.generateOTP();
68
+ const expAt = new Date(Date.now() + this.expMin * 60 * 1000).toISOString();
69
+
70
+ this.db.get(`SELECT * FROM verifications WHERE email = ?`, [email], (err, row)=>{
71
+ if(err) return callback(err);
72
+
73
+ const now = new Date();
74
+ let requests = 1;
75
+
76
+ if(row){
77
+ const lastRequest = row.lastRequest ? new Date(row.lastRequest) : null;
78
+
79
+ if(lastRequest && now.toDateString() === lastRequest.toDateString()){
80
+ requests = row.requests + 1;
81
+ if(requests > this.limit){
82
+ return callback(new Error("Too many OTP requests today"));
83
+ }
84
+
85
+ const diff = (now - lastRequest) / 1000;
86
+ if(diff < this.cooldown){
87
+ return callback(new Error(`Please wait ${Math.ceil(this.cooldown - diff)} seconds before requesting a new OTP.`));
88
+ }
89
+ }
90
+ }
91
+
92
+ this.db.run(`INSERT INTO verifications (email, code, expiresAt, requests, lastRequest) VALUES (?, ?, ?, ?, ?)
93
+ ON CONFLICT(email) DO UPDATE SET
94
+ code = excluded.code,
95
+ expiresAt = excluded.expiresAt,
96
+ requests = excluded.requests,
97
+ lastRequest = excluded.lastRequest`, [email, code, expAt, requests, now.toISOString()], (DBerr)=>{
98
+ if(DBerr) return callback(DBerr);
99
+
100
+ this.otpOptions = {
101
+ from: this.sender,
102
+ to: `${email}`,
103
+ subject: this.mailSubject ? this.mailSubject.replace("{otp}", code) : undefined,
104
+ text: this.mailText ? this.mailText.replace("{otp}", code) : undefined,
105
+ html: this.htmlContent ? this.htmlContent.replace("{otp}", code) : undefined
106
+ }
107
+
108
+ this.transport.sendMail(this.otpOptions, (emailErr, info)=>{
109
+ if(emailErr) return callback(emailErr);
110
+
111
+ // console.log('📨 Email sent:', info.response);
112
+ callback(null, true);
113
+ });
114
+
115
+ // console.log('💾 Code saved to DB');
116
+ });
117
+ });
118
+
119
+ return this;
120
+
121
+ }
122
+
123
+ code(userCode){
124
+ this.userCode = userCode
125
+ return this;
126
+ }
127
+
128
+ verifyFor(email, callback){
129
+ const now = new Date().toISOString();
130
+
131
+ this.db.get(`SELECT * FROM verifications WHERE email = ? AND expiresAt > ?`, [email, now], (DBerr, row)=>{
132
+ if(DBerr) return callback(DBerr);
133
+
134
+ // console.log(`Code was got`);
135
+
136
+ if(!row){
137
+ // console.log(this.recieverEmail);
138
+ callback(null, false)
139
+ }else{
140
+ if(row.code === this.userCode){
141
+ // console.log('✅ User verified');
142
+ callback(null, true);
143
+ }else{
144
+ // console.log("❌ Code isn't correct")
145
+ callback(null, false);
146
+ }
147
+ }
148
+ });
149
+ }
150
+
151
+ makeOTP(length){
152
+ const buffer = crypto.randomBytes(length);
153
+ const number = parseInt(buffer.toString('hex'), 16)
154
+ .toString()
155
+ .slice(0, length);
156
+ return number.padStart(length, '0');
157
+ }
158
+
159
+ getOTP(email, callback){
160
+ this.db.get(`SELECT * FROM verifications WHERE email = ?`, [email], (err, row)=>{
161
+ if(err) return callback(err);
162
+ if(!row) return callback(null, null);
163
+
164
+ callback(null, { code: row.code, expiresAt: row.expiresAt });
165
+ });
166
+ }
167
+
168
+ cleanExpired() {
169
+ const now = new Date().toISOString();
170
+ this.db.run(
171
+ `DELETE FROM verifications WHERE expiresAt <= ?`,
172
+ [now],
173
+ function(err) {
174
+ if (err) console.error("Error cleaning expired OTPs:", err.message);
175
+ // Optional: console.log(`${this.changes} expired OTPs removed`);
176
+ }
177
+ );
178
+ }
179
+
180
+ }
181
+
182
+ module.exports = Verifier;
package/authverify.db ADDED
Binary file
package/index.js ADDED
@@ -0,0 +1,182 @@
1
+ const sqlite3 = require("sqlite3").verbose();
2
+ const nodemailer = require('nodemailer')
3
+ const crypto = require('crypto');
4
+ const { request } = require("http");
5
+
6
+ class Verifier {
7
+ constructor(sender = {}){
8
+ this.otpLen = sender.otp?.leng || 6;
9
+ this.expMin = sender.otp?.expMin || 3;
10
+ this.limit = sender.otp?.limit || 5;
11
+ this.cooldown = sender.otp?.cooldown || 60;
12
+ // Setup SMTP
13
+ this.transport = nodemailer.createTransport({
14
+ service: `${sender.serv}`,
15
+ auth: {
16
+ user: `${sender.sender}`,
17
+ pass: sender.pass
18
+ }
19
+ });
20
+
21
+ this.sender = `${sender.smtp?.sender}`
22
+
23
+ //making a db for saving otp codes
24
+ this.db = new sqlite3.Database('./authverify.db');
25
+ this.db.serialize(()=>{
26
+ // creating a table
27
+ this.db.run(`
28
+ CREATE TABLE IF NOT EXISTS verifications (
29
+ email TEXT PRIMARY KEY,
30
+ code TEXT,
31
+ expiresAt TEXT,
32
+ requests INTEGER DEFAULT 0,
33
+ lastRequest TEXT
34
+ )
35
+ `);
36
+ });
37
+
38
+ }
39
+
40
+ // Generate OTP securely
41
+ generateOTP() {
42
+ const buffer = crypto.randomBytes(this.otpLen);
43
+ const number = parseInt(buffer.toString('hex'), 16)
44
+ .toString()
45
+ .slice(0, this.otpLen);
46
+ return number.padStart(this.otpLen, '0');
47
+ }
48
+
49
+ html(html){
50
+ this.htmlContent = html;
51
+ return this;
52
+ }
53
+
54
+ subject(subject){
55
+ this.mailSubject = subject;
56
+ return this;
57
+ }
58
+
59
+ text(text){
60
+ this.mailText = text;
61
+ return this;
62
+ }
63
+
64
+ sendTo(email, callback){
65
+
66
+ this.recieverEmail = email;
67
+ const code = this.generateOTP();
68
+ const expAt = new Date(Date.now() + this.expMin * 60 * 1000).toISOString();
69
+
70
+ this.db.get(`SELECT * FROM verifications WHERE email = ?`, [email], (err, row)=>{
71
+ if(err) return callback(err);
72
+
73
+ const now = new Date();
74
+ let requests = 1;
75
+
76
+ if(row){
77
+ const lastRequest = row.lastRequest ? new Date(row.lastRequest) : null;
78
+
79
+ if(lastRequest && now.toDateString() === lastRequest.toDateString()){
80
+ requests = row.requests + 1;
81
+ if(requests > this.limit){
82
+ return callback(new Error("Too many OTP requests today"));
83
+ }
84
+
85
+ const diff = (now - lastRequest) / 1000;
86
+ if(diff < this.cooldown){
87
+ return callback(new Error(`Please wait ${Math.ceil(this.cooldown - diff)} seconds before requesting a new OTP.`));
88
+ }
89
+ }
90
+ }
91
+
92
+ this.db.run(`INSERT INTO verifications (email, code, expiresAt, requests, lastRequest) VALUES (?, ?, ?, ?, ?)
93
+ ON CONFLICT(email) DO UPDATE SET
94
+ code = excluded.code,
95
+ expiresAt = excluded.expiresAt,
96
+ requests = excluded.requests,
97
+ lastRequest = excluded.lastRequest`, [email, code, expAt, requests, now.toISOString()], (DBerr)=>{
98
+ if(DBerr) return callback(DBerr);
99
+
100
+ this.otpOptions = {
101
+ from: this.sender,
102
+ to: `${email}`,
103
+ subject: this.mailSubject ? this.mailSubject.replace("{otp}", code) : undefined,
104
+ text: this.mailText ? this.mailText.replace("{otp}", code) : undefined,
105
+ html: this.htmlContent ? this.htmlContent.replace("{otp}", code) : undefined
106
+ }
107
+
108
+ this.transport.sendMail(this.otpOptions, (emailErr, info)=>{
109
+ if(emailErr) return callback(emailErr);
110
+
111
+ // console.log('📨 Email sent:', info.response);
112
+ callback(null, true);
113
+ });
114
+
115
+ // console.log('💾 Code saved to DB');
116
+ });
117
+ });
118
+
119
+ return this;
120
+
121
+ }
122
+
123
+ code(userCode){
124
+ this.userCode = userCode
125
+ return this;
126
+ }
127
+
128
+ verifyFor(email, callback){
129
+ const now = new Date().toISOString();
130
+
131
+ this.db.get(`SELECT * FROM verifications WHERE email = ? AND expiresAt > ?`, [email, now], (DBerr, row)=>{
132
+ if(DBerr) return callback(DBerr);
133
+
134
+ // console.log(`Code was got`);
135
+
136
+ if(!row){
137
+ // console.log(this.recieverEmail);
138
+ callback(null, false)
139
+ }else{
140
+ if(row.code === this.userCode){
141
+ // console.log('✅ User verified');
142
+ callback(null, true);
143
+ }else{
144
+ // console.log("❌ Code isn't correct")
145
+ callback(null, false);
146
+ }
147
+ }
148
+ });
149
+ }
150
+
151
+ makeOTP(length){
152
+ const buffer = crypto.randomBytes(length);
153
+ const number = parseInt(buffer.toString('hex'), 16)
154
+ .toString()
155
+ .slice(0, length);
156
+ return number.padStart(length, '0');
157
+ }
158
+
159
+ getOTP(email, callback){
160
+ this.db.get(`SELECT * FROM verifications WHERE email = ?`, [email], (err, row)=>{
161
+ if(err) return callback(err);
162
+ if(!row) return callback(null, null);
163
+
164
+ callback(null, { code: row.code, expiresAt: row.expiresAt });
165
+ });
166
+ }
167
+
168
+ cleanExpired() {
169
+ const now = new Date().toISOString();
170
+ this.db.run(
171
+ `DELETE FROM verifications WHERE expiresAt <= ?`,
172
+ [now],
173
+ function(err) {
174
+ if (err) console.error("Error cleaning expired OTPs:", err.message);
175
+ // Optional: console.log(`${this.changes} expired OTPs removed`);
176
+ }
177
+ );
178
+ }
179
+
180
+ }
181
+
182
+ module.exports = Verifier;
package/otp.db ADDED
Binary file
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "dependencies": {
3
+ "crypto": "^1.0.1",
4
+ "express": "^5.1.0",
5
+ "nodemailer": "^7.0.6",
6
+ "sqlite3": "^5.1.7"
7
+ },
8
+ "name": "auth-verify",
9
+ "version": "0.0.1",
10
+ "description": "A simple Node.js library for sending and verifying OTP via email",
11
+ "main": "index.js",
12
+ "devDependencies": {},
13
+ "scripts": {
14
+ "test": "node test.js"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/jahongir2007/auth-verify.git"
19
+ },
20
+ "keywords": [
21
+ "auth",
22
+ "authentication",
23
+ "otp",
24
+ "email-verification",
25
+ "one-time-password",
26
+ "verification",
27
+ "nodejs",
28
+ "nodemailer",
29
+ "security",
30
+ "signup",
31
+ "login",
32
+ "two-factor",
33
+ "2fa",
34
+ "email"
35
+ ],
36
+ "author": "Jahongir Sobirov",
37
+ "license": "MIT",
38
+ "bugs": {
39
+ "url": "https://github.com/jahongir2007/auth-verify/issues"
40
+ },
41
+ "homepage": "https://jahongir2007.github.io/auth-verify/"
42
+ }
package/test.js ADDED
@@ -0,0 +1,34 @@
1
+ const Verifier = require("./Verifier"); // or "./index.js" if you renamed it
2
+
3
+ const verifier = new Verifier({
4
+ serv: "Gmail",
5
+ sender: "your_email@gmail.com",
6
+ pass: "your_app_password",
7
+ otp: {
8
+ length: 6,
9
+ expMin: 5,
10
+ limit: 5,
11
+ cooldown: 60
12
+ }
13
+ });
14
+
15
+ // Test sending OTP
16
+ verifier
17
+ .subject("Your OTP: {otp}")
18
+ .text("Your OTP code is {otp}")
19
+ .html("<h1>{otp}</h1>")
20
+ .sendTo("test_user@example.com", (err, success) => {
21
+ if (err) return console.error("Send failed:", err.message);
22
+ console.log("✅ OTP sent successfully!");
23
+
24
+ // Test verifying the same OTP
25
+ verifier.getOTP("test_user@example.com", (err, data) => {
26
+ if (err) return console.error(err);
27
+ console.log("Current OTP in DB:", data);
28
+
29
+ verifier.code(data.code).verifyFor("test_user@example.com", (err, verified) => {
30
+ if (err) return console.error(err);
31
+ console.log("Verified?", verified);
32
+ });
33
+ });
34
+ });