@prismicio/e2e-tests-utils 1.2.0 → 1.3.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.
@@ -5,8 +5,10 @@ import {
5
5
  SharedSlice,
6
6
  } from "@prismicio/types-internal/lib/customtypes";
7
7
 
8
+ import type { AuthenticationClient } from "../clients/authenticationApi";
8
9
  import type { CoreClient } from "../clients/coreApi";
9
10
  import { CustomTypesClient } from "../clients/customTypesApi";
11
+ import { ManageV2Client } from "../clients/manageV2";
10
12
  import { WroomClient } from "../clients/wroom";
11
13
  import { logHttpResponse, logger } from "../utils/log";
12
14
  import { getRepositoryUrl } from "../utils/urls";
@@ -16,8 +18,10 @@ export class RepositoryManager {
16
18
  constructor(
17
19
  readonly name: string,
18
20
  private readonly coreApiClient: CoreClient,
21
+ private readonly authApiClient: AuthenticationClient,
19
22
  private readonly wroomClient: WroomClient,
20
23
  private readonly customTypesApiClient: CustomTypesClient,
24
+ private readonly manageV2Client: ManageV2Client,
21
25
  ) {}
22
26
 
23
27
  async configure(config: RepositoryConfig): Promise<void> {
@@ -65,6 +69,10 @@ export class RepositoryManager {
65
69
  if (config.preview) {
66
70
  await this.createPreview(config.preview);
67
71
  }
72
+
73
+ if (config.rolePerLocal) {
74
+ await this.toggleRolePerLocal(true);
75
+ }
68
76
  }
69
77
  /** @returns the repository base url, like https://my-repo.prismic.io */
70
78
  getBaseURL(): string {
@@ -260,62 +268,6 @@ export class RepositoryManager {
260
268
  profiler.done({ message: `preview '${id}' deleted` });
261
269
  }
262
270
 
263
- /**
264
- * Create a webhook.
265
- *
266
- * @returns A Promise that resolves with the webhook id.
267
- */
268
- async createWebhook(
269
- name: string,
270
- url: string,
271
- secret: string,
272
- triggers: {
273
- documentsPublished?: boolean;
274
- documentsUnpublished?: boolean;
275
- releasesCreated?: boolean;
276
- releasesUpdated?: boolean;
277
- tagsCreated?: boolean;
278
- tagsDeleted?: boolean;
279
- },
280
- active: boolean,
281
- ): Promise<string> {
282
- const profiler = logger.startTimer();
283
-
284
- const response = await this.wroomClient.post(
285
- this.name,
286
- "app/settings/webhooks/create",
287
- {
288
- name,
289
- url,
290
- secret,
291
- active: active ? "on" : "off",
292
- ...triggers,
293
- },
294
- );
295
- this.failIfNot200(response, `Could not create webhook ${name}`);
296
- profiler.done({ message: `webhook '${name}' created` });
297
-
298
- return response.data.created;
299
- }
300
-
301
- /**
302
- * Deletes a webhook.
303
- *
304
- * @param id - The webhook ID.
305
- */
306
- async deleteWebhook(id: string): Promise<void> {
307
- const profiler = logger.startTimer();
308
-
309
- const response = await this.wroomClient.post(
310
- this.name,
311
- `app/settings/webhooks/${id}/delete`,
312
- {},
313
- );
314
-
315
- this.failIfNot200(response, `Could not delete webhook with id ${id}`);
316
- profiler.done({ message: `webhook '${id}' deleted` });
317
- }
318
-
319
271
  /**
320
272
  * Create Custom Types using the Custom types api.
321
273
  *
@@ -335,44 +287,217 @@ export class RepositoryManager {
335
287
  }
336
288
 
337
289
  /**
338
- * Create a permanent access token along with an application name
290
+ * Create an access token to query private items of the Content api.
339
291
  *
340
292
  * @param appName - mandatory authorized application name
293
+ * @param tokenScope - access token scope. Use "master" to when your content
294
+ * api is fully private or "master+releases" to access private releases
341
295
  */
342
- async createPermanentAccessToken(appName: string): Promise<string> {
296
+ async createContentAPIToken(
297
+ appName: string,
298
+ tokenScope: "master" | "master+releases" = "master",
299
+ ): Promise<string> {
343
300
  const profiler = logger.startTimer();
344
301
  type AuthorizedAppResponse = {
302
+ id: string;
345
303
  name: string;
346
- wroom_auths: { token: string }[];
304
+ wroom_auths: { token: string; scope: "master" | "master+releases" }[];
347
305
  };
348
306
  const existingApps: AxiosResponse<AuthorizedAppResponse[]> =
349
307
  await this.wroomClient.get(this.name, "settings/security/contentapi");
350
308
 
351
309
  this.failIfNot200(
352
310
  existingApps,
353
- `Could not get status of existing applications to generate a permanent token`,
311
+ `Could not get status of existing applications to generate a content api token`,
354
312
  );
355
- const existingApp = existingApps.data.find(({ name, wroom_auths }) => {
313
+ let app = existingApps.data.find(({ name, wroom_auths }) => {
356
314
  return name === appName && wroom_auths.length > 0;
357
315
  });
358
- if (existingApp) {
359
- return existingApp.wroom_auths[0].token;
316
+
317
+ if (!app) {
318
+ const response: AxiosResponse<AuthorizedAppResponse> =
319
+ await this.wroomClient.post(this.name, "settings/security/oauthapp", {
320
+ app_name: appName,
321
+ });
322
+
323
+ this.failIfNot200(
324
+ response,
325
+ `Could not create content api app ${appName}`,
326
+ );
327
+ app = response.data;
328
+ }
329
+
330
+ let tokenInfo = app.wroom_auths.find(({ scope }) => scope === tokenScope);
331
+ if (!tokenInfo) {
332
+ const response = await this.wroomClient.post(
333
+ this.name,
334
+ "settings/security/authorizations",
335
+ {
336
+ app: app.id,
337
+ scope: tokenScope,
338
+ },
339
+ );
340
+ this.failIfNot200(
341
+ response,
342
+ `Could not create content api access token for app ${appName} with scope ${tokenScope}`,
343
+ );
344
+ tokenInfo = response.data;
345
+ }
346
+
347
+ profiler.done({
348
+ message: `content api access token for app '${appName}' created`,
349
+ });
350
+
351
+ if (!tokenInfo?.token) {
352
+ throw `Could not create content api access token for app ${appName} with scope ${tokenScope}`;
353
+ }
354
+
355
+ return tokenInfo.token;
356
+ }
357
+
358
+ /** Create a permanent access token to authenticate to Prismic public apis. */
359
+ async createPermanentAccessToken(): Promise<string> {
360
+ const profiler = logger.startTimer();
361
+
362
+ const token = await this.authApiClient.getMachine2MachineToken(this.name);
363
+
364
+ profiler.done({
365
+ message: `machine2machine token created`,
366
+ });
367
+
368
+ return token;
369
+ }
370
+
371
+ /**
372
+ * Toggle the Role per local feature
373
+ *
374
+ * @param enabled - The feature new status
375
+ */
376
+ async toggleRolePerLocal(enabled: boolean): Promise<void> {
377
+ const profiler = logger.startTimer();
378
+
379
+ const response = await this.manageV2Client.toggleRolePerLocal({
380
+ repository: this.name,
381
+ enabled: enabled,
382
+ });
383
+
384
+ this.failIfNot200(
385
+ response,
386
+ `Could not ${enabled ? "enable" : "disable"} Role per local for ${
387
+ this.name
388
+ }`,
389
+ );
390
+ profiler.done({
391
+ message: `Role per local ${enabled ? "enabled" : "disabled"}`,
392
+ });
393
+ }
394
+
395
+ /**
396
+ * Change the Repository Plan
397
+ *
398
+ * @param {string} newPlanId - The Id of the new Plan to apply
399
+ */
400
+ async changePlan(newPlanId: string): Promise<void> {
401
+ const profiler = logger.startTimer();
402
+
403
+ const response = await this.manageV2Client.changePlan({
404
+ repository: this.name,
405
+ newPlanId: newPlanId,
406
+ bypassManualBilling: true, // For now the library does not support Stripe features
407
+ });
408
+
409
+ this.failIfNot200(response, "Could not change the Repository Plan");
410
+ profiler.done({
411
+ message: `Repository Plan changed to ${newPlanId}`,
412
+ });
413
+ }
414
+
415
+ /**
416
+ * Add a new user to the repository
417
+ *
418
+ * @param {string} email - The email of the user
419
+ */
420
+ async addUser(email: string): Promise<void> {
421
+ const profiler = logger.startTimer();
422
+
423
+ const response = await this.manageV2Client.addUserToRepository({
424
+ repository: this.name,
425
+ email: email,
426
+ });
427
+
428
+ const { data, status } = response;
429
+ const success =
430
+ status === 200 ||
431
+ (status === 409 &&
432
+ JSON.stringify(data).includes("already a member of the repo"));
433
+ if (!success) {
434
+ logHttpResponse(response);
435
+ throw new Error(`Could not add a new user ${email} to the repository`);
360
436
  }
361
- const response: AxiosResponse<AuthorizedAppResponse> =
362
- await this.wroomClient.post(this.name, "settings/security/oauthapp", {
363
- app_name: appName,
364
- });
437
+ profiler.done({
438
+ message: `User ${email} was added to the repository`,
439
+ });
440
+ }
441
+
442
+ /**
443
+ * Remove a user from the repository
444
+ *
445
+ * @param {string} email - The email of the user
446
+ */
447
+ async removeUser(email: string): Promise<void> {
448
+ const profiler = logger.startTimer();
449
+
450
+ const response = await this.manageV2Client.removeUserFromRepository({
451
+ repository: this.name,
452
+ email: email,
453
+ });
365
454
 
366
455
  this.failIfNot200(
367
456
  response,
368
- `Could not create permanent access token for app name ${appName}`,
457
+ `Could not remove the user ${email} from the repository`,
369
458
  );
370
459
  profiler.done({
371
- message: `permanent access token for app name '${appName}' created`,
460
+ message: `User ${email} was removed from the repository`,
372
461
  });
462
+ }
373
463
 
374
- // only return the generated token since there is no need to access more
375
- return response.data.wroom_auths[0].token;
464
+ /**
465
+ * Update the role of a user in a repository
466
+ *
467
+ * @param {string} email - The email of the user
468
+ * @param {string | Record<string, string>} role - The new Role of the user,
469
+ * either a string for basic workflow or an object such as `{ "lang_id":
470
+ * "Writer" }`
471
+ *
472
+ * Example of roles are
473
+ *
474
+ * - Administrator
475
+ * - Writer
476
+ * - Contributor
477
+ * - Manager (publisher)
478
+ */
479
+ async updateUserRole(
480
+ email: string,
481
+ role: string | Record<string, string>,
482
+ ): Promise<void> {
483
+ const profiler = logger.startTimer();
484
+
485
+ const response =
486
+ typeof role === "string"
487
+ ? await this.wroomClient.updateRole(this.name, email, role)
488
+ : await this.wroomClient.updateRolePerLocal(this.name, email, role);
489
+
490
+ this.failIfNot200(
491
+ response,
492
+ `Could not update the ${
493
+ typeof role === "string" ? "role" : "rolePerLocal"
494
+ } of the user ${email}`,
495
+ );
496
+ profiler.done({
497
+ message: `Updated User's ${
498
+ typeof role === "string" ? "role" : "rolePerLocal"
499
+ } for user ${email}`,
500
+ });
376
501
  }
377
502
  }
378
503
 
@@ -383,6 +508,7 @@ export type RepositoryConfig = {
383
508
  slices?: SharedSlice[];
384
509
  customTypes?: CustomType[];
385
510
  preview?: Preview;
511
+ rolePerLocal?: boolean;
386
512
  };
387
513
 
388
514
  export type Preview = {
package/src/types.ts CHANGED
@@ -1 +1,27 @@
1
- export type Credentials = { email: string; password: string };
1
+ export type UrlConfig = {
2
+ /** Prismic base url */
3
+ baseURL: string;
4
+ /** Custom types api base url */
5
+ customTypesApi: string;
6
+ /** Auth service api base url */
7
+ authenticationApi: string;
8
+ };
9
+
10
+ export type AuthConfig = {
11
+ email: string;
12
+ password: string;
13
+ };
14
+
15
+ export type ManageV2Config = {
16
+ secret: string;
17
+ audience: string;
18
+ };
19
+
20
+ // Global configuration Object
21
+ export type SetupConfiguration = {
22
+ // If provided as a string: It is treated as the base URL for Prismic. Other
23
+ // URLs (Custom Types API, Auth API) will be derived from it.
24
+ urlConfig: UrlConfig | string;
25
+ authConfig: AuthConfig;
26
+ manageV2Config?: ManageV2Config;
27
+ };