🐞 Add antivirus inside Twake Drive (#725)
🐞 Add antivirus inside Twake Drive (#725)
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
import "./load_test_config";
|
||||
import "reflect-metadata";
|
||||
import { afterAll, beforeEach, describe, expect, it, jest } from "@jest/globals";
|
||||
import { init, TestPlatform } from "../setup";
|
||||
import { deserialize } from "class-transformer";
|
||||
import UserApi from "../common/user-api";
|
||||
import { DriveItemDetailsMockClass } from "../common/entities/mock_entities";
|
||||
import { DocumentsEngine } from "../../../src/services/documents/services/engine";
|
||||
import { e2e_createDocumentFile, e2e_createVersion } from "../documents/utils";
|
||||
import { ResourceUpdateResponse } from "../../../src/utils/types";
|
||||
import { File } from "../../../src/services/files/entities/file";
|
||||
import { FileVersion } from "../../../src/services/documents/entities/file-version";
|
||||
|
||||
describe("The documents antivirus", () => {
|
||||
let platform: TestPlatform;
|
||||
const notifyDocumentAVScanAlert = jest.spyOn(
|
||||
DocumentsEngine.prototype,
|
||||
"notifyDocumentAVScanAlert",
|
||||
);
|
||||
|
||||
beforeEach(async () => {
|
||||
platform = await init({
|
||||
services: [
|
||||
"webserver",
|
||||
"database",
|
||||
"applications",
|
||||
"search",
|
||||
"storage",
|
||||
"message-queue",
|
||||
"user",
|
||||
"files",
|
||||
"auth",
|
||||
"statistics",
|
||||
"platform-services",
|
||||
"documents",
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await platform?.tearDown();
|
||||
// @ts-ignore
|
||||
platform = null;
|
||||
});
|
||||
|
||||
describe("On document create", () => {
|
||||
it("Should scan the document and detect it as safe", async () => {
|
||||
// Create an admin user
|
||||
const oneUser = await UserApi.getInstance(platform, true, { companyRole: "admin" });
|
||||
const document = await oneUser.uploadFileAndCreateDocument("../../common/assets/sample.doc");
|
||||
|
||||
expect(document).toBeDefined();
|
||||
expect(document.av_status).toBe("scanning");
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
|
||||
const documentResponse = await oneUser.getDocument(document.id);
|
||||
const deserializedDocument = deserialize<DriveItemDetailsMockClass>(
|
||||
DriveItemDetailsMockClass,
|
||||
documentResponse.body,
|
||||
);
|
||||
expect(deserializedDocument).toBeDefined();
|
||||
expect(deserializedDocument.item.av_status).toBe("safe");
|
||||
});
|
||||
|
||||
it.skip("Should scan the document and detect it as malicious", async () => {
|
||||
// Create an admin user
|
||||
const oneUser = await UserApi.getInstance(platform, true, { companyRole: "admin" });
|
||||
const document = await oneUser.uploadTestMalAndCreateDocument("test-malware.txt");
|
||||
|
||||
expect(document).toBeDefined();
|
||||
expect(document.av_status).toBe("scanning");
|
||||
});
|
||||
|
||||
it("Should skip the scan if the document is too large", async () => {
|
||||
// Create an admin user
|
||||
const oneUser = await UserApi.getInstance(platform, true, { companyRole: "admin" });
|
||||
|
||||
// 2.8 MB file > 1 MB limit
|
||||
const document = await oneUser.uploadFileAndCreateDocument("../../common/assets/sample.mp4");
|
||||
|
||||
expect(document).toBeDefined();
|
||||
expect(document.av_status).toBe("skipped");
|
||||
expect(notifyDocumentAVScanAlert).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("On version creation", () => {
|
||||
it("Should scan the document and detect it as safe.", async () => {
|
||||
// Create an admin user
|
||||
const oneUser = await UserApi.getInstance(platform, true, { companyRole: "admin" });
|
||||
|
||||
// Create a default document for the user
|
||||
const document = await oneUser.uploadFileAndCreateDocument("../../common/assets/sample.doc");
|
||||
|
||||
// Upload a file and deserialize the response
|
||||
const fileUploadResponse = await e2e_createDocumentFile(platform);
|
||||
const fileUploadResult = deserialize<ResourceUpdateResponse<File>>(
|
||||
ResourceUpdateResponse,
|
||||
fileUploadResponse.body,
|
||||
);
|
||||
console.log("🚀🚀 document:: ", document);
|
||||
console.log("🚀🚀 fileUploadResponseS:: ", fileUploadResponse.body);
|
||||
|
||||
// Prepare metadata with the uploaded file's ID
|
||||
const fileMetadata = { external_id: fileUploadResult.resource.id };
|
||||
|
||||
// Create a new version of the document with the uploaded file metadata
|
||||
const versionResponse = await e2e_createVersion(
|
||||
platform,
|
||||
document.id,
|
||||
{ filename: "file2", file_metadata: fileMetadata },
|
||||
oneUser.jwt,
|
||||
);
|
||||
const versionResult = deserialize<FileVersion>(FileVersion, versionResponse.body);
|
||||
expect(versionResult).toBeDefined();
|
||||
console.log("🚀🚀 VERSION RESULT IS:: ", versionResponse.body);
|
||||
|
||||
// Retrieve the document and verify the antivirus status
|
||||
const documentResponse = await oneUser.getDocument(versionResult.drive_item_id);
|
||||
const deserializedDocument = deserialize<DriveItemDetailsMockClass>(
|
||||
DriveItemDetailsMockClass,
|
||||
documentResponse.body,
|
||||
);
|
||||
|
||||
console.log("🚀🚀 RESP IS:: ", documentResponse.body);
|
||||
|
||||
// Ensure the document has been scanned and is no longer marked as "uploaded"
|
||||
expect(deserializedDocument.item.av_status).not.toBe("uploaded");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"drive": {
|
||||
"featureAntivirus": true
|
||||
},
|
||||
"av": {
|
||||
"host": "av",
|
||||
"port": 3310,
|
||||
"debugMode": false,
|
||||
"timeout": 2000,
|
||||
"maxFileSize": 1048576
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// @ts-ignore
|
||||
import path from "path";
|
||||
// @ts-ignore
|
||||
import config from "config";
|
||||
|
||||
// @ts-ignore
|
||||
const ourConfigDir = path.join(__dirname, 'config');
|
||||
let configs = config.util.loadFileConfigs(ourConfigDir);
|
||||
config.util.extendDeep(config, configs);
|
||||
@@ -32,6 +32,7 @@ export class DriveFileMockClass {
|
||||
creator: string;
|
||||
is_directory: boolean;
|
||||
scope: "personal" | "shared";
|
||||
av_status: string;
|
||||
created_by: Record<string, any>;
|
||||
shared_by: Record<string, any>;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import { Response } from "light-my-request";
|
||||
* in the application.
|
||||
*/
|
||||
export default class UserApi {
|
||||
|
||||
private static readonly DOC_URL = "/internal/services/documents/v1";
|
||||
|
||||
static readonly ALL_FILES = [
|
||||
@@ -38,7 +37,7 @@ export default class UserApi {
|
||||
"sample.pdf",
|
||||
"sample.doc",
|
||||
"sample.zip",
|
||||
"sample.mp4"
|
||||
"sample.mp4",
|
||||
];
|
||||
|
||||
platform: TestPlatform;
|
||||
@@ -51,9 +50,7 @@ export default class UserApi {
|
||||
api: Api;
|
||||
session: string;
|
||||
|
||||
private constructor(
|
||||
platform: TestPlatform
|
||||
) {
|
||||
private constructor(platform: TestPlatform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
@@ -66,12 +63,14 @@ export default class UserApi {
|
||||
company_id: this.workspace.company_id,
|
||||
};
|
||||
this.user = await this.dbService.createUser([workspacePK], options, uuidv1());
|
||||
this.anonymous = await this.dbService.createUser([workspacePK],
|
||||
this.anonymous = await this.dbService.createUser(
|
||||
[workspacePK],
|
||||
{
|
||||
...options,
|
||||
identity_provider: "anonymous",
|
||||
},
|
||||
uuidv1());
|
||||
uuidv1(),
|
||||
);
|
||||
} else {
|
||||
this.user = this.platform.currentUser;
|
||||
}
|
||||
@@ -128,7 +127,7 @@ export default class UserApi {
|
||||
events: {
|
||||
"http://schemas.openid.net/event/backchannel-logout": {},
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
const verifierMock = jest.spyOn(OidcJwtVerifier.prototype, "verifyLogoutToken");
|
||||
verifierMock.mockImplementation(() => {
|
||||
@@ -140,28 +139,34 @@ export default class UserApi {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static async getInstance(platform: TestPlatform, newUser = false, options?: {}): Promise<UserApi> {
|
||||
public static async getInstance(
|
||||
platform: TestPlatform,
|
||||
newUser = false,
|
||||
options?: {},
|
||||
): Promise<UserApi> {
|
||||
const helpers = new UserApi(platform);
|
||||
await helpers.init(newUser, options);
|
||||
return helpers;
|
||||
}
|
||||
|
||||
async uploadRandomFile() {
|
||||
return await this.uploadFile(UserApi.ALL_FILES[Math.floor((Math.random() * UserApi.ALL_FILES.length))]);
|
||||
return await this.uploadFile(
|
||||
UserApi.ALL_FILES[Math.floor(Math.random() * UserApi.ALL_FILES.length)],
|
||||
);
|
||||
}
|
||||
|
||||
private async injectUploadRequest(readable: Readable | string) {
|
||||
if (typeof readable === "string")
|
||||
readable = Readable.from(readable);
|
||||
private async injectUploadRequest(readable: Readable | string, filename?: string) {
|
||||
if (typeof readable === "string") readable = Readable.from(readable);
|
||||
const url = "/internal/services/files/v1";
|
||||
const form = formAutoContent({ file: readable });
|
||||
form.headers["authorization"] = `Bearer ${this.jwt}`;
|
||||
|
||||
return await this.platform.app.inject({
|
||||
method: "POST",
|
||||
url: `${url}/companies/${this.platform.workspace.company_id}/files?thumbnail_sync=0`,
|
||||
...form
|
||||
url: `${url}/companies/${this.platform.workspace.company_id}/files?thumbnail_sync=0${
|
||||
filename ? `&filename=${filename}` : ""
|
||||
}`,
|
||||
...form,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,38 +178,64 @@ export default class UserApi {
|
||||
if (filesUploadRaw.statusCode == 200) {
|
||||
const filesUpload: ResourceUpdateResponse<File> = deserialize<ResourceUpdateResponse<File>>(
|
||||
ResourceUpdateResponse,
|
||||
filesUploadRaw.body
|
||||
filesUploadRaw.body,
|
||||
);
|
||||
return filesUpload.resource;
|
||||
} else this.throwServerError(filesUploadRaw.statusCode);
|
||||
}
|
||||
|
||||
private throwServerError(code: number) {
|
||||
throw new Error("Error code: " + code)
|
||||
throw new Error("Error code: " + code);
|
||||
}
|
||||
|
||||
public getJWTTokenForUser(userId: string): string {
|
||||
const payload = {
|
||||
sub: userId,
|
||||
role: ""
|
||||
role: "",
|
||||
};
|
||||
return this.platform.authService.sign(payload);
|
||||
}
|
||||
|
||||
async uploadFileAndCreateDocument(
|
||||
filename: string,
|
||||
parent_id = "root"
|
||||
) {
|
||||
async uploadEicarTestFile(filename: string) {
|
||||
// EICAR test file content
|
||||
const eicarContent = "X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*";
|
||||
// Create a readable stream from the EICAR content
|
||||
const eicarStream = new Readable();
|
||||
eicarStream.push(eicarContent);
|
||||
eicarStream.push(null); // End of the stream
|
||||
|
||||
// Upload using the stream
|
||||
const filesUploadRaw = await this.injectUploadRequest(eicarStream, filename);
|
||||
|
||||
if (filesUploadRaw.statusCode === 200) {
|
||||
const filesUpload = deserialize<ResourceUpdateResponse<File>>(
|
||||
ResourceUpdateResponse,
|
||||
filesUploadRaw.body,
|
||||
);
|
||||
console.log("UPLOADED FILE IS: ", filesUpload.resource);
|
||||
return filesUpload.resource;
|
||||
} else {
|
||||
this.throwServerError(filesUploadRaw.statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
async uploadFileAndCreateDocument(filename: string, parent_id = "root") {
|
||||
return this.uploadFile(filename).then(f => this.createDocumentFromFile(f, parent_id));
|
||||
};
|
||||
}
|
||||
|
||||
async uploadTestMalAndCreateDocument(filename: string, parent_id = "root") {
|
||||
return this.uploadEicarTestFile(filename).then(f => this.createDocumentFromFile(f, parent_id));
|
||||
}
|
||||
|
||||
async uploadRandomFileAndCreateDocument(parent_id = "root") {
|
||||
return this.uploadRandomFile().then(f => this.createDocumentFromFile(f, parent_id));
|
||||
};
|
||||
}
|
||||
|
||||
async uploadAllFilesAndCreateDocuments(parent_id = "root") {
|
||||
return await Promise.all(UserApi.ALL_FILES.map(f => this.uploadFileAndCreateDocument(f, parent_id)));
|
||||
};
|
||||
return await Promise.all(
|
||||
UserApi.ALL_FILES.map(f => this.uploadFileAndCreateDocument(f, parent_id)),
|
||||
);
|
||||
}
|
||||
|
||||
async uploadAllFilesOneByOne(parent_id = "root") {
|
||||
const files: Array<DriveFile> = [];
|
||||
@@ -214,16 +245,19 @@ export default class UserApi {
|
||||
files.push(doc);
|
||||
}
|
||||
return files;
|
||||
};
|
||||
}
|
||||
|
||||
async createDirectory(parent = "root", overrides?: Partial<DriveFile>) {
|
||||
const directory = await this.createDocument({
|
||||
company_id: this.platform.workspace.company_id,
|
||||
name: "Test Folder Name",
|
||||
parent_id: parent,
|
||||
is_directory: true,
|
||||
...overrides
|
||||
}, {});
|
||||
const directory = await this.createDocument(
|
||||
{
|
||||
company_id: this.platform.workspace.company_id,
|
||||
name: "Test Folder Name",
|
||||
parent_id: parent,
|
||||
is_directory: true,
|
||||
...overrides,
|
||||
},
|
||||
{},
|
||||
);
|
||||
expect(directory).toBeDefined();
|
||||
expect(directory).not.toBeNull();
|
||||
expect(directory.id).toBeDefined();
|
||||
@@ -245,25 +279,28 @@ export default class UserApi {
|
||||
}
|
||||
|
||||
/** Gets the public link access token then `impersonateWithJWT` as an anonymous user with that link */
|
||||
async impersonatePublicLinkAccessOf<T>(item: Partial<DriveFile> & { id: string }, cb: () => Promise<T>): Promise<T> {
|
||||
async impersonatePublicLinkAccessOf<T>(
|
||||
item: Partial<DriveFile> & { id: string },
|
||||
cb: () => Promise<T>,
|
||||
): Promise<T> {
|
||||
const publicToken = await this.getPublicLinkAccessToken(item);
|
||||
expect(publicToken?.value?.length ?? "").toBeGreaterThan(0);
|
||||
return this.impersonateWithJWT(publicToken?.value, cb);
|
||||
}
|
||||
|
||||
async createDocument(
|
||||
item: Partial<DriveFile>,
|
||||
version: Partial<FileVersion>
|
||||
) {
|
||||
const response = await this.api.post(`${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item`,
|
||||
async createDocument(item: Partial<DriveFile>, version: Partial<FileVersion>) {
|
||||
const response = await this.api.post(
|
||||
`${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item`,
|
||||
{
|
||||
item,
|
||||
version
|
||||
}, {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
});
|
||||
version,
|
||||
},
|
||||
{
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
);
|
||||
return deserialize<DriveFile>(DriveFile, response.body);
|
||||
};
|
||||
}
|
||||
|
||||
async createDefaultDocument(overrides?: Partial<DriveFile>): Promise<DriveFile> {
|
||||
const scope: "personal" | "shared" = "shared";
|
||||
@@ -276,28 +313,38 @@ export default class UserApi {
|
||||
};
|
||||
|
||||
return await this.createDocument(item, {});
|
||||
};
|
||||
}
|
||||
|
||||
async shareWithPublicLink(doc: Partial<DriveFile> & { id: string }, accessLevel: publicAccessLevel) {
|
||||
async shareWithPublicLink(
|
||||
doc: Partial<DriveFile> & { id: string },
|
||||
accessLevel: publicAccessLevel,
|
||||
) {
|
||||
return await this.updateDocument(doc.id, {
|
||||
...doc,
|
||||
access_info: {
|
||||
...doc.access_info!,
|
||||
public: {
|
||||
...doc.access_info?.public!,
|
||||
level: accessLevel
|
||||
}
|
||||
}
|
||||
level: accessLevel,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async shareWithPublicLinkWithOkCheck(doc: Partial<DriveFile> & { id: string }, accessLevel: publicAccessLevel) {
|
||||
const shareResponse = await this.shareWithPublicLink(doc, accessLevel);
|
||||
async shareWithPublicLinkWithOkCheck(
|
||||
doc: Partial<DriveFile> & { id: string },
|
||||
accessLevel: publicAccessLevel,
|
||||
) {
|
||||
const shareResponse = await this.shareWithPublicLink(doc, accessLevel);
|
||||
expect(shareResponse.statusCode).toBe(200);
|
||||
return deserialize<DriveFile>(DriveFile, shareResponse.body);
|
||||
}
|
||||
|
||||
async shareWithPermissions(doc: Partial<DriveFile> & { id: string }, toUserId: string, permissions: DriveFileAccessLevel) {
|
||||
async shareWithPermissions(
|
||||
doc: Partial<DriveFile> & { id: string },
|
||||
toUserId: string,
|
||||
permissions: DriveFileAccessLevel,
|
||||
) {
|
||||
doc.access_info.entities.push({
|
||||
type: "user",
|
||||
id: toUserId,
|
||||
@@ -316,21 +363,19 @@ export default class UserApi {
|
||||
payload: {
|
||||
company_id: doc.company_id,
|
||||
document_id: doc.id,
|
||||
token: doc.access_info.public?.token
|
||||
}
|
||||
token: doc.access_info.public?.token,
|
||||
},
|
||||
});
|
||||
const { access_token } = deserialize<AccessTokenMockClass>(
|
||||
AccessTokenMockClass,
|
||||
accessRes.body
|
||||
accessRes.body,
|
||||
);
|
||||
expect(access_token).toBeDefined();
|
||||
|
||||
return access_token;
|
||||
}
|
||||
|
||||
async createRandomDocument(
|
||||
parent_id = "root"
|
||||
) {
|
||||
async createRandomDocument(parent_id = "root") {
|
||||
const file = await this.uploadRandomFile();
|
||||
|
||||
const doc = await this.createDocumentFromFile(file, parent_id);
|
||||
@@ -340,7 +385,7 @@ export default class UserApi {
|
||||
expect(doc.parent_id).toEqual(parent_id);
|
||||
|
||||
return doc;
|
||||
};
|
||||
}
|
||||
|
||||
async createDocumentFromFilename(
|
||||
file_name:
|
||||
@@ -361,16 +406,13 @@ export default class UserApi {
|
||||
expect(doc.parent_id).toEqual(parent_id);
|
||||
|
||||
return doc;
|
||||
};
|
||||
}
|
||||
|
||||
async createDocumentFromFile(
|
||||
file: File,
|
||||
parent_id = "root"
|
||||
) {
|
||||
async createDocumentFromFile(file: File, parent_id = "root") {
|
||||
const item = {
|
||||
name: file.metadata.name,
|
||||
parent_id: parent_id,
|
||||
company_id: file.company_id
|
||||
company_id: file.company_id,
|
||||
};
|
||||
|
||||
const version = {
|
||||
@@ -378,35 +420,31 @@ export default class UserApi {
|
||||
name: file.metadata.name,
|
||||
size: file.upload_data?.size,
|
||||
thumbnails: [],
|
||||
external_id: file.id
|
||||
}
|
||||
external_id: file.id,
|
||||
},
|
||||
};
|
||||
|
||||
return await this.createDocument(item, version);
|
||||
};
|
||||
}
|
||||
|
||||
async updateDocument(
|
||||
id: string | "root" | "trash" | "shared_with_me",
|
||||
item: Partial<DriveFile>
|
||||
) {
|
||||
async updateDocument(id: string | "root" | "trash" | "shared_with_me", item: Partial<DriveFile>) {
|
||||
return await this.api.post(
|
||||
`${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item/${id}`,
|
||||
item,
|
||||
{
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
});
|
||||
};
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async beginEditingDocument(
|
||||
driveFileId: string,
|
||||
editorApplicationId: string,
|
||||
): Promise<Response> {
|
||||
async beginEditingDocument(driveFileId: string, editorApplicationId: string): Promise<Response> {
|
||||
return await this.api.post(
|
||||
`${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item/${driveFileId}/editing_session`,
|
||||
{ editorApplicationId },
|
||||
{
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
});
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async updateEditingDocument(
|
||||
@@ -415,7 +453,7 @@ export default class UserApi {
|
||||
userId: string | null = null,
|
||||
): Promise<Response> {
|
||||
const fullPath = `${__dirname}/assets/${UserApi.ALL_FILES[0]}`;
|
||||
const readable= Readable.from(fs.createReadStream(fullPath));
|
||||
const readable = Readable.from(fs.createReadStream(fullPath));
|
||||
const form = formAutoContent({ file: readable });
|
||||
form.headers["authorization"] = `Bearer ${this.jwt}`;
|
||||
let queryString = keepEditing ? "keepEditing=true" : "";
|
||||
@@ -423,23 +461,23 @@ export default class UserApi {
|
||||
queryString += `${queryString.length ? "&" : ""}userId=${encodeURIComponent(userId)}`;
|
||||
return await this.platform.app.inject({
|
||||
method: "POST",
|
||||
url: `${UserApi.DOC_URL}/editing_session/${encodeURIComponent(editingSessionKey)}${queryString ? "?" : ""}${queryString}`,
|
||||
url: `${UserApi.DOC_URL}/editing_session/${encodeURIComponent(editingSessionKey)}${
|
||||
queryString ? "?" : ""
|
||||
}${queryString}`,
|
||||
headers: {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
...form,
|
||||
});
|
||||
}
|
||||
|
||||
async cancelEditingDocument(
|
||||
editingSessionKey: string,
|
||||
): Promise<Response> {
|
||||
async cancelEditingDocument(editingSessionKey: string): Promise<Response> {
|
||||
return await this.platform.app.inject({
|
||||
method: "DELETE",
|
||||
url: `${UserApi.DOC_URL}/editing_session/${editingSessionKey}`,
|
||||
headers: {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
}
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -449,65 +487,56 @@ export default class UserApi {
|
||||
): Promise<string> {
|
||||
const result = await this.beginEditingDocument(driveFileId, editorApplicationId);
|
||||
expect(result.statusCode).toBe(200);
|
||||
const {editingSessionKey} = result.json();
|
||||
const { editingSessionKey } = result.json();
|
||||
expect(editingSessionKey).toBeTruthy();
|
||||
return editingSessionKey;
|
||||
}
|
||||
|
||||
async searchDocument(
|
||||
payload: Record<string, any>
|
||||
) {
|
||||
async searchDocument(payload: Record<string, any>) {
|
||||
const response = await this.platform.app.inject({
|
||||
method: "POST",
|
||||
url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/search`,
|
||||
headers: {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
payload
|
||||
payload,
|
||||
});
|
||||
|
||||
return deserialize<SearchResultMockClass>(
|
||||
SearchResultMockClass,
|
||||
response.body);
|
||||
};
|
||||
return deserialize<SearchResultMockClass>(SearchResultMockClass, response.body);
|
||||
}
|
||||
|
||||
async browseDocuments(
|
||||
id: string,
|
||||
payload: Record<string, any> = {}
|
||||
) {
|
||||
async browseDocuments(id: string, payload: Record<string, any> = {}) {
|
||||
const response = await this.platform.app.inject({
|
||||
method: "POST",
|
||||
url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/browse/${id}`,
|
||||
headers: {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
payload
|
||||
payload,
|
||||
});
|
||||
|
||||
return deserialize<DriveItemDetailsMockClass>(
|
||||
DriveItemDetailsMockClass,
|
||||
response.body);
|
||||
};
|
||||
return deserialize<DriveItemDetailsMockClass>(DriveItemDetailsMockClass, response.body);
|
||||
}
|
||||
|
||||
async getDocument(id: string | "root" | "trash" | "shared_with_me") {
|
||||
return await this.platform.app.inject({
|
||||
method: "GET",
|
||||
url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item/${id}`,
|
||||
headers: {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
}
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
async zipDocument(id: string | "root" | "trash" | "shared_with_me") {
|
||||
return await this.platform.app.inject({
|
||||
method: "GET",
|
||||
url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item/download/zip?items=${id}`,
|
||||
headers: {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
}
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
async getDocumentOKCheck(id: string | "root" | "trash" | "shared_with_me") {
|
||||
const response = await this.getDocument(id);
|
||||
@@ -515,42 +544,38 @@ export default class UserApi {
|
||||
const doc = deserialize<DriveItemDetailsMockClass>(DriveItemDetailsMockClass, response.body);
|
||||
expect(doc.item?.id).toBe(id);
|
||||
return doc;
|
||||
};
|
||||
}
|
||||
|
||||
async getDocumentByEditingKey(editing_session_key: string) {
|
||||
return await this.platform.app.inject({
|
||||
method: "GET",
|
||||
url: `${UserApi.DOC_URL}/editing_session/${encodeURIComponent(editing_session_key)}`,
|
||||
headers: {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
}
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
async sharedWithMeDocuments(
|
||||
payload: Record<string, any>
|
||||
) {
|
||||
async sharedWithMeDocuments(payload: Record<string, any>) {
|
||||
const response = await this.platform.app.inject({
|
||||
method: "POST",
|
||||
url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/browse/shared_with_me`,
|
||||
headers: {
|
||||
authorization: `Bearer ${this.jwt}`
|
||||
authorization: `Bearer ${this.jwt}`,
|
||||
},
|
||||
payload
|
||||
payload,
|
||||
});
|
||||
|
||||
return deserialize<DriveItemDetailsMockClass>(
|
||||
DriveItemDetailsMockClass,
|
||||
response.body);
|
||||
};
|
||||
return deserialize<DriveItemDetailsMockClass>(DriveItemDetailsMockClass, response.body);
|
||||
}
|
||||
|
||||
async quota() {
|
||||
const url = "/internal/services/users/v1/users";
|
||||
|
||||
const response = await this.platform.app.inject({
|
||||
method: "GET",
|
||||
headers: { "authorization": `Bearer ${this.jwt}` },
|
||||
url: `${url}/${this.user.id}/quota?companyId=${this.platform.workspace.company_id}`
|
||||
headers: { authorization: `Bearer ${this.jwt}` },
|
||||
url: `${url}/${this.user.id}/quota?companyId=${this.platform.workspace.company_id}`,
|
||||
});
|
||||
|
||||
return deserialize<UserQuota>(UserQuotaMockClass, response.body);
|
||||
@@ -560,7 +585,7 @@ export default class UserApi {
|
||||
return await this.platform.app.inject({
|
||||
method: "DELETE",
|
||||
url: `${UserApi.DOC_URL}/companies/${this.platform.workspace.company_id}/item/${id}`,
|
||||
headers: { "authorization": `Bearer ${this.jwt}` },
|
||||
headers: { authorization: `Bearer ${this.jwt}` },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ describe("The Documents Browser Window and API", () => {
|
||||
for (const file of files) {
|
||||
await currentUser.shareWithPermissions(file, anotherUser.user.id, "read");
|
||||
}
|
||||
// for opensearch to index the files
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -147,6 +149,7 @@ describe("The Documents Browser Window and API", () => {
|
||||
it("Should paginate shared with me ", async () => {
|
||||
let page_token: any = "1";
|
||||
const limitStr = "2";
|
||||
|
||||
let docs = await anotherUser.browseDocuments(sharedWIthMeFolder, {
|
||||
paginate: { page_token, limitStr },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user