SMS gone, approvals in
This commit is contained in:
+71
-25
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user