@spinajs/rbac-http-user 2.0.468 → 2.0.471
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/lib/cjs/controllers/LoginController.d.ts +35 -3
- package/lib/cjs/controllers/LoginController.d.ts.map +1 -1
- package/lib/cjs/controllers/LoginController.js +37 -10
- package/lib/cjs/controllers/LoginController.js.map +1 -1
- package/lib/cjs/controllers/TwoFactorAuthController.d.ts +39 -3
- package/lib/cjs/controllers/TwoFactorAuthController.d.ts.map +1 -1
- package/lib/cjs/controllers/TwoFactorAuthController.js +41 -1
- package/lib/cjs/controllers/TwoFactorAuthController.js.map +1 -1
- package/lib/cjs/controllers/UserController.d.ts +37 -3
- package/lib/cjs/controllers/UserController.d.ts.map +1 -1
- package/lib/cjs/controllers/UserController.js +33 -0
- package/lib/cjs/controllers/UserController.js.map +1 -1
- package/lib/cjs/controllers/UserMetadataController.d.ts +134 -11
- package/lib/cjs/controllers/UserMetadataController.d.ts.map +1 -1
- package/lib/cjs/controllers/UserMetadataController.js +130 -8
- package/lib/cjs/controllers/UserMetadataController.js.map +1 -1
- package/lib/cjs/dto/metadata-dto.d.ts +3 -0
- package/lib/cjs/dto/metadata-dto.d.ts.map +1 -1
- package/lib/cjs/dto/metadata-dto.js +3 -3
- package/lib/cjs/dto/metadata-dto.js.map +1 -1
- package/lib/cjs/dto/password-dto.d.ts +3 -0
- package/lib/cjs/dto/password-dto.d.ts.map +1 -1
- package/lib/cjs/dto/password-dto.js +3 -3
- package/lib/cjs/dto/password-dto.js.map +1 -1
- package/lib/cjs/dto/token-dto.d.ts +2 -0
- package/lib/cjs/dto/token-dto.d.ts.map +1 -1
- package/lib/cjs/dto/token-dto.js +2 -1
- package/lib/cjs/dto/token-dto.js.map +1 -1
- package/lib/cjs/dto/userLogin-dto.d.ts +3 -1
- package/lib/cjs/dto/userLogin-dto.d.ts.map +1 -1
- package/lib/cjs/dto/userLogin-dto.js +2 -2
- package/lib/cjs/dto/userLogin-dto.js.map +1 -1
- package/lib/mjs/controllers/LoginController.d.ts +35 -3
- package/lib/mjs/controllers/LoginController.d.ts.map +1 -1
- package/lib/mjs/controllers/LoginController.js +37 -10
- package/lib/mjs/controllers/LoginController.js.map +1 -1
- package/lib/mjs/controllers/TwoFactorAuthController.d.ts +39 -3
- package/lib/mjs/controllers/TwoFactorAuthController.d.ts.map +1 -1
- package/lib/mjs/controllers/TwoFactorAuthController.js +42 -2
- package/lib/mjs/controllers/TwoFactorAuthController.js.map +1 -1
- package/lib/mjs/controllers/UserController.d.ts +37 -3
- package/lib/mjs/controllers/UserController.d.ts.map +1 -1
- package/lib/mjs/controllers/UserController.js +33 -0
- package/lib/mjs/controllers/UserController.js.map +1 -1
- package/lib/mjs/controllers/UserMetadataController.d.ts +134 -11
- package/lib/mjs/controllers/UserMetadataController.d.ts.map +1 -1
- package/lib/mjs/controllers/UserMetadataController.js +130 -8
- package/lib/mjs/controllers/UserMetadataController.js.map +1 -1
- package/lib/mjs/dto/metadata-dto.d.ts +3 -0
- package/lib/mjs/dto/metadata-dto.d.ts.map +1 -1
- package/lib/mjs/dto/metadata-dto.js +3 -3
- package/lib/mjs/dto/metadata-dto.js.map +1 -1
- package/lib/mjs/dto/password-dto.d.ts +3 -0
- package/lib/mjs/dto/password-dto.d.ts.map +1 -1
- package/lib/mjs/dto/password-dto.js +3 -3
- package/lib/mjs/dto/password-dto.js.map +1 -1
- package/lib/mjs/dto/token-dto.d.ts +2 -0
- package/lib/mjs/dto/token-dto.d.ts.map +1 -1
- package/lib/mjs/dto/token-dto.js +2 -1
- package/lib/mjs/dto/token-dto.js.map +1 -1
- package/lib/mjs/dto/userLogin-dto.d.ts +3 -1
- package/lib/mjs/dto/userLogin-dto.d.ts.map +1 -1
- package/lib/mjs/dto/userLogin-dto.js +2 -2
- package/lib/mjs/dto/userLogin-dto.js.map +1 -1
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +11 -11
|
@@ -2,7 +2,14 @@ import { UserLoginDto } from '../dto/userLogin-dto.js';
|
|
|
2
2
|
import { BaseController, Ok, Unauthorized } from '@spinajs/http';
|
|
3
3
|
import { AuthProvider, SessionProvider, AccessControl } from '@spinajs/rbac';
|
|
4
4
|
import { Configuration } from '@spinajs/configuration';
|
|
5
|
+
import { ILoginResponse } from '@spinajs/rbac-http';
|
|
5
6
|
import { User } from '@spinajs/rbac';
|
|
7
|
+
/**
|
|
8
|
+
* Authentication endpoints.
|
|
9
|
+
* Handles user login, logout, and current-session inspection.
|
|
10
|
+
* All session state is maintained via the signed `ssid` cookie.
|
|
11
|
+
* @tags Authentication
|
|
12
|
+
*/
|
|
6
13
|
export declare class LoginController extends BaseController {
|
|
7
14
|
protected Configuration: Configuration;
|
|
8
15
|
protected AuthProvider: AuthProvider;
|
|
@@ -12,8 +19,33 @@ export declare class LoginController extends BaseController {
|
|
|
12
19
|
protected TwoFactorAuthForceUser: boolean;
|
|
13
20
|
protected SessionCookieConfig: any;
|
|
14
21
|
protected AC: AccessControl;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Login
|
|
24
|
+
* Authenticates the user with email and password. On success, sets the signed `ssid` session cookie
|
|
25
|
+
* and returns user data with their RBAC grants. When two-factor authentication is enabled and
|
|
26
|
+
* configured for the user, the response instead signals that 2FA verification is required.
|
|
27
|
+
* If the caller already has an active session it is invalidated before creating a new one.
|
|
28
|
+
* @security []
|
|
29
|
+
* @returns {ILoginResponse} On full login: IUserWithGrants. On 2FA required: ITwoFactorAuthRequired. On 2FA setup required: ITwoFactorInitRequired
|
|
30
|
+
* @response 401 Invalid email or password
|
|
31
|
+
*/
|
|
32
|
+
login(logged: User, ssid: string, credentials: UserLoginDto): Promise<Ok<ILoginResponse> | Unauthorized>;
|
|
33
|
+
/**
|
|
34
|
+
* Logout
|
|
35
|
+
* Destroys the current session identified by the `ssid` cookie and clears the cookie on the client.
|
|
36
|
+
* Requires the user to be logged in (session exists), but full authorization (2FA) is not required.
|
|
37
|
+
* @security cookieAuth
|
|
38
|
+
* @response 401 No active session
|
|
39
|
+
*/
|
|
40
|
+
logout(ssid: string): Promise<Ok<any>>;
|
|
41
|
+
/**
|
|
42
|
+
* Get current user
|
|
43
|
+
* Returns the user object associated with the current session.
|
|
44
|
+
* Requires the user to be logged in (session exists), but full authorization (2FA) is not required.
|
|
45
|
+
* @security cookieAuth
|
|
46
|
+
* @returns {IUserProfile} User data from the current session
|
|
47
|
+
* @response 401 No active session
|
|
48
|
+
*/
|
|
49
|
+
whoami(User: User): Promise<Ok<User>>;
|
|
18
50
|
}
|
|
19
51
|
//# sourceMappingURL=LoginController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoginController.d.ts","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAwB,EAAE,EAAe,YAAY,EAAU,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAE,YAAY,EAAE,eAAe,EAAsB,aAAa,EAAiB,MAAM,eAAe,CAAC;AAEhH,OAAO,EAA6B,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"LoginController.d.ts","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAwB,EAAE,EAAe,YAAY,EAAU,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAE,YAAY,EAAE,eAAe,EAAsB,aAAa,EAAiB,MAAM,eAAe,CAAC;AAEhH,OAAO,EAA6B,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAElF,OAAO,EAAsC,cAAc,EAAmB,MAAM,oBAAoB,CAAC;AACzG,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGrC;;;;;GAKG;AACH,qBACa,eAAgB,SAAQ,cAAc;IAEjD,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IAGvC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC;IAGrC,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAK3C,SAAS,CAAC,qBAAqB,EAAE,MAAM,CAAC;IAKxC,SAAS,CAAC,oBAAoB,EAAE,OAAO,CAAC;IAMxC,SAAS,CAAC,sBAAsB,EAAE,OAAO,CAAC;IAG1C,SAAS,CAAC,mBAAmB,EAAE,GAAG,CAAC;IAGnC,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;;OASG;IAEU,KAAK,CAAiB,MAAM,EAAE,IAAI,EAAgB,IAAI,EAAE,MAAM,EAAU,WAAW,EAAE,YAAY,GAAG,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC;IAwG3J;;;;;;OAMG;IAGU,MAAM,CAAe,IAAI,EAAE,MAAM;IA0B9C;;;;;;;OAOG;IAGU,MAAM,CAAiB,IAAI,EAAE,IAAI;CAK/C"}
|
|
@@ -20,7 +20,23 @@ const di_1 = require("@spinajs/di");
|
|
|
20
20
|
const configuration_1 = require("@spinajs/configuration");
|
|
21
21
|
const rbac_http_1 = require("@spinajs/rbac-http");
|
|
22
22
|
const rbac_2 = require("@spinajs/rbac");
|
|
23
|
+
/**
|
|
24
|
+
* Authentication endpoints.
|
|
25
|
+
* Handles user login, logout, and current-session inspection.
|
|
26
|
+
* All session state is maintained via the signed `ssid` cookie.
|
|
27
|
+
* @tags Authentication
|
|
28
|
+
*/
|
|
23
29
|
let LoginController = class LoginController extends http_1.BaseController {
|
|
30
|
+
/**
|
|
31
|
+
* Login
|
|
32
|
+
* Authenticates the user with email and password. On success, sets the signed `ssid` session cookie
|
|
33
|
+
* and returns user data with their RBAC grants. When two-factor authentication is enabled and
|
|
34
|
+
* configured for the user, the response instead signals that 2FA verification is required.
|
|
35
|
+
* If the caller already has an active session it is invalidated before creating a new one.
|
|
36
|
+
* @security []
|
|
37
|
+
* @returns {ILoginResponse} On full login: IUserWithGrants. On 2FA required: ITwoFactorAuthRequired. On 2FA setup required: ITwoFactorInitRequired
|
|
38
|
+
* @response 401 Invalid email or password
|
|
39
|
+
*/
|
|
24
40
|
async login(logged, ssid, credentials) {
|
|
25
41
|
try {
|
|
26
42
|
// if logged user is already logged in, delete his session
|
|
@@ -45,7 +61,7 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
45
61
|
},
|
|
46
62
|
},
|
|
47
63
|
];
|
|
48
|
-
let result
|
|
64
|
+
let result;
|
|
49
65
|
session.Data.set('User', user.Uuid);
|
|
50
66
|
// we have two states for user
|
|
51
67
|
// LOGGED - when user use proper login/password and session is created
|
|
@@ -61,9 +77,7 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
61
77
|
});
|
|
62
78
|
session.Data.set('Authorized', false);
|
|
63
79
|
session.Data.set('TwoFactorAuth', true);
|
|
64
|
-
result = {
|
|
65
|
-
TwoFactorInitRequired: true,
|
|
66
|
-
};
|
|
80
|
+
result = { TwoFactorInitRequired: true };
|
|
67
81
|
}
|
|
68
82
|
else if (this.TwoFactorAuthEnabled && user.Metadata['2fa:enabled']) {
|
|
69
83
|
this._log.trace('User logged in, 2fa required', {
|
|
@@ -71,19 +85,17 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
71
85
|
});
|
|
72
86
|
session.Data.set('Authorized', false);
|
|
73
87
|
session.Data.set('TwoFactorAuth', true);
|
|
74
|
-
result = {
|
|
75
|
-
TwoFactorAuthRequired: true,
|
|
76
|
-
};
|
|
88
|
+
result = { TwoFactorAuthRequired: true };
|
|
77
89
|
}
|
|
78
90
|
else {
|
|
79
91
|
session.Data.set('Authorized', true);
|
|
80
92
|
const grants = this.AC.getGrants();
|
|
81
93
|
const userGrants = user.Role.map(r => (0, rbac_1._unwindGrants)(r, grants));
|
|
82
94
|
const combinedGrants = Object.assign({}, ...userGrants);
|
|
95
|
+
// dehydrateWithRelations({ dateTimeFormat: 'iso' }) converts DateTime to ISO strings
|
|
96
|
+
// at runtime — the ORM types don't reflect the dateTimeFormat option in generics
|
|
83
97
|
result = {
|
|
84
|
-
...user.dehydrateWithRelations({
|
|
85
|
-
dateTimeFormat: "iso"
|
|
86
|
-
}),
|
|
98
|
+
...user.dehydrateWithRelations({ dateTimeFormat: "iso" }),
|
|
87
99
|
Grants: combinedGrants,
|
|
88
100
|
};
|
|
89
101
|
}
|
|
@@ -105,6 +117,13 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
105
117
|
});
|
|
106
118
|
}
|
|
107
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Logout
|
|
122
|
+
* Destroys the current session identified by the `ssid` cookie and clears the cookie on the client.
|
|
123
|
+
* Requires the user to be logged in (session exists), but full authorization (2FA) is not required.
|
|
124
|
+
* @security cookieAuth
|
|
125
|
+
* @response 401 No active session
|
|
126
|
+
*/
|
|
108
127
|
async logout(ssid) {
|
|
109
128
|
if (!ssid) {
|
|
110
129
|
return new http_1.Ok();
|
|
@@ -127,6 +146,14 @@ let LoginController = class LoginController extends http_1.BaseController {
|
|
|
127
146
|
],
|
|
128
147
|
});
|
|
129
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Get current user
|
|
151
|
+
* Returns the user object associated with the current session.
|
|
152
|
+
* Requires the user to be logged in (session exists), but full authorization (2FA) is not required.
|
|
153
|
+
* @security cookieAuth
|
|
154
|
+
* @returns {IUserProfile} User data from the current session
|
|
155
|
+
* @response 401 No active session
|
|
156
|
+
*/
|
|
130
157
|
async whoami(User) {
|
|
131
158
|
// user is taken from session data
|
|
132
159
|
return new http_1.Ok(User);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoginController.js","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,8DAAuD;AACvD,wCAA4G;AAC5G,wCAAgH;AAChH,oCAAyC;AACzC,0DAAkF;AAElF,
|
|
1
|
+
{"version":3,"file":"LoginController.js","sourceRoot":"","sources":["../../../src/controllers/LoginController.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,12 +2,48 @@ import { TokenDto } from './../dto/token-dto.js';
|
|
|
2
2
|
import { BaseController, Ok, ForbiddenResponse } from '@spinajs/http';
|
|
3
3
|
import { ISession, SessionProvider, User as UserModel, AccessControl } from '@spinajs/rbac';
|
|
4
4
|
import { QueueService } from '@spinajs/queue';
|
|
5
|
+
import { IEnable2faResponse, IUserWithGrants } from "@spinajs/rbac-http";
|
|
6
|
+
/**
|
|
7
|
+
* Two-factor authentication (TOTP) management.
|
|
8
|
+
* Enables, disables, and verifies TOTP-based two-factor authentication for users.
|
|
9
|
+
* All routes are only available when 2FA is enabled in the system configuration.
|
|
10
|
+
* The caller must be logged in but does NOT need to be fully authorized (2FA verified),
|
|
11
|
+
* allowing these routes to be used during the 2FA verification step itself.
|
|
12
|
+
* @tags Two-Factor Authentication
|
|
13
|
+
*/
|
|
5
14
|
export declare class TwoFactorAuthController extends BaseController {
|
|
6
15
|
protected Queue: QueueService;
|
|
7
16
|
protected SessionProvider: SessionProvider;
|
|
8
17
|
protected AC: AccessControl;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Enable two-factor authentication
|
|
20
|
+
* Generates a TOTP secret for the authenticated user and returns the OTP provisioning URI
|
|
21
|
+
* to be scanned by an authenticator app. Throws if 2FA is already enabled for the user.
|
|
22
|
+
* @security cookieAuth
|
|
23
|
+
* @returns {IEnable2faResponse} OTP provisioning URI to scan with an authenticator app
|
|
24
|
+
* @response 400 Two-factor authentication is already enabled for this user
|
|
25
|
+
* @response 401 Unauthorized — valid session required
|
|
26
|
+
*/
|
|
27
|
+
enable2fa(user: UserModel): Promise<Ok<IEnable2faResponse>>;
|
|
28
|
+
/**
|
|
29
|
+
* Disable two-factor authentication
|
|
30
|
+
* Removes the TOTP secret and disables 2FA for the authenticated user.
|
|
31
|
+
* Throws if 2FA is not currently enabled for the user.
|
|
32
|
+
* @security cookieAuth
|
|
33
|
+
* @response 200 Two-factor authentication disabled successfully
|
|
34
|
+
* @response 400 Two-factor authentication is not enabled for this user
|
|
35
|
+
* @response 401 Unauthorized — valid session required
|
|
36
|
+
*/
|
|
37
|
+
disable2Fa(user: UserModel): Promise<Ok<any>>;
|
|
38
|
+
/**
|
|
39
|
+
* Verify TOTP token
|
|
40
|
+
* Validates the provided TOTP token against the user's 2FA secret. On success, marks the session
|
|
41
|
+
* as fully authorized and returns the user profile with RBAC grants — identical to a full login response.
|
|
42
|
+
* @security cookieAuth
|
|
43
|
+
* @returns {IUserWithGrants} User profile merged with RBAC grants on successful 2FA verification
|
|
44
|
+
* @response 403 Invalid or expired TOTP token
|
|
45
|
+
* @response 401 Unauthorized — valid session required
|
|
46
|
+
*/
|
|
47
|
+
verifyToken(logged: UserModel, token: TokenDto, session: ISession): Promise<Ok<IUserWithGrants> | ForbiddenResponse>;
|
|
12
48
|
}
|
|
13
49
|
//# sourceMappingURL=TwoFactorAuthController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TwoFactorAuthController.d.ts","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAY,EAAE,EAAa,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,IAAI,SAAS,EAAyC,aAAa,EAAE,MAAM,eAAe,CAAC;AAOnI,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"TwoFactorAuthController.d.ts","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAY,EAAE,EAAa,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,IAAI,SAAS,EAAyC,aAAa,EAAE,MAAM,eAAe,CAAC;AAOnI,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAA6B,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAKpG;;;;;;;GAOG;AACH,qBAGa,uBAAwB,SAAQ,cAAc;IAEvD,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC;IAG9B,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAG3C,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;OAQG;IAEU,SAAS,CAAS,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC;IAYhF;;;;;;;;OAQG;IAEU,UAAU,CAAS,IAAI,EAAE,SAAS;IAS/C;;;;;;;;OAQG;IAEU,WAAW,CAAS,MAAM,EAAE,SAAS,EAAU,KAAK,EAAE,QAAQ,EAAa,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,iBAAiB,CAAC;CA4C/J"}
|
|
@@ -26,7 +26,24 @@ const rbac_http_2 = require("@spinajs/rbac-http");
|
|
|
26
26
|
const _2fa_js_1 = require("./../actions/2fa.js");
|
|
27
27
|
const _2fa_js_2 = require("../actions/2fa.js");
|
|
28
28
|
const exceptions_1 = require("@spinajs/exceptions");
|
|
29
|
+
/**
|
|
30
|
+
* Two-factor authentication (TOTP) management.
|
|
31
|
+
* Enables, disables, and verifies TOTP-based two-factor authentication for users.
|
|
32
|
+
* All routes are only available when 2FA is enabled in the system configuration.
|
|
33
|
+
* The caller must be logged in but does NOT need to be fully authorized (2FA verified),
|
|
34
|
+
* allowing these routes to be used during the 2FA verification step itself.
|
|
35
|
+
* @tags Two-Factor Authentication
|
|
36
|
+
*/
|
|
29
37
|
let TwoFactorAuthController = class TwoFactorAuthController extends http_1.BaseController {
|
|
38
|
+
/**
|
|
39
|
+
* Enable two-factor authentication
|
|
40
|
+
* Generates a TOTP secret for the authenticated user and returns the OTP provisioning URI
|
|
41
|
+
* to be scanned by an authenticator app. Throws if 2FA is already enabled for the user.
|
|
42
|
+
* @security cookieAuth
|
|
43
|
+
* @returns {IEnable2faResponse} OTP provisioning URI to scan with an authenticator app
|
|
44
|
+
* @response 400 Two-factor authentication is already enabled for this user
|
|
45
|
+
* @response 401 Unauthorized — valid session required
|
|
46
|
+
*/
|
|
30
47
|
async enable2fa(user) {
|
|
31
48
|
if (user.Metadata['2fa:enabled']) {
|
|
32
49
|
throw new exceptions_1.InvalidOperation(`User ${user.Uuid} already has 2fa enabled`);
|
|
@@ -36,6 +53,15 @@ let TwoFactorAuthController = class TwoFactorAuthController extends http_1.BaseC
|
|
|
36
53
|
otp: result
|
|
37
54
|
});
|
|
38
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Disable two-factor authentication
|
|
58
|
+
* Removes the TOTP secret and disables 2FA for the authenticated user.
|
|
59
|
+
* Throws if 2FA is not currently enabled for the user.
|
|
60
|
+
* @security cookieAuth
|
|
61
|
+
* @response 200 Two-factor authentication disabled successfully
|
|
62
|
+
* @response 400 Two-factor authentication is not enabled for this user
|
|
63
|
+
* @response 401 Unauthorized — valid session required
|
|
64
|
+
*/
|
|
39
65
|
async disable2Fa(user) {
|
|
40
66
|
if (!user.Metadata['2fa:enabled']) {
|
|
41
67
|
throw new exceptions_1.InvalidOperation(`User ${user.Uuid} already has 2fa disabled`);
|
|
@@ -43,6 +69,15 @@ let TwoFactorAuthController = class TwoFactorAuthController extends http_1.BaseC
|
|
|
43
69
|
await (0, _2fa_js_1.disableUser2Fa)(user);
|
|
44
70
|
return new http_1.Ok();
|
|
45
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Verify TOTP token
|
|
74
|
+
* Validates the provided TOTP token against the user's 2FA secret. On success, marks the session
|
|
75
|
+
* as fully authorized and returns the user profile with RBAC grants — identical to a full login response.
|
|
76
|
+
* @security cookieAuth
|
|
77
|
+
* @returns {IUserWithGrants} User profile merged with RBAC grants on successful 2FA verification
|
|
78
|
+
* @response 403 Invalid or expired TOTP token
|
|
79
|
+
* @response 401 Unauthorized — valid session required
|
|
80
|
+
*/
|
|
46
81
|
async verifyToken(logged, token, session) {
|
|
47
82
|
try {
|
|
48
83
|
await (0, _2fa_js_1.auth2Fa)(logged, token.Token);
|
|
@@ -65,7 +100,12 @@ let TwoFactorAuthController = class TwoFactorAuthController extends http_1.BaseC
|
|
|
65
100
|
});
|
|
66
101
|
}
|
|
67
102
|
catch (err) {
|
|
68
|
-
|
|
103
|
+
if (err instanceof Error) {
|
|
104
|
+
this._log.error(err, "2fa verification failed");
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this._log.error("2fa verification failed", { error: err });
|
|
108
|
+
}
|
|
69
109
|
return new http_1.ForbiddenResponse({
|
|
70
110
|
error: {
|
|
71
111
|
code: 'E_2FA_FAILED',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TwoFactorAuthController.js","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wDAAiD;AACjD,wCAA2F;AAC3F,wCAAmI;AACnI,kDAA6C;AAC7C,wCAA6C;AAE7C,4DAA8D;AAC9D,0DAAqE;AACrE,oCAAyC;AACzC,0CAA8C;AAE9C,
|
|
1
|
+
{"version":3,"file":"TwoFactorAuthController.js","sourceRoot":"","sources":["../../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,47 @@
|
|
|
1
1
|
import { PasswordDto } from '../dto/password-dto.js';
|
|
2
2
|
import { User as UserModel, PasswordProvider, SessionProvider, AccessControl } from '@spinajs/rbac';
|
|
3
3
|
import { BaseController, Ok } from '@spinajs/http';
|
|
4
|
+
import { IGrantsMap } from '@spinajs/rbac-http';
|
|
5
|
+
/**
|
|
6
|
+
* Current user profile management.
|
|
7
|
+
* Allows an authenticated user to read and modify their own account — refresh profile data,
|
|
8
|
+
* view their RBAC grants, and change their password.
|
|
9
|
+
* @tags User
|
|
10
|
+
*/
|
|
4
11
|
export declare class UserController extends BaseController {
|
|
5
12
|
protected PasswordProvider: PasswordProvider;
|
|
6
13
|
protected CoockieSecret: string;
|
|
7
14
|
protected SessionProvider: SessionProvider;
|
|
8
15
|
protected AC: AccessControl;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Refresh current user profile
|
|
18
|
+
* Reloads the authenticated user's record from the database (including metadata) and
|
|
19
|
+
* updates the session with the latest data. Returns the refreshed user data.
|
|
20
|
+
* @security cookieAuth
|
|
21
|
+
* @returns {IUserProfile} Refreshed user profile data
|
|
22
|
+
* @response 401 Unauthorized — valid session required
|
|
23
|
+
* @response 403 Forbidden — insufficient permissions
|
|
24
|
+
*/
|
|
25
|
+
refresh(user: UserModel, ssid: string): Promise<Ok<import("@spinajs/orm").ModelData<UserModel>>>;
|
|
26
|
+
/**
|
|
27
|
+
* Get current user grants
|
|
28
|
+
* Returns the flattened RBAC grants for the authenticated user, combining all roles
|
|
29
|
+
* the user is assigned to into a single permission map keyed by resource.
|
|
30
|
+
* @security cookieAuth
|
|
31
|
+
* @returns {IGrantsMap} Combined RBAC grants map: resource → action → permission descriptor
|
|
32
|
+
* @response 401 Unauthorized — valid session required
|
|
33
|
+
* @response 403 Forbidden — insufficient permissions
|
|
34
|
+
*/
|
|
35
|
+
getGrants(user: UserModel): Promise<Ok<IGrantsMap>>;
|
|
36
|
+
/**
|
|
37
|
+
* Change own password
|
|
38
|
+
* Changes the authenticated user's password. Requires the current (old) password for verification.
|
|
39
|
+
* The new password and its confirmation must match.
|
|
40
|
+
* @security cookieAuth
|
|
41
|
+
* @response 400 Old password is incorrect, or new passwords do not match
|
|
42
|
+
* @response 401 Unauthorized — valid session required
|
|
43
|
+
* @response 403 Forbidden — insufficient permissions
|
|
44
|
+
*/
|
|
45
|
+
newPassword(user: UserModel, pwd: PasswordDto): Promise<Ok<unknown>>;
|
|
12
46
|
}
|
|
13
47
|
//# sourceMappingURL=UserController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserController.d.ts","sourceRoot":"","sources":["../../../src/controllers/UserController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAgD,aAAa,EAAE,MAAM,eAAe,CAAC;AAClJ,OAAO,EAAE,cAAc,EAAiB,EAAE,EAA+B,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"UserController.d.ts","sourceRoot":"","sources":["../../../src/controllers/UserController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAgD,aAAa,EAAE,MAAM,eAAe,CAAC;AAClJ,OAAO,EAAE,cAAc,EAAiB,EAAE,EAA+B,MAAM,eAAe,CAAC;AAM/F,OAAO,EAAgD,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAK9F;;;;;GAKG;AACH,qBAGa,cAAe,SAAQ,cAAc;IAEhD,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAG7C,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC;IAGhC,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAG3C,SAAS,CAAC,EAAE,EAAE,aAAa,CAAC;IAE5B;;;;;;;;OAQG;IAGU,OAAO,CAAS,IAAI,EAAE,SAAS,EAAY,IAAI,EAAE,MAAM;IAiBpE;;;;;;;;OAQG;IAGU,SAAS,CAAS,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAUxE;;;;;;;;OAQG;IAGU,WAAW,CAAS,IAAI,EAAE,SAAS,EAAU,GAAG,EAAE,WAAW;CAkB3E"}
|
|
@@ -55,7 +55,22 @@ const configuration_1 = require("@spinajs/configuration");
|
|
|
55
55
|
const cs = __importStar(require("cookie-signature"));
|
|
56
56
|
const rbac_http_1 = require("@spinajs/rbac-http");
|
|
57
57
|
const util_1 = require("@spinajs/util");
|
|
58
|
+
/**
|
|
59
|
+
* Current user profile management.
|
|
60
|
+
* Allows an authenticated user to read and modify their own account — refresh profile data,
|
|
61
|
+
* view their RBAC grants, and change their password.
|
|
62
|
+
* @tags User
|
|
63
|
+
*/
|
|
58
64
|
let UserController = class UserController extends http_1.BaseController {
|
|
65
|
+
/**
|
|
66
|
+
* Refresh current user profile
|
|
67
|
+
* Reloads the authenticated user's record from the database (including metadata) and
|
|
68
|
+
* updates the session with the latest data. Returns the refreshed user data.
|
|
69
|
+
* @security cookieAuth
|
|
70
|
+
* @returns {IUserProfile} Refreshed user profile data
|
|
71
|
+
* @response 401 Unauthorized — valid session required
|
|
72
|
+
* @response 403 Forbidden — insufficient permissions
|
|
73
|
+
*/
|
|
59
74
|
async refresh(user, ssid) {
|
|
60
75
|
// get user data from db
|
|
61
76
|
await user.refresh();
|
|
@@ -70,12 +85,30 @@ let UserController = class UserController extends http_1.BaseController {
|
|
|
70
85
|
}
|
|
71
86
|
return new http_1.Ok(user.dehydrate());
|
|
72
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Get current user grants
|
|
90
|
+
* Returns the flattened RBAC grants for the authenticated user, combining all roles
|
|
91
|
+
* the user is assigned to into a single permission map keyed by resource.
|
|
92
|
+
* @security cookieAuth
|
|
93
|
+
* @returns {IGrantsMap} Combined RBAC grants map: resource → action → permission descriptor
|
|
94
|
+
* @response 401 Unauthorized — valid session required
|
|
95
|
+
* @response 403 Forbidden — insufficient permissions
|
|
96
|
+
*/
|
|
73
97
|
async getGrants(user) {
|
|
74
98
|
const grants = this.AC.getGrants();
|
|
75
99
|
const userGrants = user.Role.map(r => (0, rbac_1._unwindGrants)(r, grants));
|
|
76
100
|
const combinedGrants = Object.assign({}, ...userGrants);
|
|
77
101
|
return new http_1.Ok(combinedGrants);
|
|
78
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Change own password
|
|
105
|
+
* Changes the authenticated user's password. Requires the current (old) password for verification.
|
|
106
|
+
* The new password and its confirmation must match.
|
|
107
|
+
* @security cookieAuth
|
|
108
|
+
* @response 400 Old password is incorrect, or new passwords do not match
|
|
109
|
+
* @response 401 Unauthorized — valid session required
|
|
110
|
+
* @response 403 Forbidden — insufficient permissions
|
|
111
|
+
*/
|
|
79
112
|
async newPassword(user, pwd) {
|
|
80
113
|
if (pwd.Password !== pwd.ConfirmPassword) {
|
|
81
114
|
throw new exceptions_1.InvalidArgument('password does not match');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserController.js","sourceRoot":"","sources":["../../../src/controllers/UserController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4DAAqD;AACrD,wCAAkJ;AAClJ,wCAA+F;AAC/F,oDAAsD;AACtD,oCAAyC;AACzC,0DAAgD;AAChD,qDAAuC;AAEvC,
|
|
1
|
+
{"version":3,"file":"UserController.js","sourceRoot":"","sources":["../../../src/controllers/UserController.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,22 +2,145 @@ import { Ok, BaseController } from '@spinajs/http';
|
|
|
2
2
|
import { User as UserModel, UserMetadata } from '@spinajs/rbac';
|
|
3
3
|
import { PaginationDTO, OrderDTO, IFilterRequest } from '@spinajs/orm-http';
|
|
4
4
|
import { UserMetadataDto } from '../dto/metadata-dto.js';
|
|
5
|
+
import { FilterableUserMetadata } from '../models/FilterableUserMetadata.js';
|
|
6
|
+
/**
|
|
7
|
+
* User metadata management.
|
|
8
|
+
* Provides CRUD operations for key-value metadata entries attached to user accounts.
|
|
9
|
+
* Admin routes operate on any user (identified by UUID), while own routes operate on the
|
|
10
|
+
* currently authenticated user's metadata.
|
|
11
|
+
* @tags User Metadata
|
|
12
|
+
*/
|
|
5
13
|
export declare class UserMetadataController extends BaseController {
|
|
6
14
|
/**
|
|
7
|
-
*
|
|
15
|
+
* List metadata for a specific user (admin)
|
|
16
|
+
* Returns a paginated, filtered, and ordered list of metadata entries for the given user.
|
|
17
|
+
* @security cookieAuth
|
|
18
|
+
* @param user User UUID path parameter
|
|
19
|
+
* @param pagination.page Page number (zero-based)
|
|
20
|
+
* @param pagination.limit Number of entries per page
|
|
21
|
+
* @param order.column Column to sort by (default: Id)
|
|
22
|
+
* @param order.order Sort direction: ASC or DESC (default: DESC)
|
|
23
|
+
* @returns {IUserMetadataEntry[]} Paginated list of metadata entries for the user
|
|
24
|
+
* @response 401 Unauthorized — valid session required
|
|
25
|
+
* @response 403 Forbidden — readAny permission required
|
|
26
|
+
* @response 404 User not found
|
|
8
27
|
*/
|
|
9
|
-
readUserMeta(user: UserModel, pagination?: PaginationDTO, order?: OrderDTO, filter?: IFilterRequest): Promise<Ok
|
|
10
|
-
getUserMeta(user: UserModel, key: string): Promise<Ok>;
|
|
11
|
-
addUserMetadata(user: UserModel, metadata: UserMetadata): Promise<Ok>;
|
|
12
|
-
updateUserMetadata(meta: UserMetadata, _user: UserModel, data: UserMetadataDto): Promise<Ok>;
|
|
13
|
-
deleteUserMetadata(user: UserModel, meta: number): Promise<Ok>;
|
|
28
|
+
readUserMeta(user: UserModel, pagination?: PaginationDTO, order?: OrderDTO, filter?: IFilterRequest): Promise<Ok<import("@spinajs/orm").ISelectQueryBuilder<FilterableUserMetadata[]> & import("@spinajs/orm").QueryScope>>;
|
|
14
29
|
/**
|
|
15
|
-
*
|
|
30
|
+
* Get a single metadata entry for a specific user (admin)
|
|
31
|
+
* Retrieves one metadata entry by key for the given user.
|
|
32
|
+
* @security cookieAuth
|
|
33
|
+
* @param user User UUID path parameter
|
|
34
|
+
* @param key Metadata key to retrieve
|
|
35
|
+
* @returns {IUserMetadataEntry} Single metadata entry for the user
|
|
36
|
+
* @response 401 Unauthorized — valid session required
|
|
37
|
+
* @response 403 Forbidden — readAny permission required
|
|
38
|
+
* @response 404 User or metadata key not found
|
|
39
|
+
*/
|
|
40
|
+
getUserMeta(user: UserModel, key: string): Promise<Ok<UserMetadata>>;
|
|
41
|
+
/**
|
|
42
|
+
* Add or update metadata for a specific user (admin)
|
|
43
|
+
* Inserts a new metadata entry for the given user, or updates it if the key already exists.
|
|
44
|
+
* @security cookieAuth
|
|
45
|
+
* @param user User UUID path parameter
|
|
46
|
+
* @response 200 Metadata created or updated successfully
|
|
47
|
+
* @response 401 Unauthorized — valid session required
|
|
48
|
+
* @response 403 Forbidden — updateAny permission required
|
|
49
|
+
* @response 404 User not found
|
|
50
|
+
*/
|
|
51
|
+
addUserMetadata(user: UserModel, metadata: UserMetadata): Promise<Ok<any>>;
|
|
52
|
+
/**
|
|
53
|
+
* Update a metadata entry for a specific user (admin)
|
|
54
|
+
* Updates Key, Value, and Type of an existing metadata entry identified by Id or Key.
|
|
55
|
+
* @security cookieAuth
|
|
56
|
+
* @param _user User UUID path parameter (used for authorization scope)
|
|
57
|
+
* @param meta Metadata Id or Key to update
|
|
58
|
+
|
|
59
|
+
* @response 200 Metadata updated successfully
|
|
60
|
+
* @response 401 Unauthorized — valid session required
|
|
61
|
+
* @response 403 Forbidden — updateAny permission required
|
|
62
|
+
* @response 404 User or metadata entry not found
|
|
63
|
+
*/
|
|
64
|
+
updateUserMetadata(meta: UserMetadata, _user: UserModel, data: UserMetadataDto): Promise<Ok<any>>;
|
|
65
|
+
/**
|
|
66
|
+
* Delete a metadata entry for a specific user (admin)
|
|
67
|
+
* Permanently removes a metadata entry by Id from the given user's metadata.
|
|
68
|
+
* @security cookieAuth
|
|
69
|
+
* @param user User UUID path parameter
|
|
70
|
+
* @param meta Metadata Id to delete
|
|
71
|
+
* @response 200 Metadata deleted successfully
|
|
72
|
+
* @response 401 Unauthorized — valid session required
|
|
73
|
+
* @response 403 Forbidden — deleteAny permission required
|
|
74
|
+
* @response 404 User or metadata entry not found
|
|
75
|
+
*/
|
|
76
|
+
deleteUserMetadata(user: UserModel, meta: number): Promise<Ok<any>>;
|
|
77
|
+
/**
|
|
78
|
+
* List own metadata
|
|
79
|
+
* Returns a paginated, filtered, and ordered list of metadata entries for the authenticated user.
|
|
80
|
+
* @security cookieAuth
|
|
81
|
+
* @param pagination.page Page number (zero-based)
|
|
82
|
+
* @param pagination.limit Number of entries per page
|
|
83
|
+
* @param order.column Column to sort by (default: Id)
|
|
84
|
+
* @param order.order Sort direction: ASC or DESC (default: DESC)
|
|
85
|
+
* @returns {IUserMetadataEntry[]} Paginated list of own metadata entries
|
|
86
|
+
* @response 401 Unauthorized — valid session required
|
|
87
|
+
* @response 403 Forbidden — readOwn permission required
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* List own metadata
|
|
91
|
+
* Returns a paginated, filtered, and ordered list of metadata entries for the authenticated user.
|
|
92
|
+
* @security cookieAuth
|
|
93
|
+
* @param pagination.page Page number (zero-based)
|
|
94
|
+
* @param pagination.limit Number of entries per page
|
|
95
|
+
* @param order.column Column to sort by (default: Id)
|
|
96
|
+
* @param order.order Sort direction: ASC or DESC (default: DESC)
|
|
97
|
+
* @returns {IUserMetadataEntry[]} Paginated list of own metadata entries
|
|
98
|
+
* @response 401 Unauthorized — valid session required
|
|
99
|
+
* @response 403 Forbidden — readOwn permission required
|
|
100
|
+
*/
|
|
101
|
+
readMeta(pagination?: PaginationDTO, order?: OrderDTO, filter?: IFilterRequest): Promise<Ok<import("@spinajs/orm").ISelectQueryBuilder<FilterableUserMetadata[]> & import("@spinajs/orm").QueryScope>>;
|
|
102
|
+
/**
|
|
103
|
+
* Get own metadata entry by key
|
|
104
|
+
* Retrieves a single metadata entry by key for the authenticated user.
|
|
105
|
+
* @security cookieAuth
|
|
106
|
+
* @param key Metadata key to retrieve
|
|
107
|
+
* @returns {IUserMetadataEntry} Single own metadata entry by key
|
|
108
|
+
* @response 401 Unauthorized — valid session required
|
|
109
|
+
* @response 403 Forbidden — readOwn permission required
|
|
110
|
+
* @response 404 Metadata key not found
|
|
111
|
+
*/
|
|
112
|
+
getMeta(key: string): Promise<Ok<UserMetadata>>;
|
|
113
|
+
/**
|
|
114
|
+
* Add or update own metadata
|
|
115
|
+
* Inserts a new metadata entry for the authenticated user, or updates it if the key already exists.
|
|
116
|
+
* @security cookieAuth
|
|
117
|
+
* @response 200 Metadata created or updated successfully
|
|
118
|
+
* @response 401 Unauthorized — valid session required
|
|
119
|
+
* @response 403 Forbidden — updateOwn permission required
|
|
16
120
|
*/
|
|
17
|
-
readMeta(pagination?: PaginationDTO, order?: OrderDTO, filter?: IFilterRequest): Promise<Ok>;
|
|
18
|
-
getMeta(key: string): Promise<Ok>;
|
|
19
121
|
addMetadata(metadata: UserMetadata): Promise<void>;
|
|
20
|
-
|
|
21
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Update own metadata entry
|
|
124
|
+
* Updates Key, Value, and Type of an existing metadata entry identified by Id or Key.
|
|
125
|
+
* @security cookieAuth
|
|
126
|
+
* @param meta Metadata Id or Key to update
|
|
127
|
+
|
|
128
|
+
* @response 200 Metadata updated successfully
|
|
129
|
+
* @response 401 Unauthorized — valid session required
|
|
130
|
+
* @response 403 Forbidden — updateOwn permission required
|
|
131
|
+
* @response 404 Metadata entry not found
|
|
132
|
+
*/
|
|
133
|
+
updateMetadata(meta: string, data: UserMetadataDto): Promise<Ok<any>>;
|
|
134
|
+
/**
|
|
135
|
+
* Delete own metadata entry
|
|
136
|
+
* Permanently removes a metadata entry by Id from the authenticated user's metadata.
|
|
137
|
+
* @security cookieAuth
|
|
138
|
+
* @param meta Metadata Id to delete
|
|
139
|
+
* @response 200 Metadata deleted successfully
|
|
140
|
+
* @response 401 Unauthorized — valid session required
|
|
141
|
+
* @response 403 Forbidden — deleteOwn permission required
|
|
142
|
+
* @response 404 Metadata entry not found
|
|
143
|
+
*/
|
|
144
|
+
deleteMetadata(meta: number): Promise<Ok<any>>;
|
|
22
145
|
}
|
|
23
146
|
//# sourceMappingURL=UserMetadataController.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserMetadataController.d.ts","sourceRoot":"","sources":["../../../src/controllers/UserMetadataController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,EAAE,EAAwC,cAAc,EAAS,MAAM,eAAe,CAAC;AAChH,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAW,aAAa,EAAE,QAAQ,EAAU,cAAc,EAAa,MAAM,mBAAmB,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"UserMetadataController.d.ts","sourceRoot":"","sources":["../../../src/controllers/UserMetadataController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,EAAE,EAAwC,cAAc,EAAS,MAAM,eAAe,CAAC;AAChH,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAW,aAAa,EAAE,QAAQ,EAAU,cAAc,EAAa,MAAM,mBAAmB,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAE7E;;;;;;GAMG;AACH,qBAGa,sBAAuB,SAAQ,cAAc;IAEtD;;;;;;;;;;;;;OAaG;IAGU,YAAY,CACc,IAAI,EAAE,SAAS,EACzC,UAAU,CAAC,EAAE,aAAa,EAC1B,KAAK,CAAC,EAAE,QAAQ,EAEzB,MAAM,CAAC,EAAE,cAAc;IAY3B;;;;;;;;;;OAUG;IAGU,WAAW,CACe,IAAI,EAAE,SAAS,EACzC,GAAG,EAAE,MAAM;IAOxB;;;;;;;;;OASG;IAGU,eAAe,CACW,IAAI,EAAE,SAAS,EACvC,QAAQ,EAAE,YAAY;IAOrC;;;;;;;;;;;OAWG;IAGU,kBAAkB,CAOxB,IAAI,EAAE,YAAY,EACc,KAAK,EAAE,SAAS,EAC3C,IAAI,EAAE,eAAe;IAUjC;;;;;;;;;;OAUG;IAGU,kBAAkB,CACQ,IAAI,EAAE,SAAS,EACzC,IAAI,EAAE,MAAM;IASzB;;;;;;;;;;;OAWG;IAIH;;;;;;;;;;;OAWG;IAGU,QAAQ,CACR,UAAU,CAAC,EAAE,aAAa,EAC1B,KAAK,CAAC,EAAE,QAAQ,EAEzB,MAAM,CAAC,EAAE,cAAc;IAS3B;;;;;;;;;OASG;IAGU,OAAO,CAAU,GAAG,EAAE,MAAM;IAMzC;;;;;;;OAOG;IAGU,WAAW,CAAY,QAAQ,EAAE,YAAY;IAI1D;;;;;;;;;;OAUG;IAGU,cAAc,CAAU,IAAI,EAAE,MAAM,EAAU,IAAI,EAAE,eAAe;IAUhF;;;;;;;;;OASG;IAGU,cAAc,CAAU,IAAI,EAAE,MAAM;CAOpD"}
|