cnpmcore 4.28.4 → 4.29.0
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/app/common/CryptoUtil.js +7 -9
- package/dist/app/common/constants.d.ts +1 -0
- package/dist/app/common/constants.js +2 -1
- package/dist/app/core/entity/Org.d.ts +18 -0
- package/dist/app/core/entity/Org.js +16 -0
- package/dist/app/core/entity/OrgMember.d.ts +18 -0
- package/dist/app/core/entity/OrgMember.js +16 -0
- package/dist/app/core/entity/Team.d.ts +20 -0
- package/dist/app/core/entity/Team.js +17 -0
- package/dist/app/core/entity/TeamMember.d.ts +16 -0
- package/dist/app/core/entity/TeamMember.js +15 -0
- package/dist/app/core/entity/TeamPackage.d.ts +16 -0
- package/dist/app/core/entity/TeamPackage.js +15 -0
- package/dist/app/core/service/OrgService.d.ts +20 -0
- package/dist/app/core/service/OrgService.js +131 -0
- package/dist/app/core/service/TeamService.d.ts +16 -0
- package/dist/app/core/service/TeamService.js +110 -0
- package/dist/app/port/UserRoleManager.d.ts +2 -0
- package/dist/app/port/UserRoleManager.js +26 -1
- package/dist/app/port/controller/OrgController.d.ts +34 -0
- package/dist/app/port/controller/OrgController.js +217 -0
- package/dist/app/port/controller/PackageVersionFileController.js +3 -1
- package/dist/app/port/controller/TeamController.d.ts +48 -0
- package/dist/app/port/controller/TeamController.js +326 -0
- package/dist/app/port/controller/package/DownloadPackageVersionTar.js +3 -1
- package/dist/app/port/controller/package/ShowPackageController.d.ts +1 -0
- package/dist/app/port/controller/package/ShowPackageController.js +15 -5
- package/dist/app/port/controller/package/ShowPackageVersionController.js +2 -1
- package/dist/app/repository/OrgRepository.d.ts +23 -0
- package/dist/app/repository/OrgRepository.js +115 -0
- package/dist/app/repository/PackageRepository.d.ts +1 -0
- package/dist/app/repository/PackageRepository.js +7 -1
- package/dist/app/repository/TeamRepository.d.ts +33 -0
- package/dist/app/repository/TeamRepository.js +177 -0
- package/dist/app/repository/UserRepository.d.ts +1 -0
- package/dist/app/repository/UserRepository.js +7 -1
- package/dist/app/repository/model/Org.d.ts +9 -0
- package/dist/app/repository/model/Org.js +45 -0
- package/dist/app/repository/model/OrgMember.d.ts +10 -0
- package/dist/app/repository/model/OrgMember.js +49 -0
- package/dist/app/repository/model/Team.d.ts +10 -0
- package/dist/app/repository/model/Team.js +49 -0
- package/dist/app/repository/model/TeamMember.d.ts +9 -0
- package/dist/app/repository/model/TeamMember.js +45 -0
- package/dist/app/repository/model/TeamPackage.d.ts +9 -0
- package/dist/app/repository/model/TeamPackage.js +45 -0
- package/package.json +1 -1
|
@@ -5,18 +5,16 @@ export function genRSAKeys() {
|
|
|
5
5
|
const key = generateKeyPairSync('rsa', {
|
|
6
6
|
modulusLength: 512,
|
|
7
7
|
});
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
// export({ format: 'pem' }) returns string; .toString('base64') is a no-op on string.
|
|
9
|
+
// Use type assertion to fix TS2554 on Node 18 type definitions.
|
|
10
|
+
const publicKey = key.publicKey.export({
|
|
10
11
|
type: 'pkcs1',
|
|
11
12
|
format: 'pem',
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
const privateKey = key.privateKey
|
|
15
|
-
.export({
|
|
13
|
+
});
|
|
14
|
+
const privateKey = key.privateKey.export({
|
|
16
15
|
type: 'pkcs1',
|
|
17
16
|
format: 'pem',
|
|
18
|
-
})
|
|
19
|
-
.toString('base64');
|
|
17
|
+
});
|
|
20
18
|
return { publicKey, privateKey };
|
|
21
19
|
}
|
|
22
20
|
// encrypt rsa private key
|
|
@@ -35,4 +33,4 @@ export function decryptRSA(privateKey, encryptedBase64) {
|
|
|
35
33
|
});
|
|
36
34
|
return key.decrypt(encryptedBase64, 'utf8');
|
|
37
35
|
}
|
|
38
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ3J5cHRvVXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2FwcC9jb21tb24vQ3J5cHRvVXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFbEQsT0FBTyxPQUFPLE1BQU0sVUFBVSxDQUFDO0FBRS9CLHdCQUF3QjtBQUN4QixNQUFNLFVBQVUsVUFBVTtJQUN4QixNQUFNLEdBQUcsR0FBRyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUU7UUFDckMsYUFBYSxFQUFFLEdBQUc7S0FDbkIsQ0FBQyxDQUFDO0lBQ0gsc0ZBQXNGO0lBQ3RGLGdFQUFnRTtJQUNoRSxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNyQyxJQUFJLEVBQUUsT0FBTztRQUNiLE1BQU0sRUFBRSxLQUFLO0tBQ2QsQ0FBVyxDQUFDO0lBQ2IsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7UUFDdkMsSUFBSSxFQUFFLE9BQU87UUFDYixNQUFNLEVBQUUsS0FBSztLQUNkLENBQVcsQ0FBQztJQUNiLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLENBQUM7QUFDbkMsQ0FBQztBQUVELDBCQUEwQjtBQUMxQixNQUFNLFVBQVUsVUFBVSxDQUFDLFNBQWlCLEVBQUUsU0FBaUI7SUFDN0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLGtCQUFrQixFQUFFO1FBQ3JELGdCQUFnQixFQUFFLE9BQU87UUFDekIsV0FBVyxFQUFFLFNBQVM7S0FDdkIsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUMxQyxDQUFDO0FBRUQsMEJBQTBCO0FBQzFCLE1BQU0sVUFBVSxVQUFVLENBQUMsVUFBa0IsRUFBRSxlQUF1QjtJQUNwRSxNQUFNLEdBQUcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsbUJBQW1CLEVBQUU7UUFDdkQsZ0JBQWdCLEVBQUUsT0FBTztRQUN6QixXQUFXLEVBQUUsU0FBUztLQUN2QixDQUFDLENBQUM7SUFDSCxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQzlDLENBQUMifQ==
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const BUG_VERSIONS = "bug-versions";
|
|
2
|
+
export declare const DEVELOPERS_TEAM = "developers";
|
|
2
3
|
export declare const LATEST_TAG = "latest";
|
|
3
4
|
export declare const GLOBAL_WORKER = "GLOBAL_WORKER";
|
|
4
5
|
export declare const PROXY_CACHE_DIR_NAME = "proxy-cache-packages";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export const BUG_VERSIONS = 'bug-versions';
|
|
2
|
+
export const DEVELOPERS_TEAM = 'developers';
|
|
2
3
|
export const LATEST_TAG = 'latest';
|
|
3
4
|
export const GLOBAL_WORKER = 'GLOBAL_WORKER';
|
|
4
5
|
export const PROXY_CACHE_DIR_NAME = 'proxy-cache-packages';
|
|
@@ -33,4 +34,4 @@ export var PackageAccessLevel;
|
|
|
33
34
|
PackageAccessLevel["write"] = "write";
|
|
34
35
|
PackageAccessLevel["read"] = "read";
|
|
35
36
|
})(PackageAccessLevel || (PackageAccessLevel = {}));
|
|
36
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vYXBwL2NvbW1vbi9jb25zdGFudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLGNBQWMsQ0FBQztBQUMzQyxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsWUFBWSxDQUFDO0FBQzVDLE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUM7QUFDbkMsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLGVBQWUsQ0FBQztBQUM3QyxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxzQkFBc0IsQ0FBQztBQUMzRCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxxQ0FBcUMsQ0FBQztBQUMzRSxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLGlDQUFpQyxFQUFFLG9DQUFvQyxDQUFDLENBQUM7QUFFOUcsTUFBTSxDQUFOLElBQVksUUFNWDtBQU5ELFdBQVksUUFBUTtJQUNsQix5QkFBYSxDQUFBO0lBQ2IsMkJBQWUsQ0FBQTtJQUNmLDJCQUFlLENBQUE7SUFDZiwyQkFBZSxDQUFBO0lBQ2YsdUJBQVcsQ0FBQTtBQUNiLENBQUMsRUFOVyxRQUFRLEtBQVIsUUFBUSxRQU1uQjtBQUNELE1BQU0sQ0FBTixJQUFZLGlCQUdYO0FBSEQsV0FBWSxpQkFBaUI7SUFDM0Isa0NBQWEsQ0FBQTtJQUNiLDRDQUF1QixDQUFBO0FBQ3pCLENBQUMsRUFIVyxpQkFBaUIsS0FBakIsaUJBQWlCLFFBRzVCO0FBQ0QsTUFBTSxDQUFOLElBQVksY0FJWDtBQUpELFdBQVksY0FBYztJQUN4QixtQ0FBaUIsQ0FBQTtJQUNqQixpQ0FBZSxDQUFBO0lBQ2YsbUNBQWlCLENBQUE7QUFDbkIsQ0FBQyxFQUpXLGNBQWMsS0FBZCxjQUFjLFFBSXpCO0FBRUQsTUFBTSxDQUFOLElBQVksa0JBR1g7QUFIRCxXQUFZLGtCQUFrQjtJQUM1Qix5Q0FBbUIsQ0FBQTtJQUNuQixtQ0FBYSxDQUFBO0FBQ2YsQ0FBQyxFQUhXLGtCQUFrQixLQUFsQixrQkFBa0IsUUFHN0I7QUFFRCxNQUFNLENBQU4sSUFBWSxrQkFHWDtBQUhELFdBQVksa0JBQWtCO0lBQzVCLHFDQUFlLENBQUE7SUFDZixtQ0FBYSxDQUFBO0FBQ2YsQ0FBQyxFQUhXLGtCQUFrQixLQUFsQixrQkFBa0IsUUFHN0IifQ==
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { EasyData } from '../util/EntityUtil.ts';
|
|
2
|
+
import { Entity, EntityData } from './Entity.ts';
|
|
3
|
+
interface OrgData extends EntityData {
|
|
4
|
+
orgId: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
}
|
|
8
|
+
export type CreateOrgData = Omit<EasyData<OrgData, 'orgId'>, 'id' | 'description'> & {
|
|
9
|
+
description?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare class Org extends Entity {
|
|
12
|
+
orgId: string;
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
constructor(data: OrgData);
|
|
16
|
+
static create(data: CreateOrgData): Org;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EntityUtil } from "../util/EntityUtil.js";
|
|
2
|
+
import { Entity } from "./Entity.js";
|
|
3
|
+
export class Org extends Entity {
|
|
4
|
+
constructor(data) {
|
|
5
|
+
super(data);
|
|
6
|
+
this.orgId = data.orgId;
|
|
7
|
+
this.name = data.name;
|
|
8
|
+
this.description = data.description ?? '';
|
|
9
|
+
}
|
|
10
|
+
static create(data) {
|
|
11
|
+
const fullData = { ...data, description: data.description ?? '' };
|
|
12
|
+
const newData = EntityUtil.defaultData(fullData, 'orgId');
|
|
13
|
+
return new Org(newData);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3JnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYXBwL2NvcmUvZW50aXR5L09yZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQVksVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDN0QsT0FBTyxFQUFFLE1BQU0sRUFBYyxNQUFNLGFBQWEsQ0FBQztBQVVqRCxNQUFNLE9BQU8sR0FBSSxTQUFRLE1BQU07SUFLN0IsWUFBWSxJQUFhO1FBQ3ZCLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNaLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUN4QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQztJQUM1QyxDQUFDO0lBRUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFtQjtRQUMvQixNQUFNLFFBQVEsR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ2xFLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzFELE9BQU8sSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUIsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { EasyData } from '../util/EntityUtil.ts';
|
|
2
|
+
import { Entity, EntityData } from './Entity.ts';
|
|
3
|
+
interface OrgMemberData extends EntityData {
|
|
4
|
+
orgMemberId: string;
|
|
5
|
+
orgId: string;
|
|
6
|
+
userId: string;
|
|
7
|
+
role: 'owner' | 'member';
|
|
8
|
+
}
|
|
9
|
+
export type CreateOrgMemberData = Omit<EasyData<OrgMemberData, 'orgMemberId'>, 'id'>;
|
|
10
|
+
export declare class OrgMember extends Entity {
|
|
11
|
+
orgMemberId: string;
|
|
12
|
+
orgId: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
role: 'owner' | 'member';
|
|
15
|
+
constructor(data: OrgMemberData);
|
|
16
|
+
static create(data: CreateOrgMemberData): OrgMember;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EntityUtil } from "../util/EntityUtil.js";
|
|
2
|
+
import { Entity } from "./Entity.js";
|
|
3
|
+
export class OrgMember extends Entity {
|
|
4
|
+
constructor(data) {
|
|
5
|
+
super(data);
|
|
6
|
+
this.orgMemberId = data.orgMemberId;
|
|
7
|
+
this.orgId = data.orgId;
|
|
8
|
+
this.userId = data.userId;
|
|
9
|
+
this.role = data.role;
|
|
10
|
+
}
|
|
11
|
+
static create(data) {
|
|
12
|
+
const newData = EntityUtil.defaultData(data, 'orgMemberId');
|
|
13
|
+
return new OrgMember(newData);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3JnTWVtYmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYXBwL2NvcmUvZW50aXR5L09yZ01lbWJlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQVksVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDN0QsT0FBTyxFQUFFLE1BQU0sRUFBYyxNQUFNLGFBQWEsQ0FBQztBQVdqRCxNQUFNLE9BQU8sU0FBVSxTQUFRLE1BQU07SUFNbkMsWUFBWSxJQUFtQjtRQUM3QixLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDWixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDcEMsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMxQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDeEIsQ0FBQztJQUVELE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBeUI7UUFDckMsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDNUQsT0FBTyxJQUFJLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNoQyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EasyData } from '../util/EntityUtil.ts';
|
|
2
|
+
import { Entity, EntityData } from './Entity.ts';
|
|
3
|
+
interface TeamData extends EntityData {
|
|
4
|
+
teamId: string;
|
|
5
|
+
orgId: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
}
|
|
9
|
+
export type CreateTeamData = Omit<EasyData<TeamData, 'teamId'>, 'id' | 'description'> & {
|
|
10
|
+
description?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare class Team extends Entity {
|
|
13
|
+
teamId: string;
|
|
14
|
+
orgId: string;
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
constructor(data: TeamData);
|
|
18
|
+
static create(data: CreateTeamData): Team;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EntityUtil } from "../util/EntityUtil.js";
|
|
2
|
+
import { Entity } from "./Entity.js";
|
|
3
|
+
export class Team extends Entity {
|
|
4
|
+
constructor(data) {
|
|
5
|
+
super(data);
|
|
6
|
+
this.teamId = data.teamId;
|
|
7
|
+
this.orgId = data.orgId;
|
|
8
|
+
this.name = data.name;
|
|
9
|
+
this.description = data.description ?? '';
|
|
10
|
+
}
|
|
11
|
+
static create(data) {
|
|
12
|
+
const fullData = { ...data, description: data.description ?? '' };
|
|
13
|
+
const newData = EntityUtil.defaultData(fullData, 'teamId');
|
|
14
|
+
return new Team(newData);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGVhbS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2FwcC9jb3JlL2VudGl0eS9UZWFtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBWSxVQUFVLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsTUFBTSxFQUFjLE1BQU0sYUFBYSxDQUFDO0FBV2pELE1BQU0sT0FBTyxJQUFLLFNBQVEsTUFBTTtJQU05QixZQUFZLElBQWM7UUFDeEIsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ1osSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQzFCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUN4QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsQ0FBQztJQUM1QyxDQUFDO0lBRUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFvQjtRQUNoQyxNQUFNLFFBQVEsR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ2xFLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzNELE9BQU8sSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0IsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EasyData } from '../util/EntityUtil.ts';
|
|
2
|
+
import { Entity, EntityData } from './Entity.ts';
|
|
3
|
+
interface TeamMemberData extends EntityData {
|
|
4
|
+
teamMemberId: string;
|
|
5
|
+
teamId: string;
|
|
6
|
+
userId: string;
|
|
7
|
+
}
|
|
8
|
+
export type CreateTeamMemberData = Omit<EasyData<TeamMemberData, 'teamMemberId'>, 'id'>;
|
|
9
|
+
export declare class TeamMember extends Entity {
|
|
10
|
+
teamMemberId: string;
|
|
11
|
+
teamId: string;
|
|
12
|
+
userId: string;
|
|
13
|
+
constructor(data: TeamMemberData);
|
|
14
|
+
static create(data: CreateTeamMemberData): TeamMember;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EntityUtil } from "../util/EntityUtil.js";
|
|
2
|
+
import { Entity } from "./Entity.js";
|
|
3
|
+
export class TeamMember extends Entity {
|
|
4
|
+
constructor(data) {
|
|
5
|
+
super(data);
|
|
6
|
+
this.teamMemberId = data.teamMemberId;
|
|
7
|
+
this.teamId = data.teamId;
|
|
8
|
+
this.userId = data.userId;
|
|
9
|
+
}
|
|
10
|
+
static create(data) {
|
|
11
|
+
const newData = EntityUtil.defaultData(data, 'teamMemberId');
|
|
12
|
+
return new TeamMember(newData);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGVhbU1lbWJlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2FwcC9jb3JlL2VudGl0eS9UZWFtTWVtYmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBWSxVQUFVLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsTUFBTSxFQUFjLE1BQU0sYUFBYSxDQUFDO0FBVWpELE1BQU0sT0FBTyxVQUFXLFNBQVEsTUFBTTtJQUtwQyxZQUFZLElBQW9CO1FBQzlCLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNaLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztRQUN0QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDMUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQzVCLENBQUM7SUFFRCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQTBCO1FBQ3RDLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQzdELE9BQU8sSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakMsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EasyData } from '../util/EntityUtil.ts';
|
|
2
|
+
import { Entity, EntityData } from './Entity.ts';
|
|
3
|
+
interface TeamPackageData extends EntityData {
|
|
4
|
+
teamPackageId: string;
|
|
5
|
+
teamId: string;
|
|
6
|
+
packageId: string;
|
|
7
|
+
}
|
|
8
|
+
export type CreateTeamPackageData = Omit<EasyData<TeamPackageData, 'teamPackageId'>, 'id'>;
|
|
9
|
+
export declare class TeamPackage extends Entity {
|
|
10
|
+
teamPackageId: string;
|
|
11
|
+
teamId: string;
|
|
12
|
+
packageId: string;
|
|
13
|
+
constructor(data: TeamPackageData);
|
|
14
|
+
static create(data: CreateTeamPackageData): TeamPackage;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EntityUtil } from "../util/EntityUtil.js";
|
|
2
|
+
import { Entity } from "./Entity.js";
|
|
3
|
+
export class TeamPackage extends Entity {
|
|
4
|
+
constructor(data) {
|
|
5
|
+
super(data);
|
|
6
|
+
this.teamPackageId = data.teamPackageId;
|
|
7
|
+
this.teamId = data.teamId;
|
|
8
|
+
this.packageId = data.packageId;
|
|
9
|
+
}
|
|
10
|
+
static create(data) {
|
|
11
|
+
const newData = EntityUtil.defaultData(data, 'teamPackageId');
|
|
12
|
+
return new TeamPackage(newData);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGVhbVBhY2thZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hcHAvY29yZS9lbnRpdHkvVGVhbVBhY2thZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFZLFVBQVUsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzdELE9BQU8sRUFBRSxNQUFNLEVBQWMsTUFBTSxhQUFhLENBQUM7QUFVakQsTUFBTSxPQUFPLFdBQVksU0FBUSxNQUFNO0lBS3JDLFlBQVksSUFBcUI7UUFDL0IsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ1osSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMxQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDbEMsQ0FBQztJQUVELE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBMkI7UUFDdkMsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDOUQsT0FBTyxJQUFJLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNsQyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AbstractService } from '../../common/AbstractService.ts';
|
|
2
|
+
import { Org } from '../entity/Org.ts';
|
|
3
|
+
import { OrgMember } from '../entity/OrgMember.ts';
|
|
4
|
+
export interface CreateOrgCmd {
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
creatorUserId: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class OrgService extends AbstractService {
|
|
10
|
+
private readonly orgRepository;
|
|
11
|
+
private readonly teamRepository;
|
|
12
|
+
createOrg(cmd: CreateOrgCmd): Promise<Org>;
|
|
13
|
+
removeOrg(orgId: string): Promise<void>;
|
|
14
|
+
findOrgByName(name: string): Promise<Org | null>;
|
|
15
|
+
ensureOrgForScope(scope: string): Promise<Org>;
|
|
16
|
+
addMember(orgId: string, userId: string, role?: 'owner' | 'member'): Promise<OrgMember>;
|
|
17
|
+
removeMember(orgId: string, userId: string): Promise<void>;
|
|
18
|
+
listMembers(orgId: string): Promise<OrgMember[]>;
|
|
19
|
+
requiredOrgOwnerOrAdmin(orgId: string, userId: string, isAdmin: boolean): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { AccessLevel, Inject, SingletonProto } from 'egg';
|
|
11
|
+
import { ForbiddenError, NotFoundError } from 'egg/errors';
|
|
12
|
+
import { AbstractService } from "../../common/AbstractService.js";
|
|
13
|
+
import { DEVELOPERS_TEAM } from "../../common/constants.js";
|
|
14
|
+
import { Org } from "../entity/Org.js";
|
|
15
|
+
import { OrgMember } from "../entity/OrgMember.js";
|
|
16
|
+
import { Team } from "../entity/Team.js";
|
|
17
|
+
import { TeamMember } from "../entity/TeamMember.js";
|
|
18
|
+
let OrgService = class OrgService extends AbstractService {
|
|
19
|
+
async createOrg(cmd) {
|
|
20
|
+
const existing = await this.orgRepository.findOrgByName(cmd.name);
|
|
21
|
+
if (existing) {
|
|
22
|
+
throw new ForbiddenError(`Org "${cmd.name}" already exists`);
|
|
23
|
+
}
|
|
24
|
+
// Create org + developers team + owner + team member in one transaction
|
|
25
|
+
const org = Org.create({
|
|
26
|
+
name: cmd.name,
|
|
27
|
+
description: cmd.description,
|
|
28
|
+
});
|
|
29
|
+
const developersTeam = Team.create({
|
|
30
|
+
orgId: org.orgId,
|
|
31
|
+
name: DEVELOPERS_TEAM,
|
|
32
|
+
description: 'default team',
|
|
33
|
+
});
|
|
34
|
+
const ownerMember = OrgMember.create({
|
|
35
|
+
orgId: org.orgId,
|
|
36
|
+
userId: cmd.creatorUserId,
|
|
37
|
+
role: 'owner',
|
|
38
|
+
});
|
|
39
|
+
const teamMember = TeamMember.create({
|
|
40
|
+
teamId: developersTeam.teamId,
|
|
41
|
+
userId: cmd.creatorUserId,
|
|
42
|
+
});
|
|
43
|
+
await this.orgRepository.createOrgCascade(org, developersTeam, ownerMember, teamMember);
|
|
44
|
+
this.logger.info('[OrgService:createOrg] orgId: %s, name: %s, creatorUserId: %s', org.orgId, org.name, cmd.creatorUserId);
|
|
45
|
+
return org;
|
|
46
|
+
}
|
|
47
|
+
async removeOrg(orgId) {
|
|
48
|
+
await this.orgRepository.removeOrgCascade(orgId);
|
|
49
|
+
this.logger.info('[OrgService:removeOrg] orgId: %s', orgId);
|
|
50
|
+
}
|
|
51
|
+
async findOrgByName(name) {
|
|
52
|
+
return await this.orgRepository.findOrgByName(name);
|
|
53
|
+
}
|
|
54
|
+
// Auto-create org for allowScopes if it doesn't exist
|
|
55
|
+
async ensureOrgForScope(scope) {
|
|
56
|
+
const orgName = scope.replace(/^@/, '');
|
|
57
|
+
const existing = await this.orgRepository.findOrgByName(orgName);
|
|
58
|
+
if (existing)
|
|
59
|
+
return existing;
|
|
60
|
+
const org = Org.create({
|
|
61
|
+
name: orgName,
|
|
62
|
+
description: `Auto-created org for scope ${scope}`,
|
|
63
|
+
});
|
|
64
|
+
await this.orgRepository.saveOrg(org);
|
|
65
|
+
this.logger.info('[OrgService:ensureOrgForScope] orgId: %s, scope: %s', org.orgId, scope);
|
|
66
|
+
return org;
|
|
67
|
+
}
|
|
68
|
+
async addMember(orgId, userId, role = 'member') {
|
|
69
|
+
const org = await this.orgRepository.findOrgByOrgId(orgId);
|
|
70
|
+
if (!org) {
|
|
71
|
+
throw new NotFoundError('Org not found');
|
|
72
|
+
}
|
|
73
|
+
// Upsert org member
|
|
74
|
+
let member = await this.orgRepository.findMember(orgId, userId);
|
|
75
|
+
if (member) {
|
|
76
|
+
member.role = role;
|
|
77
|
+
await this.orgRepository.saveMember(member);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
member = OrgMember.create({ orgId, userId, role });
|
|
81
|
+
await this.orgRepository.saveMember(member);
|
|
82
|
+
}
|
|
83
|
+
// Auto-add to developers team
|
|
84
|
+
const developersTeam = await this.teamRepository.findTeam(orgId, DEVELOPERS_TEAM);
|
|
85
|
+
if (developersTeam) {
|
|
86
|
+
const existingTeamMember = await this.teamRepository.findMember(developersTeam.teamId, userId);
|
|
87
|
+
if (!existingTeamMember) {
|
|
88
|
+
const teamMember = TeamMember.create({
|
|
89
|
+
teamId: developersTeam.teamId,
|
|
90
|
+
userId,
|
|
91
|
+
});
|
|
92
|
+
await this.teamRepository.addMember(teamMember);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
this.logger.info('[OrgService:addMember] orgId: %s, userId: %s, role: %s', orgId, userId, role);
|
|
96
|
+
return member;
|
|
97
|
+
}
|
|
98
|
+
async removeMember(orgId, userId) {
|
|
99
|
+
// Remove from all teams in this org
|
|
100
|
+
await this.teamRepository.removeMemberFromAllTeams(orgId, userId);
|
|
101
|
+
// Remove from org
|
|
102
|
+
await this.orgRepository.removeMember(orgId, userId);
|
|
103
|
+
this.logger.info('[OrgService:removeMember] orgId: %s, userId: %s', orgId, userId);
|
|
104
|
+
}
|
|
105
|
+
async listMembers(orgId) {
|
|
106
|
+
return await this.orgRepository.listMembers(orgId);
|
|
107
|
+
}
|
|
108
|
+
async requiredOrgOwnerOrAdmin(orgId, userId, isAdmin) {
|
|
109
|
+
if (isAdmin)
|
|
110
|
+
return;
|
|
111
|
+
const member = await this.orgRepository.findMember(orgId, userId);
|
|
112
|
+
if (!member || member.role !== 'owner') {
|
|
113
|
+
throw new ForbiddenError('Only org owner or admin can perform this action');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
__decorate([
|
|
118
|
+
Inject(),
|
|
119
|
+
__metadata("design:type", Function)
|
|
120
|
+
], OrgService.prototype, "orgRepository", void 0);
|
|
121
|
+
__decorate([
|
|
122
|
+
Inject(),
|
|
123
|
+
__metadata("design:type", Function)
|
|
124
|
+
], OrgService.prototype, "teamRepository", void 0);
|
|
125
|
+
OrgService = __decorate([
|
|
126
|
+
SingletonProto({
|
|
127
|
+
accessLevel: AccessLevel.PUBLIC,
|
|
128
|
+
})
|
|
129
|
+
], OrgService);
|
|
130
|
+
export { OrgService };
|
|
131
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3JnU2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2FwcC9jb3JlL3NlcnZpY2UvT3JnU2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFDMUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFM0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUc1RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFXOUMsSUFBTSxVQUFVLEdBQWhCLE1BQU0sVUFBVyxTQUFRLGVBQWU7SUFPN0MsS0FBSyxDQUFDLFNBQVMsQ0FBQyxHQUFpQjtRQUMvQixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsRSxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLGNBQWMsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxJQUFJLGtCQUFrQixDQUFDLENBQUM7UUFDL0QsQ0FBQztRQUVELHdFQUF3RTtRQUN4RSxNQUFNLEdBQUcsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO1lBQ3JCLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSTtZQUNkLFdBQVcsRUFBRSxHQUFHLENBQUMsV0FBVztTQUM3QixDQUFDLENBQUM7UUFDSCxN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
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AbstractService } from '../../common/AbstractService.ts';
|
|
2
|
+
import { Team } from '../entity/Team.ts';
|
|
3
|
+
import { TeamMember } from '../entity/TeamMember.ts';
|
|
4
|
+
import { TeamPackage } from '../entity/TeamPackage.ts';
|
|
5
|
+
export declare class TeamService extends AbstractService {
|
|
6
|
+
private readonly orgRepository;
|
|
7
|
+
private readonly teamRepository;
|
|
8
|
+
createTeam(orgId: string, name: string, description?: string): Promise<Team>;
|
|
9
|
+
removeTeam(teamId: string): Promise<void>;
|
|
10
|
+
addMember(teamId: string, userId: string): Promise<TeamMember>;
|
|
11
|
+
removeMember(teamId: string, userId: string): Promise<void>;
|
|
12
|
+
listMembers(teamId: string): Promise<TeamMember[]>;
|
|
13
|
+
grantPackageAccess(teamId: string, packageId: string): Promise<TeamPackage>;
|
|
14
|
+
revokePackageAccess(teamId: string, packageId: string): Promise<void>;
|
|
15
|
+
listPackages(teamId: string): Promise<TeamPackage[]>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { AccessLevel, Inject, SingletonProto } from 'egg';
|
|
11
|
+
import { ForbiddenError, NotFoundError } from 'egg/errors';
|
|
12
|
+
import { AbstractService } from "../../common/AbstractService.js";
|
|
13
|
+
import { DEVELOPERS_TEAM } from "../../common/constants.js";
|
|
14
|
+
import { Team } from "../entity/Team.js";
|
|
15
|
+
import { TeamMember } from "../entity/TeamMember.js";
|
|
16
|
+
import { TeamPackage } from "../entity/TeamPackage.js";
|
|
17
|
+
let TeamService = class TeamService extends AbstractService {
|
|
18
|
+
async createTeam(orgId, name, description) {
|
|
19
|
+
const existing = await this.teamRepository.findTeam(orgId, name);
|
|
20
|
+
if (existing) {
|
|
21
|
+
throw new ForbiddenError(`Team "${name}" already exists`);
|
|
22
|
+
}
|
|
23
|
+
const team = Team.create({
|
|
24
|
+
orgId,
|
|
25
|
+
name,
|
|
26
|
+
description,
|
|
27
|
+
});
|
|
28
|
+
await this.teamRepository.saveTeam(team);
|
|
29
|
+
this.logger.info('[TeamService:createTeam] teamId: %s, orgId: %s, name: %s', team.teamId, orgId, name);
|
|
30
|
+
return team;
|
|
31
|
+
}
|
|
32
|
+
async removeTeam(teamId) {
|
|
33
|
+
const team = await this.teamRepository.findTeamByTeamId(teamId);
|
|
34
|
+
if (!team) {
|
|
35
|
+
throw new NotFoundError('Team not found');
|
|
36
|
+
}
|
|
37
|
+
if (team.name === DEVELOPERS_TEAM) {
|
|
38
|
+
throw new ForbiddenError('Cannot delete the developers team');
|
|
39
|
+
}
|
|
40
|
+
// Cascade: remove packages + members + team in one transaction
|
|
41
|
+
await this.teamRepository.removeTeamCascade(teamId);
|
|
42
|
+
this.logger.info('[TeamService:removeTeam] teamId: %s', teamId);
|
|
43
|
+
}
|
|
44
|
+
async addMember(teamId, userId) {
|
|
45
|
+
const team = await this.teamRepository.findTeamByTeamId(teamId);
|
|
46
|
+
if (!team) {
|
|
47
|
+
throw new NotFoundError('Team not found');
|
|
48
|
+
}
|
|
49
|
+
// For allowScopes orgs, skip org member check (self-registry users have implicit access)
|
|
50
|
+
// For other orgs, must be an org member first
|
|
51
|
+
const org = await this.orgRepository.findOrgByOrgId(team.orgId);
|
|
52
|
+
if (org && !this.config.cnpmcore.allowScopes.includes(`@${org.name}`)) {
|
|
53
|
+
const orgMember = await this.orgRepository.findMember(team.orgId, userId);
|
|
54
|
+
if (!orgMember) {
|
|
55
|
+
throw new ForbiddenError('User must be an org member before joining a team');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const existing = await this.teamRepository.findMember(teamId, userId);
|
|
59
|
+
if (existing) {
|
|
60
|
+
return existing;
|
|
61
|
+
}
|
|
62
|
+
const member = TeamMember.create({ teamId, userId });
|
|
63
|
+
await this.teamRepository.addMember(member);
|
|
64
|
+
this.logger.info('[TeamService:addMember] teamId: %s, userId: %s', teamId, userId);
|
|
65
|
+
return member;
|
|
66
|
+
}
|
|
67
|
+
async removeMember(teamId, userId) {
|
|
68
|
+
await this.teamRepository.removeMember(teamId, userId);
|
|
69
|
+
this.logger.info('[TeamService:removeMember] teamId: %s, userId: %s', teamId, userId);
|
|
70
|
+
}
|
|
71
|
+
async listMembers(teamId) {
|
|
72
|
+
return await this.teamRepository.listMembers(teamId);
|
|
73
|
+
}
|
|
74
|
+
async grantPackageAccess(teamId, packageId) {
|
|
75
|
+
const team = await this.teamRepository.findTeamByTeamId(teamId);
|
|
76
|
+
if (!team) {
|
|
77
|
+
throw new NotFoundError('Team not found');
|
|
78
|
+
}
|
|
79
|
+
const existing = await this.teamRepository.findPackage(teamId, packageId);
|
|
80
|
+
if (existing) {
|
|
81
|
+
return existing;
|
|
82
|
+
}
|
|
83
|
+
const teamPackage = TeamPackage.create({ teamId, packageId });
|
|
84
|
+
await this.teamRepository.addPackage(teamPackage);
|
|
85
|
+
this.logger.info('[TeamService:grantPackageAccess] teamId: %s, packageId: %s', teamId, packageId);
|
|
86
|
+
return teamPackage;
|
|
87
|
+
}
|
|
88
|
+
async revokePackageAccess(teamId, packageId) {
|
|
89
|
+
await this.teamRepository.removePackage(teamId, packageId);
|
|
90
|
+
this.logger.info('[TeamService:revokePackageAccess] teamId: %s, packageId: %s', teamId, packageId);
|
|
91
|
+
}
|
|
92
|
+
async listPackages(teamId) {
|
|
93
|
+
return await this.teamRepository.listPackages(teamId);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
__decorate([
|
|
97
|
+
Inject(),
|
|
98
|
+
__metadata("design:type", Function)
|
|
99
|
+
], TeamService.prototype, "orgRepository", void 0);
|
|
100
|
+
__decorate([
|
|
101
|
+
Inject(),
|
|
102
|
+
__metadata("design:type", Function)
|
|
103
|
+
], TeamService.prototype, "teamRepository", void 0);
|
|
104
|
+
TeamService = __decorate([
|
|
105
|
+
SingletonProto({
|
|
106
|
+
accessLevel: AccessLevel.PUBLIC,
|
|
107
|
+
})
|
|
108
|
+
], TeamService);
|
|
109
|
+
export { TeamService };
|
|
110
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGVhbVNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hcHAvY29yZS9zZXJ2aWNlL1RlYW1TZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLGNBQWMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUMxRCxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUUzRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRzVELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBS2hELElBQU0sV0FBVyxHQUFqQixNQUFNLFdBQVksU0FBUSxlQUFlO0lBTzlDLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBYSxFQUFFLElBQVksRUFBRSxXQUFvQjtRQUNoRSxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNqRSxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLGNBQWMsQ0FBQyxTQUFTLElBQUksa0JBQWtCLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztZQUN2QixLQUFLO1lBQ0wsSUFBSTtZQUNKLFdBQVc7U0FDWixDQUFDLENBQUM7UUFDSCxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxNQUFNLENBQUMs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
|
|
@@ -9,6 +9,7 @@ export declare class UserRoleManager {
|
|
|
9
9
|
protected logger: Logger;
|
|
10
10
|
private readonly registryManagerService;
|
|
11
11
|
private readonly tokenService;
|
|
12
|
+
private readonly teamRepository;
|
|
12
13
|
private handleAuthorized;
|
|
13
14
|
private currentAuthorizedUser;
|
|
14
15
|
private currentAuthorizedToken;
|
|
@@ -21,4 +22,5 @@ export declare class UserRoleManager {
|
|
|
21
22
|
requiredPackageMaintainer(pkg: PackageEntity, user: UserEntity): Promise<void>;
|
|
22
23
|
requiredPackageScope(scope: string, user: UserEntity): Promise<void>;
|
|
23
24
|
isAdmin(ctx: Context): Promise<boolean>;
|
|
25
|
+
checkReadAccess(ctx: Context, scope: string, name: string): Promise<boolean>;
|
|
24
26
|
}
|
|
@@ -159,6 +159,27 @@ let UserRoleManager = class UserRoleManager {
|
|
|
159
159
|
return false;
|
|
160
160
|
return user.name in this.config.cnpmcore.admins;
|
|
161
161
|
}
|
|
162
|
+
// self scope + no team binding = everyone can read, returns false
|
|
163
|
+
// self scope + team binding = only team members can read, returns true
|
|
164
|
+
// returns true if package is team-bound (private cache needed)
|
|
165
|
+
async checkReadAccess(ctx, scope, name) {
|
|
166
|
+
if (!scope || !this.config.cnpmcore.allowScopes.includes(scope))
|
|
167
|
+
return false;
|
|
168
|
+
const pkg = await this.packageRepository.findPackage(scope, name);
|
|
169
|
+
if (!pkg)
|
|
170
|
+
return false; // let downstream throw 404
|
|
171
|
+
const hasTeamBinding = await this.teamRepository.hasAnyTeamBinding(pkg.packageId);
|
|
172
|
+
if (!hasTeamBinding)
|
|
173
|
+
return false; // no team binding, everyone can read
|
|
174
|
+
// team binding exists, require auth
|
|
175
|
+
const user = await this.requiredAuthorizedUser(ctx, 'read');
|
|
176
|
+
if (await this.isAdmin(ctx))
|
|
177
|
+
return true;
|
|
178
|
+
const hasAccess = await this.teamRepository.hasPackageAccess(pkg.packageId, user.userId);
|
|
179
|
+
if (hasAccess)
|
|
180
|
+
return true;
|
|
181
|
+
throw new ForbiddenError(`"${user.name}" is not authorized to access ${pkg.fullname}`);
|
|
182
|
+
}
|
|
162
183
|
};
|
|
163
184
|
__decorate([
|
|
164
185
|
Inject(),
|
|
@@ -180,6 +201,10 @@ __decorate([
|
|
|
180
201
|
Inject(),
|
|
181
202
|
__metadata("design:type", Function)
|
|
182
203
|
], UserRoleManager.prototype, "tokenService", void 0);
|
|
204
|
+
__decorate([
|
|
205
|
+
Inject(),
|
|
206
|
+
__metadata("design:type", Function)
|
|
207
|
+
], UserRoleManager.prototype, "teamRepository", void 0);
|
|
183
208
|
UserRoleManager = __decorate([
|
|
184
209
|
ContextProto({
|
|
185
210
|
// only inject on port module
|
|
@@ -187,4 +212,4 @@ UserRoleManager = __decorate([
|
|
|
187
212
|
})
|
|
188
213
|
], UserRoleManager);
|
|
189
214
|
export { UserRoleManager };
|
|
190
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
215
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXNlclJvbGVNYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vYXBwL3BvcnQvVXNlclJvbGVNYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBVyxXQUFXLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBa0IsTUFBTSxLQUFLLENBQUM7QUFDakYsT0FBTyxFQUFFLGNBQWMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUUvRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFnQnBELElBQU0sZUFBZSxHQUFyQixNQUFNLGVBQWU7SUFBckI7UUFjRyxxQkFBZ0IsR0FBRyxLQUFLLENBQUM7SUFvTG5DLENBQUM7SUFoTEMsdUJBQXVCO0lBQ3ZCLDBCQUEwQjtJQUMxQix1Q0FBdUM7SUFDdkMscUNBQXFDO0lBQ3JDLGdFQUFnRTtJQUN6RCxLQUFLLENBQUMsa0JBQWtCLENBQUMsR0FBWSxFQUFFLFFBQWdCO1FBQzVELE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUUvRCwwQkFBMEI7UUFDMUIsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCx3Q0FBd0M7UUFDeEMsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN6RSxtRUFBbUU7UUFDbkUsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLHNCQUF1QixDQUFDO1FBQzFDLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFFbEUsdUNBQXVDO1FBQ3ZDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEdBQUcsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2hELE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEUsTUFBTSxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUM1RSxNQUFNLGNBQWMsR0FBRyxHQUFHLEVBQUUsVUFBVSxLQUFLLFlBQVksQ0FBQyxVQUFVLENBQUM7UUFDbkUsSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNuQixpQ0FBaUM7WUFDakMsbUNBQW1DO1lBQ25DLE1BQU0sSUFBSSxDQUFDLHlCQUF5QixDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNoRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3JDLHFEQUFxRDtZQUNyRCxtREFBbUQ7WUFDbkQsTUFBTSxJQUFJLGNBQWMsQ0FBQyxvQ0FBb0MsUUFBUSxHQUFHLENBQUMsQ0FBQztRQUM1RSxDQUFDO1FBRUQsc0NBQXNDO1FBQ3RDLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM3QyxJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQ1IsMkJBQTJCO1lBQzNCLE1BQU0sSUFBSSxDQUFDLHlCQUF5QixDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsSUFBSTtJQUNKLDJFQUEyRTtJQUMzRSw4QkFBOEI7SUFDOUIsa0VBQWtFO0lBQ2xFLHdDQUF3QztJQUN4QyxtQkFBbUI7SUFDbkIsNkJBQTZCO0lBQzdCLHVDQUF1QztJQUN2Qyw0QkFBNEI7SUFDNUIsNkJBQTZCO0lBQzdCLElBQUk7SUFDRyxLQUFLLENBQUMseUJBQXlCLENBQUMsR0FBWTtRQUNqRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzFCLElBQUksQ0FBQyxJQUFJLENBQUMscUJBQXFCO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBQzdDLE9BQU87Z0JBQ0wsS0FBSyxFQUFFLElBQUksQ0FBQyxzQkFBc0I7Z0JBQ2xDLElBQUksRUFBRSxJQUFJLENBQUMscUJBQXFCO2FBQ2pDLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztRQUM3QixNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFTLGVBQWUsQ0FBQyxDQUFDO1FBQ3ZELElBQUksQ0FBQyxhQUFhO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDaEMsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3RGLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1lBQzVCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELHVDQUF1QztRQUN2QyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsZ0JBQWdCLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkUsSUFBSSxDQUFDLHNCQUFzQixHQUFHLHNCQUFzQixDQUFDLEtBQUssQ0FBQztRQUMzRCxJQUFJLENBQUMscUJBQXFCLEdBQUcsc0JBQXNCLENBQUMsSUFBSSxDQUFDO1FBQ3pELEdBQUcsQ0FBQyxNQUFNLEdBQUcsc0JBQXNCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUNoRCxPQUFPLHNCQUFzQixDQUFDO0lBQ2hDLENBQUM7SUFFTSxLQUFLLENBQUMsc0JBQXNCLENBQUMsR0FBWSxFQUFFLElBQWU7UUFDL0QsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN6RSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztZQUM1QixNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQy9DLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUM7WUFDaEUsTUFBTSxJQUFJLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7UUFDRCxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLHNCQUFzQixDQUFDO1FBQy9DLCtFQUErRTtRQUMvRSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLDhCQUE4QixJQUFJLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUM5RSxJQUFJLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxJQUFJLGNBQWMsQ0FBQyxvQkFBb0IsS0FBSyxDQUFDLFNBQVMsaUJBQWlCLENBQUMsQ0FBQztZQUNqRixDQUFDO1lBQ0QsTUFBTSxTQUFTLEdBQVcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNoRCxpREFBaUQ7WUFDakQscURBQXFEO1lBQ3JELHdEQUF3RDtZQUN4RCxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzdDLE1BQU0sQ0FBQyxHQUFHLG9CQUFvQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMvQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUNOLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3BDLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUNkLE1BQU0sSUFBSSxjQUFjLENBQUMseUNBQXlDLENBQUMsQ0FBQztnQkFDdEUsQ0FBQztZQUNILENBQUM7aUJBQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNuQixNQUFNLElBQUksY0FBYyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7WUFDOUQsQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN2QixJQUFJLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxJQUFJLGNBQWMsQ0FBQyxvQkFBb0IsS0FBSyxDQUFDLFNBQVMsaUJBQWlCLENBQUMsQ0FBQztZQUNqRixDQUFDO1lBQ0QsSUFBSSxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3ZCLE1BQU0sSUFBSSxjQUFjLENBQUMscUJBQXFCLEtBQUssQ0FBQyxTQUFTLGlCQUFpQixDQUFDLENBQUM7WUFDbEYsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTSxLQUFLLENBQUMseUJBQXlCLENBQUMsR0FBa0IsRUFBRSxJQUFnQjtRQUN6RSxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdkYsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ2hCLE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDeEQsTUFBTSxJQUFJLGNBQWMsQ0FDdEIsSUFBSSxJQUFJLENBQUMsSUFBSSw4QkFBOEIsR0FBRyxDQUFDLFFBQVEsa0NBQWtDLEtBQUssR0FBRyxDQUNsRyxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFTSxLQUFLLENBQUMsb0JBQW9CLENBQUMsS0FBYSxFQUFFLElBQWdCO1FBQy9ELE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO1FBQzVDLElBQUksY0FBYyxDQUFDLDJCQUEyQixFQUFFLENBQUM7WUFDL0MsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLGNBQWMsQ0FBQyxXQUFXLENBQUM7UUFDOUQsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxJQUFJLGNBQWMsQ0FBQywwQ0FBMEMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEcsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDakMsTUFBTSxJQUFJLGNBQWMsQ0FBQyxVQUFVLEtBQUssOEJBQThCLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25HLENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFZO1FBQy9CLE1BQU0sc0JBQXNCLEdBQUcsTUFBTSxJQUFJLENBQUMseUJBQXlCLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDekUsSUFBSSxDQUFDLHNCQUFzQjtZQUFFLE9BQU8sS0FBSyxDQUFDO1FBQzFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsc0JBQXNCLENBQUM7UUFDL0MsSUFBSSxLQUFLLENBQUMsVUFBVTtZQUFFLE9BQU8sS0FBSyxDQUFDO1FBQ25DLE9BQU8sSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7SUFDbEQsQ0FBQztJQUVELGtFQUFrRTtJQUNsRSx1RUFBdUU7SUFDdkUsK0RBQStEO0lBQ3hELEtBQUssQ0FBQyxlQUFlLENBQUMsR0FBWSxFQUFFLEtBQWEsRUFBRSxJQUFZO1FBQ3BFLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sS0FBSyxDQUFDO1FBRTlFLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLEtBQUssQ0FBQyxDQUFDLDJCQUEyQjtRQUVuRCxNQUFNLGNBQWMsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ2xGLElBQUksQ0FBQyxjQUFjO1lBQUUsT0FBTyxLQUFLLENBQUMsQ0FBQyxxQ0FBcUM7UUFFeEUsb0NBQW9DO1FBQ3BDLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUM1RCxJQUFJLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFBRSxPQUFPLElBQUksQ0FBQztRQUV6QyxNQUFNLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDekYsSUFBSSxTQUFTO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFFM0IsTUFBTSxJQUFJLGNBQWMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLGlDQUFpQyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUN6RixDQUFDO0NBQ0YsQ0FBQTtBQWhNa0I7SUFEaEIsTUFBTSxFQUFFOzswREFDNkM7QUFFckM7SUFEaEIsTUFBTSxFQUFFOzsrQ0FDdUI7QUFFdEI7SUFEVCxNQUFNLEVBQUU7OytDQUNnQjtBQUVSO0lBRGhCLE1BQU0sRUFBRTs7K0RBQ3VEO0FBRS9DO0lBRGhCLE1BQU0sRUFBRTs7cURBQ21DO0FBRTNCO0lBRGhCLE1BQU0sRUFBRTs7dURBQ3VDO0FBWnJDLGVBQWU7SUFKM0IsWUFBWSxDQUFDO1FBQ1osNkJBQTZCO1FBQzdCLFdBQVcsRUFBRSxXQUFXLENBQUMsT0FBTztLQUNqQyxDQUFDO0dBQ1csZUFBZSxDQWtNM0IifQ==
|