const AdminJSFastify = require('@adminjs/fastify') const AdminJS = require('adminjs') const userController = require("./controllers/userController"); const cors = require("cors"); const swagger = require("./config/swagger"); const rawBody = require("raw-body"); const uuidv4 = require("uuid").v4; 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 now = () => Date.now(); const fastifyEnv = require("fastify-env"); 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"; const path = require("path"); // Using static content for swagger documentation. Generated swagger UI is not user friendly. Fastify.register(require("fastify-static"), { root: path.join(__dirname, "api-docs"), prefix: "/api-docs", // optional: default '/' }); Fastify.register(require("fastify-swagger"), swagger.options); const customJwtAuth = require("./customAuthJwt"); Fastify.register(customJwtAuth); //login route - accept user credentials and send a token with role . "user" role is required to use the app. // support login using application/x-www-form-urlencoded so users can login via a web form in addition to api Fastify.register(require("fastify-formbody")); 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); }); Fastify.register(require("point-of-view"), { engine: { nunjucks: require("nunjucks"), }, root: path.join(__dirname, "views"), includeViewExtension: true, }); // * This is for user login * Fastify.post("/api/login", { schema: { description: "This is for Login User", tags: ["Login"], summary: "This is for User Login", body: { type: "object", required: ["username", "password"], properties: { username: { type: "string" }, password: { type: "string" }, }, }, }, async handler(req, reply) { loginObject = await userController.loginUser(req); if (loginObject.same) { const phoneVerified = loginObject.user.phoneVerified; const oneTimePasswordSetFlag = loginObject.user.oneTimePasswordSetFlag; console.log( "oneTimePasswordSetFlag is ......", oneTimePasswordSetFlag, typeof oneTimePasswordSetFlag, typeof phoneVerified ); if (!phoneVerified) { reply.send({ armintatankdata: { error: false, phoneVerified: false, phone: loginObject.user.phone, oneTimePasswordSetFlag: oneTimePasswordSetFlag, message: "Please Verify your phone number", }, }); } else if (oneTimePasswordSetFlag) { reply.send({ armintatankdata: { error: false, phoneVerified: phoneVerified, phone: loginObject.user.phone, oneTimePasswordSetFlag: true, message: "Password must be reset", }, }); } else { const token = fastify.jwt.sign( { username: loginObject.user.username, userId: loginObject.user._id, roles: loginObject.user.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: "12h" } ); var arr = loginObject.user.profile.role; var arrayToString = JSON.stringify(Object.assign({}, arr)); // convert array to string var stringToJsonObject = JSON.parse(arrayToString); // convert string to json object // console.log({ // username: loginObject.user.username, // roles: loginObject.user.profile.role, // rolesasobj: stringToJsonObject, // }); // console.log("sending token \n"); // console.log(token); reply.send({ armintatankdata: { error: false, apiversion: fastify.config.APIVERSION, access_token: token, username: loginObject.user.username, phoneVerified: loginObject.user.phoneVerified, oneTimePasswordSetFlag: loginObject.user.oneTimePasswordSetFlag, type: loginObject.user.profile.role, typeasobj: stringToJsonObject, }, }); } } else { error = { armintatankdata: { error: true, code: 400, message: "Invalid UserId , Password supplied", }, }; reply.send(error); } }, }); Fastify.get("/api/reset_token/:username", { async handler(req, reply) { try { const get_user = await userController.getSingleUser(req); const token = fastify.jwt.sign( { username: get_user.username, userId: get_user._id, roles: get_user.profile.role, }, { expiresIn: "12h" } ); reply.send({ access_token: token, username: get_user.username }); } catch (err) { console.log(err); error = { armintatankdata: { error: true, code: 400, message: "Reset Token failed", }, }; reply.status(401).send(error); } }, }); Fastify.get("/testtemp", (req, reply) => { reply.view("layouts/main", {}); }); //fastify-auth plugin is required so we can define routes in seperate files and verify jwt supplied in preHandlers for each request. const multer = require("fastify-multer"); Fastify.register(require("fastify-auth")); const dbConnection = require("./config/config"); Fastify.register(dbConnection); Fastify.register(multer.contentParser); const { Schema } = require("mongoose"); // fastify.register(dbConnection); Fastify.register(require("./routes/usersRoute")); // 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 Fastify.register(require("./routes/forTestingRoute")); const start = async () => { const app = Fastify const admin = new AdminJS({ databases: [], rootPath: '/admin' }) try { // await AdminJSFastify.buildRouter( // admin, // app, // ) await app.listen(3000, "0.0.0.0"); Fastify.log.info(`listening on ${Fastify.server.address().port}`); Fastify.log.info(`server listening on ${Fastify.config}`); } catch (err) { Fastify.log.error(err); process.exit(1); } }; start();