@boxyhq/saml-jackson 1.1.6 → 1.2.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/controller/error.d.ts +5 -0
- package/dist/controller/error.js +6 -1
- package/dist/controller/utils.d.ts +13 -0
- package/dist/controller/utils.js +27 -1
- package/dist/db/mem.js +7 -3
- package/dist/directory-sync/Base.d.ts +15 -0
- package/dist/directory-sync/Base.js +39 -0
- package/dist/directory-sync/DirectoryConfig.d.ts +43 -0
- package/dist/directory-sync/DirectoryConfig.js +186 -0
- package/dist/directory-sync/DirectoryGroups.d.ts +26 -0
- package/dist/directory-sync/DirectoryGroups.js +254 -0
- package/dist/directory-sync/DirectoryUsers.d.ts +22 -0
- package/dist/directory-sync/DirectoryUsers.js +175 -0
- package/dist/directory-sync/Groups.d.ts +47 -0
- package/dist/directory-sync/Groups.js +195 -0
- package/dist/directory-sync/Users.d.ts +47 -0
- package/dist/directory-sync/Users.js +135 -0
- package/dist/directory-sync/WebhookEventsLogger.d.ts +13 -0
- package/dist/directory-sync/WebhookEventsLogger.js +57 -0
- package/dist/directory-sync/events.d.ts +7 -0
- package/dist/directory-sync/events.js +53 -0
- package/dist/directory-sync/index.d.ts +6 -0
- package/dist/directory-sync/index.js +42 -0
- package/dist/directory-sync/request.d.ts +7 -0
- package/dist/directory-sync/request.js +30 -0
- package/dist/directory-sync/transform.d.ts +7 -0
- package/dist/directory-sync/transform.js +26 -0
- package/dist/directory-sync/utils.d.ts +39 -0
- package/dist/directory-sync/utils.js +140 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -3
- package/dist/typings.d.ts +275 -7
- package/dist/typings.js +9 -0
- package/package.json +3 -1
@@ -1,5 +1,10 @@
|
|
1
|
+
import { ApiError } from '../typings';
|
1
2
|
export declare class JacksonError extends Error {
|
2
3
|
name: string;
|
3
4
|
statusCode: number;
|
4
5
|
constructor(message: string, statusCode?: number);
|
5
6
|
}
|
7
|
+
export declare const apiError: (err: any) => {
|
8
|
+
data: null;
|
9
|
+
error: ApiError;
|
10
|
+
};
|
package/dist/controller/error.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.JacksonError = void 0;
|
3
|
+
exports.apiError = exports.JacksonError = void 0;
|
4
4
|
class JacksonError extends Error {
|
5
5
|
constructor(message, statusCode = 500) {
|
6
6
|
super(message);
|
@@ -10,3 +10,8 @@ class JacksonError extends Error {
|
|
10
10
|
}
|
11
11
|
}
|
12
12
|
exports.JacksonError = JacksonError;
|
13
|
+
const apiError = (err) => {
|
14
|
+
const { message, statusCode = 500 } = err;
|
15
|
+
return { data: null, error: { message, code: statusCode } };
|
16
|
+
};
|
17
|
+
exports.apiError = apiError;
|
@@ -4,10 +4,23 @@ export declare enum IndexNames {
|
|
4
4
|
EntityID = "entityID",
|
5
5
|
TenantProduct = "tenantProduct"
|
6
6
|
}
|
7
|
+
export declare const storeNamespacePrefix: {
|
8
|
+
dsync: {
|
9
|
+
config: string;
|
10
|
+
logs: string;
|
11
|
+
users: string;
|
12
|
+
groups: string;
|
13
|
+
members: string;
|
14
|
+
};
|
15
|
+
saml: {
|
16
|
+
config: string;
|
17
|
+
};
|
18
|
+
};
|
7
19
|
export declare const relayStatePrefix = "boxyhq_jackson_";
|
8
20
|
export declare const validateAbsoluteUrl: (url: any, message: any) => void;
|
9
21
|
export declare const OAuthErrorResponse: ({ error, error_description, redirect_uri, state, }: OAuthErrorHandlerParams) => string;
|
10
22
|
export declare function getErrorMessage(error: unknown): string;
|
23
|
+
export declare const createRandomSecret: (length: number) => Promise<string>;
|
11
24
|
export declare function loadJWSPrivateKey(key: string, alg: string): Promise<jose.KeyLike>;
|
12
25
|
export declare function isJWSKeyPairLoaded(jwsKeyPair: {
|
13
26
|
private: string;
|
package/dist/controller/utils.js
CHANGED
@@ -31,16 +31,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
31
31
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
32
32
|
});
|
33
33
|
};
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
36
|
+
};
|
34
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
35
|
-
exports.generateJwkThumbprint = exports.exportPublicKeyJWK = exports.importJWTPublicKey = exports.isJWSKeyPairLoaded = exports.loadJWSPrivateKey = exports.getErrorMessage = exports.OAuthErrorResponse = exports.validateAbsoluteUrl = exports.relayStatePrefix = exports.IndexNames = void 0;
|
38
|
+
exports.generateJwkThumbprint = exports.exportPublicKeyJWK = exports.importJWTPublicKey = exports.isJWSKeyPairLoaded = exports.loadJWSPrivateKey = exports.createRandomSecret = exports.getErrorMessage = exports.OAuthErrorResponse = exports.validateAbsoluteUrl = exports.relayStatePrefix = exports.storeNamespacePrefix = exports.IndexNames = void 0;
|
36
39
|
const error_1 = require("./error");
|
37
40
|
const redirect = __importStar(require("./oauth/redirect"));
|
41
|
+
const crypto_1 = __importDefault(require("crypto"));
|
38
42
|
const jose = __importStar(require("jose"));
|
39
43
|
var IndexNames;
|
40
44
|
(function (IndexNames) {
|
41
45
|
IndexNames["EntityID"] = "entityID";
|
42
46
|
IndexNames["TenantProduct"] = "tenantProduct";
|
43
47
|
})(IndexNames = exports.IndexNames || (exports.IndexNames = {}));
|
48
|
+
// The namespace prefix for the database store
|
49
|
+
exports.storeNamespacePrefix = {
|
50
|
+
dsync: {
|
51
|
+
config: 'dsync:config',
|
52
|
+
logs: 'dsync:logs',
|
53
|
+
users: 'dsync:users',
|
54
|
+
groups: 'dsync:groups',
|
55
|
+
members: 'dsync:members',
|
56
|
+
},
|
57
|
+
saml: {
|
58
|
+
config: 'saml:config',
|
59
|
+
},
|
60
|
+
};
|
44
61
|
exports.relayStatePrefix = 'boxyhq_jackson_';
|
45
62
|
const validateAbsoluteUrl = (url, message) => {
|
46
63
|
try {
|
@@ -63,6 +80,15 @@ function getErrorMessage(error) {
|
|
63
80
|
return String(error);
|
64
81
|
}
|
65
82
|
exports.getErrorMessage = getErrorMessage;
|
83
|
+
const createRandomSecret = (length) => __awaiter(void 0, void 0, void 0, function* () {
|
84
|
+
return crypto_1.default
|
85
|
+
.randomBytes(length)
|
86
|
+
.toString('base64')
|
87
|
+
.replace(/\+/g, '-')
|
88
|
+
.replace(/\//g, '_')
|
89
|
+
.replace(/=/g, '');
|
90
|
+
});
|
91
|
+
exports.createRandomSecret = createRandomSecret;
|
66
92
|
function loadJWSPrivateKey(key, alg) {
|
67
93
|
return __awaiter(this, void 0, void 0, function* () {
|
68
94
|
const pkcs8 = Buffer.from(key, 'base64').toString('ascii');
|
package/dist/db/mem.js
CHANGED
@@ -73,13 +73,17 @@ class Mem {
|
|
73
73
|
getAll(namespace, pageOffset, pageLimit) {
|
74
74
|
return __awaiter(this, void 0, void 0, function* () {
|
75
75
|
const offsetAndLimitValueCheck = !dbutils.isNumeric(pageOffset) && !dbutils.isNumeric(pageLimit);
|
76
|
-
|
76
|
+
const returnValue = [];
|
77
77
|
const skip = Number(offsetAndLimitValueCheck ? 0 : pageOffset);
|
78
|
+
let take = Number(offsetAndLimitValueCheck ? this.options.pageLimit : pageLimit);
|
78
79
|
let count = 0;
|
79
80
|
take += skip;
|
80
|
-
const returnValue = [];
|
81
81
|
if (namespace) {
|
82
|
-
const
|
82
|
+
const index = dbutils.keyFromParts(dbutils.createdAtPrefix, namespace);
|
83
|
+
if (this.indexes[index] === undefined) {
|
84
|
+
return [];
|
85
|
+
}
|
86
|
+
const val = Array.from(this.indexes[index]);
|
83
87
|
const iterator = val.reverse().values();
|
84
88
|
for (const value of iterator) {
|
85
89
|
if (count >= take) {
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import type { Storable, DatabaseStore } from '../typings';
|
2
|
+
export declare class Base {
|
3
|
+
protected db: DatabaseStore;
|
4
|
+
protected tenant: null | string;
|
5
|
+
protected product: null | string;
|
6
|
+
constructor({ db }: {
|
7
|
+
db: DatabaseStore;
|
8
|
+
});
|
9
|
+
store(type: 'groups' | 'members' | 'users' | 'logs'): Storable;
|
10
|
+
setTenant(tenant: string): this;
|
11
|
+
setProduct(product: string): this;
|
12
|
+
setTenantAndProduct(tenant: string, product: string): this;
|
13
|
+
with(tenant: string, product: string): this;
|
14
|
+
createId(): string;
|
15
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.Base = void 0;
|
4
|
+
const utils_1 = require("../controller/utils");
|
5
|
+
const uuid_1 = require("uuid");
|
6
|
+
class Base {
|
7
|
+
constructor({ db }) {
|
8
|
+
this.tenant = null;
|
9
|
+
this.product = null;
|
10
|
+
this.db = db;
|
11
|
+
}
|
12
|
+
// Return the database store
|
13
|
+
store(type) {
|
14
|
+
if (!this.tenant || !this.product) {
|
15
|
+
throw new Error('Set tenant and product before using store.');
|
16
|
+
}
|
17
|
+
return this.db.store(`${utils_1.storeNamespacePrefix.dsync[type]}:${this.tenant}:${this.product}`);
|
18
|
+
}
|
19
|
+
setTenant(tenant) {
|
20
|
+
this.tenant = tenant;
|
21
|
+
return this;
|
22
|
+
}
|
23
|
+
setProduct(product) {
|
24
|
+
this.product = product;
|
25
|
+
return this;
|
26
|
+
}
|
27
|
+
// Set the tenant and product
|
28
|
+
setTenantAndProduct(tenant, product) {
|
29
|
+
return this.setTenant(tenant).setProduct(product);
|
30
|
+
}
|
31
|
+
// Set the tenant and product
|
32
|
+
with(tenant, product) {
|
33
|
+
return this.setTenant(tenant).setProduct(product);
|
34
|
+
}
|
35
|
+
createId() {
|
36
|
+
return (0, uuid_1.v4)();
|
37
|
+
}
|
38
|
+
}
|
39
|
+
exports.Base = Base;
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import type { Directory, JacksonOption, DatabaseStore, DirectoryType, ApiError } from '../typings';
|
2
|
+
export declare class DirectoryConfig {
|
3
|
+
private _store;
|
4
|
+
private opts;
|
5
|
+
private db;
|
6
|
+
constructor({ db, opts }: {
|
7
|
+
db: DatabaseStore;
|
8
|
+
opts: JacksonOption;
|
9
|
+
});
|
10
|
+
private store;
|
11
|
+
create({ name, tenant, product, webhook_url, webhook_secret, type, }: {
|
12
|
+
name?: string;
|
13
|
+
tenant: string;
|
14
|
+
product: string;
|
15
|
+
webhook_url?: string;
|
16
|
+
webhook_secret?: string;
|
17
|
+
type?: DirectoryType;
|
18
|
+
}): Promise<{
|
19
|
+
data: Directory | null;
|
20
|
+
error: ApiError | null;
|
21
|
+
}>;
|
22
|
+
get(id: string): Promise<{
|
23
|
+
data: Directory | null;
|
24
|
+
error: ApiError | null;
|
25
|
+
}>;
|
26
|
+
update(id: string, param: Omit<Partial<Directory>, 'id' | 'tenant' | 'prodct' | 'scim'>): Promise<{
|
27
|
+
data: Directory | null;
|
28
|
+
error: ApiError | null;
|
29
|
+
}>;
|
30
|
+
getByTenantAndProduct(tenant: string, product: string): Promise<{
|
31
|
+
data: Directory | null;
|
32
|
+
error: ApiError | null;
|
33
|
+
}>;
|
34
|
+
list({ pageOffset, pageLimit, }: {
|
35
|
+
pageOffset: number;
|
36
|
+
pageLimit: number;
|
37
|
+
}): Promise<{
|
38
|
+
data: Directory[] | null;
|
39
|
+
error: ApiError | null;
|
40
|
+
}>;
|
41
|
+
delete(id: string): Promise<void>;
|
42
|
+
private transform;
|
43
|
+
}
|
@@ -0,0 +1,186 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
+
if (mod && mod.__esModule) return mod;
|
20
|
+
var result = {};
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
+
__setModuleDefault(result, mod);
|
23
|
+
return result;
|
24
|
+
};
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
32
|
+
});
|
33
|
+
};
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
35
|
+
exports.DirectoryConfig = void 0;
|
36
|
+
const dbutils = __importStar(require("../db/utils"));
|
37
|
+
const utils_1 = require("../controller/utils");
|
38
|
+
const error_1 = require("../controller/error");
|
39
|
+
const utils_2 = require("../controller/utils");
|
40
|
+
class DirectoryConfig {
|
41
|
+
constructor({ db, opts }) {
|
42
|
+
this._store = null;
|
43
|
+
this.opts = opts;
|
44
|
+
this.db = db;
|
45
|
+
}
|
46
|
+
// Return the database store
|
47
|
+
store() {
|
48
|
+
return this._store || (this._store = this.db.store(utils_2.storeNamespacePrefix.dsync.config));
|
49
|
+
}
|
50
|
+
// Create the configuration
|
51
|
+
create({ name, tenant, product, webhook_url, webhook_secret, type = 'generic-scim-v2', }) {
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
53
|
+
try {
|
54
|
+
if (!tenant || !product) {
|
55
|
+
throw new error_1.JacksonError('Missing required parameters.', 400);
|
56
|
+
}
|
57
|
+
if (!name) {
|
58
|
+
name = `scim-${tenant}-${product}`;
|
59
|
+
}
|
60
|
+
const id = dbutils.keyDigest(dbutils.keyFromParts(tenant, product));
|
61
|
+
const hasWebhook = webhook_url && webhook_secret;
|
62
|
+
const directory = {
|
63
|
+
id,
|
64
|
+
name,
|
65
|
+
tenant,
|
66
|
+
product,
|
67
|
+
type,
|
68
|
+
log_webhook_events: false,
|
69
|
+
scim: {
|
70
|
+
path: `${this.opts.scimPath}/${id}`,
|
71
|
+
secret: yield (0, utils_1.createRandomSecret)(16),
|
72
|
+
},
|
73
|
+
webhook: {
|
74
|
+
endpoint: hasWebhook ? webhook_url : '',
|
75
|
+
secret: hasWebhook ? webhook_secret : '',
|
76
|
+
},
|
77
|
+
};
|
78
|
+
yield this.store().put(id, directory);
|
79
|
+
return { data: this.transform(directory), error: null };
|
80
|
+
}
|
81
|
+
catch (err) {
|
82
|
+
return (0, error_1.apiError)(err);
|
83
|
+
}
|
84
|
+
});
|
85
|
+
}
|
86
|
+
// Get the configuration by id
|
87
|
+
get(id) {
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
89
|
+
try {
|
90
|
+
if (!id) {
|
91
|
+
throw new error_1.JacksonError('Missing required parameters.', 400);
|
92
|
+
}
|
93
|
+
const directory = yield this.store().get(id);
|
94
|
+
if (!directory) {
|
95
|
+
throw new error_1.JacksonError('Directory configuration not found.', 404);
|
96
|
+
}
|
97
|
+
return { data: this.transform(directory), error: null };
|
98
|
+
}
|
99
|
+
catch (err) {
|
100
|
+
return (0, error_1.apiError)(err);
|
101
|
+
}
|
102
|
+
});
|
103
|
+
}
|
104
|
+
// Update the configuration. Partial updates are supported
|
105
|
+
update(id, param) {
|
106
|
+
return __awaiter(this, void 0, void 0, function* () {
|
107
|
+
try {
|
108
|
+
if (!id) {
|
109
|
+
throw new error_1.JacksonError('Missing required parameters.', 400);
|
110
|
+
}
|
111
|
+
const { name, log_webhook_events, webhook, type } = param;
|
112
|
+
const directory = yield this.store().get(id);
|
113
|
+
if (name) {
|
114
|
+
directory.name = name;
|
115
|
+
}
|
116
|
+
if (log_webhook_events !== undefined) {
|
117
|
+
directory.log_webhook_events = log_webhook_events;
|
118
|
+
}
|
119
|
+
if (webhook) {
|
120
|
+
directory.webhook = webhook;
|
121
|
+
}
|
122
|
+
if (type) {
|
123
|
+
directory.type = type;
|
124
|
+
}
|
125
|
+
yield this.store().put(id, Object.assign({}, directory));
|
126
|
+
return { data: this.transform(directory), error: null };
|
127
|
+
}
|
128
|
+
catch (err) {
|
129
|
+
return (0, error_1.apiError)(err);
|
130
|
+
}
|
131
|
+
});
|
132
|
+
}
|
133
|
+
// Get the configuration by tenant and product
|
134
|
+
getByTenantAndProduct(tenant, product) {
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
136
|
+
try {
|
137
|
+
if (!tenant || !product) {
|
138
|
+
throw new error_1.JacksonError('Missing required parameters.', 400);
|
139
|
+
}
|
140
|
+
return yield this.get(dbutils.keyDigest(dbutils.keyFromParts(tenant, product)));
|
141
|
+
}
|
142
|
+
catch (err) {
|
143
|
+
return (0, error_1.apiError)(err);
|
144
|
+
}
|
145
|
+
});
|
146
|
+
}
|
147
|
+
// Get all configurations
|
148
|
+
list({ pageOffset, pageLimit, }) {
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
150
|
+
try {
|
151
|
+
const directories = (yield this.store().getAll(pageOffset, pageLimit));
|
152
|
+
const transformedDirectories = directories
|
153
|
+
? directories.map((directory) => this.transform(directory))
|
154
|
+
: [];
|
155
|
+
return {
|
156
|
+
data: transformedDirectories,
|
157
|
+
error: null,
|
158
|
+
};
|
159
|
+
}
|
160
|
+
catch (err) {
|
161
|
+
return (0, error_1.apiError)(err);
|
162
|
+
}
|
163
|
+
});
|
164
|
+
}
|
165
|
+
// Delete a configuration by id
|
166
|
+
// Note: This feature is not yet implemented
|
167
|
+
delete(id) {
|
168
|
+
return __awaiter(this, void 0, void 0, function* () {
|
169
|
+
if (!id) {
|
170
|
+
throw new error_1.JacksonError('Missing required parameter.', 400);
|
171
|
+
}
|
172
|
+
// TODO: Delete the users and groups associated with the configuration
|
173
|
+
yield this.store().delete(id);
|
174
|
+
return;
|
175
|
+
});
|
176
|
+
}
|
177
|
+
transform(directory) {
|
178
|
+
// Add the flag to ensure SCIM compliance when using Azure AD
|
179
|
+
if (directory.type === 'azure-scim-v2') {
|
180
|
+
directory.scim.path = `${directory.scim.path}/?aadOptscim062020`;
|
181
|
+
}
|
182
|
+
directory.scim.endpoint = `${this.opts.externalUrl}${directory.scim.path}`;
|
183
|
+
return directory;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
exports.DirectoryConfig = DirectoryConfig;
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import type { Group, DirectoryConfig, DirectorySyncResponse, Directory, DirectorySyncGroupMember, DirectorySyncRequest, Users, Groups, IDirectoryGroups, EventCallback } from '../typings';
|
2
|
+
export declare class DirectoryGroups implements IDirectoryGroups {
|
3
|
+
private directories;
|
4
|
+
private users;
|
5
|
+
private groups;
|
6
|
+
private callback;
|
7
|
+
constructor({ directories, users, groups, }: {
|
8
|
+
directories: DirectoryConfig;
|
9
|
+
users: Users;
|
10
|
+
groups: Groups;
|
11
|
+
});
|
12
|
+
create(directory: Directory, body: any): Promise<DirectorySyncResponse>;
|
13
|
+
get(group: Group): Promise<DirectorySyncResponse>;
|
14
|
+
delete(directory: Directory, group: Group): Promise<DirectorySyncResponse>;
|
15
|
+
getAll(queryParams: {
|
16
|
+
filter?: string;
|
17
|
+
}): Promise<DirectorySyncResponse>;
|
18
|
+
updateDisplayName(directory: Directory, group: Group, body: any): Promise<Group>;
|
19
|
+
patch(directory: Directory, group: Group, body: any): Promise<DirectorySyncResponse>;
|
20
|
+
update(directory: Directory, group: Group, body: any): Promise<DirectorySyncResponse>;
|
21
|
+
addGroupMembers(directory: Directory, group: Group, members: DirectorySyncGroupMember[] | undefined, sendWebhookEvent?: boolean): Promise<void>;
|
22
|
+
removeGroupMembers(directory: Directory, group: Group, members: DirectorySyncGroupMember[], sendWebhookEvent?: boolean): Promise<void>;
|
23
|
+
addOrRemoveGroupMembers(directory: Directory, group: Group, members: DirectorySyncGroupMember[]): Promise<void>;
|
24
|
+
private respondWithError;
|
25
|
+
handleRequest(request: DirectorySyncRequest, callback?: EventCallback): Promise<DirectorySyncResponse>;
|
26
|
+
}
|