chnages pushed

Signed-off-by: Diwakar Mehta <diwakar.mehta@digimantra.com>
This commit is contained in:
Diwakar Mehta 2025-06-19 15:31:18 +05:30
parent 804f5b2583
commit 219b783c9e
11 changed files with 221 additions and 99 deletions

View file

@ -4,6 +4,7 @@ DB_USER=
DB_PASSWORD= DB_PASSWORD=
DB_HOST= DB_HOST=
DB_PORT= DB_PORT=
NODE_ENV=
# twilio creds # twilio creds

127
.gitignore vendored
View file

@ -1,2 +1,127 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env .env
node_modules .env.*
!.env.example
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# vitepress build output
**/.vitepress/dist
# vitepress cache directory
**/.vitepress/cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

46
package-lock.json generated
View file

@ -1427,22 +1427,22 @@
} }
}, },
"node_modules/pg": { "node_modules/pg": {
"version": "8.16.0", "version": "8.16.1",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.16.0.tgz", "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.1.tgz",
"integrity": "sha512-7SKfdvP8CTNXjMUzfcVTaI+TDzBEeaUnVwiVGZQD1Hh33Kpev7liQba9uLd4CfN8r9mCVsD0JIpq03+Unpz+kg==", "integrity": "sha512-5n6e7MgF5ABRsssOsX9xC95p+NUuhgDQDBSsrKSZJjYVqZHGyrmJuknym2IbVhGtzV9siBdzH9SEIQAuWF+sdg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"pg-connection-string": "^2.9.0", "pg-connection-string": "^2.9.1",
"pg-pool": "^3.10.0", "pg-pool": "^3.10.1",
"pg-protocol": "^1.10.0", "pg-protocol": "^1.10.1",
"pg-types": "2.2.0", "pg-types": "2.2.0",
"pgpass": "1.0.5" "pgpass": "1.0.5"
}, },
"engines": { "engines": {
"node": ">= 8.0.0" "node": ">= 16.0.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"pg-cloudflare": "^1.2.5" "pg-cloudflare": "^1.2.6"
}, },
"peerDependencies": { "peerDependencies": {
"pg-native": ">=3.0.1" "pg-native": ">=3.0.1"
@ -1454,16 +1454,16 @@
} }
}, },
"node_modules/pg-cloudflare": { "node_modules/pg-cloudflare": {
"version": "1.2.5", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz", "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.6.tgz",
"integrity": "sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==", "integrity": "sha512-uxmJAnmIgmYgnSFzgOf2cqGQBzwnRYcrEgXuFjJNEkpedEIPBSEzxY7ph4uA9k1mI+l/GR0HjPNS6FKNZe8SBQ==",
"license": "MIT", "license": "MIT",
"optional": true "optional": true
}, },
"node_modules/pg-connection-string": { "node_modules/pg-connection-string": {
"version": "2.9.0", "version": "2.9.1",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.0.tgz", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz",
"integrity": "sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ==", "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/pg-hstore": { "node_modules/pg-hstore": {
@ -1488,18 +1488,18 @@
} }
}, },
"node_modules/pg-pool": { "node_modules/pg-pool": {
"version": "3.10.0", "version": "3.10.1",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.0.tgz", "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz",
"integrity": "sha512-DzZ26On4sQ0KmqnO34muPcmKbhrjmyiO4lCCR0VwEd7MjmiKf5NTg/6+apUEu0NF7ESa37CGzFxH513CoUmWnA==", "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==",
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"pg": ">=8.0" "pg": ">=8.0"
} }
}, },
"node_modules/pg-protocol": { "node_modules/pg-protocol": {
"version": "1.10.0", "version": "1.10.1",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.0.tgz", "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.1.tgz",
"integrity": "sha512-IpdytjudNuLv8nhlHs/UrVBhU0e78J0oIS/0AVdTbWxSOkFUVdsHC/NrorO6nXsQNDTT1kzDSOMJubBQviX18Q==", "integrity": "sha512-9YS3ZonDj0Lxny//aF0ITPdfrEPgKWCJvONsSXAaIUhgpzlzl5JgaZNlbTFxvYNfm2terGEnHeOSUlF6qRGBzw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/pg-types": { "node_modules/pg-types": {
@ -1999,9 +1999,9 @@
} }
}, },
"node_modules/swagger-ui-dist": { "node_modules/swagger-ui-dist": {
"version": "5.24.2", "version": "5.25.2",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.24.2.tgz", "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.25.2.tgz",
"integrity": "sha512-aDl7fBdPri+LdB27sh4Ou2sRuzDgw63f65KvVg3TE5UWsclJ46bE7iF4Zk9uqg7253vNi+FxacSUVbn7sCnbaQ==", "integrity": "sha512-V4JyoygUe5nCbn7bAD0fVKSC0yNcL3ROIQtGC7M0NATKuyosCSmMU6T0yDZIIuGpSxjsjZh/D2Ejb8lnF2jjxw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@scarf/scarf": "=1.4.0" "@scarf/scarf": "=1.4.0"

View file

@ -1,6 +1,7 @@
import dotenv from "dotenv"; import dotenv from "dotenv";
import path from "path"; dotenv.config()
dotenv.config({ path: path.join(process.cwd(), "../.env") }); import path from 'path';
dotenv.config({ path: path.join(process.cwd(), "../.env") })
const getDb = () => { const getDb = () => {
return { return {

View file

@ -1,8 +1,10 @@
import dotenv from "dotenv"; import dotenv from 'dotenv'
dotenv.config(); dotenv.config()
import User from "../models/user.js"; import db from "../models/index.js";
const { users } = db;
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
import twilio from "twilio"; import twilio from "twilio";
// console.log('process.env: ', process.env);
const JWT_SECRET = process.env.JWT_SECRET; const JWT_SECRET = process.env.JWT_SECRET;
const accountSid = process.env.TWILIO_ACCOUNT_SID; const accountSid = process.env.TWILIO_ACCOUNT_SID;
@ -33,22 +35,21 @@ const registerLogin = async (req, res) => {
const otp = Math.floor(100000 + Math.random() * 900000).toString(); const otp = Math.floor(100000 + Math.random() * 900000).toString();
const otp_expiry = new Date(Date.now() + 10 * 60 * 1000); // 10 mins const otp_expiry = new Date(Date.now() + 10 * 60 * 1000); // 10 mins
const twilioResponse = await sendOtpFromTwilio(full_number, otp); // const twilioResponse = await sendOtpFromTwilio(full_number, otp);
console.log("twilioResponse:", twilioResponse.sid || twilioResponse); // console.log("twilioResponse:", twilioResponse.sid || twilioResponse);
let user = await User.findOne({ where: { full_number } }); let user = await users.findOne({ where: { country_code:countryCode, phone_number:phoneNumber } });
if (!user) { if (!user) {
user = await User.create({ user = await users.create({
country_code: countryCode, country_code: countryCode,
phone_number: phoneNumber, phone_number: phoneNumber,
full_number: full_number,
otp, otp,
otp_expiry, otp_expiry
}); });
} else { } else {
await User.update({ otp, otp_expiry }, { where: { full_number } }); await users.update({ otp, otp_expiry }, { country_code:countryCode, phone_number:phoneNumber } );
user = await User.findOne({ where: { full_number } }); user = await users.findOne({ country_code:countryCode, phone_number:phoneNumber } );
} }
res.status(201).json({ res.status(201).json({
@ -56,7 +57,7 @@ const registerLogin = async (req, res) => {
user: { id: user.id, full_number }, user: { id: user.id, full_number },
}); });
} catch (err) { } catch (err) {
console.error("registerLogin error:", err); console.log("registerLogin error:",err);
res.status(500).json({ error: err.message }); res.status(500).json({ error: err.message });
} }
}; };
@ -72,7 +73,7 @@ const verifyOtp = async (req, res) => {
.json({ error: "Phone number and OTP are required" }); .json({ error: "Phone number and OTP are required" });
} }
const user = await User.findOne({ where: { full_number } }); const user = await users.findOne({ where: { full_number } });
if (!user) { if (!user) {
return res.status(404).json({ error: "User not found" }); return res.status(404).json({ error: "User not found" });
} }
@ -133,14 +134,14 @@ const triggerOtp = async (req, res) => {
const { countryCode, phoneNumber } = req.body; const { countryCode, phoneNumber } = req.body;
const full_number = countryCode.toString() + phoneNumber; const full_number = countryCode.toString() + phoneNumber;
const exist = await User.findOne({ where: { full_number: full_number } }); const exist = await users.findOne({ where: { country_code:countryCode,phone_number:phoneNumber } });
if (!exist) return res.status(400).json({ message: "Number Not exist" }); if (!exist) return res.status(400).json({ message: "Number Not exist" });
const otp = Math.floor(100000 + Math.random() * 900000).toString(); const otp = Math.floor(100000 + Math.random() * 900000).toString();
const otp_expiry = new Date(Date.now() + 10 * 60 * 1000); // 10 mins const otp_expiry = new Date(Date.now() + 10 * 60 * 1000); // 10 mins
const twilioResponse = await sendOtpFromTwilio(full_number, otp); const twilioResponse = await sendOtpFromTwilio(full_number, otp);
console.log("twilioResponse:", twilioResponse.sid || twilioResponse); console.log("twilioResponse:", twilioResponse.sid || twilioResponse);
await User.update( await users.update(
{ {
otp: otp, otp: otp,
otp_expiry: otp_expiry, otp_expiry: otp_expiry,
@ -158,41 +159,42 @@ const triggerOtp = async (req, res) => {
}; };
const generateAccessToken = (user) => { const generateAccessToken = (user) => {
try { try {
return jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: process.env.ACCESS_TOKEN_EXPIRY }); return jwt.sign({ id: user.id }, process.env.JWT_SECRET, {
} catch (error) { expiresIn: process.env.ACCESS_TOKEN_EXPIRY,
return res.status(400).json({ message: 'Invalid or expired token' }); });
} } catch (error) {
return res.status(400).json({ message: "Invalid or expired token" });
}
}; };
const generateRefreshToken = (user) => { const generateRefreshToken = (user) => {
try { try {
return jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: process.env.REFRESH_TOKEN_EXPIRY }); return jwt.sign({ id: user.id }, process.env.JWT_SECRET, {
} catch (err) { expiresIn: process.env.REFRESH_TOKEN_EXPIRY,
return res.status(400).json({ message: 'Invalid or expired refresh token' }); });
} } catch (err) {
return res
.status(400)
.json({ message: "Invalid or expired refresh token" });
}
}; };
const refreshAccessToken = async (req, res) => { const refreshAccessToken = async (req, res) => {
const refreshToken = req.body.refreshToken; const refreshToken = req.body.refreshToken;
if (!refreshToken) { if (!refreshToken) {
return res return res.status(400).json({ message: "Refresh token not provided" });
.status(400)
.json({ message: "Refresh token not provided" });
} }
try { try {
const decoded = jwt.verify(refreshToken, process.env.JWT_SECRET); const decoded = jwt.verify(refreshToken, process.env.JWT_SECRET);
const user = await User.findByPk(decoded.id); const user = await User.findByPk(decoded.id);
if (!user) if (!user) return res.status(404).json({ message: "User not found" });
return res
.status(404)
.json({ message: "User not found" });
const newAccessToken = generateAccessToken({ const newAccessToken = generateAccessToken({
id: decoded.id id: decoded.id,
}); });
return res.status(200).json({ accessToken: newAccessToken }); return res.status(200).json({ accessToken: newAccessToken });
@ -210,5 +212,5 @@ export default {
// login, // login,
triggerOtp, triggerOtp,
refreshAccessToken, refreshAccessToken,
generateRefreshToken generateRefreshToken,
}; };

View file

@ -1,4 +1,4 @@
import User from '../models/user.js'; import User from '../models/users.js';
// UPDATE USER // UPDATE USER
const updateUser = async (req, res) => { const updateUser = async (req, res) => {

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
/** @type {import('sequelize-cli').Migration} */ /** @type {import('sequelize-cli').Migration} */
export async function up(queryInterface, Sequelize) { export async function up(queryInterface, Sequelize) {
await queryInterface.createTable('Users', { await queryInterface.createTable('users', {
id: { id: {
allowNull: false, allowNull: false,
autoIncrement: true, autoIncrement: true,
@ -17,9 +17,6 @@ export async function up(queryInterface, Sequelize) {
phone_number: { phone_number: {
type: Sequelize.STRING type: Sequelize.STRING
}, },
full_number: {
type: Sequelize.STRING
},
otp: { otp: {
type: Sequelize.STRING type: Sequelize.STRING
}, },
@ -37,5 +34,5 @@ export async function up(queryInterface, Sequelize) {
}); });
} }
export async function down(queryInterface, Sequelize) { export async function down(queryInterface, Sequelize) {
await queryInterface.dropTable('Users'); await queryInterface.dropTable('users');
} }

View file

@ -33,6 +33,7 @@ for (const file of files) {
const model = modelModule.default(sequelize, DataTypes); const model = modelModule.default(sequelize, DataTypes);
db[model.name] = model; db[model.name] = model;
} }
console.log(db)
Object.keys(db).forEach((modelName) => { Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) { if (db[modelName].associate) {

View file

@ -1,32 +0,0 @@
"use strict";
import { Model } from "sequelize";
export default (sequelize, DataTypes) => {
class User extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
}
User.init(
{
name: DataTypes.STRING,
country_code: DataTypes.STRING,
phone_number: DataTypes.STRING,
full_number: DataTypes.STRING,
otp: DataTypes.STRING,
otp_expiry: DataTypes.DATE,
},
{
sequelize,
modelName: "User",
underscored: true,
timestamps: true,
}
);
return User;
};

25
src/models/users.js Normal file
View file

@ -0,0 +1,25 @@
'use strict';
import { Model } from 'sequelize';
export default (sequelize, DataTypes) => {
class users extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
}
}
users.init({
name: DataTypes.STRING,
country_code: DataTypes.STRING,
phone_number: DataTypes.STRING,
otp: DataTypes.STRING,
otp_expiry: DataTypes.DATE
}, {
sequelize,
modelName: 'users',
});
return users;
};

View file

@ -1,5 +1,7 @@
import dotenv from 'dotenv' import dotenv from 'dotenv'
import path from 'path'
dotenv.config() dotenv.config()
// console.log(process.env)
import express, { urlencoded, json } from "express"; import express, { urlencoded, json } from "express";
// import { connectDB } from "./models/index.js"; // import { connectDB } from "./models/index.js";
import indexRoutes from "./routes/index.js"; import indexRoutes from "./routes/index.js";