feat: add CPF to user registration and update seed users
Build and Deploy (Gitea) / build-and-deploy (push) Successful in 45s
Details
Build and Deploy (Gitea) / build-and-deploy (push) Successful in 45s
Details
This commit is contained in:
parent
5be0eda2a2
commit
f495d94019
63
server.ts
63
server.ts
|
|
@ -56,9 +56,9 @@ function requireAdmin(req: AuthenticatedRequest, res: Response, next: NextFuncti
|
||||||
|
|
||||||
// 1. Auth: Register
|
// 1. Auth: Register
|
||||||
app.post('/api/auth/register', async (req: Request, res: Response) => {
|
app.post('/api/auth/register', async (req: Request, res: Response) => {
|
||||||
const { name, email, password, birthDate, whatsapp } = req.body;
|
const { name, email, password, cpf, birthDate, whatsapp } = req.body;
|
||||||
|
|
||||||
if (!name || !email || !password || !birthDate || !whatsapp) {
|
if (!name || !email || !password || !cpf || !birthDate || !whatsapp) {
|
||||||
res.status(400).json({ error: 'Preencha todos os campos obrigatórios' });
|
res.status(400).json({ error: 'Preencha todos os campos obrigatórios' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -71,33 +71,34 @@ app.post('/api/auth/register', async (req: Request, res: Response) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Generate Asaas Customer ID (Real call if configured, or simulated)
|
// Generate Asaas Customer ID (Real call if configured, or simulated)
|
||||||
const asaasCustomerId = await AsaasService.createCustomer(name, email);
|
const asaasCustomerId = await AsaasService.createCustomer(name, email, cpf);
|
||||||
|
|
||||||
const salt = bcrypt.genSaltSync(10);
|
const salt = bcrypt.genSaltSync(10);
|
||||||
const passwordHash = bcrypt.hashSync(password, salt);
|
const passwordHash = bcrypt.hashSync(password, salt);
|
||||||
|
|
||||||
const createdAt = new Date();
|
const createdAt = new Date();
|
||||||
|
|
||||||
// Calculate trial ends at
|
// Calculate trial ends at
|
||||||
const trialDays = db.settings?.trialDurationDays || 7;
|
const trialDays = db.settings?.trialDurationDays || 7;
|
||||||
const trialEndsAt = new Date(createdAt);
|
const trialEndsAt = new Date(createdAt);
|
||||||
trialEndsAt.setDate(trialEndsAt.getDate() + trialDays);
|
trialEndsAt.setDate(trialEndsAt.getDate() + trialDays);
|
||||||
|
|
||||||
const newUser: User = {
|
const newUser: User = {
|
||||||
id: `usr_${Math.random().toString(36).substring(2, 9)}`,
|
id: `usr_${Math.random().toString(36).substring(2, 9)}`,
|
||||||
name,
|
name,
|
||||||
email: email.toLowerCase(),
|
email: email.toLowerCase(),
|
||||||
password: passwordHash,
|
password: passwordHash,
|
||||||
role: 'student',
|
role: 'student',
|
||||||
subscriptionStatus: 'TRIAL', // Defaults to trial
|
subscriptionStatus: 'TRIAL', // Defaults to trial
|
||||||
asaasCustomerId,
|
asaasCustomerId,
|
||||||
birthDate,
|
cpf,
|
||||||
whatsapp,
|
birthDate,
|
||||||
trialEndsAt: trialEndsAt.toISOString(),
|
whatsapp,
|
||||||
createdAt: createdAt.toISOString()
|
trialEndsAt: trialEndsAt.toISOString(),
|
||||||
};
|
createdAt: createdAt.toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
db.users.push(newUser);
|
db.users.push(newUser);
|
||||||
saveDb(db);
|
saveDb(db);
|
||||||
|
|
@ -336,7 +337,7 @@ app.post('/api/courses/:id/unlock', authenticateToken, checkoutRateLimiter, asyn
|
||||||
customerId = null;
|
customerId = null;
|
||||||
}
|
}
|
||||||
if (!customerId) {
|
if (!customerId) {
|
||||||
customerId = await AsaasService.createCustomer(user.name, user.email);
|
customerId = await AsaasService.createCustomer(user.name, user.email, user.cpf);
|
||||||
user.asaasCustomerId = customerId;
|
user.asaasCustomerId = customerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,7 +521,7 @@ app.post('/api/subscription/subscribe', authenticateToken, async (req: Authentic
|
||||||
customerId = null;
|
customerId = null;
|
||||||
}
|
}
|
||||||
if (!customerId) {
|
if (!customerId) {
|
||||||
customerId = await AsaasService.createCustomer(user.name, user.email);
|
customerId = await AsaasService.createCustomer(user.name, user.email, user.cpf);
|
||||||
user.asaasCustomerId = customerId;
|
user.asaasCustomerId = customerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
15
src/App.tsx
15
src/App.tsx
|
|
@ -35,6 +35,7 @@ export default function App() {
|
||||||
const [regName, setRegName] = useState('');
|
const [regName, setRegName] = useState('');
|
||||||
const [regEmail, setRegEmail] = useState('');
|
const [regEmail, setRegEmail] = useState('');
|
||||||
const [regPassword, setRegPassword] = useState('');
|
const [regPassword, setRegPassword] = useState('');
|
||||||
|
const [regCpf, setRegCpf] = useState('');
|
||||||
const [regBirthDate, setRegBirthDate] = useState('');
|
const [regBirthDate, setRegBirthDate] = useState('');
|
||||||
const [regWhatsapp, setRegWhatsapp] = useState('');
|
const [regWhatsapp, setRegWhatsapp] = useState('');
|
||||||
const [authError, setAuthError] = useState<string | null>(null);
|
const [authError, setAuthError] = useState<string | null>(null);
|
||||||
|
|
@ -134,7 +135,7 @@ export default function App() {
|
||||||
const res = await fetch('/api/auth/register', {
|
const res = await fetch('/api/auth/register', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ name: regName, email: regEmail, password: regPassword, birthDate: regBirthDate, whatsapp: regWhatsapp })
|
body: JSON.stringify({ name: regName, email: regEmail, password: regPassword, cpf: regCpf, birthDate: regBirthDate, whatsapp: regWhatsapp })
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
|
|
@ -355,6 +356,18 @@ export default function App() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-1">
|
||||||
|
<label className="text-[10px] text-zinc-400 font-bold uppercase tracking-wider">CPF</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
required
|
||||||
|
value={regCpf}
|
||||||
|
onChange={(e) => setRegCpf(e.target.value)}
|
||||||
|
placeholder="000.000.000-00"
|
||||||
|
className="w-full glass-input rounded-lg p-3 text-xs text-white focus:outline-none"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<label className="text-[10px] text-zinc-400 font-bold uppercase tracking-wider">Data de Nascimento</label>
|
<label className="text-[10px] text-zinc-400 font-bold uppercase tracking-wider">Data de Nascimento</label>
|
||||||
<input
|
<input
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ function createInitialDb(): DatabaseSchema {
|
||||||
role: 'admin',
|
role: 'admin',
|
||||||
subscriptionStatus: 'ACTIVE',
|
subscriptionStatus: 'ACTIVE',
|
||||||
asaasCustomerId: null,
|
asaasCustomerId: null,
|
||||||
|
cpf: '111.111.111-11',
|
||||||
unlockedCourses: [],
|
unlockedCourses: [],
|
||||||
createdAt: now
|
createdAt: now
|
||||||
},
|
},
|
||||||
|
|
@ -97,6 +98,7 @@ function createInitialDb(): DatabaseSchema {
|
||||||
role: 'student',
|
role: 'student',
|
||||||
subscriptionStatus: 'ACTIVE',
|
subscriptionStatus: 'ACTIVE',
|
||||||
asaasCustomerId: 'cus_00001',
|
asaasCustomerId: 'cus_00001',
|
||||||
|
cpf: '111.111.111-11',
|
||||||
unlockedCourses: ['crs_excel'], // Excel starts unlocked for Joao
|
unlockedCourses: ['crs_excel'], // Excel starts unlocked for Joao
|
||||||
createdAt: new Date(Date.now() - 30 * 24 * 3600 * 1000).toISOString()
|
createdAt: new Date(Date.now() - 30 * 24 * 3600 * 1000).toISOString()
|
||||||
},
|
},
|
||||||
|
|
@ -108,6 +110,7 @@ function createInitialDb(): DatabaseSchema {
|
||||||
role: 'student',
|
role: 'student',
|
||||||
subscriptionStatus: 'ACTIVE',
|
subscriptionStatus: 'ACTIVE',
|
||||||
asaasCustomerId: 'cus_00002',
|
asaasCustomerId: 'cus_00002',
|
||||||
|
cpf: '111.111.111-11',
|
||||||
unlockedCourses: [],
|
unlockedCourses: [],
|
||||||
createdAt: new Date(Date.now() - 15 * 24 * 3600 * 1000).toISOString()
|
createdAt: new Date(Date.now() - 15 * 24 * 3600 * 1000).toISOString()
|
||||||
},
|
},
|
||||||
|
|
@ -119,6 +122,7 @@ function createInitialDb(): DatabaseSchema {
|
||||||
role: 'student',
|
role: 'student',
|
||||||
subscriptionStatus: 'OVERDUE',
|
subscriptionStatus: 'OVERDUE',
|
||||||
asaasCustomerId: 'cus_00003',
|
asaasCustomerId: 'cus_00003',
|
||||||
|
cpf: '111.111.111-11',
|
||||||
unlockedCourses: [],
|
unlockedCourses: [],
|
||||||
createdAt: new Date(Date.now() - 45 * 24 * 3600 * 1000).toISOString()
|
createdAt: new Date(Date.now() - 45 * 24 * 3600 * 1000).toISOString()
|
||||||
},
|
},
|
||||||
|
|
@ -130,6 +134,7 @@ function createInitialDb(): DatabaseSchema {
|
||||||
role: 'student',
|
role: 'student',
|
||||||
subscriptionStatus: 'CANCELED',
|
subscriptionStatus: 'CANCELED',
|
||||||
asaasCustomerId: 'cus_00004',
|
asaasCustomerId: 'cus_00004',
|
||||||
|
cpf: '111.111.111-11',
|
||||||
unlockedCourses: [],
|
unlockedCourses: [],
|
||||||
createdAt: new Date(Date.now() - 60 * 24 * 3600 * 1000).toISOString()
|
createdAt: new Date(Date.now() - 60 * 24 * 3600 * 1000).toISOString()
|
||||||
},
|
},
|
||||||
|
|
@ -141,6 +146,7 @@ function createInitialDb(): DatabaseSchema {
|
||||||
role: 'student',
|
role: 'student',
|
||||||
subscriptionStatus: 'ACTIVE',
|
subscriptionStatus: 'ACTIVE',
|
||||||
asaasCustomerId: 'cus_test',
|
asaasCustomerId: 'cus_test',
|
||||||
|
cpf: '111.111.111-11',
|
||||||
unlockedCourses: [], // Starts with only the free courses unlocked
|
unlockedCourses: [], // Starts with only the free courses unlocked
|
||||||
createdAt: now
|
createdAt: now
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ export interface User {
|
||||||
subscriptionStatus: SubscriptionStatus;
|
subscriptionStatus: SubscriptionStatus;
|
||||||
asaasCustomerId: string | null;
|
asaasCustomerId: string | null;
|
||||||
unlockedCourses?: string[]; // IDs of courses unlocked individually
|
unlockedCourses?: string[]; // IDs of courses unlocked individually
|
||||||
|
cpf?: string;
|
||||||
birthDate?: string;
|
birthDate?: string;
|
||||||
whatsapp?: string;
|
whatsapp?: string;
|
||||||
trialEndsAt?: string | null;
|
trialEndsAt?: string | null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue