academe-kit 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +33 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +760 -100
- package/dist/index.esm.js +33 -9
- package/dist/index.esm.js.map +1 -1
- package/dist/types/services/CertificateService.d.ts +123 -66
- package/dist/types/services/InstitutionService.d.ts +2 -3
- package/dist/types/services/userService.d.ts +2 -0
- package/dist/types/types/academe-api.d.ts +618 -16
- package/package.json +1 -1
|
@@ -221,6 +221,221 @@ export interface paths {
|
|
|
221
221
|
};
|
|
222
222
|
trace?: never;
|
|
223
223
|
};
|
|
224
|
+
"/auth/forgot-password": {
|
|
225
|
+
parameters: {
|
|
226
|
+
query?: never;
|
|
227
|
+
header?: never;
|
|
228
|
+
path?: never;
|
|
229
|
+
cookie?: never;
|
|
230
|
+
};
|
|
231
|
+
get?: never;
|
|
232
|
+
put?: never;
|
|
233
|
+
/**
|
|
234
|
+
* Request password reset email
|
|
235
|
+
* @description Sends a password reset email to the specified address if a user with that email exists.
|
|
236
|
+
*
|
|
237
|
+
* **Security Note:**
|
|
238
|
+
* For security reasons, this endpoint always returns a success response regardless of whether
|
|
239
|
+
* the email exists in the system. This prevents email enumeration attacks.
|
|
240
|
+
*
|
|
241
|
+
* **Flow:**
|
|
242
|
+
* 1. Client sends email address
|
|
243
|
+
* 2. Backend searches for user by email in Keycloak
|
|
244
|
+
* 3. If user exists, Keycloak sends password reset email with UPDATE_PASSWORD action
|
|
245
|
+
* 4. User receives email with link valid for 1 hour
|
|
246
|
+
* 5. Endpoint returns success (regardless of whether email was found)
|
|
247
|
+
*
|
|
248
|
+
* **Email Template:**
|
|
249
|
+
* The email sent uses the Keycloak realm's configured email template for password reset.
|
|
250
|
+
*/
|
|
251
|
+
post: {
|
|
252
|
+
parameters: {
|
|
253
|
+
query?: never;
|
|
254
|
+
header?: never;
|
|
255
|
+
path?: never;
|
|
256
|
+
cookie?: never;
|
|
257
|
+
};
|
|
258
|
+
requestBody: {
|
|
259
|
+
content: {
|
|
260
|
+
"application/json": {
|
|
261
|
+
/**
|
|
262
|
+
* Format: email
|
|
263
|
+
* @description User's email address
|
|
264
|
+
* @example user@example.com
|
|
265
|
+
*/
|
|
266
|
+
email: string;
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
responses: {
|
|
271
|
+
/** @description Request processed successfully (always returned for security) */
|
|
272
|
+
200: {
|
|
273
|
+
headers: {
|
|
274
|
+
[name: string]: unknown;
|
|
275
|
+
};
|
|
276
|
+
content: {
|
|
277
|
+
"application/json": {
|
|
278
|
+
/** @example success */
|
|
279
|
+
status?: string;
|
|
280
|
+
/** @example If this email is registered, you will receive password reset instructions. */
|
|
281
|
+
message?: string;
|
|
282
|
+
};
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
/** @description Bad Request - Email not provided */
|
|
286
|
+
400: {
|
|
287
|
+
headers: {
|
|
288
|
+
[name: string]: unknown;
|
|
289
|
+
};
|
|
290
|
+
content: {
|
|
291
|
+
"application/json": {
|
|
292
|
+
/** @example error */
|
|
293
|
+
status?: string;
|
|
294
|
+
/** @example Email is required */
|
|
295
|
+
message?: string;
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
/** @description Internal Server Error */
|
|
300
|
+
500: {
|
|
301
|
+
headers: {
|
|
302
|
+
[name: string]: unknown;
|
|
303
|
+
};
|
|
304
|
+
content: {
|
|
305
|
+
"application/json": {
|
|
306
|
+
/** @example error */
|
|
307
|
+
status?: string;
|
|
308
|
+
/** @example Internal server error */
|
|
309
|
+
message?: string;
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
};
|
|
314
|
+
};
|
|
315
|
+
delete?: never;
|
|
316
|
+
options?: never;
|
|
317
|
+
head?: never;
|
|
318
|
+
patch?: never;
|
|
319
|
+
trace?: never;
|
|
320
|
+
};
|
|
321
|
+
"/auth/google-exchange": {
|
|
322
|
+
parameters: {
|
|
323
|
+
query?: never;
|
|
324
|
+
header?: never;
|
|
325
|
+
path?: never;
|
|
326
|
+
cookie?: never;
|
|
327
|
+
};
|
|
328
|
+
get?: never;
|
|
329
|
+
put?: never;
|
|
330
|
+
/**
|
|
331
|
+
* Exchange Google access token for Keycloak tokens
|
|
332
|
+
* @description Exchanges a Google access token for Keycloak tokens.
|
|
333
|
+
*
|
|
334
|
+
* **Flow:**
|
|
335
|
+
* 1. Client sends Google access token
|
|
336
|
+
* 2. Backend fetches user email from Google Userinfo API
|
|
337
|
+
* 3. Backend verifies the email exists in the local database
|
|
338
|
+
* 4. If user exists, performs Keycloak token exchange
|
|
339
|
+
* 5. Returns Keycloak tokens (access_token, refresh_token, etc.)
|
|
340
|
+
*
|
|
341
|
+
* **Error Cases:**
|
|
342
|
+
* - 400: Invalid or expired Google token
|
|
343
|
+
* - 404: User email not found in database
|
|
344
|
+
*/
|
|
345
|
+
post: {
|
|
346
|
+
parameters: {
|
|
347
|
+
query?: never;
|
|
348
|
+
header?: never;
|
|
349
|
+
path?: never;
|
|
350
|
+
cookie?: never;
|
|
351
|
+
};
|
|
352
|
+
requestBody: {
|
|
353
|
+
content: {
|
|
354
|
+
"application/json": {
|
|
355
|
+
/**
|
|
356
|
+
* @description Google OAuth2 access token
|
|
357
|
+
* @example ya29.a0AfH6SM...
|
|
358
|
+
*/
|
|
359
|
+
googleAccessToken: string;
|
|
360
|
+
};
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
responses: {
|
|
364
|
+
/** @description Token exchange successful */
|
|
365
|
+
200: {
|
|
366
|
+
headers: {
|
|
367
|
+
[name: string]: unknown;
|
|
368
|
+
};
|
|
369
|
+
content: {
|
|
370
|
+
"application/json": {
|
|
371
|
+
/** @example success */
|
|
372
|
+
status?: string;
|
|
373
|
+
data?: {
|
|
374
|
+
/** @description Keycloak access token */
|
|
375
|
+
access_token?: string;
|
|
376
|
+
/** @description Keycloak refresh token */
|
|
377
|
+
refresh_token?: string;
|
|
378
|
+
/** @description Token expiration time in seconds */
|
|
379
|
+
expires_in?: number;
|
|
380
|
+
/** @description Refresh token expiration time in seconds */
|
|
381
|
+
refresh_expires_in?: number;
|
|
382
|
+
/** @example Bearer */
|
|
383
|
+
token_type?: string;
|
|
384
|
+
scope?: string;
|
|
385
|
+
};
|
|
386
|
+
};
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
/** @description Bad Request - Invalid Google token or missing googleAccessToken */
|
|
390
|
+
400: {
|
|
391
|
+
headers: {
|
|
392
|
+
[name: string]: unknown;
|
|
393
|
+
};
|
|
394
|
+
content: {
|
|
395
|
+
"application/json": {
|
|
396
|
+
/** @example error */
|
|
397
|
+
status?: string;
|
|
398
|
+
/** @example Token do Google inválido ou expirado */
|
|
399
|
+
message?: string;
|
|
400
|
+
};
|
|
401
|
+
};
|
|
402
|
+
};
|
|
403
|
+
/** @description Not Found - User email not registered in database */
|
|
404
|
+
404: {
|
|
405
|
+
headers: {
|
|
406
|
+
[name: string]: unknown;
|
|
407
|
+
};
|
|
408
|
+
content: {
|
|
409
|
+
"application/json": {
|
|
410
|
+
/** @example error */
|
|
411
|
+
status?: string;
|
|
412
|
+
/** @example Usuário não encontrado */
|
|
413
|
+
message?: string;
|
|
414
|
+
};
|
|
415
|
+
};
|
|
416
|
+
};
|
|
417
|
+
/** @description Internal Server Error */
|
|
418
|
+
500: {
|
|
419
|
+
headers: {
|
|
420
|
+
[name: string]: unknown;
|
|
421
|
+
};
|
|
422
|
+
content: {
|
|
423
|
+
"application/json": {
|
|
424
|
+
/** @example error */
|
|
425
|
+
status?: string;
|
|
426
|
+
/** @example Internal server error */
|
|
427
|
+
message?: string;
|
|
428
|
+
};
|
|
429
|
+
};
|
|
430
|
+
};
|
|
431
|
+
};
|
|
432
|
+
};
|
|
433
|
+
delete?: never;
|
|
434
|
+
options?: never;
|
|
435
|
+
head?: never;
|
|
436
|
+
patch?: never;
|
|
437
|
+
trace?: never;
|
|
438
|
+
};
|
|
224
439
|
"/auth/token": {
|
|
225
440
|
parameters: {
|
|
226
441
|
query?: never;
|
|
@@ -823,6 +1038,68 @@ export interface paths {
|
|
|
823
1038
|
patch?: never;
|
|
824
1039
|
trace?: never;
|
|
825
1040
|
};
|
|
1041
|
+
"/certificates/{userId}/download-all": {
|
|
1042
|
+
parameters: {
|
|
1043
|
+
query?: never;
|
|
1044
|
+
header?: never;
|
|
1045
|
+
path?: never;
|
|
1046
|
+
cookie?: never;
|
|
1047
|
+
};
|
|
1048
|
+
/**
|
|
1049
|
+
* Download all certificates of a user as a single PDF
|
|
1050
|
+
* @description Downloads all certificates of the given user merged into a single PDF file.
|
|
1051
|
+
* Each certificate occupies one page in the resulting file.
|
|
1052
|
+
* PDFs are downloaded from S3 in parallel and merged using pdf-lib.
|
|
1053
|
+
*/
|
|
1054
|
+
get: {
|
|
1055
|
+
parameters: {
|
|
1056
|
+
query?: never;
|
|
1057
|
+
header?: never;
|
|
1058
|
+
path: {
|
|
1059
|
+
/** @description ID of the user whose certificates will be downloaded */
|
|
1060
|
+
userId: string;
|
|
1061
|
+
};
|
|
1062
|
+
cookie?: never;
|
|
1063
|
+
};
|
|
1064
|
+
requestBody?: never;
|
|
1065
|
+
responses: {
|
|
1066
|
+
/** @description Merged PDF file containing all user certificates */
|
|
1067
|
+
200: {
|
|
1068
|
+
headers: {
|
|
1069
|
+
/** @description attachment; filename="Meus-Certificados.pdf" */
|
|
1070
|
+
"Content-Disposition"?: string;
|
|
1071
|
+
[name: string]: unknown;
|
|
1072
|
+
};
|
|
1073
|
+
content: {
|
|
1074
|
+
"application/pdf": string;
|
|
1075
|
+
};
|
|
1076
|
+
};
|
|
1077
|
+
401: components["responses"]["Unauthorized"];
|
|
1078
|
+
/** @description No certificates found for the user */
|
|
1079
|
+
404: {
|
|
1080
|
+
headers: {
|
|
1081
|
+
[name: string]: unknown;
|
|
1082
|
+
};
|
|
1083
|
+
content: {
|
|
1084
|
+
"application/json": {
|
|
1085
|
+
/** @example error */
|
|
1086
|
+
status?: string;
|
|
1087
|
+
/** @example No certificates found for this user */
|
|
1088
|
+
message?: string;
|
|
1089
|
+
};
|
|
1090
|
+
};
|
|
1091
|
+
};
|
|
1092
|
+
500: components["responses"]["ServerError"];
|
|
1093
|
+
};
|
|
1094
|
+
};
|
|
1095
|
+
put?: never;
|
|
1096
|
+
post?: never;
|
|
1097
|
+
delete?: never;
|
|
1098
|
+
options?: never;
|
|
1099
|
+
head?: never;
|
|
1100
|
+
patch?: never;
|
|
1101
|
+
trace?: never;
|
|
1102
|
+
};
|
|
826
1103
|
"/certificates": {
|
|
827
1104
|
parameters: {
|
|
828
1105
|
query?: never;
|
|
@@ -832,13 +1109,24 @@ export interface paths {
|
|
|
832
1109
|
};
|
|
833
1110
|
/**
|
|
834
1111
|
* List all certificates
|
|
835
|
-
* @description Retrieve a list of all certificates in the system.
|
|
1112
|
+
* @description Retrieve a paginated list of all certificates in the system.
|
|
836
1113
|
* Each certificate includes course information (id, title, description) when available.
|
|
837
1114
|
* Course data is extracted from the related Quiz through QuizAttempt.
|
|
838
1115
|
*/
|
|
839
1116
|
get: {
|
|
840
1117
|
parameters: {
|
|
841
|
-
query?:
|
|
1118
|
+
query?: {
|
|
1119
|
+
/** @description Filter certificates by user ID */
|
|
1120
|
+
userId?: string;
|
|
1121
|
+
/** @description Search term */
|
|
1122
|
+
search?: components["parameters"]["search"];
|
|
1123
|
+
/** @description Page number */
|
|
1124
|
+
page?: components["parameters"]["page"];
|
|
1125
|
+
/** @description Items per page */
|
|
1126
|
+
limit?: components["parameters"]["limit"];
|
|
1127
|
+
/** @description Whether to include course data in the response (default true). Pass false to skip course lookup. */
|
|
1128
|
+
includeCourse?: boolean;
|
|
1129
|
+
};
|
|
842
1130
|
header?: never;
|
|
843
1131
|
path?: never;
|
|
844
1132
|
cookie?: never;
|
|
@@ -855,6 +1143,16 @@ export interface paths {
|
|
|
855
1143
|
/** @example success */
|
|
856
1144
|
status?: string;
|
|
857
1145
|
data?: components["schemas"]["Certificate"][];
|
|
1146
|
+
meta?: {
|
|
1147
|
+
/** @example 10 */
|
|
1148
|
+
total?: number;
|
|
1149
|
+
/** @example 1 */
|
|
1150
|
+
page?: number;
|
|
1151
|
+
/** @example 10 */
|
|
1152
|
+
limit?: number;
|
|
1153
|
+
/** @example 1 */
|
|
1154
|
+
totalPages?: number;
|
|
1155
|
+
};
|
|
858
1156
|
};
|
|
859
1157
|
};
|
|
860
1158
|
};
|
|
@@ -890,8 +1188,6 @@ export interface paths {
|
|
|
890
1188
|
/** @example success */
|
|
891
1189
|
status?: string;
|
|
892
1190
|
data?: components["schemas"]["Certificate"];
|
|
893
|
-
/** @example Certificate created successfully */
|
|
894
|
-
message?: string;
|
|
895
1191
|
};
|
|
896
1192
|
};
|
|
897
1193
|
};
|
|
@@ -969,18 +1265,11 @@ export interface paths {
|
|
|
969
1265
|
requestBody?: never;
|
|
970
1266
|
responses: {
|
|
971
1267
|
/** @description Certificate deleted successfully */
|
|
972
|
-
|
|
1268
|
+
204: {
|
|
973
1269
|
headers: {
|
|
974
1270
|
[name: string]: unknown;
|
|
975
1271
|
};
|
|
976
|
-
content
|
|
977
|
-
"application/json": {
|
|
978
|
-
/** @example success */
|
|
979
|
-
status?: string;
|
|
980
|
-
/** @example Certificate deleted successfully */
|
|
981
|
-
message?: string;
|
|
982
|
-
};
|
|
983
|
-
};
|
|
1272
|
+
content?: never;
|
|
984
1273
|
};
|
|
985
1274
|
400: components["responses"]["BadRequest"];
|
|
986
1275
|
401: components["responses"]["Unauthorized"];
|
|
@@ -1020,8 +1309,6 @@ export interface paths {
|
|
|
1020
1309
|
/** @example success */
|
|
1021
1310
|
status?: string;
|
|
1022
1311
|
data?: components["schemas"]["Certificate"];
|
|
1023
|
-
/** @example Certificate updated successfully */
|
|
1024
|
-
message?: string;
|
|
1025
1312
|
};
|
|
1026
1313
|
};
|
|
1027
1314
|
};
|
|
@@ -1033,6 +1320,109 @@ export interface paths {
|
|
|
1033
1320
|
};
|
|
1034
1321
|
trace?: never;
|
|
1035
1322
|
};
|
|
1323
|
+
"/certificates/{id}/download": {
|
|
1324
|
+
parameters: {
|
|
1325
|
+
query?: never;
|
|
1326
|
+
header?: never;
|
|
1327
|
+
path?: never;
|
|
1328
|
+
cookie?: never;
|
|
1329
|
+
};
|
|
1330
|
+
/**
|
|
1331
|
+
* Download certificate PDF
|
|
1332
|
+
* @description Download the PDF of a specific certificate.
|
|
1333
|
+
* Acts as a proxy to download from S3, avoiding CORS issues.
|
|
1334
|
+
* Only the certificate owner can download their certificate.
|
|
1335
|
+
*/
|
|
1336
|
+
get: {
|
|
1337
|
+
parameters: {
|
|
1338
|
+
query?: never;
|
|
1339
|
+
header?: never;
|
|
1340
|
+
path: {
|
|
1341
|
+
/** @description Resource ID */
|
|
1342
|
+
id: components["parameters"]["id"];
|
|
1343
|
+
};
|
|
1344
|
+
cookie?: never;
|
|
1345
|
+
};
|
|
1346
|
+
requestBody?: never;
|
|
1347
|
+
responses: {
|
|
1348
|
+
/** @description Certificate PDF file */
|
|
1349
|
+
200: {
|
|
1350
|
+
headers: {
|
|
1351
|
+
[name: string]: unknown;
|
|
1352
|
+
};
|
|
1353
|
+
content: {
|
|
1354
|
+
"application/pdf": string;
|
|
1355
|
+
};
|
|
1356
|
+
};
|
|
1357
|
+
401: components["responses"]["Unauthorized"];
|
|
1358
|
+
403: components["responses"]["Forbidden"];
|
|
1359
|
+
404: components["responses"]["NotFound"];
|
|
1360
|
+
500: components["responses"]["ServerError"];
|
|
1361
|
+
};
|
|
1362
|
+
};
|
|
1363
|
+
put?: never;
|
|
1364
|
+
post?: never;
|
|
1365
|
+
delete?: never;
|
|
1366
|
+
options?: never;
|
|
1367
|
+
head?: never;
|
|
1368
|
+
patch?: never;
|
|
1369
|
+
trace?: never;
|
|
1370
|
+
};
|
|
1371
|
+
"/certificates/generate": {
|
|
1372
|
+
parameters: {
|
|
1373
|
+
query?: never;
|
|
1374
|
+
header?: never;
|
|
1375
|
+
path?: never;
|
|
1376
|
+
cookie?: never;
|
|
1377
|
+
};
|
|
1378
|
+
get?: never;
|
|
1379
|
+
put?: never;
|
|
1380
|
+
/**
|
|
1381
|
+
* Generate a certificate PDF server-side
|
|
1382
|
+
* @description Generates a certificate PDF on the server and creates the certificate record.
|
|
1383
|
+
* This eliminates CORS issues by downloading the template image on the server.
|
|
1384
|
+
*/
|
|
1385
|
+
post: {
|
|
1386
|
+
parameters: {
|
|
1387
|
+
query?: never;
|
|
1388
|
+
header?: never;
|
|
1389
|
+
path?: never;
|
|
1390
|
+
cookie?: never;
|
|
1391
|
+
};
|
|
1392
|
+
requestBody: {
|
|
1393
|
+
content: {
|
|
1394
|
+
"application/json": components["schemas"]["GenerateCertificateDto"];
|
|
1395
|
+
};
|
|
1396
|
+
};
|
|
1397
|
+
responses: {
|
|
1398
|
+
/** @description Certificate generated and created successfully */
|
|
1399
|
+
201: {
|
|
1400
|
+
headers: {
|
|
1401
|
+
[name: string]: unknown;
|
|
1402
|
+
};
|
|
1403
|
+
content: {
|
|
1404
|
+
"application/json": {
|
|
1405
|
+
/** @example success */
|
|
1406
|
+
status?: string;
|
|
1407
|
+
data?: {
|
|
1408
|
+
certificate?: components["schemas"]["Certificate"];
|
|
1409
|
+
/** @example https://s3.amazonaws.com/bucket/certificate.pdf */
|
|
1410
|
+
pdfUrl?: string;
|
|
1411
|
+
};
|
|
1412
|
+
};
|
|
1413
|
+
};
|
|
1414
|
+
};
|
|
1415
|
+
400: components["responses"]["BadRequest"];
|
|
1416
|
+
401: components["responses"]["Unauthorized"];
|
|
1417
|
+
500: components["responses"]["ServerError"];
|
|
1418
|
+
};
|
|
1419
|
+
};
|
|
1420
|
+
delete?: never;
|
|
1421
|
+
options?: never;
|
|
1422
|
+
head?: never;
|
|
1423
|
+
patch?: never;
|
|
1424
|
+
trace?: never;
|
|
1425
|
+
};
|
|
1036
1426
|
"/classrooms": {
|
|
1037
1427
|
parameters: {
|
|
1038
1428
|
query?: never;
|
|
@@ -9540,6 +9930,8 @@ export interface paths {
|
|
|
9540
9930
|
requestBody: {
|
|
9541
9931
|
content: {
|
|
9542
9932
|
"application/json": {
|
|
9933
|
+
/** @example sa@academe.com.br */
|
|
9934
|
+
email?: string;
|
|
9543
9935
|
/** @example John */
|
|
9544
9936
|
firstName?: string;
|
|
9545
9937
|
/** @example Doe */
|
|
@@ -9939,7 +10331,19 @@ export interface paths {
|
|
|
9939
10331
|
head?: never;
|
|
9940
10332
|
/**
|
|
9941
10333
|
* Update user
|
|
9942
|
-
* @description Update user information
|
|
10334
|
+
* @description Update user information.
|
|
10335
|
+
*
|
|
10336
|
+
* **Profile and seat code behavior:**
|
|
10337
|
+
* - Send `groupId` to change the user's profile/group.
|
|
10338
|
+
* - When `groupId` changes, the system will:
|
|
10339
|
+
* 1. Release the previous seat code used by the user (`isReserved = false`)
|
|
10340
|
+
* 2. Allocate a seat code for the new group in the same institution registration
|
|
10341
|
+
* 3. Create a new seat code automatically if none is available for that group
|
|
10342
|
+
*
|
|
10343
|
+
* **Important:**
|
|
10344
|
+
* - The target group must exist.
|
|
10345
|
+
* - The institution must have a seat configured for the target group.
|
|
10346
|
+
* - If any institution registration cannot be migrated to the new group, the operation fails.
|
|
9943
10347
|
*/
|
|
9944
10348
|
patch: {
|
|
9945
10349
|
parameters: {
|
|
@@ -10255,6 +10659,165 @@ export interface paths {
|
|
|
10255
10659
|
patch?: never;
|
|
10256
10660
|
trace?: never;
|
|
10257
10661
|
};
|
|
10662
|
+
"/users/register-hotmart": {
|
|
10663
|
+
parameters: {
|
|
10664
|
+
query?: never;
|
|
10665
|
+
header?: never;
|
|
10666
|
+
path?: never;
|
|
10667
|
+
cookie?: never;
|
|
10668
|
+
};
|
|
10669
|
+
get?: never;
|
|
10670
|
+
put?: never;
|
|
10671
|
+
/**
|
|
10672
|
+
* Hotmart webhook for user registration and lifecycle
|
|
10673
|
+
* @description Public endpoint that receives webhook events from Hotmart.
|
|
10674
|
+
* Handles user creation and deactivation based on purchase events.
|
|
10675
|
+
*
|
|
10676
|
+
* **Supported Events:**
|
|
10677
|
+
*
|
|
10678
|
+
* | Event | Action |
|
|
10679
|
+
* |-------|--------|
|
|
10680
|
+
* | `PURCHASE_APPROVED` | Enqueues user creation with buyer data |
|
|
10681
|
+
* | `PURCHASE_CANCELED` | Deactivates (soft deletes) the user |
|
|
10682
|
+
* | `PURCHASE_REFUNDED` | Deactivates (soft deletes) the user |
|
|
10683
|
+
* | `PURCHASE_CHARGEBACK` | Deactivates (soft deletes) the user |
|
|
10684
|
+
*
|
|
10685
|
+
* **User Creation Flow (PURCHASE_APPROVED):**
|
|
10686
|
+
* 1. Extracts buyer information from the Hotmart payload
|
|
10687
|
+
* 2. Determines institution based on offer code
|
|
10688
|
+
* 3. Enqueues user creation request for async processing
|
|
10689
|
+
* 4. User is created in Keycloak and database by the worker
|
|
10690
|
+
*
|
|
10691
|
+
* **Offer-based Institution Assignment:**
|
|
10692
|
+
* - Offer code `d9to7y3w` → Institution `580268b1-458d-4f4c-901d-281eccf3b40d`
|
|
10693
|
+
*
|
|
10694
|
+
* **User Deactivation Flow:**
|
|
10695
|
+
* 1. Looks up the user by buyer email
|
|
10696
|
+
* 2. Soft deletes the user (marks as inactive)
|
|
10697
|
+
* 3. Disables the user in Keycloak
|
|
10698
|
+
*
|
|
10699
|
+
* All events return HTTP 200 to acknowledge receipt.
|
|
10700
|
+
* Unrecognized events are logged and ignored.
|
|
10701
|
+
*/
|
|
10702
|
+
post: {
|
|
10703
|
+
parameters: {
|
|
10704
|
+
query?: never;
|
|
10705
|
+
header?: never;
|
|
10706
|
+
path?: never;
|
|
10707
|
+
cookie?: never;
|
|
10708
|
+
};
|
|
10709
|
+
requestBody: {
|
|
10710
|
+
content: {
|
|
10711
|
+
"application/json": {
|
|
10712
|
+
/**
|
|
10713
|
+
* Format: uuid
|
|
10714
|
+
* @description Unique webhook event ID
|
|
10715
|
+
* @example d96fafd0-75ed-4ca7-8fa8-c6a57f48e384
|
|
10716
|
+
*/
|
|
10717
|
+
id: string;
|
|
10718
|
+
/**
|
|
10719
|
+
* @description Hotmart event type
|
|
10720
|
+
* @example PURCHASE_APPROVED
|
|
10721
|
+
* @enum {string}
|
|
10722
|
+
*/
|
|
10723
|
+
event: "PURCHASE_APPROVED" | "PURCHASE_CANCELED" | "PURCHASE_REFUNDED" | "PURCHASE_CHARGEBACK" | "PURCHASE_COMPLETE" | "PURCHASE_PROTEST" | "PURCHASE_DELAYED";
|
|
10724
|
+
/**
|
|
10725
|
+
* @description Event creation timestamp (Unix milliseconds)
|
|
10726
|
+
* @example 1773161133350
|
|
10727
|
+
*/
|
|
10728
|
+
creation_date: number;
|
|
10729
|
+
/**
|
|
10730
|
+
* @description Webhook payload version
|
|
10731
|
+
* @example 2.0.0
|
|
10732
|
+
*/
|
|
10733
|
+
version: string;
|
|
10734
|
+
data: {
|
|
10735
|
+
buyer: {
|
|
10736
|
+
/**
|
|
10737
|
+
* Format: email
|
|
10738
|
+
* @example buyer@example.com
|
|
10739
|
+
*/
|
|
10740
|
+
email: string;
|
|
10741
|
+
/** @example Teste */
|
|
10742
|
+
first_name: string;
|
|
10743
|
+
/** @example Comprador */
|
|
10744
|
+
last_name: string;
|
|
10745
|
+
/** @example Teste Comprador */
|
|
10746
|
+
name?: string;
|
|
10747
|
+
/** @example 69526128664 */
|
|
10748
|
+
document?: string;
|
|
10749
|
+
/** @example CPF */
|
|
10750
|
+
document_type?: string;
|
|
10751
|
+
/** @example 99999999900 */
|
|
10752
|
+
checkout_phone?: string;
|
|
10753
|
+
};
|
|
10754
|
+
purchase: {
|
|
10755
|
+
/** @example HP16015479281022 */
|
|
10756
|
+
transaction: string;
|
|
10757
|
+
/** @example APPROVED */
|
|
10758
|
+
status: string;
|
|
10759
|
+
offer?: {
|
|
10760
|
+
/**
|
|
10761
|
+
* @description Offer code used to determine institution assignment
|
|
10762
|
+
* @example d9to7y3w
|
|
10763
|
+
*/
|
|
10764
|
+
code?: string;
|
|
10765
|
+
};
|
|
10766
|
+
};
|
|
10767
|
+
product: {
|
|
10768
|
+
id?: number;
|
|
10769
|
+
name?: string;
|
|
10770
|
+
/** Format: uuid */
|
|
10771
|
+
ucode?: string;
|
|
10772
|
+
};
|
|
10773
|
+
subscription?: {
|
|
10774
|
+
subscriber?: {
|
|
10775
|
+
code?: string;
|
|
10776
|
+
};
|
|
10777
|
+
plan?: {
|
|
10778
|
+
name?: string;
|
|
10779
|
+
id?: number;
|
|
10780
|
+
};
|
|
10781
|
+
status?: string;
|
|
10782
|
+
};
|
|
10783
|
+
};
|
|
10784
|
+
};
|
|
10785
|
+
};
|
|
10786
|
+
};
|
|
10787
|
+
responses: {
|
|
10788
|
+
/** @description Webhook event processed successfully */
|
|
10789
|
+
200: {
|
|
10790
|
+
headers: {
|
|
10791
|
+
[name: string]: unknown;
|
|
10792
|
+
};
|
|
10793
|
+
content: {
|
|
10794
|
+
"application/json": {
|
|
10795
|
+
/** @example success */
|
|
10796
|
+
status?: string;
|
|
10797
|
+
/**
|
|
10798
|
+
* @description Action taken for the event
|
|
10799
|
+
* @example user_creation_enqueued
|
|
10800
|
+
* @enum {string}
|
|
10801
|
+
*/
|
|
10802
|
+
action?: "user_creation_enqueued" | "user_deactivated" | "user_not_found" | "event_ignored";
|
|
10803
|
+
/**
|
|
10804
|
+
* Format: uuid
|
|
10805
|
+
* @description Request ID for tracking (only on user_creation_enqueued)
|
|
10806
|
+
* @example 550e8400-e29b-41d4-a716-446655440000
|
|
10807
|
+
*/
|
|
10808
|
+
requestId?: string;
|
|
10809
|
+
};
|
|
10810
|
+
};
|
|
10811
|
+
};
|
|
10812
|
+
500: components["responses"]["ServerError"];
|
|
10813
|
+
};
|
|
10814
|
+
};
|
|
10815
|
+
delete?: never;
|
|
10816
|
+
options?: never;
|
|
10817
|
+
head?: never;
|
|
10818
|
+
patch?: never;
|
|
10819
|
+
trace?: never;
|
|
10820
|
+
};
|
|
10258
10821
|
}
|
|
10259
10822
|
export type webhooks = Record<string, never>;
|
|
10260
10823
|
export interface components {
|
|
@@ -11500,6 +12063,20 @@ export interface components {
|
|
|
11500
12063
|
};
|
|
11501
12064
|
};
|
|
11502
12065
|
};
|
|
12066
|
+
ForgotPasswordRequest: {
|
|
12067
|
+
/**
|
|
12068
|
+
* Format: email
|
|
12069
|
+
* @description User's email address for password reset
|
|
12070
|
+
* @example user@example.com
|
|
12071
|
+
*/
|
|
12072
|
+
email: string;
|
|
12073
|
+
};
|
|
12074
|
+
ForgotPasswordResponse: {
|
|
12075
|
+
/** @example success */
|
|
12076
|
+
status?: string;
|
|
12077
|
+
/** @example If this email is registered, you will receive password reset instructions. */
|
|
12078
|
+
message?: string;
|
|
12079
|
+
};
|
|
11503
12080
|
CreateInstitutionClassroomDto: {
|
|
11504
12081
|
/**
|
|
11505
12082
|
* Format: uuid
|
|
@@ -11680,10 +12257,14 @@ export interface components {
|
|
|
11680
12257
|
* @description Product ID associated with this seat
|
|
11681
12258
|
*/
|
|
11682
12259
|
productId?: string;
|
|
12260
|
+
/** @description Total number of seat codes for this seat */
|
|
12261
|
+
total?: number;
|
|
11683
12262
|
/** @description Available quantity for this group in the institution */
|
|
11684
12263
|
availableQuantity?: number;
|
|
11685
12264
|
/** @description Number of users currently assigned to this group in the institution */
|
|
11686
12265
|
usedQuantity?: number;
|
|
12266
|
+
/** @description Number of reserved seat codes without active registration */
|
|
12267
|
+
reservedQuantity?: number;
|
|
11687
12268
|
/** Format: date-time */
|
|
11688
12269
|
createdAt?: string;
|
|
11689
12270
|
/** Format: date-time */
|
|
@@ -12172,6 +12753,27 @@ export interface components {
|
|
|
12172
12753
|
/** Format: uri */
|
|
12173
12754
|
url?: string;
|
|
12174
12755
|
};
|
|
12756
|
+
GenerateCertificateDto: {
|
|
12757
|
+
/** Format: uuid */
|
|
12758
|
+
userId: string;
|
|
12759
|
+
/** Format: uuid */
|
|
12760
|
+
quizAttemptId?: string;
|
|
12761
|
+
/** Format: uuid */
|
|
12762
|
+
certificateTemplateId: string;
|
|
12763
|
+
/** @example João Silva */
|
|
12764
|
+
studentName: string;
|
|
12765
|
+
/** @example Introdução ao JavaScript */
|
|
12766
|
+
quizTitle: string;
|
|
12767
|
+
/** @example 85 */
|
|
12768
|
+
score?: number;
|
|
12769
|
+
/** @example CERT-2024-000001 */
|
|
12770
|
+
certificateNumber?: string;
|
|
12771
|
+
/**
|
|
12772
|
+
* Format: date-time
|
|
12773
|
+
* @example 2024-01-01T00:00:00.000Z
|
|
12774
|
+
*/
|
|
12775
|
+
issuedAt?: string;
|
|
12776
|
+
};
|
|
12175
12777
|
CreateGuardianDto: {
|
|
12176
12778
|
/**
|
|
12177
12779
|
* Format: email
|