snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
import { request } from '@playwright/test';
import { Users } from './userStates';
import { BASE_API_URL } from '../config/constants';
export default async function addCustomOAuth(): Promise<void> {
const api = await request.newContext();
const headers = {
'X-Auth-Token': Users.admin.data.loginToken,
'X-User-Id': Users.admin.data._id,
};
await api.post(`${BASE_API_URL}/settings.addCustomOAuth`, { data: { name: 'Test' }, headers });
await api.post(`${BASE_API_URL}/settings/Accounts_OAuth_Custom-Test`, { data: { value: false }, headers });
await api.post(`${BASE_API_URL}/settings/Accounts_OAuth_Custom-Test-url`, { data: { value: 'https://rocket.chat' }, headers });
await api.post(`${BASE_API_URL}/settings/Accounts_OAuth_Custom-Test-login_style`, { data: { value: 'redirect' }, headers });
await api.post(`${BASE_API_URL}/settings/Accounts_OAuth_Custom-Test-id`, { data: { value: 'abc' }, headers });
await api.post(`${BASE_API_URL}/settings/Accounts_OAuth_Custom-Test-secret`, { data: { value: 'def' }, headers });
await api.post(`${BASE_API_URL}/settings/Accounts_OAuth_Custom-Test-authorize_path`, { data: { value: '/authorize' }, headers });
}

View File

@@ -0,0 +1,53 @@
import { faker } from '@faker-js/faker';
import type { IUser } from '@rocket.chat/core-typings';
import { DEFAULT_USER_CREDENTIALS } from '../../config/constants';
import type { IUserState } from '../userStates';
type UserFixture = IUser & {
username: string;
__rooms: string[];
};
export function createUserFixture(user: IUserState): UserFixture {
const { username, hashedToken, loginExpire, e2e } = user.data;
return {
_id: `${username}`,
type: 'user',
active: true,
emails: [{ address: `${username}@email.com`, verified: true }],
roles: ['user'],
name: username,
lastLogin: new Date(),
statusConnection: 'offline',
utcOffset: -3,
username,
services: {
password: { bcrypt: DEFAULT_USER_CREDENTIALS.bcrypt },
email2fa: { enabled: true, changedAt: new Date() },
email: {
verificationTokens: [
{
token: faker.string.uuid(),
address: `${username}@email.com`,
when: new Date(),
},
],
},
resume: {
loginTokens: [
{
when: loginExpire,
hashedToken,
},
],
},
emailCode: { code: '', attempts: 0, expire: new Date() },
},
createdAt: new Date(),
_updatedAt: new Date(),
__rooms: ['GENERAL'],
e2e,
};
}

View File

@@ -0,0 +1,19 @@
import type { Browser, Page } from '@playwright/test';
import type { IUserState } from './userStates';
export const createAuxContext = async (
browser: Browser,
userState: IUserState,
route = '/',
waitForMainContent = true,
): Promise<{ page: Page }> => {
const page = await browser.newPage({ storageState: userState.state });
await page.goto(route);
if (waitForMainContent) {
await page.locator('#main-content').waitFor();
}
return { page };
};

View File

@@ -0,0 +1 @@
another_file

View File

@@ -0,0 +1 @@
any_file

Binary file not shown.

View File

@@ -0,0 +1,4 @@
"imported-csv-group","billy.bob","private",""
"imported-csv-channel","billy.bob","public",""
"imported-csv-with-members-group","billy.bob","private","billy.bob;billy.joe"
"imported-csv-with-members-channel","billy.bob","public","billy.bob;billy.joe"
1 imported-csv-group billy.bob private
2 imported-csv-channel billy.bob public
3 imported-csv-with-members-group billy.bob private billy.bob;billy.joe
4 imported-csv-with-members-channel billy.bob public billy.bob;billy.joe

View File

@@ -0,0 +1,3 @@
billy.bob, billy.bob@example.com, Billy Bob Jr.
billy.joe, billy.joe@example.com, Billy Joe Jr.
billy.billy, billy.billy@example.com, Billy Billy Jr.
1 billy.bob billy.bob@example.com Billy Bob Jr.
2 billy.joe billy.joe@example.com Billy Joe Jr.
3 billy.billy billy.billy@example.com Billy Billy Jr.

View File

@@ -0,0 +1,13 @@
<mxfile host="app.diagrams.net" modified="2024-05-21T16:10:09.295Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36" etag="ZxZRCTHi-kxhlzk7b9_Z" version="24.4.4" type="device">
<diagram name="Página-1" id="9eBILa8281JaQ4yUkDbp">
<mxGraphModel dx="1434" dy="786" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="dopCU4gkJe7Sfp6IDYO1-1" value="&lt;b&gt;&lt;font style=&quot;font-size: 30px;&quot;&gt;Rocket.Chat&lt;/font&gt;&lt;/b&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="314" y="350" width="200" height="50" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@@ -0,0 +1,2 @@
"billy.joe","billy.bob","1479162481336","this is a test message"
"billy.bob","billy.joe","1479162481654","this is another message, a test message"
1 billy.joe billy.bob 1479162481336 this is a test message
2 billy.bob billy.joe 1479162481654 this is another message, a test message

View File

@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Iframe Login</title>
</head>
<script>
function login() {
console.log('logging in');
window.parent.postMessage({
event: 'login-with-token',
loginToken: 'REPLACE_WITH_TOKEN',
}, '*');
}
window.addEventListener('message', (event) => {
if(event.data.event === 'login-error') {
document.getElementById('login-error').innerText = "Login failed";
}
});
</script>
<body>
<h1>Iframe Authentication Login Form</h1>
<form id="login-form">
<label for="username">Username:</label><br/>
<input type="text" id="username" name="username" placeholder="Enter username" /><br/><br/>
<label for="password">Password:</label><br/>
<input type="password" id="password" name="password" placeholder="Enter password" /><br/><br/>
<button id="submit" type="button"
onclick="login()">Login</button>
</form>
<div id="login-error"></div>
</body>
</html>

View File

@@ -0,0 +1,6 @@
# Comment
# Name Age
Tom 23
Marcus 22
Bryan 21

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

View File

@@ -0,0 +1,4 @@
username,email,status,billing-active,has-2fa,has-sso,userid,fullname,displayname,expiration-timestamp
user4.test,user4@email.com.br,Primary Owner,0,0,0,U03TVFGMHUY,user4.test,,
user5.test,user5@email.com.br,Primary Owner,0,0,0,U0G9QF9C6,user5.test,,
user6.test,user6@email.com.br,Primary Owner,0,0,0,U03TVFGMH,user6.test,,
1 username email status billing-active has-2fa has-sso userid fullname displayname expiration-timestamp
2 user4.test user4@email.com.br Primary Owner 0 0 0 U03TVFGMHUY user4.test
3 user5.test user5@email.com.br Primary Owner 0 0 0 U0G9QF9C6 user5.test
4 user6.test user6@email.com.br Primary Owner 0 0 0 U03TVFGMH user6.test

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

View File

@@ -0,0 +1,84 @@
import type { ISetting, IUser } from '@rocket.chat/core-typings';
import { MongoClient } from 'mongodb';
import * as constants from '../config/constants';
import { createUserFixture } from './collections/users';
import { Users } from './userStates';
export default async function injectInitialData() {
const connection = await MongoClient.connect(constants.URL_MONGODB);
const usersFixtures = [
createUserFixture(Users.user1),
createUserFixture(Users.user2),
createUserFixture(Users.user3),
createUserFixture(Users.userE2EE),
createUserFixture(Users.userNotAllowedByApp),
];
await Promise.all(
usersFixtures.map((user) =>
connection.db().collection('users').updateOne({ username: user.username }, { $set: user }, { upsert: true }),
),
);
await connection
.db()
.collection<IUser>('users')
.updateOne(
{ username: Users.admin.data.username },
{ $addToSet: { 'services.resume.loginTokens': { when: Users.admin.data.loginExpire, hashedToken: Users.admin.data.hashedToken } } },
);
await Promise.all(
[
{
_id: 'API_Enable_Rate_Limiter_Dev',
value: false,
},
{
_id: 'Show_Setup_Wizard',
value: 'completed',
},
{
_id: 'Country',
value: 'brazil',
},
{
_id: 'Organization_Type',
value: 'community',
},
{
_id: 'Industry',
value: 'aerospaceDefense',
},
{
_id: 'Size',
value: 0,
},
{
_id: 'Organization_Name',
value: 'any_name',
},
{
_id: 'API_Enable_Rate_Limiter_Dev',
value: false,
},
{
_id: 'Accounts_OAuth_Google',
value: false,
},
{
_id: 'Livechat_Require_Contact_Verification',
value: 'never',
},
].map((setting) =>
connection
.db()
.collection<ISetting>('rocketchat_settings')
.updateOne({ _id: setting._id }, { $set: { value: setting.value } }),
),
);
return { usersFixtures };
}

View File

@@ -0,0 +1,8 @@
import type { Page, Response } from '@playwright/test';
const isMediaResponse = (response: Response) =>
/api\/v1\/rooms\.media(?:\/|\?|$)/.test(response.url()) && response.request().method() === 'POST';
export const createMediaResponsePromise = (page: Page) => {
return page.waitForResponse((response) => isMediaResponse(response));
};

View File

@@ -0,0 +1,155 @@
import crypto from 'crypto';
import type { BrowserContextOptions, Page } from '@playwright/test';
import { BASE_URL } from '../config/constants';
export type IUserState = {
data: {
_id: string;
username: string;
loginToken: string;
loginExpire: Date;
hashedToken: string;
e2e?: {
private_key: string;
public_key: string;
};
e2ePassword?: string;
};
state: Exclude<BrowserContextOptions['storageState'], string | undefined>;
};
const e2eeData: Record<string, { server: IUserState['data']['e2e']; client: { private_key: string } }> = {
userE2EE: {
server: {
private_key:
'{"$binary":"hvTpjm9S6L6sBARrdqjjzkuI8fmoIYOpEkXuLS5nW50S8WGG73deDRQXM6GcFZQCi5iJXkRICJCXyVnDcr6HE5vVbQkDyXe6qx/cHYqKKA9DajAzE8Za4VrAPH7dU+UijWy2YZhBDhfcmfkJ4iRFhLuZSoetmtLSs3MdgoAtp4NTO2LAkiAki83iRKXHLE+CMf1EYxF8S359x/mScMNIgaasYRM+HVJaayEZMOwj2hlDTawcX6hXKdyxr/0PwKdpFUtPAxwmAIaW2iSkY5L4W5U8kQKvPVQo8VmYNZkoHtTKuNFBw+TrIAprsPwZIl3/2BM4TgxCU6hrQsewoZQcYKtmu9uEUYk38bQ/DKz8B3xD3oPG8aviY+OSQIhkVJ9vb1L1xrNud9sOxurq49N91KA40ooO0YDHF0kBwj8Ue8BlLRNIlVXCiOy9hxBxo3DC6uDKFgJdAae04yFWGamafHpt8nX2dDxTi54k6vieNdQpqLLthS7WGiLEaUR5RaFQDVUBXgFGdcrIfwwKcZy7Uk/PTU/ETjf76mG2Mb3lGAdJc03YUT4yBrcWoQpusPWdJ+7I/bCFjGa0ZSj0TGQ6R+CGSPFc5FK+qrsUolKDUgOTGrtLnpuMoCtuhvwe3JfvdiEHGFiKJZhrEV7ggVm48IUC5P14DnSX8TFveqV0VyF/r9pT7/BRdTihT/t3Inq5lEISGW7fQ07LUyd+unSHJ+Ex5riE6A+Ag8t/MPOAAt6adGhkAot9jme97D/wJA/YMnLPoQNaRAHtlv7laOPuR2FCJjS3Q7L+o/BWOi4I6TJ3VIvKd5JgQBz0CVTkgFVGGgvTXer5FljK3r5YBGBJBx7GVEJ9YSFm5fYyKXG9dFpGG22UE3DNq73pAVc0xqSYnDmz8s3XDNiV0nMp31EZFoP3K4rTFdzmMe+8LQqE4TvIX39rPBLrD7YVpS3xKNoaDsdCQPnqo10+plpaxS+0768prZT9DFlfYuijOu09V8P2tny/8Oayw0FOa0Ju97ExnD7MXcwTdvREHre3Rc/W7tL+KbTQ/9y1DHH7ilHR51zcuS7pkCmRVpuXsQVPhJvg1qkxU9Z+KQqpyle76/sAHsO5Ezhp7EZZ4j2JVo54CwmlENyxD2wngxOXB+RYQcd3Uaoa8VGxSPcPE4xSm0h2E3m2xhnMtEMUmat2R+d+2kNuZHSAFNKdnX8EBeGrKBLwTduOriTmmGgELc3j0fWx4Q5JfoY87oh1OtNqO2txVC6CbzvO+KDkB7h/2iRNZMmY//KIP0mHlSkpMkWqWVp+/wUgVlH+GoSVabWGaaKgZjYXqT8Xpb3fFJ2VOp9FfX7MexHaCnQf1lL6PfoNHawJLp8m9YtVo1EOXsi/TIkZvEbJf7BwUf9nRku9GX9CVkY50KFcP9ZwhBZWUpH3V4WKrLwr/RRdWnOkWCzK2Em6P/N5ei+Cc4bNax1Oms/9AMTFmBjfFHjoAVH+NbqubUgr+nL9/GXnax9fiaToJQvAAoH5Vzmi4IrZOrvE/OHKypVA/SCNOLCEwysai/w+aczFKZV6SUNmslFbApByrPA/Txvs1LiLVJgj9xL/Jn9QTLSCzFA3x/gGzFJRNLxfE1pJ0tHvQtlUn3hDQUy0blDii6tFyog87tSHHo/v/rE0Ps8Q4k/c7yAMelVEEGXomqdw2s5kh4jhR0BcFFA7KWypRB7Bzy2juR1TA1miu1aWmnl6nnhRgQ2NbpSbyOj1LlYpkyI0hekDx4t9txfwmqH/84AS9f9gmCZX8gkIMC0iXgcWyjth2X9xL3z/SWsyvb7863jdB8IWaOFHg3k12nuJGRmytvqq+0VQfqZ5guzXMzKvvE51TQwQQqYscoXmjeBvIFfF7MGel0FSc7iUHsel3rwaRi2C/0UAif4wAXJg4SyUBRvWU8hDG2Hp8X9UECXF15AgzUMJDEtShZYGoB+/xN9N7WvbXcOoFWevI+DbICqg14DR9uSN1lBNGJKgtDRlcWZEhCcXq8aSvzaFxT6vDUaAGcYbmlo7V8/XhNg7bqyHmDicuH5E1JUcjCoOfzvk8wRGpyX/mHuWsMxLiJQoLrwRmg8sU4IwgFUV7j/CBmBWpquMQg9cIoaz87hAeWyIts0HuWfnfeW1gXBUFLLeDoOk4ss+h/P2RAH1q2JIst3+KRNIDTZzVhu6QGF/JeweXkL2d9FVOGCUKDLLQ8ngKoFtPR4bZr1qnqtSJb67nRpGukpEqC4JGpGRtkWDRXKYKQ=="}',
public_key:
'{"alg":"RSA-OAEP-256","e":"AQAB","ext":true,"key_ops":["encrypt"],"kty":"RSA","n":"qVLMv2Iwm_Hyhlnh4etNlHEiCXBzJWbqMwOZ6pz_JuZY2HiqbLmSfBtpvwBKZvcmP92BqLl-qZuLV_bJD_11UBS3gR6ykgU-RsTz1L-V8vA2QZEyULP4DqkMcRCV_7WE_sn_ScePgKszx1284gnngct_1Tv37zB6Ifz7gb1THRwAqOGcE2htea4yQEhyX8ZAl_-95DTWLbXqEAuofqDpXMcQo487VezBWIaDdfw2VX0qi6kM-pt03Gx8uMniyAjhK1G8Dro3wgAtz4PNIwOsdXEvWTSyoXLVMsIuZeO9OGdJKXnZFtVEMzXLyQTD1LjXlsM_TF09fbkN41Tz12ojmQ"}',
},
client: {
private_key:
'{"alg":"RSA-OAEP-256","d":"IpABtkEzPenNwQng105CKD5NndKj1msi_CXMibzhQk37rbg3xXi9w3KPC8th5JGnb5rl6AxxI-rZrytzUD3C8AVCjes3tSG33BdA1FkFITFSSeD6_ck2pbtxDDVAARHK431VDHjdPHz11Ui3kQZHiNGCtwKGMf9Zts1eg1WjfQnQw2ta4-38mwHpq-4Cm_F1brNTTAu5XlHMws4-TDlYhY3nFU2XvoiR2RPDbMddtvXpDZIVo9s7h3jcS4JxHeJd7mWfwcR_Wf0ArRJIhckgPQtTAAjADNpw_HAdERfJyOAJUnxtHkv4uTu_k23qDpPGEi8euFpQ_1UD8B_Z1Rxylw","dp":"OS3zu_VYJZmOXl1dRXxYGP69MR4YQ3TFJ58HFIxvebD060byGHL-mwf0R6-a1hBkHfSeUI9iPipEcjQeevasPqm5CG8eYMvGU2vhsoq1gfY79rsoKjnThCO3XiUbNeM-G9MRKMRa3ooQ8fUVHyEWKFo1ajoFbVHxZuqTAOgrYT8","dq":"yXtWRU1vM5imQJhIZBt5BO1Rfn-koHTvTM3c5QDdPLyNoGTKTyeoT3P9clN6qevJKTyJJTWiwuz8ZECSksh_m9STCY1ry2HqlF2EKdCZnTQzhoJvb6d7547Witc9eh2rBjsILSxVBadLzOFe8opkkQkdkM_gN_Rr3TtXEAo1vn8","e":"AQAB","ext":true,"key_ops":["decrypt"],"kty":"RSA","n":"qVLMv2Iwm_Hyhlnh4etNlHEiCXBzJWbqMwOZ6pz_JuZY2HiqbLmSfBtpvwBKZvcmP92BqLl-qZuLV_bJD_11UBS3gR6ykgU-RsTz1L-V8vA2QZEyULP4DqkMcRCV_7WE_sn_ScePgKszx1284gnngct_1Tv37zB6Ifz7gb1THRwAqOGcE2htea4yQEhyX8ZAl_-95DTWLbXqEAuofqDpXMcQo487VezBWIaDdfw2VX0qi6kM-pt03Gx8uMniyAjhK1G8Dro3wgAtz4PNIwOsdXEvWTSyoXLVMsIuZeO9OGdJKXnZFtVEMzXLyQTD1LjXlsM_TF09fbkN41Tz12ojmQ","p":"0GJaXeKlxgcz6pX0DdwtWG38x9vN2wfLrN3F8N_0stzyPMjMpLGXOdGq1k1V6FROYvLHZsqdCpziwJ3a1PQaGUg2lO-KeBghlbDk4xfYbzSSPhVdwvUT27dysd3-_TsBvNpVCqCLb9Wgl8f0jrrRmRTSztYSLw3ckL939OJoe0M","q":"0AOMQqdGlz0Tm81uqpzCuQcQLMj-IhmPIMuuTnIU55KCmEwmlf0mkgesj-EEBsC1h6ScC5fvznGNvSGqVQAP5ANNZxGiB73q-2YgH3FpuEeHekufl260E_9tgIuqjtCv-eT_cLUhnRNyuP2ZiqRZsBWLuaQYkTubyGRi6izoofM","qi":"FXbIXivKdh0VBgMtLe5f1OjzyrSW_IfIvz8ZM66F4tUTxnNKk5vSb_q2NPyIOVYbdonuVguX-0VO54Ct16k8VdpQSMmUxGbyQAtIck2IzEzpfbRJgn06wiAI3j8q1nRFhrzhfrpJWVyuTiXBgaeOLWBz8fBpjDU7rptmcoU3tZ4"}',
},
},
};
function generateContext(username: string): IUserState {
const date = new Date();
date.setFullYear(date.getFullYear() + 1);
const token = {
token: crypto.createHash('sha256').update(username).digest('base64'),
when: date,
};
const hashedToken = crypto.createHash('sha256').update(token.token).digest('base64');
return {
data: {
_id: username,
username,
loginToken: token.token,
loginExpire: token.when,
hashedToken,
...(e2eeData[username] && {
e2e: e2eeData[username]?.server,
e2ePassword: 'minus mobile dexter forest elvis',
}),
},
state: {
cookies: [
{
sameSite: 'Lax',
name: 'rc_uid',
value: username,
domain: 'localhost',
path: '/',
expires: -1,
httpOnly: false,
secure: false,
},
{
sameSite: 'Lax',
name: 'rc_token',
value: token.token,
domain: 'localhost',
path: '/',
expires: -1,
httpOnly: false,
secure: false,
},
],
origins: [
{
origin: BASE_URL,
localStorage: [
{
name: 'userLanguage',
value: 'en-US',
},
{
name: 'Meteor.loginToken',
value: token.token,
},
{
name: 'Meteor.loginTokenExpires',
value: token.when.toISOString(),
},
{
name: 'Meteor.userId',
value: username,
},
...(e2eeData[username]
? [
{
name: 'private_key',
value: e2eeData[username]?.client.private_key,
},
]
: []),
],
},
],
},
};
}
export const Users = {
user1: generateContext('user1'),
user2: generateContext('user2'),
user3: generateContext('user3'),
userNotAllowedByApp: generateContext('userNotAllowedByApp'),
userE2EE: generateContext('userE2EE'),
samluser1: generateContext('samluser1'),
samluser2: generateContext('samluser2'),
samluser4: generateContext('samluser4'),
samluser5: generateContext('samluser5'),
samluser6: generateContext('samluser6'),
samluser7: generateContext('samluser7'),
samlusernoname: generateContext('custom_saml_username'),
samlusernoname2: generateContext('custom_saml_username2'),
userForSamlMerge: generateContext('user_for_saml_merge'),
userForSamlMerge2: generateContext('user_for_saml_merge2'),
admin: generateContext('rocketchat.internal.admin.test'),
};
export async function storeState(page: Page, user: IUserState) {
user.state.origins = (await page.context().storageState()).origins;
}
export async function restoreState(page: Page, user: IUserState, options: { except?: string[] } = {}) {
let ls = user.state.origins[0].localStorage;
if (options.except?.length) {
ls = ls.filter(({ name }) => !options.except?.includes(name));
}
await page.evaluate((items) => {
items.forEach(({ name, value }) => {
window.localStorage.setItem(name, value);
});
}, ls);
await page.waitForTimeout(2000); // Wait for the login to be completed
}