diff --git a/src/controllers/admincontroller.js b/src/controllers/admincontroller.js index 5148f1f5..c389ef56 100644 --- a/src/controllers/admincontroller.js +++ b/src/controllers/admincontroller.js @@ -3,9 +3,28 @@ const boom = require("boom"); const jwt = require('jsonwebtoken') const bcrypt = require('bcrypt') + const fastify = require("fastify"); const { Tank, MotorData, IotData } = require('../models/tanks') +const JWT_SECRET = 'your-secret-key'; + +async function generateCustomerId() { + let customerId; + let isUnique = false; + + while (!isUnique) { + // Generate a random number or string for the customer ID + customerId = Math.floor(1000 + Math.random() * 9000).toString(); // Generates a random number between 1000 and 9999 + + // Check for uniqueness in the Admin collection + const existingAdmin = await Admin.findOne({ customerId }); + if (!existingAdmin) { + isUnique = true; // Exit the loop if the customer ID is unique + } + } + return customerId; +} // exports.adminSignUp = async (request, reply) => { @@ -39,73 +58,355 @@ const { Tank, MotorData, IotData } = require('../models/tanks') // } // } -exports.adminSignUp = async (request, reply) => { +// exports.adminSignUp = async (request, reply) => { - try { - const { email, password } = request.body +// try { +// const { email, password } = request.body - // Check if the email address is valid - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ - if (!emailRegex.test(email)) { - return reply.status(400).send({ message: 'Invalid email address' }) - } +// // Check if the email address is valid +// const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ +// if (!emailRegex.test(email)) { +// return reply.status(400).send({ message: 'Invalid email address' }) +// } - // Check if an admin with the same email address already exists - const existingAdmin = await Admin.findOne({ email }) +// // Check if an admin with the same email address already exists +// const existingAdmin = await Admin.findOne({ email }) - if (existingAdmin) { - return reply.status(400).send({ message: 'Email already registered' }) - } +// if (existingAdmin) { +// return reply.status(400).send({ message: 'Email already registered' }) +// } - // Hash the password using bcrypt - const hashedPassword = await bcrypt.hash(password, 10) +// // Hash the password using bcrypt +// const hashedPassword = await bcrypt.hash(password, 10) - // Create a new admin object with the hashed password - const admin = new Admin({ email, password: hashedPassword }) +// // Create a new admin object with the hashed password +// const admin = new Admin({ email, password: hashedPassword }) - // Save the new admin to the database - await admin.save() +// // Save the new admin to the database +// await admin.save() - // Generate a JWT token for the new admin - // const token = jwt.sign({ email: admin.email }, 'secret') +// // Generate a JWT token for the new admin +// // const token = jwt.sign({ email: admin.email }, 'secret') - // // Return the token to the client - // return { token } - reply.send({message : "Admin Account Created Sucessfully"}) - } catch (err) { - reply.status(500).send({ message: err.message }) - } - } +// // // Return the token to the client +// // return { token } +// reply.send({message : "Admin Account Created Sucessfully"}) +// } catch (err) { +// reply.status(500).send({ message: err.message }) +// } +// } - exports.adminLogin = async (request, reply) => { - try { - const { email, password } = request.body +// exports.adminLogin = async (request, reply) => { +// try { +// const { email, password } = request.body - // Check if an admin with the email address exists - const admin = await Admin.findOne({ email }) +// // Check if an admin with the email address exists +// const admin = await Admin.findOne({ email }) - if (!admin) { - return reply.status(401).send({ message: 'Invalid email or password' }) - } +// if (!admin) { +// return reply.status(401).send({ message: 'Invalid email or password' }) +// } - // Compare the password entered by the user with the hashed password stored in the database - const isPasswordValid = await bcrypt.compare(password, admin.password) +// // Compare the password entered by the user with the hashed password stored in the database +// const isPasswordValid = await bcrypt.compare(password, admin.password) - if (!isPasswordValid) { - return reply.status(401).send({ message: 'Invalid email or password' }) - } +// if (!isPasswordValid) { +// return reply.status(401).send({ message: 'Invalid email or password' }) +// } - // Generate a JWT token for the authenticated admin - const token = jwt.sign({ email: admin.email }, 'secret') +// // Generate a JWT token for the authenticated admin +// const token = jwt.sign({ email: admin.email }, 'secret') - // Return the token to the client - return { token } - } catch (err) { - reply.status(500).send({ message: err.message }) - } +// // Return the token to the client +// return { token } +// } catch (err) { +// reply.status(500).send({ message: err.message }) +// } +// } + + +// Admin Sign-Up Function +// exports.adminSignUp = async (request, reply) => { +// try { +// const { phone,username, password } = request.body; + +// // Check if the email address is valid +// // const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; +// // if (!emailRegex.test(email)) { +// // return reply.status(400).send({ message: 'Invalid email address' }); +// // } +// if (!username || username.trim() === '') { +// return reply.status(400).send({ message: 'Username is required' }); +// } + + +// // Check if an admin with the same email address already exists +// const existingAdminUsername = await Admin.findOne({ username }); +// const existingAdmin = await Admin.findOne({ phone }); +// if (existingAdmin) { +// return reply.status(400).send({ message: 'phone already registered' }); +// } +// if (existingAdminUsername) { +// return reply.status(400).send({ message: 'Username already registered' }); +// } + +// // Hash the password using bcrypt +// const hashedPassword = await bcrypt.hash(password, 10); + +// // Create a new admin object with the hashed password +// const admin = new Admin({ phone,username, password: hashedPassword }); + +// // Save the new admin to the database +// await admin.save(); + +// reply.send({ message: 'Admin Account Created Successfully' }); +// } catch (err) { +// reply.status(500).send({ message: err.message }); +// } +// }; + +exports.adminSignUp = async (request, reply) => { + try { + const { phone, username, password, role } = request.body; + + if (!username || username.trim() === '') { + return reply.status(400).send({ message: 'Username is required' }); + } + + // Validate role + if (!['admin', 'sales', 'store'].includes(role)) { + return reply.status(400).send({ message: 'Invalid role. Must be either admin, sales, or store' }); + } + + + + // Check if an admin with the same phone number or username already exists + const existingAdminUsername = await Admin.findOne({ username }); + const existingAdmin = await Admin.findOne({ phone }); + + if (existingAdmin) { + return reply.status(400).send({ message: 'Phone already registered' }); + } + if (existingAdminUsername) { + return reply.status(400).send({ message: 'Username already registered' }); + } + + // Hash the password using bcrypt + const hashedPassword = await bcrypt.hash(password, 10); + + const c_id = await generateCustomerId(); // Assuming you have this function defined elsewhere + const building = 'ADMIN'; // You can customize this logic to derive from a parameter or a default value + const customerId = `AWSU${building}${c_id}`; // Construct the customer ID + + // Create a new admin object with the hashed password and role + const admin = new Admin({ phone, username, password: hashedPassword, customerId, role }); + + // Save the new admin to the database + await admin.save(); + + reply.send({ message: 'Admin Account Created Successfully' }); + } catch (err) { + reply.status(500).send({ message: err.message }); + } +}; + + +// Admin Login Function (With Phone Number) +exports.adminLogin = async (request, reply) => { + try { + const { phone, password } = request.body; + + // Check if an admin with the phone number exists + const admin = await Admin.findOne({ phone }); + + if (!admin) { + return reply.status(401).send({ message: 'Invalid phone number or password' }); + } + + // Compare the password entered by the user with the hashed password stored in the database + const isPasswordValid = await bcrypt.compare(password, admin.password); + + if (!isPasswordValid) { + return reply.status(401).send({ message: 'Invalid phone number or password' }); + } + + // Generate a JWT token for the authenticated admin + const token = jwt.sign({ phone: admin.phone, role: 'admin' }, JWT_SECRET, { expiresIn: '1h' }); + + return reply.send({ token }); + } catch (err) { + reply.status(500).send({ message: err.message }); + } +}; + +// Sales and Store Login (Phone and Password) +// exports.salesStoreLogin = async (request, reply) => { +// try { +// const { phone, password } = request.body; + +// // Check if a user (sales or store) with the phone number exists +// const admin = await Admin.findOne({ phone }); + +// if (!admin) { +// return reply.status(401).send({ message: 'Invalid phone number or password' }); +// } + +// // Compare the password entered by the user with the hashed password stored in the database +// const isPasswordValid = await bcrypt.compare(password, admin.password); + +// if (!isPasswordValid) { +// return reply.status(401).send({ message: 'Invalid phone number or password' }); +// } + +// // Generate a JWT token for the authenticated user (with role sales or store) +// const token = jwt.sign({ phone: admin.phone, role: admin.role }, JWT_SECRET, { expiresIn: '1h' }); + +// return reply.send({ token }); +// } catch (err) { +// reply.status(500).send({ message: err.message }); +// } +// }; + +exports.salesStoreLogin = async (request, reply) => { + try { + const { phone, password, role } = request.body; + + // Check if a user (sales or store) with the phone number and role exists + const user = await Admin.findOne({ phone, role }); + + if (!user) { + return reply.status(401).send({ message: 'Invalid phone number, password, or role' }); + } + + // Compare the password entered by the user with the hashed password stored in the database + const isPasswordValid = await bcrypt.compare(password, user.password); + + if (!isPasswordValid) { + return reply.status(401).send({ message: 'Invalid phone number, password, or role' }); + } + + // Generate a JWT token for the authenticated user (with role sales or store) + const token = jwt.sign({ phone: user.phone, role: user.role }, JWT_SECRET, { expiresIn: '1h' }); + + return reply.send({ token }); + } catch (err) { + reply.status(500).send({ message: err.message }); + } +}; + + +exports.getUsersByRole = async (request, reply) => { + try { + const { role } = request.params; + + // Ensure the role is either 'sales' or 'store' + if (!['sales', 'store'].includes(role)) { + return reply.status(400).send({ message: 'Invalid role. Must be either sales or store.' }); + } + + // Find users with the specific role (sales or store) + const users = await Admin.find({ role }); + + // Send back the list of users + reply.send(users); + } catch (err) { + reply.status(500).send({ message: err.message }); } +}; + +exports.getUserByCustomerId = async (request, reply) => { + try { + const { customerId } = request.params; + + // Check if customerId is provided + if (!customerId) { + return reply.status(400).send({ message: 'Customer ID is required' }); + } + + // Fetch the user from the database + const user = await Admin.findOne({ customerId }); + + // If user not found, return a 404 response + if (!user) { + return reply.status(404).send({ message: 'User not found' }); + } + + // Return the user data + return reply.send(user); + } catch (err) { + return reply.status(500).send({ message: err.message }); + } +}; + + +// Create Sales/Store User (Admin Only) +// exports.createUser = async (request, reply) => { +// const { phone, password, role } = request.body; + +// // Validate role (only sales or store) +// if (!['sales', 'store'].includes(role)) { +// return reply.status(400).send({ message: 'Invalid role. Must be either sales or store' }); +// } + +// try { +// const existingUser = await Admin.findOne({ phone }); + +// if (existingUser) { +// return reply.status(400).send({ message: 'User with this phone number already exists' }); +// } + +// // Hash the password +// const hashedPassword = await bcrypt.hash(password, 10); + +// // Create the new user +// const newUser = new Admin({ +// phone, +// password: hashedPassword, +// role, +// }); + +// await newUser.save(); + +// return reply.send({ message: 'User created successfully' }); +// } catch (err) { +// reply.status(500).send({ message: err.message }); +// } +// }; + +exports.createUser = async (request, reply) => { + const { phone, password, role } = request.body; + + // Validate role (only sales or store) + if (!['sales', 'store'].includes(role)) { + return reply.status(400).send({ message: 'Invalid role. Must be either sales or store' }); + } + + try { + const existingUser = await Admin.findOne({ phone }); + + if (existingUser) { + return reply.status(400).send({ message: 'User with this phone number already exists' }); + } + + // Hash the password + const hashedPassword = await bcrypt.hash(password, 10); + + // Create the new user + const newUser = new Admin({ + phone, + password: hashedPassword, + role, + }); + + await newUser.save(); + return reply.send({ message: 'User created successfully' }); + } catch (err) { + reply.status(500).send({ message: err.message }); + } +}; + @@ -120,8 +421,3 @@ exports.adminSignUp = async (request, reply) => { } } - - - - - \ No newline at end of file diff --git a/src/models/admin.js b/src/models/admin.js index 29de8268..2a962f4c 100644 --- a/src/models/admin.js +++ b/src/models/admin.js @@ -1,18 +1,40 @@ const mongoose = require('mongoose') + + const adminSchema = new mongoose.Schema({ - email: { + + phone: { + type: String, + required: true, + //unique: true, + }, + + username: { type: String, required: true, unique: true, - lowercase: true }, password: { type: String, required: true - } + }, + role: { + type: String, + enum: ['admin', 'sales', 'store'], + default: 'sales', + }, + customerId: { + type: String, + required: true, // Customer ID is now required + unique: true, + }, + date: { + type: Date, + default: Date.now, + }, }) const Admin = mongoose.model('Admin', adminSchema) -module.exports = Admin +module.exports = Admin \ No newline at end of file diff --git a/src/routes/adminRoute.js b/src/routes/adminRoute.js index cbf3eff6..54629f06 100644 --- a/src/routes/adminRoute.js +++ b/src/routes/adminRoute.js @@ -3,31 +3,58 @@ const adminController = require('../controllers/admincontroller') module.exports = function (fastify, opts, next) { +// fastify.route({ +// method: "POST", +// url: "/api/adminSignup", +// schema: { +// tags: ["Admin"], +// description: "This is for cretae New Admin Account", +// summary: "This is for cretae New Admin Account", +// body: { +// type: "object", +// properties: { +// phone : { type: "string" }, +// password: { type: "string" }, +// username:{type:"string"}, +// }, +// }, +// security: [ +// { +// basicAuth: [], +// }, +// ], +// }, + +// handler: adminController.adminSignUp, + +// }); + fastify.route({ - method: "POST", - url: "/api/adminSignup", - schema: { - tags: ["Admin"], - description: "This is for cretae New Admin Account", - summary: "This is for cretae New Admin Account", - body: { - type: "object", - properties: { - email: { type: "string" }, - password: { type: "string" }, - - }, + method: "POST", + url: "/api/adminSignup", + schema: { + tags: ["Admin"], + description: "This is for creating a new Admin/sales/store Account", + summary: "This is for creating a new Admin/sales/store Account", + body: { + type: "object", + required: ["phone", "username", "password", "role"], // Add role to required fields + properties: { + phone: { type: "string" }, + password: { type: "string" }, + username: { type: "string" }, + role: { type: "string", enum: ["admin", "sales", "store"] }, // Define allowed roles }, - security: [ - { - basicAuth: [], - }, - ], }, + security: [ + { + basicAuth: [], + }, + ], + }, + handler: adminController.adminSignUp, +}); - handler: adminController.adminSignUp, - - }); fastify.post("/api/adminLogin", { schema: { @@ -36,9 +63,9 @@ fastify.route({ summary: "This is for Login Admin", body: { type: "object", - required: ["email", "password"], + required: ["phone", "password"], properties: { - email: { type: "string" }, + phone : { type: "string" }, password: { type: "string" }, }, }, @@ -46,6 +73,100 @@ fastify.route({ handler: adminController.adminLogin, }); +fastify.post("/api/salesStoreLogin", { + schema: { + description: "Login for sales/store users", + tags: ["Sales/Store Login"], + summary: "Login for sales/store users", + body: { + type: "object", + required: ["phone", "password", "role"], + properties: { + phone : { type: "string" }, + password: { type: "string" }, + role: { type: "string", enum: ["sales", "store"] } + }, + }, + }, + handler: adminController.salesStoreLogin, +}); + + +fastify.get("/api/getUsersByRole/:role", { + schema: { + description: "Get list of users by role (sales/store)", + tags: ["Sales/Store Users"], + summary: "Get list of users by role", + params: { + type: "object", + properties: { + role: { type: "string", enum: ["sales", "store"] }, + }, + required: ["role"], + }, + response: { + 200: { + type: "array", + items: { + type: "object", + properties: { + phone: { type: "string" }, + username: { type: "string" }, + role: { type: "string" }, + date: { type: "string", format: "date-time" } + } + } + } + } + }, + handler: adminController.getUsersByRole, +}); + +fastify.route({ + method: "GET", + url: "/api/users/:customerId", // Use path parameters for customerId + schema: { + tags: ["Admin"], + description: "Retrieve user information by customerId", + summary: "Get user by customerId", + params: { + type: "object", + required: ["customerId"], + properties: { + customerId: { type: "string" }, + }, + }, + security: [ + { + basicAuth: [], + }, + ], + }, + handler: adminController.getUserByCustomerId, // Link the handler function +}); + + +// fastify.post("/api/createUser", { +// schema: { +// description: "This is for Create sale/store", +// tags: ["createUser for sale/sore"], +// summary: "This is for Create sale/store", +// body: { +// type: "object", +// required: ["phone", "password", "role"], +// properties: { +// phone : { type: "string" }, +// password: { type: "string" }, +// role: { type: "string", enum: ["sales", "store"] } +// }, +// }, +// }, +// handler: adminController.createUser, +// }); + + + + fastify.post("/api/integratingHardwareidToTank", { schema: { description: "This is for integrating hardwareId with tank",