Browse Source

Bugfix/owner as grantee of private access (#8321)

* Fix owner as grantee of private access

* Update changelog
main
Thomas Kaul 22 hours ago
committed by GitHub
parent
commit
97722822ed
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 11
      apps/api/src/app/endpoints/accesses/access.controller.ts
  3. 11
      apps/api/src/app/endpoints/accesses/accesses.controller.ts
  4. 35
      libs/common/src/lib/helper.spec.ts
  5. 11
      libs/common/src/lib/helper.ts

1
CHANGELOG.md

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fixed the double submission of forms in the account detail dialog, the create or update access dialog, the historical market data editor, the import activities dialog, the coupon system and the create asset profile dialog of the admin control panel
- Fixed an issue where users could grant a private access to themselves
## 3.93.0 - 2026-10-25

11
apps/api/src/app/endpoints/accesses/access.controller.ts

@ -102,7 +102,13 @@ export class AccessController {
);
}
if (!isValidGranteeOfAccess({ granteeUserId: data.granteeUserId, type })) {
if (
!isValidGranteeOfAccess({
type,
granteeUserId: data.granteeUserId,
userId: this.request.user.id
})
) {
throw new HttpException(
getReasonPhrase(StatusCodes.BAD_REQUEST),
StatusCodes.BAD_REQUEST
@ -205,7 +211,8 @@ export class AccessController {
if (
!isValidGranteeOfAccess({
granteeUserId: data.granteeUserId,
type: originalAccess.type
type: originalAccess.type,
userId: this.request.user.id
})
) {
throw new HttpException(

11
apps/api/src/app/endpoints/accesses/accesses.controller.ts

@ -75,7 +75,13 @@ export class AccessesController {
);
}
if (!isValidGranteeOfAccess({ granteeUserId: data.granteeUserId, type })) {
if (
!isValidGranteeOfAccess({
type,
granteeUserId: data.granteeUserId,
userId: this.request.user.id
})
) {
throw new HttpException(
getReasonPhrase(StatusCodes.BAD_REQUEST),
StatusCodes.BAD_REQUEST
@ -195,7 +201,8 @@ export class AccessesController {
if (
!isValidGranteeOfAccess({
granteeUserId: data.granteeUserId,
type: originalAccess.type
type: originalAccess.type,
userId: this.request.user.id
})
) {
throw new HttpException(

35
libs/common/src/lib/helper.spec.ts

@ -691,41 +691,54 @@ describe('Helper', () => {
describe('Is valid grantee of access', () => {
const granteeUserId = 'ffb08949-2f8a-4b6e-88fd-0f1e6b6b5f5d';
const userId = '6b5d4e2a-7c1f-4a3b-9e8d-2f0c1a5b7d3e';
it('A private access with a grantee', () => {
expect(
isValidGranteeOfAccess({ granteeUserId, type: 'PRIVATE' })
isValidGranteeOfAccess({ granteeUserId, userId, type: 'PRIVATE' })
).toEqual(true);
});
it('A private access without a grantee', () => {
expect(isValidGranteeOfAccess({ type: 'PRIVATE' })).toEqual(false);
expect(isValidGranteeOfAccess({ userId, type: 'PRIVATE' })).toEqual(
false
);
});
it('A private access with an empty grantee', () => {
expect(
isValidGranteeOfAccess({ granteeUserId: null, type: 'PRIVATE' })
isValidGranteeOfAccess({ userId, granteeUserId: null, type: 'PRIVATE' })
).toEqual(false);
});
it('A private access with its owner as grantee', () => {
expect(
isValidGranteeOfAccess({
userId,
granteeUserId: userId,
type: 'PRIVATE'
})
).toEqual(false);
});
it('A public access without a grantee', () => {
expect(isValidGranteeOfAccess({ type: 'PUBLIC' })).toEqual(true);
expect(isValidGranteeOfAccess({ userId, type: 'PUBLIC' })).toEqual(true);
});
it('A public access with a grantee', () => {
expect(isValidGranteeOfAccess({ granteeUserId, type: 'PUBLIC' })).toEqual(
false
);
expect(
isValidGranteeOfAccess({ granteeUserId, userId, type: 'PUBLIC' })
).toEqual(false);
});
it('An access of the model context protocol without a grantee', () => {
expect(isValidGranteeOfAccess({ type: 'MCP' })).toEqual(true);
expect(isValidGranteeOfAccess({ userId, type: 'MCP' })).toEqual(true);
});
it('An access of the model context protocol with a grantee', () => {
expect(isValidGranteeOfAccess({ granteeUserId, type: 'MCP' })).toEqual(
false
);
expect(
isValidGranteeOfAccess({ granteeUserId, userId, type: 'MCP' })
).toEqual(false);
});
});

11
libs/common/src/lib/helper.ts

@ -766,15 +766,22 @@ export function isValidDateAfter1970(aDate: Date | string) {
* A private access is granted to a user, while a public access and an access
* of a client of the model context protocol are credentials on their own and
* have no grantee. A row which mixes both is neither, hence it is rejected.
* The owner of an access cannot be its grantee.
*/
export function isValidGranteeOfAccess({
granteeUserId,
type
type,
userId
}: {
granteeUserId?: string | null;
type: AccessType;
userId: string;
}) {
return type === 'PRIVATE' ? !!granteeUserId : !granteeUserId;
if (type === 'PRIVATE') {
return !!granteeUserId && granteeUserId !== userId;
}
return !granteeUserId;
}
export function isValidSearchQuery(aQuery: string) {

Loading…
Cancel
Save