SMS gone, approvals in

This commit is contained in:
2026-10-01 13:05:10 +05:30
parent 075b6b9968
commit 6937b4e114
11 changed files with 350 additions and 175 deletions
+71 -25
View File
@@ -22,6 +22,7 @@ execSync('npx prisma db push --skip-generate --accept-data-loss', {
env: process.env,
});
const bcrypt = require('bcryptjs');
const app = require('../src/app');
const prisma = require('../src/db');
const { ageBadge } = require('../src/lib/stockRules');
@@ -61,31 +62,30 @@ async function run(port) {
assert(ageBadge(45) === 'yellow', '45 days is yellow');
assert(ageBadge(46) === 'red', '46 days is red');
const unknown = await request(port, 'POST', '/api/auth/send-otp', {
const unknown = await request(port, 'POST', '/api/auth/dealer-login', {
body: { phone: '94770000099' },
});
assert(unknown.status === 404, `unknown phone should be 404, got ${unknown.status}`);
const adminHash = await bcrypt.hash('admin-pass-123', 10);
await prisma.user.create({
data: { name: 'Super Admin', phone: '94770000001', role: 'superAdmin' },
data: {
name: 'Super Admin',
phone: '94770000001',
role: 'superAdmin',
passwordHash: adminHash,
},
});
const sent = await request(port, 'POST', '/api/auth/send-otp', {
body: { phone: '94770000001' },
const badPassword = await request(port, 'POST', '/api/auth/staff-login', {
body: { phone: '94770000001', password: 'wrong-password' },
});
assert(sent.status === 200 && sent.json.success === true, 'OTP send failed');
assert(badPassword.status === 401, 'wrong password should be rejected');
const adminRow = await prisma.user.findUnique({ where: { phone: '94770000001' } });
const wrongCode = adminRow.currentOtp === '000000' ? '111111' : '000000';
const badOtp = await request(port, 'POST', '/api/auth/verify-otp', {
body: { phone: '94770000001', otp: wrongCode },
const verified = await request(port, 'POST', '/api/auth/staff-login', {
body: { phone: '94770000001', password: 'admin-pass-123' },
});
assert(badOtp.status === 401, 'wrong OTP should be rejected');
const verified = await request(port, 'POST', '/api/auth/verify-otp', {
body: { phone: '94770000001', otp: adminRow.currentOtp },
});
assert(verified.status === 200 && verified.json.token, 'OTP verify failed');
assert(verified.status === 200 && verified.json.token, 'staff login failed');
const adminToken = verified.json.token;
const me = await request(port, 'GET', '/api/auth/me', { token: adminToken });
@@ -112,6 +112,7 @@ async function run(port) {
body: {
name: 'Nimal Perera',
phone: '94771111111',
password: 'rep-pass-123',
dealerIds: [dealerA.json.data.id, dealerB.json.data.id],
},
});
@@ -123,19 +124,64 @@ async function run(port) {
});
assert(dealerUser.status === 201, 'dealer user create failed');
async function login(phone) {
const otpSend = await request(port, 'POST', '/api/auth/send-otp', { body: { phone } });
assert(otpSend.status === 200, `otp send failed for ${phone}`);
const row = await prisma.user.findUnique({ where: { phone } });
const otpVerify = await request(port, 'POST', '/api/auth/verify-otp', {
body: { phone, otp: row.currentOtp },
async function staffLogin(phone, password) {
const result = await request(port, 'POST', '/api/auth/staff-login', {
body: { phone, password },
});
assert(otpVerify.status === 200, `otp verify failed for ${phone}`);
return otpVerify.json.token;
assert(result.status === 200 && result.json.token, `staff login failed for ${phone}`);
return result.json.token;
}
const repToken = await login('94771111111');
const dealerToken = await login('94772222222');
async function approveDealer(phone, token) {
const started = await request(port, 'POST', '/api/auth/dealer-login', { body: { phone } });
assert(started.status === 201, `dealer login failed for ${phone}: ${started.status}`);
const approved = await request(
port,
'POST',
`/api/auth/login-requests/${started.json.requestId}/approve`,
{ token }
);
assert(approved.status === 200, `approve failed for ${phone}: ${approved.status}`);
const ready = await request(
port,
'GET',
`/api/auth/dealer-login/${started.json.requestId}?secret=${encodeURIComponent(started.json.secret)}`
);
assert(ready.status === 200 && ready.json.token, `dealer token missing for ${phone}`);
return ready.json.token;
}
const repToken = await staffLogin('94771111111', 'rep-pass-123');
const dealerStaff = await request(port, 'POST', '/api/auth/staff-login', {
body: { phone: '94772222222', password: 'rep-pass-123' },
});
assert(dealerStaff.status === 401, 'dealer should not use staff login');
const otherDealer = await request(port, 'POST', '/api/admin/dealer-users', {
token: adminToken,
body: { name: 'Jaffna Desk', phone: '94773333333', dealerId: dealerC.json.data.id },
});
assert(otherDealer.status === 201, 'second dealer user create failed');
const outsideRequest = await request(port, 'POST', '/api/auth/dealer-login', {
body: { phone: '94773333333' },
});
assert(outsideRequest.status === 201, 'outside dealer login failed');
const repQueue = await request(port, 'GET', '/api/auth/login-requests', { token: repToken });
assert(
repQueue.status === 200 &&
!repQueue.json.data.some((item) => item.id === outsideRequest.json.requestId),
'sales rep should not see an unassigned dealer login'
);
const repDenied = await request(
port,
'POST',
`/api/auth/login-requests/${outsideRequest.json.requestId}/approve`,
{ token: repToken }
);
assert(repDenied.status === 403, 'sales rep should not approve an unassigned dealer');
const dealerToken = await approveDealer('94772222222', adminToken);
const forbiddenStock = await request(port, 'POST', '/api/stocks', {
token: dealerToken,