sso.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { expect, type Page, Test } from '@playwright/test';
  2. import { type MailBuffer, MailServer } from 'maildev';
  3. import * as OTPAuth from "otpauth";
  4. import * as utils from '../../global-utils';
  5. import { retrieveEmailCode } from './2fa';
  6. /**
  7. * If a MailBuffer is passed it will be used and consume the expected emails
  8. */
  9. export async function logNewUser(
  10. test: Test,
  11. page: Page,
  12. user: { email: string, name: string, password: string },
  13. options: { mailBuffer?: MailBuffer, override?: boolean } = {}
  14. ) {
  15. await test.step(`Create user ${user.name}`, async () => {
  16. await page.context().clearCookies();
  17. await test.step('Landing page', async () => {
  18. await utils.cleanLanding(page);
  19. if( options.override ) {
  20. await page.getByRole('button', { name: 'Continue' }).click();
  21. } else {
  22. await page.getByLabel(/Email address/).fill(user.email);
  23. await page.getByRole('button', { name: /Use single sign-on/ }).click();
  24. }
  25. });
  26. await test.step('Keycloak login', async () => {
  27. await expect(page.getByRole('heading', { name: 'Sign in to your account' })).toBeVisible();
  28. await page.getByLabel(/Username/).fill(user.name);
  29. await page.getByLabel('Password', { exact: true }).fill(user.password);
  30. await page.getByRole('button', { name: 'Sign In' }).click();
  31. });
  32. await test.step('Create Vault account', async () => {
  33. await expect(page.getByRole('heading', { name: 'Join organisation' })).toBeVisible();
  34. await page.getByLabel('New master password (required)', { exact: true }).fill(user.password);
  35. await page.getByLabel('Confirm new master password (').fill(user.password);
  36. await page.getByRole('button', { name: 'Create account' }).click();
  37. });
  38. await test.step('Default vault page', async () => {
  39. await expect(page).toHaveTitle(/Vaultwarden Web/);
  40. await expect(page.getByTitle('All vaults', { exact: true })).toBeVisible();
  41. });
  42. await utils.checkNotification(page, 'Account successfully created!');
  43. await utils.checkNotification(page, 'Invitation accepted');
  44. if( options.mailBuffer ){
  45. let mailBuffer = options.mailBuffer;
  46. await test.step('Check emails', async () => {
  47. await mailBuffer.expect((m) => m.subject === "Welcome");
  48. await mailBuffer.expect((m) => m.subject.includes("New Device Logged"));
  49. });
  50. }
  51. });
  52. }
  53. /**
  54. * If a MailBuffer is passed it will be used and consume the expected emails
  55. */
  56. export async function logUser(
  57. test: Test,
  58. page: Page,
  59. user: { email: string, password: string },
  60. options: {
  61. mailBuffer ?: MailBuffer,
  62. override?: boolean,
  63. totp?: OTPAuth.TOTP,
  64. mail2fa?: boolean,
  65. } = {}
  66. ) {
  67. let mailBuffer = options.mailBuffer;
  68. await test.step(`Log user ${user.email}`, async () => {
  69. await page.context().clearCookies();
  70. await test.step('Landing page', async () => {
  71. await utils.cleanLanding(page);
  72. if( options.override ) {
  73. await page.getByRole('button', { name: 'Continue' }).click();
  74. } else {
  75. await page.getByLabel(/Email address/).fill(user.email);
  76. await page.getByRole('button', { name: /Use single sign-on/ }).click();
  77. }
  78. });
  79. await test.step('Keycloak login', async () => {
  80. await expect(page.getByRole('heading', { name: 'Sign in to your account' })).toBeVisible();
  81. await page.getByLabel(/Username/).fill(user.name);
  82. await page.getByLabel('Password', { exact: true }).fill(user.password);
  83. await page.getByRole('button', { name: 'Sign In' }).click();
  84. });
  85. if( options.totp || options.mail2fa ){
  86. let code;
  87. await test.step('2FA check', async () => {
  88. await expect(page.getByRole('heading', { name: 'Verify your Identity' })).toBeVisible();
  89. if( options.totp ) {
  90. const totp = options.totp;
  91. let timestamp = Date.now(); // Needed to use the next token
  92. timestamp = timestamp + (totp.period - (Math.floor(timestamp / 1000) % totp.period) + 1) * 1000;
  93. code = totp.generate({timestamp});
  94. } else if( options.mail2fa ){
  95. code = await retrieveEmailCode(test, page, mailBuffer);
  96. }
  97. await page.getByLabel(/Verification code/).fill(code);
  98. await page.getByRole('button', { name: 'Continue' }).click();
  99. });
  100. }
  101. await test.step('Unlock vault', async () => {
  102. await expect(page).toHaveTitle('Vaultwarden Web');
  103. await expect(page.getByRole('heading', { name: 'Your vault is locked' })).toBeVisible();
  104. await page.getByLabel('Master password').fill(user.password);
  105. await page.getByRole('button', { name: 'Unlock' }).click();
  106. });
  107. await test.step('Default vault page', async () => {
  108. await expect(page).toHaveTitle(/Vaultwarden Web/);
  109. await expect(page.getByTitle('All vaults', { exact: true })).toBeVisible();
  110. });
  111. if( mailBuffer ){
  112. await test.step('Check email', async () => {
  113. await mailBuffer.expect((m) => m.subject.includes("New Device Logged"));
  114. });
  115. }
  116. });
  117. }