Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20, 22]
node-version: [18, 20, 22]
services:
postgres:
image: postgres
Expand Down
32 changes: 24 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@


###################
# Build source
###################
FROM node:22-slim AS build
# Build artifacts from sources
RUN mkdir -p /app/dist /app/source
WORKDIR /app

Expand All @@ -29,12 +25,23 @@ COPY source/ui /app/source/ui
RUN npm run build-ui
# outputs files in /app/dist

FROM node:22-slim AS utilities
# Fetch utilities that needs to be included

#Install dependencies
RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
xz-utils lbzip2 \
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/* /var/tmp/*

#Install ktx
RUN curl -fsSL -o "/tmp/KTX-Software-Linux-x86_64.tar.bz2" "https://github.com/KhronosGroup/KTX-Software/releases/download/v4.4.2/KTX-Software-4.4.2-Linux-x86_64.tar.bz2"\
&& tar -xf "/tmp/KTX-Software-Linux-x86_64.tar.bz2" -C /usr/local/ --strip-components=1 \
&& rm -rf /tmp/*

###################
# The actual container to be published
###################
FROM node:22-slim
# Build the distributed container
LABEL org.opencontainers.image.source=https://github.com/Holusion/eCorpus
LABEL org.opencontainers.image.description="eCorpus base image"
LABEL org.opencontainers.image.documentation="https://ecorpus.eu"
Expand All @@ -51,6 +58,15 @@ ENV BUILD_REF=${BUILD_REF}

ENV NODE_ENV=production

#Install additional runtime dependencies
RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
ocl-icd-libopencl1 \
&& ln -s libOpenCL.so.1 /usr/lib/x86_64-linux-gnu/libOpenCL.so\
&& rm -rf /var/lib/apt/lists/* /var/tmp/*

COPY --from=utilities /usr/local/lib /usr/local/lib
COPY --from=utilities /usr/local/bin /usr/local/bin


WORKDIR /app
COPY source/server/package*.json /app/
Expand Down
Binary file added source/e2e/__test_fixtures/Diffuse.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added source/e2e/__test_fixtures/cube.blend
Binary file not shown.
12 changes: 12 additions & 0 deletions source/e2e/__test_fixtures/cube.mtl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Blender 4.2.16 LTS MTL File: 'cube.blend'
# www.blender.org

newmtl Material
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd Diffuse.jpg
39 changes: 39 additions & 0 deletions source/e2e/__test_fixtures/cube.obj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Blender 4.2.16 LTS
# www.blender.org
mtllib cube.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 0.000000 0.333333
vt 0.333333 0.333333
vt 0.333333 0.666667
vt 0.000000 0.666667
vt 0.666667 1.000000
vt 0.333333 1.000000
vt 0.666667 0.666667
vt 0.666667 0.333333
vt 1.000000 0.333333
vt 1.000000 0.666667
vt 0.666667 0.000000
vt 1.000000 0.000000
vt 0.333333 0.000000
s 0
usemtl Material
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/6/2 7/3/2 8/7/2
f 8/7/3 7/3/3 5/2/3 6/8/3
f 6/8/4 2/9/4 4/10/4 8/7/4
f 2/8/5 1/11/5 3/12/5 4/9/5
f 6/8/6 5/2/6 1/13/6 2/11/6
25 changes: 16 additions & 9 deletions source/e2e/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ export type CreateSceneOptions = {
autoDelete?:boolean,
}

type AccessLevel = "use" | "create" | "admin";

type UniqueAccount = {username:string, password:string, uid:number};

type TestFixture = {
adminPage:Page,
userPage:Page,
createScene:(opts?:CreateSceneOptions)=>Promise<string>,
uniqueAccount: {username:string, password:string, uid:number},

uniqueAccount: (level?:AccessLevel)=>Promise<UniqueAccount>,
}

export {expect} from "@playwright/test";
Expand Down Expand Up @@ -70,25 +73,29 @@ export const test = base.extend<TestFixture>({
await ctx.close();
},
uniqueAccount: async ({browser}, use)=>{
let adminContext = await browser.newContext({storageState: "playwright/.auth/admin.json"});

await use(async (level :AccessLevel = "create")=>{
let username = `testUserLogin${randomBytes(2).readUInt16LE().toString(36)}`;
let password = randomBytes(16).toString("base64");
let adminContext = await browser.newContext({storageState: "playwright/.auth/admin.json"});
//Create a user for this specific test
let res = await adminContext.request.post("/users", {
let res = await adminContext.request.post("/users", {
data: JSON.stringify({
username,
email: `${username}@example.com`,
password,
level: "create",
level,
}),
headers:{
"Content-Type": "application/json",
}
});
let body = JSON.parse(await res.text());
expect(body).toHaveProperty("uid");
let uid :number =body.uid;
await use({username, password, uid});
await adminContext.close();
},
let uid :number = body.uid;
return {username, password, uid};
});

await adminContext.close();
}
});
18 changes: 10 additions & 8 deletions source/e2e/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion source/e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.49.1",
"@types/node": "^22.10.7"
"@types/node": "^22.19.12"
},
"dependencies": {
"@types/yauzl": "^2.10.3",
Expand Down
2 changes: 1 addition & 1 deletion source/e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineConfig, devices } from '@playwright/test';
import path from 'path';
import path from 'node:path';

/**
* Read environment variables from file.
Expand Down
55 changes: 14 additions & 41 deletions source/e2e/tests/accessRights.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import path from "node:path";
import fs, { readFile } from "node:fs/promises";
import { randomBytes, randomUUID } from "node:crypto";

import { test, expect } from '../fixtures';
import { test, expect } from '../fixtures.js';

const fixtures = path.resolve(import.meta.dirname, "../__test_fixtures");

Expand All @@ -13,47 +11,22 @@ test.use({ storageState: { cookies: [], origins: [] }, locale: "cimode" });
//The _actual_ route access rights are tested in unit tests
//We want to have the user properly informed and that's what we're testing here

test("can't create a new scene", async function({page, request}){
const name = randomUUID();

test("can't see upload page anonymously", async function({page}){
await page.goto("/ui/upload/");
const f = page.getByRole("form", {name: "titles.createOrUpdateScene"});
await expect(f).toBeVisible();
await f.getByRole("button", {name: "labels.selectFile"}).setInputFiles(path.join(fixtures, "cube.glb"));
await f.getByRole("textbox", {name: "labels.sceneTitle"}).fill(name);
await f.getByRole("button", {name: "buttons.upload"}).click();

await expect(page.getByRole("status").getByText("Unauthorized")).toBeVisible();

let res = await request.get(`/scenes/${name}`);
await expect(res).not.toBeOK();
await expect(page.getByRole("heading", {name: "Error"})).toBeVisible();
await expect(page.getByText('errors.requireUser')).toBeVisible();
});

test("can't see upload page as non-creator user", async function({page, uniqueAccount}){
const {username, password} = await uniqueAccount("use");

await page.goto("/auth/login/");
await page.getByRole("textbox", {name: "labels.username"}).fill(username);
await page.getByRole("textbox", {name: "labels.password"}).fill(password);
await page.getByRole("button", {name: "labels.signin"}).click();
await page.goto(`/ui/upload`);

test("can't upload a zip", async function({page, userPage}){
const name = randomUUID();
let res = await userPage.request.post(`/scenes/${name}`,{
data: await fs.readFile(path.join(fixtures, "cube.glb")),
});
await expect(res).toBeOK();
res = await userPage.request.get(`/scenes/${name}`, {
headers: {
"Accept": "application/zip",
}
});
await expect(page.getByRole("heading", {name: "Error"})).toBeVisible();
await expect(page.getByText('errors.requireCreate')).toBeVisible();

let body = await res.body();
await page.goto("/ui/upload/");
const f = page.getByRole("form", {name: "titles.createOrUpdateScene"});
await expect(f).toBeVisible();
await f.getByRole("button", {name: "labels.selectFile"}).setInputFiles({
name: "scene.zip",
mimeType: "application/zip",
buffer: body,
});

await f.getByRole("button", {name: "buttons.upload"}).click();

await expect(page.getByText("scene: Error: [401] Unauthorized", {exact: true})).toBeVisible();
});
})
2 changes: 1 addition & 1 deletion source/e2e/tests/download.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ test("downloads a scene archive", async ({page, request})=>{
await once(zip, "end");
expect(entries).toHaveLength(2);
expect(entries.map(e=>e.fileName).sort()).toEqual([
`scenes/${name}/models/${name}.glb`,
`scenes/${name}/${name}.glb`,
`scenes/${name}/scene.svx.json`,
]);
});
Expand Down
6 changes: 1 addition & 5 deletions source/e2e/tests/scene_settings.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import path from "node:path";
import fs from "node:fs/promises";


import { expect, test } from '../fixtures';
import { expect, test } from '../fixtures.js';
import { randomUUID } from "node:crypto";


Expand Down
Loading
Loading