module.exports = function (app) { const router = require('express').Router(), userCtl = require('../controllers/user'), Joi = require('joi'); Joi.objectId = require('joi-objectid')(Joi); const { validateInputRequest } = require('../middlewares/validate'); const { ApplicationTypes, RefSources, DEFAULT_LANG } = require('../helpers/constants'); // Joi schema for appInfo based on RefSourceSchema from customer model const appInfoSchema = Joi.object({ appTypes: Joi.array().items( Joi.string().valid(...Object.values(ApplicationTypes)) ).optional(), refSources: Joi.array().items( Joi.string().valid(...Object.values(RefSources)) ).optional(), }); // Joi schema for signup const signupSchema = Joi.object({ contactEmail: Joi.string().email().required(), password: Joi.string().required(), contactName: Joi.string().required(), companyName: Joi.string().required(), country: Joi.string().required(), // Fallback fields used when no addresses array provided address: Joi.string().optional(), city: Joi.string().optional(), state: Joi.string().optional(), postalCode: Joi.string().optional(), contactPhone: Joi.string().optional(), // Only allow addresses array for address input addresses: Joi.array().items(Joi.object({ /* Full Name of the (billing) address mostly mean the name of the person on card, bank account or entity business name */ name: Joi.string().optional(), line1: Joi.string().optional(), line2: Joi.string().optional(), city: Joi.string().optional(), state: Joi.string().optional(), postalCode: Joi.string().optional(), country: Joi.string().required(), phone: Joi.string().optional(), email: Joi.string().email().optional(), isBilling: Joi.boolean().optional() })).min(1).optional(), // AppInfo structure based on RefSourceSchema appInfo: appInfoSchema.optional(), taxId: Joi.string().allow('').optional(), lang: Joi.string().default(DEFAULT_LANG).optional(), partner: Joi.objectId().allow('').allow(null).optional(), emailToken: Joi.string().optional(), token: Joi.string().optional(), }) .or('emailToken', 'token'); // Require either emailToken OR token for verification // On routes that end in /users router.route('/').post(userCtl.createUser_post); /** * @api {get} /users/:id Get User * @apiVersion 1.2.1 * @apiName GetUser * @apiGroup Users * @apiDescription Retrieve a user document by ID. The response shape is * controlled by the optional `view` query parameter. * * @apiParam {String} id User ObjectId. * * @apiQuery {String} [view] Controls the response shape. When set, `membership.*` * fields are always excluded. Supported values: * - `profile` — `_id, username, contact, name, phone, email, Country`. * No `password`, no `membership`, no `addresses`. * - `edit` — `_id, kind, active, username, password, name, address, country, * phone, fax, email, contact, licence, parent, Country`. * - `billing` — `_id, name, address, country, Country`. * - *(omitted)* — full document without `addresses` (see `withAddresses`). * @apiQuery {Boolean} [withAddresses=false] When `true` and `view` is omitted, * returns the full document **including** the `addresses` array. * * `Country` (populated object with `code` and `name`) is included in all views. * * @apiSuccess {Object} user User document (shape varies by `view`). * * @apiError (401) {Object} error Not authorized. * @apiError (409) {Object} error Invalid user ID. */ // On routes that end in /users/:id router.route('/:id') .get(userCtl.getUser_get) .put(userCtl.updateUser_put) .delete(userCtl.deleteUser) /** * @api {post} /users/login Login to AgMission server * @apiVersion 1.2.1 * @apiName PostUsersLogin * @apiGroup Users * @apiDescription Login to AgMission Server. The returned token can be used for other API calls. For accounts used in aircrafts, * user should login at the beginning of each work session such as beginning of the day to make sure the token is still valid or not. * @apiParam {String} username The account's username * @apiParam {String} password The account's password * @apiParamExample {json} Request-Example: * { * "username": "me@mail.com", "password": "notell" * } * @apiSuccess {String} token Authorization token * @apiSuccessExample {json} Success * HTTP/1.1 200 OK * { * "token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI1YWQ1Zjc4NWE5OWEzZjFkOWZjMmM5ZDAiLCJ1dCI6OSwiaWF0IjoxNTIzOTk0NjM1fQ.H_FRXwFiq33Pt9ZSF2LejWfrIG8ijb1xgFEl2Y7affT" * } * @apiuse WrongCredentialError * @apiuse InActiveAccountError */ router.post('/login', userCtl.login_post); router.route('/exists').post(userCtl.isUserNameExists_post); router.route('/search').post(userCtl.search_post); router.post('/clearTempData', userCtl.clearTempData_post); router.post('/updateLang', userCtl.setUserLanguage_post); router.post('/getUserDetail', userCtl.getUserDetail_post); router.post('/mailPwdReset', userCtl.mailPwdReset_post); router.post('/resetPassword/validate', userCtl.validateResetPwdToken_post); router.post('/resetPassword', userCtl.resetPassword_post); // Email verification endpoints (add these before signup) router.post('/signup/requestVerifyEmail', userCtl.requestEmailVerification_post); router.post('/signup/validate', userCtl.verifyEmailCode_post); router.post('/signup', validateInputRequest(signupSchema), userCtl.signup_post); app.use('/api/users', router); };