@mindline/sync 1.0.11 → 1.0.13
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/configs.json +21 -0
- package/index.js +154 -60
- package/index.test.js +4 -7
- package/package.json +1 -1
- package/sync.d.ts +49 -34
- package/targets.json +20 -0
- package/users.json +22 -0
- package/workspaces.json +9 -0
package/configs.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "1",
|
|
4
|
+
"name": "ProdSync",
|
|
5
|
+
"description": "Automated sync of users from Mindline1 to Mindline2",
|
|
6
|
+
"targetConfigs":
|
|
7
|
+
[
|
|
8
|
+
{
|
|
9
|
+
"tid": "7f4567b8-f9a9-4ad3-9cb5-ef16a80e5744",
|
|
10
|
+
"sourceGroups": ["TODO"],
|
|
11
|
+
"targetGroup": ""
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"tid": "df9c2e0a-f6fe-43bb-a155-d51f66dffe0e",
|
|
15
|
+
"sourceGroups": [],
|
|
16
|
+
"targetGroup": "TODO"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"enabled": "false"
|
|
20
|
+
}
|
|
21
|
+
]
|
package/index.js
CHANGED
|
@@ -1,107 +1,201 @@
|
|
|
1
1
|
//index.js
|
|
2
2
|
|
|
3
|
-
// called by unit
|
|
3
|
+
// called by unit tests
|
|
4
4
|
export function sum(a, b) {
|
|
5
5
|
return a + b;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
// called by simpleclass test app
|
|
9
7
|
export function helloNpm() {
|
|
10
8
|
return "hello NPM";
|
|
11
9
|
}
|
|
12
10
|
|
|
11
|
+
const FILTER_FIELD = "WorkspaceIDs";
|
|
12
|
+
|
|
13
13
|
export class User {
|
|
14
14
|
constructor(){
|
|
15
|
-
this.authority = "";
|
|
16
15
|
this.oid = "";
|
|
17
|
-
this.tid = "";
|
|
18
|
-
this.upn = "";
|
|
19
16
|
this.name = "";
|
|
17
|
+
this.mail = "";
|
|
18
|
+
this.authority = "";
|
|
19
|
+
this.tid = "";
|
|
20
|
+
this.companyName = "";
|
|
21
|
+
this.companyDomain = "";
|
|
22
|
+
this.associatedWorkspaces = {};
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
export class
|
|
24
|
-
constructor(){
|
|
25
|
-
this.vts = null;
|
|
26
|
-
this.sts = null;
|
|
27
|
-
this.scs = null;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// shared base class of virtual and sync tenants
|
|
32
|
-
export class Tenant {
|
|
26
|
+
export class Target {
|
|
33
27
|
constructor(){
|
|
34
|
-
this.authority = "";
|
|
35
28
|
this.tid = "";
|
|
36
29
|
this.name = "";
|
|
37
30
|
this.domain = "";
|
|
31
|
+
this.type = "";
|
|
32
|
+
this.authority = "";
|
|
33
|
+
this.readServicePrincipal = "";
|
|
34
|
+
this.writeServicePrincipal = "";
|
|
38
35
|
}
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
export class VirtualTenant extends Tenant {
|
|
38
|
+
export class Config {
|
|
43
39
|
constructor(){
|
|
44
|
-
|
|
40
|
+
this.id = "";
|
|
41
|
+
this.name = "";
|
|
45
42
|
this.description = "";
|
|
43
|
+
this.targetConfigs = {};
|
|
44
|
+
this.enabled = false;
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
export class SyncTenant extends Tenant {
|
|
48
|
+
export class Workspace {
|
|
51
49
|
constructor(){
|
|
52
|
-
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
56
|
-
this.
|
|
50
|
+
this.id = "";
|
|
51
|
+
this.name = "";
|
|
52
|
+
this.associatedUsers = {};
|
|
53
|
+
this.associatedTargets = {};
|
|
54
|
+
this.associatedConfigs = {};
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
this.
|
|
65
|
-
this.
|
|
58
|
+
export class PortalConfigInfo {
|
|
59
|
+
constructor() {
|
|
60
|
+
this.us = {};
|
|
61
|
+
this.ts = {};
|
|
62
|
+
this.cs = {};
|
|
63
|
+
this.ws = {};
|
|
64
|
+
}
|
|
65
|
+
tagWithWorkspaces() {
|
|
66
|
+
// for each Workspace tag associated User, Target, Config with Workspace.id
|
|
67
|
+
for (let workspace of this.ws) {
|
|
68
|
+
// find matching Users to tag with this workspace
|
|
69
|
+
for (let userID of workspace.associatedUsers) {
|
|
70
|
+
let user = this.us.find((currentUser) => currentUser.oid === userID);
|
|
71
|
+
if (user !== undefined) {
|
|
72
|
+
// we found the user
|
|
73
|
+
if (user[FILTER_FIELD] === undefined) {
|
|
74
|
+
// the user does not have the filter field yet
|
|
75
|
+
try {
|
|
76
|
+
user[FILTER_FIELD] = workspace.id;
|
|
77
|
+
} catch (e) {
|
|
78
|
+
debugger;
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
// the user does have the filter field
|
|
83
|
+
user[FILTER_FIELD] += ", ";
|
|
84
|
+
user[FILTER_FIELD] += workspace.id;
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
// we should not have PCI that does not have Workspace component objects
|
|
88
|
+
debugger;
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// find matching Targets to tag with this workspace
|
|
93
|
+
for (let targetID of workspace.associatedTargets) {
|
|
94
|
+
let target = this.ts.find(
|
|
95
|
+
(currentTarget) => currentTarget.tid === targetID
|
|
96
|
+
);
|
|
97
|
+
if (target !== undefined) {
|
|
98
|
+
// we found the target
|
|
99
|
+
if (target[FILTER_FIELD] === undefined) {
|
|
100
|
+
// the target does not have the filter field yet
|
|
101
|
+
try {
|
|
102
|
+
target[FILTER_FIELD] = workspace.id;
|
|
103
|
+
} catch (e) {
|
|
104
|
+
debugger;
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
// the target does have the filter field
|
|
109
|
+
target[FILTER_FIELD] += ", ";
|
|
110
|
+
target[FILTER_FIELD] += workspace.id;
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
// we should not have PCI that does not have Workspace component objects
|
|
114
|
+
debugger;
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// find matching Configs to tag with this workspace
|
|
119
|
+
for (let configID of workspace.associatedConfigs) {
|
|
120
|
+
let config = this.cs.find(
|
|
121
|
+
(currentConfig) => currentConfig.id === configID
|
|
122
|
+
);
|
|
123
|
+
if (config !== undefined) {
|
|
124
|
+
// we found the config
|
|
125
|
+
if (config[FILTER_FIELD] === undefined) {
|
|
126
|
+
// the config does not have the filter field yet
|
|
127
|
+
try {
|
|
128
|
+
config[FILTER_FIELD] = workspace.id;
|
|
129
|
+
} catch (e) {
|
|
130
|
+
debugger;
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
// the config does have the filter field
|
|
135
|
+
config[FILTER_FIELD] += ", ";
|
|
136
|
+
config[FILTER_FIELD] += workspace.id;
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
// we should not have PCI that does not have Workspace component objects
|
|
140
|
+
debugger;
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
66
146
|
}
|
|
67
147
|
}
|
|
68
148
|
|
|
69
149
|
import { deserializeArray } from 'class-transformer';
|
|
70
|
-
import
|
|
71
|
-
import
|
|
72
|
-
import
|
|
73
|
-
|
|
74
|
-
// called by unit test
|
|
75
|
-
export function readobjects() {
|
|
76
|
-
// convert read JSON to VirtualTenant array
|
|
77
|
-
debugger;
|
|
78
|
-
let virtuals = null;
|
|
79
|
-
var virtualTenantsString = JSON.stringify(virtualTenants);
|
|
80
|
-
try {
|
|
81
|
-
virtuals = deserializeArray(VirtualTenant, virtualTenantsString);
|
|
82
|
-
} catch (e) {
|
|
83
|
-
debugger;
|
|
84
|
-
return 0;
|
|
85
|
-
}
|
|
86
|
-
// make some assertion about the data we just read
|
|
87
|
-
return virtuals.length;
|
|
88
|
-
}
|
|
150
|
+
import users from "./users.json";
|
|
151
|
+
import targets from "./targets.json";
|
|
152
|
+
import configs from "./configs.json";
|
|
153
|
+
import workspaces from "./workspaces.json";
|
|
89
154
|
|
|
90
|
-
//
|
|
91
|
-
export function
|
|
155
|
+
// retrieve Workspace(s), User(s), Target(s), Config(s) given logged in user
|
|
156
|
+
export function InitPortal(user, portalConfigInfo)
|
|
92
157
|
{
|
|
93
158
|
debugger;
|
|
94
159
|
// for now, just get hardcoded data from JSON
|
|
95
|
-
var
|
|
96
|
-
var
|
|
97
|
-
var
|
|
160
|
+
var usersString = JSON.stringify(users);
|
|
161
|
+
var targetsString = JSON.stringify(targets);
|
|
162
|
+
var configsString = JSON.stringify(configs);
|
|
163
|
+
var workspacesString = JSON.stringify(workspaces);
|
|
98
164
|
try {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
165
|
+
portalConfigInfo.us = deserializeArray(User, usersString);
|
|
166
|
+
portalConfigInfo.ts = deserializeArray(Target, targetsString);
|
|
167
|
+
portalConfigInfo.cs = deserializeArray(Config, configsString);
|
|
168
|
+
portalConfigInfo.ws = deserializeArray(Workspace, workspacesString);
|
|
169
|
+
portalConfigInfo.tagWithWorkspaces();
|
|
170
|
+
debugger;
|
|
102
171
|
} catch (e) {
|
|
103
172
|
debugger;
|
|
104
173
|
return false;
|
|
105
174
|
}
|
|
106
175
|
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function AddTarget()
|
|
179
|
+
{
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function CompleteTarget()
|
|
184
|
+
{
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function AddUser()
|
|
189
|
+
{
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function CompleteUser()
|
|
194
|
+
{
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function CreateConfig()
|
|
199
|
+
{
|
|
200
|
+
return true;
|
|
107
201
|
}
|
package/index.test.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import {sum,
|
|
1
|
+
import {sum, User, PortalConfigInfo, InitPortal } from "./index.js";
|
|
2
2
|
import {test, expect} from "vitest";
|
|
3
3
|
|
|
4
4
|
test("adds 1 + 2 to equal 3", () => {
|
|
5
5
|
expect(sum(1, 2)).toBe(3);
|
|
6
6
|
});
|
|
7
|
-
test("loads array of VirtualTenants from JSON and expects 2", () => {
|
|
8
|
-
expect(readobjects()).toBe(2);
|
|
9
|
-
});
|
|
10
7
|
test("loads config based on a user and expects function to return true", () => {
|
|
11
8
|
let u = new User();
|
|
12
|
-
let
|
|
13
|
-
expect(
|
|
14
|
-
expect(
|
|
9
|
+
let pci = new PortalConfigInfo();
|
|
10
|
+
expect(InitPortal(u, pci)).toBe(true);
|
|
11
|
+
expect(pci.us.length).toBe(2);
|
|
15
12
|
});
|
package/package.json
CHANGED
package/sync.d.ts
CHANGED
|
@@ -2,50 +2,65 @@ declare module "@mindline/sync" {
|
|
|
2
2
|
export function sum(a: number, b: number): number;
|
|
3
3
|
export function helloNpm(): string;
|
|
4
4
|
|
|
5
|
-
//
|
|
5
|
+
// admin
|
|
6
6
|
export class User {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
oid: string; // from AAD ID token
|
|
8
|
+
name: string; // from AAD ID token
|
|
9
|
+
mail: string; // from AAD ID token TODO: preferred_username *may* differ from UPN, may differ from mail
|
|
10
|
+
authority: string; // from AAD auth response - cloud instance login endpoint
|
|
11
|
+
tid: string; // from AAD ID token
|
|
12
|
+
companyName: string; // findTenantInformationByTenantId TODO: process changes to company name
|
|
13
|
+
companyDomain: string; // findTenantInformationByTenantId TODO: process changes to company name
|
|
14
|
+
associatedWorkspaces: string[];
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
// target (Azure AD tenant, AD domain, Google workspace)
|
|
18
|
+
enum TargetType { AAD = 1, AD, Google }
|
|
19
|
+
export class Target {
|
|
20
|
+
tid: string; // from AAD ID token
|
|
21
|
+
name: string; // findTenantInformationByTenantId
|
|
22
|
+
domain: string; // findTenantInformationByTenantId
|
|
23
|
+
type: TargetType; // always AAD for now
|
|
24
|
+
authority: string; // from AAD ID auth response
|
|
25
|
+
readServicePrincipal: string; // from AAD consent
|
|
26
|
+
writeServicePrincipal: string; // from AAD consent
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
//
|
|
22
|
-
export class
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
domain: string; // from AAD: tenant default domain
|
|
29
|
+
// config
|
|
30
|
+
export class TargetConfigInfo {
|
|
31
|
+
tid: string; // target identifier
|
|
32
|
+
sourceGroups: string[]; // source groups - we can confiure multiple source groups for reading (*may* slow things down, but less work for admin)
|
|
33
|
+
targetGroup: string; // target group - we only write users to a single target group (complex to fiugure out which users get written to which groups)
|
|
27
34
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
description: string;
|
|
35
|
+
export class Config {
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
targetConfigs: TargetConfigInfo[];
|
|
40
|
+
enabled: boolean;
|
|
32
41
|
}
|
|
33
42
|
|
|
34
|
-
// class
|
|
35
|
-
export class
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
// class to group Users, Tenants, and Configs
|
|
44
|
+
export class Workspace {
|
|
45
|
+
id: string;
|
|
46
|
+
name: string;
|
|
47
|
+
associatedUsers: string[];
|
|
48
|
+
associatedTargets: string[];
|
|
49
|
+
associatedConfigs: string[];
|
|
40
50
|
}
|
|
41
51
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
export class PortalConfigInfo {
|
|
53
|
+
us: User[];
|
|
54
|
+
ts: Target[];
|
|
55
|
+
cs: Config[];
|
|
56
|
+
ws: Workspace[];
|
|
57
|
+
tagWithWorkspaces(): boolean;
|
|
47
58
|
}
|
|
48
59
|
|
|
49
|
-
export function
|
|
50
|
-
export function
|
|
60
|
+
export function InitPortal(u: User, pci: PortalConfigInfo): boolean;
|
|
61
|
+
export function AddTarget(): boolean;
|
|
62
|
+
export function CompleteTarget(): boolean;
|
|
63
|
+
export function AddUser(): boolean;
|
|
64
|
+
export function CompleteUser(): boolean;
|
|
65
|
+
export function CreateConfig(): boolean;
|
|
51
66
|
}
|
package/targets.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"tid": "7f4567b8-f9a9-4ad3-9cb5-ef16a80e5744",
|
|
4
|
+
"name": "Mindline1",
|
|
5
|
+
"domain": "mindline1.onmicrosoft.com",
|
|
6
|
+
"type": "1",
|
|
7
|
+
"authority": "https://login.microsoftonline.com/common/",
|
|
8
|
+
"readServicePrincipal": "TODO",
|
|
9
|
+
"writeServicePrincipal": "TODO"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"tid": "df9c2e0a-f6fe-43bb-a155-d51f66dffe0e",
|
|
13
|
+
"name": "Mindline2",
|
|
14
|
+
"domain": "mindline2.onmicrosoft.com",
|
|
15
|
+
"type": "1",
|
|
16
|
+
"authority": "https://login.microsoftonline.com/common/",
|
|
17
|
+
"readServicePrincipal": "TODO",
|
|
18
|
+
"writeServicePrincipal": "TODO"
|
|
19
|
+
}
|
|
20
|
+
]
|
package/users.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"oid": "102bafe7-9e62-4993-b943-2f20c609e5c9",
|
|
4
|
+
"name": "Arvind Suthar",
|
|
5
|
+
"mail": "arvind@mindline1.onmicrosoft.com",
|
|
6
|
+
"authority": "https://login.microsoftonline.com/common/",
|
|
7
|
+
"tid": "7f4567b8-f9a9-4ad3-9cb5-ef16a80e5744",
|
|
8
|
+
"companyName": "Mindline1",
|
|
9
|
+
"companyDomain": "mindline1.onmicrosoft.com",
|
|
10
|
+
"associatedWorkspaces": [ "1" ]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"oid": "e5a42d0c-4fa5-4a65-8d9b-90f989ecae9b",
|
|
14
|
+
"name": "Arvind Suthar",
|
|
15
|
+
"mail": "arvind@mindline2.onmicrosoft.com",
|
|
16
|
+
"authority": "https://login.microsoftonline.com/common/",
|
|
17
|
+
"tid": "df9c2e0a-f6fe-43bb-a155-d51f66dffe0e",
|
|
18
|
+
"companyName": "Mindline2",
|
|
19
|
+
"companyDomain": "mindline2.onmicrosoft.com",
|
|
20
|
+
"associatedWorkspaces": [ "1" ]
|
|
21
|
+
}
|
|
22
|
+
]
|
package/workspaces.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "1",
|
|
4
|
+
"name": "Default",
|
|
5
|
+
"associatedUsers": [ "102bafe7-9e62-4993-b943-2f20c609e5c9", "e5a42d0c-4fa5-4a65-8d9b-90f989ecae9b" ],
|
|
6
|
+
"associatedTargets": [ "7f4567b8-f9a9-4ad3-9cb5-ef16a80e5744", "df9c2e0a-f6fe-43bb-a155-d51f66dffe0e" ],
|
|
7
|
+
"associatedConfigs": [ "1" ]
|
|
8
|
+
}
|
|
9
|
+
]
|