|
|
@ -925,43 +925,44 @@ fastify.post('/api/uploads-user/:customerId', async (request, reply) => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
fastify.post("/api/insatllLogin", {
|
|
|
|
fastify.post("/api/installLogin", {
|
|
|
|
schema: {
|
|
|
|
schema: {
|
|
|
|
description: "This is for Login Install",
|
|
|
|
description: "This is for Login Install",
|
|
|
|
tags: ["Installation"],
|
|
|
|
tags: ["Installation"],
|
|
|
|
summary: "This is for Login Install",
|
|
|
|
summary: "This is for Login Install",
|
|
|
|
body: {
|
|
|
|
body: {
|
|
|
|
type: "object",
|
|
|
|
type: "object",
|
|
|
|
required: ["phone", "password"],
|
|
|
|
required: ["type", "phone", "password"],
|
|
|
|
properties: {
|
|
|
|
properties: {
|
|
|
|
phone: { type: "string" },
|
|
|
|
type: { type: "string", description: "User role type (e.g., 'admin', 'manager')" },
|
|
|
|
password: { type: "string" },
|
|
|
|
phone: { type: "string", description: "Registered phone number" },
|
|
|
|
|
|
|
|
password: { type: "string", description: "Password for authentication" },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
async handler(req, reply) {
|
|
|
|
async handler(req, reply) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const { phone, password } = req.body;
|
|
|
|
const { type, phone, password } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
// Check if user exists in the Department Schema
|
|
|
|
// Check if user exists in the Department Schema
|
|
|
|
const user = await Deparments.findOne({ phone });
|
|
|
|
const user = await Deparments.findOne({ phone });
|
|
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
if (!user) {
|
|
|
|
return reply.code(400).send({ message: "User not found" });
|
|
|
|
return reply.code(400).send({ message: "User not found" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Verify Password
|
|
|
|
// Verify Password
|
|
|
|
const isMatch = await bcrypt.compare(password, user.services.password.bcrypt);
|
|
|
|
const isMatch = await bcrypt.compare(password, user.services.password.bcrypt);
|
|
|
|
|
|
|
|
|
|
|
|
if (!isMatch) {
|
|
|
|
if (!isMatch) {
|
|
|
|
return reply.code(400).send({ message: "Invalid credentials" });
|
|
|
|
return reply.code(400).send({ message: "Invalid credentials" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check if department details already exist in installationschema
|
|
|
|
// Check if department details already exist in installation schema
|
|
|
|
let installation = await Install.findOne({ phone });
|
|
|
|
let installation = await Install.findOne({ phone });
|
|
|
|
|
|
|
|
|
|
|
|
if (!installation) {
|
|
|
|
if (!installation) {
|
|
|
|
// Create a new entry in installationschema with departmentId as installationId
|
|
|
|
// Create a new entry in installation schema with departmentId as installationId
|
|
|
|
installation = new Install({
|
|
|
|
installation = new Install({
|
|
|
|
phone: user.phone,
|
|
|
|
phone: user.phone,
|
|
|
|
installationId: user.departmentId, // Store departmentId in installationId
|
|
|
|
installationId: user.departmentId, // Store departmentId in installationId
|
|
|
@ -979,20 +980,29 @@ fastify.post("/api/insatllLogin", {
|
|
|
|
profile: {
|
|
|
|
profile: {
|
|
|
|
state: user.state,
|
|
|
|
state: user.state,
|
|
|
|
country: user.country,
|
|
|
|
country: user.country,
|
|
|
|
|
|
|
|
role: type, // Store type in profile.role
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await installation.save();
|
|
|
|
await installation.save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure `type` is stored in `profile.role`
|
|
|
|
|
|
|
|
if (!installation.profile?.role) {
|
|
|
|
|
|
|
|
installation.profile.role = type;
|
|
|
|
|
|
|
|
await installation.save(); // Save the updated type
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Fetch profile picture if available
|
|
|
|
// Fetch profile picture if available
|
|
|
|
const profilePicture = await ProfilePictureInstall.findOne({ customerId: installation._id });
|
|
|
|
const profilePicture = await ProfilePictureInstall.findOne({ customerId: installation._id });
|
|
|
|
|
|
|
|
|
|
|
|
// Generate JWT Token
|
|
|
|
// Generate JWT Token
|
|
|
|
const token =fastify.jwt.sign({ userId: user._id, phone: user.phone }, "your_secret_key", {
|
|
|
|
const token = fastify.jwt.sign(
|
|
|
|
expiresIn: "7d",
|
|
|
|
{ userId: user._id, phone: user.phone, role: installation.profile?.role },
|
|
|
|
});
|
|
|
|
"your_secret_key",
|
|
|
|
|
|
|
|
{ expiresIn: "7d" }
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// Construct response payload
|
|
|
|
// Construct response payload
|
|
|
|
const responsePayload = {
|
|
|
|
const responsePayload = {
|
|
|
|
simplydata: {
|
|
|
|
simplydata: {
|
|
|
@ -1016,101 +1026,114 @@ fastify.post("/api/insatllLogin", {
|
|
|
|
address: installation.address || "",
|
|
|
|
address: installation.address || "",
|
|
|
|
alternativeNumber: installation.alternativeNumber || null,
|
|
|
|
alternativeNumber: installation.alternativeNumber || null,
|
|
|
|
profilePicture: profilePicture ? profilePicture.pictureUrl : null, // Include profile picture URL if available
|
|
|
|
profilePicture: profilePicture ? profilePicture.pictureUrl : null, // Include profile picture URL if available
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return reply.send(responsePayload);
|
|
|
|
return reply.send(responsePayload);
|
|
|
|
} catch (error) {
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Login Error:", error);
|
|
|
|
console.error("Login Error:", error);
|
|
|
|
return reply.code(500).send({ message: "Internal server error" });
|
|
|
|
return reply.code(500).send({ message: "Internal server error" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},});
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
fastify.post("/api/teamMemberLogin", {
|
|
|
|
|
|
|
|
schema: {
|
|
|
|
|
|
|
|
description: "Login API for team members",
|
|
|
|
fastify.post("/api/teamMemberLogin", {
|
|
|
|
tags: ["Installation"],
|
|
|
|
schema: {
|
|
|
|
summary: "Login as a Team Member",
|
|
|
|
description: "Login API for team members",
|
|
|
|
body: {
|
|
|
|
tags: ["Installation"],
|
|
|
|
type: "object",
|
|
|
|
summary: "Login as a Team Member",
|
|
|
|
required: ["phone", "password"],
|
|
|
|
body: {
|
|
|
|
properties: {
|
|
|
|
type: "object",
|
|
|
|
phone: { type: "string", description: "Registered phone number of the team member" },
|
|
|
|
required: ["type", "phone", "password"],
|
|
|
|
password: { type: "string", description: "Password for authentication" },
|
|
|
|
properties: {
|
|
|
|
},
|
|
|
|
type: { type: "string", description: "Role type of the user (e.g., 'team_member')" },
|
|
|
|
|
|
|
|
phone: { type: "string", description: "Registered phone number of the team member" },
|
|
|
|
|
|
|
|
password: { type: "string", description: "Password for authentication" },
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
async handler(request, reply) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const { type, phone, password } = request.body;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find team member in any installation
|
|
|
|
|
|
|
|
const installation = await Install.findOne({ "team_member.team_member.phone": phone });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!installation) {
|
|
|
|
|
|
|
|
return reply.status(401).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number or password",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find team member details
|
|
|
|
|
|
|
|
const teamMember = installation.team_member.team_member.find(
|
|
|
|
|
|
|
|
(member) => member.phone === phone
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!teamMember) {
|
|
|
|
|
|
|
|
return reply.status(401).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number or password",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Verify password
|
|
|
|
|
|
|
|
const isPasswordValid = await bcrypt.compare(password, teamMember.password);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!isPasswordValid) {
|
|
|
|
|
|
|
|
return reply.status(401).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number or password",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Store the `type` in the database (if not already stored)
|
|
|
|
|
|
|
|
if (!teamMember.type) {
|
|
|
|
|
|
|
|
teamMember.type = type;
|
|
|
|
|
|
|
|
await installation.save(); // Save the updated team member type
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate JWT token
|
|
|
|
|
|
|
|
const token = fastify.jwt.sign(
|
|
|
|
|
|
|
|
{ phone: teamMember.phone, role: type, installationId: installation.installationId },
|
|
|
|
|
|
|
|
process.env.JWT_SECRET,
|
|
|
|
|
|
|
|
{ expiresIn: "1h" }
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: false,
|
|
|
|
|
|
|
|
message: "Login successful",
|
|
|
|
|
|
|
|
access_token: token,
|
|
|
|
|
|
|
|
phone: teamMember.phone,
|
|
|
|
|
|
|
|
teamMemberId: teamMember.teamMemberId,
|
|
|
|
|
|
|
|
alternativePhone: teamMember.alternativePhone || null,
|
|
|
|
|
|
|
|
email: teamMember.email || null,
|
|
|
|
|
|
|
|
status: teamMember.status || "active",
|
|
|
|
|
|
|
|
type: teamMember.type, // Returning the stored type
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
|
|
console.error("Error logging in:", err);
|
|
|
|
|
|
|
|
reply.status(500).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Internal server error",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
async handler(request, reply) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const { phone, password } = request.body;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find team member in any installation
|
|
|
|
|
|
|
|
const installation = await Install.findOne({ "team_member.team_member.phone": phone });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!installation) {
|
|
|
|
|
|
|
|
return reply.status(401).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number or password",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find team member details
|
|
|
|
|
|
|
|
const teamMember = installation.team_member.team_member.find(
|
|
|
|
|
|
|
|
(member) => member.phone === phone
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!teamMember) {
|
|
|
|
|
|
|
|
return reply.status(401).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number or password",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Verify password
|
|
|
|
|
|
|
|
const isPasswordValid = await bcrypt.compare(password, teamMember.password);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!isPasswordValid) {
|
|
|
|
|
|
|
|
return reply.status(401).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number or password",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate JWT token
|
|
|
|
|
|
|
|
const token = fastify.jwt.sign(
|
|
|
|
|
|
|
|
{ phone: teamMember.phone, role: "team_member", installationId: installation.installationId },
|
|
|
|
|
|
|
|
"JWT_SECRET",
|
|
|
|
|
|
|
|
{ expiresIn: "1h" }
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: false,
|
|
|
|
|
|
|
|
message: "Login successful",
|
|
|
|
|
|
|
|
access_token: token,
|
|
|
|
|
|
|
|
phone: teamMember.phone,
|
|
|
|
|
|
|
|
teamMemberId: teamMember.teamMemberId,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
|
|
console.error("Error logging in:", err);
|
|
|
|
|
|
|
|
reply.status(500).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Internal server error",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Run the server!
|
|
|
|
// Run the server!
|
|
|
|
const start = async () => {
|
|
|
|
const start = async () => {
|
|
|
|