@sajakshrestha8/auth-service 1.0.0
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/Readme.md +20 -0
- package/index.js +3 -0
- package/package.json +25 -0
- package/repository/user.repository.js +29 -0
- package/services/register.service.js +149 -0
package/Readme.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Auth Service
|
|
2
|
+
|
|
3
|
+
Reusable authentication service for Node.js applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
npm install @as/auth-service
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
const { authService } = require("@yourusername/auth-service");
|
|
12
|
+
|
|
13
|
+
const authService = authService({
|
|
14
|
+
createUser,
|
|
15
|
+
getUserByEmail,
|
|
16
|
+
getUserByUserName,
|
|
17
|
+
saltRounds,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const result = await authService.loginService({ email, password }, db);
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sajakshrestha8/auth-service",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"start": "nodemon index.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"auth",
|
|
12
|
+
"login",
|
|
13
|
+
"register",
|
|
14
|
+
"nodejs"
|
|
15
|
+
],
|
|
16
|
+
"author": "Sajak Shrestha",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"description": "Reusable authentication service for Node.js",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"bcrypt": "^6.0.0",
|
|
21
|
+
"express": "^5.2.1",
|
|
22
|
+
"nodemon": "^3.1.11",
|
|
23
|
+
"sqlite3": "^5.1.7"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { dbGet, dbRun } = require("../database/db.utils/utils");
|
|
2
|
+
|
|
3
|
+
async function getUserByUserName(username, db) {
|
|
4
|
+
console.log("yeta aako xa");
|
|
5
|
+
const row = await dbGet(
|
|
6
|
+
"SELECT id FROM users WHERE username = ?",
|
|
7
|
+
[username],
|
|
8
|
+
db
|
|
9
|
+
);
|
|
10
|
+
return !!row;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function getUserByEmail(email, db) {
|
|
14
|
+
const row = await dbGet("SELECT * FROM users WHERE email = ?", [email], db);
|
|
15
|
+
return row;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function createUser(
|
|
19
|
+
{ firstname, lastname, username, email, password },
|
|
20
|
+
db
|
|
21
|
+
) {
|
|
22
|
+
await dbRun(
|
|
23
|
+
"INSERT INTO users (firstname, lastname, username, email, password) VALUES (?, ?, ?, ?, ?)",
|
|
24
|
+
[firstname, lastname, username, email, password],
|
|
25
|
+
db
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = { getUserByUserName, createUser, getUserByEmail };
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
const bcrypt = require("bcrypt");
|
|
2
|
+
|
|
3
|
+
const DEFAULT_SALT_ROUNDS = 10;
|
|
4
|
+
|
|
5
|
+
const validateFields = (data, requiredFields) => {
|
|
6
|
+
const errors = {};
|
|
7
|
+
|
|
8
|
+
requiredFields.forEach((field) => {
|
|
9
|
+
if (!data[field] || String(data[field]).trim() === "") {
|
|
10
|
+
errors[field] = `${field} is required`;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (data.email && !/^\S+@\S+\.\S+$/.test(data.email)) {
|
|
15
|
+
errors.email = "Invalid email format";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (data.password && data.password.length < 6) {
|
|
19
|
+
errors.password = "Password must be at least 6 characters";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return Object.keys(errors).length > 0 ? errors : null;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const authService = ({
|
|
26
|
+
createUser,
|
|
27
|
+
getUserByEmail,
|
|
28
|
+
getUserByUserName,
|
|
29
|
+
saltRounds = DEFAULT_SALT_ROUNDS,
|
|
30
|
+
}) => {
|
|
31
|
+
if (!createUser || !getUserByEmail || !getUserByUserName) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
"authService requires createUser, getUserByEmail, and getUserByUserName functions"
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const registerService = async (data, db) => {
|
|
38
|
+
try {
|
|
39
|
+
const errors = validateFields(data, [
|
|
40
|
+
"firstname",
|
|
41
|
+
"lastname",
|
|
42
|
+
"username",
|
|
43
|
+
"email",
|
|
44
|
+
"password",
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
if (errors) {
|
|
48
|
+
return { ok: false, status: 400, errors };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const { firstname, lastname, username, email, password } = data;
|
|
52
|
+
|
|
53
|
+
if (await getUserByUserName(username, db)) {
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
status: 409,
|
|
57
|
+
errors: { username: "Username already exists" },
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (await getUserByEmail(email, db)) {
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
status: 409,
|
|
65
|
+
errors: { email: "Email already exists" },
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const hashedPassword = await bcrypt.hash(password, saltRounds);
|
|
70
|
+
|
|
71
|
+
await createUser(
|
|
72
|
+
{
|
|
73
|
+
firstname,
|
|
74
|
+
lastname,
|
|
75
|
+
username,
|
|
76
|
+
email,
|
|
77
|
+
password: hashedPassword,
|
|
78
|
+
},
|
|
79
|
+
db
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
ok: true,
|
|
84
|
+
status: 201,
|
|
85
|
+
message: "User registered successfully",
|
|
86
|
+
data: { email },
|
|
87
|
+
};
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error("Register Error:", error);
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
status: 500,
|
|
93
|
+
message: "Internal server error",
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const loginService = async ({ email, password }, db) => {
|
|
99
|
+
try {
|
|
100
|
+
const errors = validateFields({ email, password }, ["email", "password"]);
|
|
101
|
+
|
|
102
|
+
if (errors) {
|
|
103
|
+
return { ok: false, status: 400, errors };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const user = await getUserByEmail(email, db);
|
|
107
|
+
|
|
108
|
+
if (!user) {
|
|
109
|
+
return {
|
|
110
|
+
ok: false,
|
|
111
|
+
status: 404,
|
|
112
|
+
message: "User not found",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const isMatch = await bcrypt.compare(password, user.password);
|
|
117
|
+
|
|
118
|
+
if (!isMatch) {
|
|
119
|
+
return {
|
|
120
|
+
ok: false,
|
|
121
|
+
status: 401,
|
|
122
|
+
message: "Incorrect password",
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
ok: true,
|
|
128
|
+
status: 200,
|
|
129
|
+
message: "Login successful",
|
|
130
|
+
data: {
|
|
131
|
+
id: user.id,
|
|
132
|
+
email: user.email,
|
|
133
|
+
username: user.username,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error("Login Error:", error);
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
status: 500,
|
|
141
|
+
message: "Internal server error",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return { registerService, loginService };
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
module.exports = { authService };
|