Supplier Schema and signup,signin

master
Bhaskara Kishore 3 years ago
parent 2321ea6077
commit 0742bc6469

@ -0,0 +1,150 @@
const fastify = require("fastify")({
logger: true,
});
const boom = require("boom");
const customJwtAuth = require("../customAuthJwt");
const bcrypt = require("bcrypt");
const saltRounds = 10;
//Get the data models
const { Supplier ,ProfilePicture, generateSupplierId} = require('../models/supplier');
async function bcryptPassword(password) {
encryptedPwd = bcrypt.hash(password, saltRounds);
return encryptedPwd;
}
async function bcryptComparePassword(pwd, encpassword) {
isSame = bcrypt.compare(pwd, encpassword);
return isSame;
}
//Supplier Login Controller
exports.loginSupplier = async (req) => {
try {
const phone = req.body.phone;
const password = req.body.password;
const supplier = await Supplier.findOne({ phone: phone });
// compare supplier password with what is supplied
if (supplier) {
isSame = await bcryptComparePassword(
password,
supplier.services.password.bcrypt
);
// if password supplied matches return object
if (isSame) {
return { same: true, supplier: supplier };
} else {
return { same: false };
}
} else {
return { same: false };
}
} catch (err) {
throw boom.boomify(err);
}
};
exports.addSupplier = async (req, reply) => {
try {
// await resetCounter();//to set customer id back to 0
var s_id = await generateSupplierId()
var building= ((req.body.suppliername).slice(0, 3)).toUpperCase();
var supplier_id = `AWS${building}${s_id}`
// console.log("This is the reply in the handler after the validations", reply);
s_data = {
supplierId: supplier_id,
suppliername: req.body.suppliername,
emails: req.body.emails,
password: req.body.password,
phone: req.body.phone,
profile: {
firstName: req.body.firstName,
lastName: req.body.lastName,
contactNumber: req.body.phone,
alternativeContactNumber: req.body.alternativeContactNumber,
country: req.body.country,
state: req.body.state,
city: req.body.city,
office_adress: req.body.office_adress,
zip: req.body.zip,
},
};
var supplier = new Supplier(s_data);
//password is not at the top level in the collection.
supplierpass = req.body.password;
// If fields are sent via form encoding , capture the fields and assign them to the user Object.
checkFormEncoding = isSupplierFormUrlEncoded(req);
if (checkFormEncoding.isSupplierFormUrlEncoded) {
suppliertobeInserted = checkFormEncoding.supplier;
console.log("thsi true url string");
supplier.suppliername = suppliertobeInserted.suppliername;
supplier.firstName = suppliertobeInserted.firstName;
supplier.lastName = suppliertobeInserted.lastName;
supplier.phone = suppliertobeInserted.phone;
supplier.emails = suppliertobeInserted.emails;
supplier.passsword = suppliertobeInserted.password;
supplier.supplierId = suppliertobeInserted.supplier_id;
supplier.office_adress = suppliertobeInserted.office_adress;
supplier.alternativeContactNumber = suppliertobeInserted.alternativeContactNumber;
}
console.log("---------checkurl ecnoded string-----------------------");
// Store hash in your password DB.
hash = await bcryptPassword(supplierpass);
if (hash) {
supplier.services.password.bcrypt = hash;
if (req.body.role) {
supplier.profile.role = req.body.role;
console.log("******************************************************");
console.log(supplier);
} else {
role = ["supplier"];
supplier.profile.role = role;
}
insertedSupplier = await supplier.save();
console.log(insertedSupplier);
if (insertedSupplier) {
// Prepare supplier object and wrap it inside the armintatankdata
var retSupplier = {
armintatankdata: {
suppliername: insertedSupplier.suppliername,
phone: insertedSupplier.phone,
supplierId: insertedSupplier.supplierId,
office_adress: insertedSupplier.office_adress,
emails: [
{
email: insertedSupplier.emails[0].email,
},
],
profile: insertedSupplier.profile,
},
status_code: 200,
};
return retSupplier;
}
}
} catch (err) {
throw boom.boomify(err);
}
};

@ -0,0 +1,467 @@
//Get the data models
const { Supplier } = require('../models/supplier');
const { ProfilePicture } = require('../models/User')
const supplierController = require("../controllers/supplierController");
const customJwtAuth = require("../customAuthJwt");
const fastify = require("fastify")({
logger: true,
//disableRequestLogging: true,
genReqId(req) {
// you get access to the req here if you need it - must be a synchronous function
return uuidv4();
},
});
const fastifyEnv = require("fastify-env");
const boom = require("boom");
const emailValidator = require("email-validator");
const libphonenumberjs = require("libphonenumber-js");
fastify.register(customJwtAuth);
const schema = {
type: "object",
required: ["PORT"],
properties: {
PORT: {
type: "string",
default: 3000,
},
APIVERSION: {
type: "string",
default: "1.0.0",
},
},
};
const options = {
confKey: "config", // optional, default: 'config'
schema: schema,
// data: data // optional, default: process.env
};
fastify.register(fastifyEnv, options).ready((err) => {
if (err) console.error(err);
console.log(fastify.config.PORT); // or fastify[options.confKey]
// output: { PORT: 3000 }
fastify.decorate("conf", {
port: fastify.config.PORT,
APIVERSION: fastify.config.APIVERSION,
});
});
const apiversion = "1.0.0";
// fastify.register(require('fastify-cookie'))
fastify.register(require('fastify-session'), {
secret: 'my-secret-key',
cookie: { secure: true }
});
isSupplierFormUrlEncoded = (req) => {
var isSupplierFormUrlEncoded = false;
console.log("check is Supplier encoe url funtion");
// This iterates through the req headers object.
// could not access req.headers.content-type due to the hyphen in the content-type key.
// console.log(`${key}: ${value}`);
for (const [key, value] of Object.entries(req.headers)) {
if (`${key}` === "content-type") {
if (`${value}` == "application/x-www-form-urlencoded") {
// console.log( "data supplied is with content type," , `${value}`)
// set isUserFormUrlEncoded value to true
isSupplierFormUrlEncoded = true;
// create user object with form variables . Password is used from the request object directly.
s_data = {
suppliername: req.body.suppliername,
phone: req.body.phone,
office_address: req.body.address1,
password: req.body.password,
emails: [
{
email: req.body.email,
},
],
profile: {
firstName: req.body.firstName,
lastName: req.body.lastName,
},
};
return { isSupplierFormUrlEncoded: isSupplierFormUrlEncoded, supplier: s_data };
} else {
return { isSupplierFormUrlEncoded: false, s_data: "" };
}
}
}
};
fastify.register((fastify, opts, done) => {
fastify.addContentTypeParser(
"application/json",
{ parseAs: "buffer" },
function (_req, body, done) {
try {
done(null, body)
} catch (error) {
error.statusCode = 400
done(error, undefined)
}
}
)
done(null)
})
//Login Supplier Handler
exports.loginSupplier = async(request, reply) =>{
loginObject = await supplierController.loginSupplier(request);
console.log("loginObject...",loginObject)
if (loginObject.same) {
const phoneVerified = loginObject.supplier.phoneVerified;
const oneTimePasswordSetFlag = loginObject.supplier.oneTimePasswordSetFlag;
console.log(
"oneTimePasswordSetFlag is ......",
oneTimePasswordSetFlag,
typeof oneTimePasswordSetFlag,
typeof phoneVerified
);
if (!phoneVerified) {
reply.send({
simplydata: {
error: false,
phoneVerified: false,
phone: loginObject.supplier.phone,
oneTimePasswordSetFlag: oneTimePasswordSetFlag,
message: "Please Verify your phone number",
},
});
} else if (!oneTimePasswordSetFlag) {
reply.send({
simplydata: {
error: false,
phoneVerified: phoneVerified,
phone: loginObject.supplier.phone,
oneTimePasswordSetFlag: true,
message: "Password must be reset",
},
});
} else {
const token = fastify.jwt.sign(
{
suppliername: loginObject.supplier.suppliername,
supplierId: loginObject.supplier._id,
roles: loginObject.supplier.profile.role,
},
//expiresIn: expressed in seconds or a string describing a time span zeit/ms. Eg: 60, "2 days", "10h", "7d".
//A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc),
//otherwise milliseconds unit is used by default ("120" is equal to "120ms").
{ expiresIn: "30d" }
);
console.log(token, "..token")
var arr = loginObject.supplier.profile.role;
var arrayToString = JSON.stringify(Object.assign({}, arr)); // convert array to string
var stringToJsonObject = JSON.parse(arrayToString); // convert string to json object
var s_id = loginObject.supplier.supplierId
console.log(s_id,"supplierId")
var profilePicture = await ProfilePicture.findOne({ supplierId:s_id});
// request.session.set('supplierId', loginObject.supplier._id)
if (!profilePicture) {
reply.send({
simplydata: {
error: false,
apiversion: fastify.config.APIVERSION,
access_token: token,
email: loginObject.supplier.emails,
phone: loginObject.supplier.phone,
supplierId: loginObject.supplier.supplierId,
suppliername: loginObject.supplier.suppliername,
office_address: loginObject.supplier.profile.address1,
phoneVerified: loginObject.supplier.phoneVerified,
oneTimePasswordSetFlag: loginObject.supplier.oneTimePasswordSetFlag,
type: loginObject.supplier.profile.role,
typeasobj: stringToJsonObject,
},
});
}if (profilePicture) {
reply.send({
simplydata: {
error: false,
apiversion: fastify.config.APIVERSION,
access_token: token,
picture:profilePicture.picture,
email: loginObject.supplier.emails,
phone: loginObject.supplier.phone,
supplierId: loginObject.supplier.supplierId,
suppliername: loginObject.supplier.suppliername,
office_address: loginObject.supplier.profile.address1,
phoneVerified: loginObject.supplier.phoneVerified,
oneTimePasswordSetFlag: loginObject.supplier.oneTimePasswordSetFlag,
type: loginObject.supplier.profile.role,
typeasobj: stringToJsonObject,
},
});
}
}
} else {
error = {
simplydata: {
error: true,
code: 400,
message: "Invalid SupplierId , Password supplied",
},
};
reply.send(error);
}
}
// Check if all the required fields are supplied by the user
exports.fieldCheck = async (req, reply) => {
try {
s_Data = {
suppliername: req.body.suppliername,
emails: req.body.emails,
password: req.body.password,
services: { password: {bcrypt: req.body.password} },
phone: req.body.phone,
profile: {
firstName: req.body.firstName,
lastName: req.body.lastName,
contactNumber: req.body.phone,
alternativeContactNumber: req.body.alternativeContactNumber,
country: req.body.country,
state: req.body.state,
city: req.body.city,
office_address: req.body.office_adress,
zip: req.body.zip,
},
};
var supplier = new Supplier(s_Data);
console.log(supplier,"..supplier")
//password is not at the top level in the collection.
password = req.body.password;
// capture fields if data is sent via form instead of json encoding
checkFormEncoding = isSupplierFormUrlEncoded(req);
if (checkFormEncoding.isSupplierFormUrlEncoded) {
suppliertobeInserted = checkFormEncoding.supplier;
supplier.suppliername = suppliertobeInserted.suppliername;
supplier.phone = suppliertobeInserted.phone;
supplier.emails = suppliertobeInserted.emails;
password = suppliertobeInserted.password;
}
console.log("User to be inserted is ", supplier.suppliername,password,supplier.phone,supplier.profile);
// check if all rerquired fields are passed.
if (
!(
supplier.suppliername &&
password &&
supplier.phone &&
// user.profile.firstName &&
// user.profile.lastName &&
// user.profile.address1 &&
supplier.emails[0].email
)
) {
console.log(
supplier.suppliername,
password,
supplier.phone,
// user.profile.firstName,
// user.profile.lastName,
supplier.emails[0].email
);
// Required Fields are missing
suppliedvalues =
supplier.suppliername +
" ," +
password +
" ," +
supplier.phone +
" ," +
supplier.firstName +
" ," +
supplier.lastName +
" ," +
supplier.emails[0].email;
error = {
armintatankdata: {
error: true,
code: 10004,
message:
"10004 - suppliername, password, phone , firstname , lastname email city country state address1 and zip are required fields. Supplied values are " +
suppliedvalues,
},
};
req.body.regError = error;
reply.send(error);
}
} catch (err) {
throw boom.boomify(err);
}
};
exports.validatePhoneFormat = async (req, reply) => {
try {
var supplier = new Supplier(req.body);
// check if user supplied phone is of the right format.
// Handle if the user data is supplied via a url encoded form
// capture fields if data is sent via form instead of json encoding
checkFormEncoding = isSupplierFormUrlEncoded(req);
console.log(checkFormEncoding);
if (checkFormEncoding.isSupplierFormUrlEncoded) {
suppliertobeInserted = checkFormEncoding.supplier;
supplier.suppliername = suppliertobeInserted.suppliername;
supplierser.firstName = suppliertobeInserted.firstName;
supplier.lastName = suppliertobeInserted.lastName;
supplier.phone = suppliertobeInserted.phone;
supplier.emails = suppliertobeInserted.emails;
}
if (supplier) {
const phoneNumber = libphonenumberjs.parsePhoneNumber(supplier.phone);
if (phoneNumber) {
// access returned collection
if (!phoneNumber.isValid()) {
error = {
armintatankdata: {
error: true,
code: 10002,
message:
"10002 - Phone # " +
user.phone +
" is not a valid phone number",
},
};
req.body.regError = error;
reply.status(406).send(error);
}
}
}
} catch (err) {
throw boom.boomify(err);
}
};
exports.verifySupplier = async (req, reply) => {
try {
var supplier = new Supplier(req.body);
// Handle if the user data is supplied via a url encoded form
// capture fields if data is sent via form instead of json encoding
checkFormEncoding = isSupplierFormUrlEncoded(req);
if (checkFormEncoding.isSupplierFormUrlEncoded) {
suppliertobeInserted = checkFormEncoding.supplier;
supplier.suppliername = suppliertobeInserted.suppliername;
supplier.firstName = suppliertobeInserted.firstName;
supplier.lastName = suppliertobeInserted.lastName;
supplierr.phone = suppliertobeInserted.phone;
supplier.emails = suppliertobeInserted.emails;
}
phone = supplier.phone;
supplierpass = req.body.password;
// check if user exists in the system. If user exists , display message that
// phone number is not available
supplierExists = await Supplier.findOne({ phone: phone });
if (supplierExists) {
// return user exists message
error = {
armintatankdata: {
error: true,
code: 10001,
message:
"10001 - Phone " +
supplierExists.phone +
" is not available. please use a different phone number",
},
};
req.body.regError = error;
reply.send(error);
}
} catch (err) {
throw boom.boomify(err);
}
};
exports.validateEmailFormat = async (req, reply) => {
try {
var supplier = new Supplier(req.body);
// Handle if the user data is supplied via a url encoded form
// capture fields if data is sent via form instead of json encoding
checkFormEncoding = isSupplierFormUrlEncoded(req);
if (checkFormEncoding.isSupplierFormUrlEncoded) {
suppliertobeInserted = checkFormEncoding.supplier;
supplier.suppliername = suppliertobeInserted.suppliername;
supplier.firstName = suppliertobeInserted.firstName;
supplier.lastName = suppliertobeInserted.lastName;
supplierr.phone = suppliertobeInserted.phone;
supplier.emails = suppliertobeInserted.emails;
}
supplieremail = await supplier.emails[0].email;
// check if user supplied email is of the right format.
if (supplier) {
const isValidEmail = emailValidator.validate(supplieremail.trim());
if (!isValidEmail) {
// Return email invalid format message
error = {
armintatankdata: {
error: true,
code: 10003,
message:
"10003 - Email " + supplier.emails[0].email + " is not a valid email",
},
};
req.body.regError = error;
reply.send(error);
}
}
} catch (err) {
throw boom.boomify(err);
}
};
exports.logoutsupplier = async (request, reply) => {
// request.session.delete();
// // send response to clear token
// reply.send({ message: 'Successfully logged out' })
const invalidatedTokens = {};
const accessToken = request.headers.authorization && request.body.access_token;
invalidatedTokens[accessToken] = true;
// // localStorage.removeItem(invalidatedTokens[accessToken])
reply.send({ message: 'Logout successful' })
}

@ -298,6 +298,7 @@ fastify.get("/api/reset_token/:customerId", {
},
{ expiresIn: "30d" }
);
reply.send({ access_token: token, customerId: get_user.customerId });
} catch (err) {
console.log(err);
@ -334,6 +335,8 @@ fastify.register(require("./routes/usersRoute"));
fastify.register(require("./routes/tanksRoute"));
fastify.register(require("./routes/createConnectionsRoute"));
fastify.register(require("./routes/tankersRoute.js"));
fastify.register(require("./routes/supplierRoute"))
// Testing route allows for retrieving a user by phone so one can see what is the phone verification code sent for a given user's phone
// Also allows deletion of a user with a given phone number

@ -0,0 +1,89 @@
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const ObjectId = Schema.Types.ObjectId;
const code = Math.floor(100000 + Math.random() * 900000);
const { User,Counter, generateBookingId,resetCounter,generateCustomerId,ProfilePicture} = require('../models/User')
const generateSupplierId = async () => {
var result = await Counter.findOneAndUpdate(
{ _id: 'supplier_id' },
{ $inc: { seq: 1 } },
{ upsert: true, new: true }
);
return result.seq;
};
const supplierSchema = new mongoose.Schema(
{
suppliername: { type: String },
phone: { type: String, unique: true, trim: true },
supplierId: {type : String, default: null},
phoneVerified: { type: Boolean, default: false },
phoneVerificationCode: { type: Number, default: 11111 },
passwordResetCode: { type: Number, default: code },
oneTimePasswordSetFlag: { type: Boolean, default: false },
emails: [{ email: String, verified: { type: Boolean, default: false } }],
services: { password: { bcrypt: String } },
profile: {
role: [{ type: String, default: "supplier" }],
firstName: { type: String, default: null },
lastName: { type: String, default: null },
contactNumber: { type: String, default: null },
alternativeContactNumber : { type: String, default: null },
office_address: { type: String, default: null },
city: { type: String, default: null },
state: { type: String, default: null },
country: { type: String, default: null },
zip: { type: String, default: null },
},
status: {
type: String,
enum: ['accept', 'pending', 'reject'],
default: 'pending'
},
currentGPS: {
// It's important to define type within type field, because
// mongoose use "type" to identify field's object type.
gpsType: { type: String, default: "Point" },
// Default value is needed. Mongoose pass an empty array to
// array type by default, but it will fail MongoDB's pre-save
// validation.
coordinates: { type: [Number], default: [0, 0] },
},
isActive: Boolean,
tenantId: ObjectId,
createdAt: {
type: Date,
default: function () {
return Date.now();
},
},
createdBy: ObjectId,
updatedAt: {
type: Date,
default: function () {
return Date.now();
},
},
updatedBy: ObjectId,
},
{ versionKey: false }
);
const Supplier = mongoose.model("Supplier", supplierSchema);
module.exports = { Supplier, generateSupplierId}

@ -0,0 +1,99 @@
const fastify = require("fastify");
const supplierController = require("../controllers/supplierController");
const validationHandler = require("../handlers/supplierHandler");
module.exports = function (fastify, opts, next) {
fastify.post("/api/supplierlogin", {
schema: {
description: "This is for Login Supplier",
tags: ["Supplier-Data"],
summary: "This is for Login Supplier",
body: {
type: "object",
required: ["phone", "password"],
properties: {
phone: { type: "string" },
password: { type: "string" },
},
},
},
handler: validationHandler.loginSupplier,
});
fastify.route({
method: "POST",
url: "/api/supplierlogout",
schema: {
description: "This is for Supplier logout",
tags: ["Supplier-Data"],
summary: "This is for Supplier logout",
params: {
type: "object",
properties: {
supplierId: {
type: "string",
description: "supplierId",
},
},
},
},
// preHandler: fastify.auth([fastify.authenticate]),
handler: validationHandler.logoutsupplier,
// onResponse: (request,reply) => {validationHandler.resetPassword(request,reply)}
});
fastify.route({
method: "POST",
url: "/api/suppliers",
schema: {
tags: ["Supplier-Data"],
description: "This is for cretae New supplier",
summary: "This is for Create New supplier.",
body: {
type: "object",
properties: {
suppliername: { type: "string" },
phone: { type: "string" },
alternativeContactNumber : { type : "string" },
password: { type: "string" },
emails: {
type: "array",
maxItems: 2,
items: {
type: "object",
properties: {
email: { type: "string", default: null },
},
},
},
office_address: { type: "string", default: null },
city: { type: "string", default: null },
state: { type: "string", default: null },
zip: { type: "string", default: null },
country: { type: "string", default: null },
},
},
security: [
{
basicAuth: [],
},
],
},
preHandler: [
validationHandler.fieldCheck,
validationHandler.verifySupplier,
// validationHandler.validatePhoneFormat,
validationHandler.validateEmailFormat,
],
handler: supplierController.addSupplier,
});
next();
}
Loading…
Cancel
Save