@tmlmobilidade/go-providers-auth 20260716.1615.24
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.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/provider.d.ts +53 -0
- package/dist/provider.js +131 -0
- package/package.json +54 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './provider.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './provider.js';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type CreateUserDto, type LoginDto, type Organization, type Permission, type Session, type User } from '@tmlmobilidade/types';
|
|
2
|
+
export declare const AUTH_SESSION_COOKIE_NAME = "session_token";
|
|
3
|
+
declare class AuthProviderClass {
|
|
4
|
+
private static _instance;
|
|
5
|
+
private constructor();
|
|
6
|
+
static getInstance(): Promise<AuthProviderClass>;
|
|
7
|
+
/**
|
|
8
|
+
* Get the organization for a user based on their session token.
|
|
9
|
+
* @param sessionToken The session token to look up.
|
|
10
|
+
* @returns The organization associated with the session token.
|
|
11
|
+
*/
|
|
12
|
+
getOrganizationFromSessionToken(sessionToken: string): Promise<Organization | undefined>;
|
|
13
|
+
/**
|
|
14
|
+
* Get permissions for a user based on their session token.
|
|
15
|
+
* @param sessionToken The session token.
|
|
16
|
+
* @returns The permissions that the user has.
|
|
17
|
+
*/
|
|
18
|
+
getPermissionsFromSessionToken(sessionToken: string): Promise<Permission[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Get permissions for a user based on their user ID.
|
|
21
|
+
* @param userId The user ID.
|
|
22
|
+
* @returns The permissions that the user has.
|
|
23
|
+
* @throws An HTTP UNAUTHORIZED error code if user not found.
|
|
24
|
+
*/
|
|
25
|
+
getPermissionsFromUserId(userId: string): Promise<Permission[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Get a user object from their session token.
|
|
28
|
+
* @param sessionToken The session token to look up.
|
|
29
|
+
* @returns The user associated with the session token.
|
|
30
|
+
* @throws An HTTP UNAUTHORIZED error code if user or session not found.
|
|
31
|
+
*/
|
|
32
|
+
getUserFromSessionToken(sessionToken: string): Promise<User>;
|
|
33
|
+
/**
|
|
34
|
+
* Login a user.
|
|
35
|
+
* @param loginDto The login credentials (email and password).
|
|
36
|
+
* @returns The newly created session for the logged in user.
|
|
37
|
+
* @throws An HTTP UNAUTHORIZED error code if user not found or password is incorrect.
|
|
38
|
+
*/
|
|
39
|
+
login(loginDto: LoginDto): Promise<Session>;
|
|
40
|
+
/**
|
|
41
|
+
* Logout a user by removing their session.
|
|
42
|
+
* @param sessionToken The session token to logout.
|
|
43
|
+
*/
|
|
44
|
+
logout(sessionToken: string): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Register a new user.
|
|
47
|
+
* @param createUserDto The data to create the user.
|
|
48
|
+
* @returns The verification token for email verification.
|
|
49
|
+
*/
|
|
50
|
+
register(createUserDto: CreateUserDto): Promise<string>;
|
|
51
|
+
}
|
|
52
|
+
export declare const authProvider: AuthProviderClass;
|
|
53
|
+
export {};
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/* * */
|
|
2
|
+
import { HTTP_STATUS, HttpException } from '@tmlmobilidade/consts';
|
|
3
|
+
import { Dates } from '@tmlmobilidade/dates';
|
|
4
|
+
import { goDB } from '@tmlmobilidade/go-interfaces-go-db';
|
|
5
|
+
import { generateRandomString, generateRandomToken } from '@tmlmobilidade/strings';
|
|
6
|
+
import { asyncSingletonProxy, mergeObjects } from '@tmlmobilidade/utils';
|
|
7
|
+
import bcrypt from 'bcryptjs';
|
|
8
|
+
/* * */
|
|
9
|
+
export const AUTH_SESSION_COOKIE_NAME = 'session_token';
|
|
10
|
+
/* * */
|
|
11
|
+
class AuthProviderClass {
|
|
12
|
+
static _instance;
|
|
13
|
+
constructor() { }
|
|
14
|
+
static async getInstance() {
|
|
15
|
+
if (!AuthProviderClass._instance) {
|
|
16
|
+
AuthProviderClass._instance = new AuthProviderClass();
|
|
17
|
+
}
|
|
18
|
+
return AuthProviderClass._instance;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get the organization for a user based on their session token.
|
|
22
|
+
* @param sessionToken The session token to look up.
|
|
23
|
+
* @returns The organization associated with the session token.
|
|
24
|
+
*/
|
|
25
|
+
async getOrganizationFromSessionToken(sessionToken) {
|
|
26
|
+
const userData = await this.getUserFromSessionToken(sessionToken);
|
|
27
|
+
const organizationData = await goDB.core.organizations.findOne({ _id: { $eq: userData.organization_id } });
|
|
28
|
+
if (!organizationData)
|
|
29
|
+
return undefined;
|
|
30
|
+
return organizationData;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get permissions for a user based on their session token.
|
|
34
|
+
* @param sessionToken The session token.
|
|
35
|
+
* @returns The permissions that the user has.
|
|
36
|
+
*/
|
|
37
|
+
async getPermissionsFromSessionToken(sessionToken) {
|
|
38
|
+
const userData = await this.getUserFromSessionToken(sessionToken);
|
|
39
|
+
return this.getPermissionsFromUserId(userData._id);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get permissions for a user based on their user ID.
|
|
43
|
+
* @param userId The user ID.
|
|
44
|
+
* @returns The permissions that the user has.
|
|
45
|
+
* @throws An HTTP UNAUTHORIZED error code if user not found.
|
|
46
|
+
*/
|
|
47
|
+
async getPermissionsFromUserId(userId) {
|
|
48
|
+
const userData = await goDB.core.users.findById(userId);
|
|
49
|
+
if (!userData)
|
|
50
|
+
throw new HttpException(HTTP_STATUS.UNAUTHORIZED, 'User not found.');
|
|
51
|
+
const rolesData = await goDB.core.roles.findMany({ _id: { $in: userData.role_ids } });
|
|
52
|
+
const allPermissions = [...rolesData.flatMap(role => role.permissions), ...userData.permissions];
|
|
53
|
+
const permissionsMap = new Map();
|
|
54
|
+
for (const permission of allPermissions) {
|
|
55
|
+
const key = `${permission.scope}:${permission.action}`;
|
|
56
|
+
if (permissionsMap.has(key)) {
|
|
57
|
+
const existingPermission = permissionsMap.get(key);
|
|
58
|
+
permissionsMap.set(key, mergeObjects(existingPermission, permission));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
permissionsMap.set(key, permission);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return Array.from(permissionsMap.values());
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get a user object from their session token.
|
|
68
|
+
* @param sessionToken The session token to look up.
|
|
69
|
+
* @returns The user associated with the session token.
|
|
70
|
+
* @throws An HTTP UNAUTHORIZED error code if user or session not found.
|
|
71
|
+
*/
|
|
72
|
+
async getUserFromSessionToken(sessionToken) {
|
|
73
|
+
const sessionData = await goDB.core.sessions.findOne({ token: { $eq: sessionToken } });
|
|
74
|
+
if (!sessionData)
|
|
75
|
+
throw new HttpException(HTTP_STATUS.UNAUTHORIZED, 'Session not found');
|
|
76
|
+
const userData = await goDB.core.users.findOne({ _id: { $eq: sessionData.user_id } });
|
|
77
|
+
if (!userData)
|
|
78
|
+
throw new HttpException(HTTP_STATUS.UNAUTHORIZED, 'User not found');
|
|
79
|
+
userData.password_hash = undefined;
|
|
80
|
+
return userData;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Login a user.
|
|
84
|
+
* @param loginDto The login credentials (email and password).
|
|
85
|
+
* @returns The newly created session for the logged in user.
|
|
86
|
+
* @throws An HTTP UNAUTHORIZED error code if user not found or password is incorrect.
|
|
87
|
+
*/
|
|
88
|
+
async login(loginDto) {
|
|
89
|
+
const userData = await goDB.core.users.findOne({ email: { $eq: loginDto.email } });
|
|
90
|
+
if (!userData)
|
|
91
|
+
throw new HttpException(HTTP_STATUS.UNAUTHORIZED, 'User not found');
|
|
92
|
+
const passwordHashMatch = await bcrypt.compare(loginDto.password, userData.password_hash ?? '');
|
|
93
|
+
if (!passwordHashMatch)
|
|
94
|
+
throw new HttpException(HTTP_STATUS.UNAUTHORIZED, 'Invalid password');
|
|
95
|
+
const createdSession = await goDB.core.sessions.insertOne({
|
|
96
|
+
_id: generateRandomString(),
|
|
97
|
+
created_at: Dates.now('utc').unix_timestamp,
|
|
98
|
+
created_by: 'system',
|
|
99
|
+
expires_at: Dates.now('utc').plus({ days: 30 }).unix_timestamp,
|
|
100
|
+
token: generateRandomToken(),
|
|
101
|
+
updated_at: Dates.now('utc').unix_timestamp,
|
|
102
|
+
updated_by: 'system',
|
|
103
|
+
user_id: userData._id.toString(),
|
|
104
|
+
});
|
|
105
|
+
return createdSession;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Logout a user by removing their session.
|
|
109
|
+
* @param sessionToken The session token to logout.
|
|
110
|
+
*/
|
|
111
|
+
async logout(sessionToken) {
|
|
112
|
+
await goDB.core.sessions.deleteOne({ token: { $eq: sessionToken } });
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Register a new user.
|
|
116
|
+
* @param createUserDto The data to create the user.
|
|
117
|
+
* @returns The verification token for email verification.
|
|
118
|
+
*/
|
|
119
|
+
async register(createUserDto) {
|
|
120
|
+
const insertNewUserResult = await goDB.core.users.insertOne(createUserDto);
|
|
121
|
+
const verificationToken = generateRandomToken();
|
|
122
|
+
await goDB.core.verificationTokens.insertOne({
|
|
123
|
+
expires_at: Dates.now('utc').plus({ days: 7 }).unix_timestamp,
|
|
124
|
+
token: verificationToken,
|
|
125
|
+
user_id: insertNewUserResult._id,
|
|
126
|
+
});
|
|
127
|
+
return verificationToken;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/* * */
|
|
131
|
+
export const authProvider = asyncSingletonProxy(AuthProviderClass);
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tmlmobilidade/go-providers-auth",
|
|
3
|
+
"version": "20260716.1615.24",
|
|
4
|
+
"author": {
|
|
5
|
+
"email": "iso@tmlmobilidade.pt",
|
|
6
|
+
"name": "TML-ISO"
|
|
7
|
+
},
|
|
8
|
+
"license": "AGPL-3.0-or-later",
|
|
9
|
+
"homepage": "https://go.tmlmobilidade.pt",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/tmlmobilidade/go/issues"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/tmlmobilidade/go.git"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"public transit",
|
|
19
|
+
"tml",
|
|
20
|
+
"transportes metropolitanos de lisboa",
|
|
21
|
+
"go"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"type": "module",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"main": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc && resolve-tspaths",
|
|
34
|
+
"lint": "eslint ./src/ && tsc --noEmit",
|
|
35
|
+
"lint:fix": "eslint ./src/ --fix",
|
|
36
|
+
"watch": "tsc-watch --onSuccess 'resolve-tspaths'"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@tmlmobilidade/consts": "*",
|
|
40
|
+
"@tmlmobilidade/dates": "*",
|
|
41
|
+
"@tmlmobilidade/go-interfaces-go-db": "*",
|
|
42
|
+
"@tmlmobilidade/strings": "*",
|
|
43
|
+
"@tmlmobilidade/types": "*",
|
|
44
|
+
"@tmlmobilidade/utils": "*",
|
|
45
|
+
"bcryptjs": "3.0.3"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@tmlmobilidade/tsconfig": "*",
|
|
49
|
+
"@types/node": "26.1.1",
|
|
50
|
+
"resolve-tspaths": "0.8.23",
|
|
51
|
+
"tsc-watch": "7.2.1",
|
|
52
|
+
"typescript": "6.0.3"
|
|
53
|
+
}
|
|
54
|
+
}
|