mirror of
https://github.com/HeyPuter/puter.git
synced 2026-05-04 00:20:45 +00:00
fix: backend tests breaking with permision (#2067)
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (20.x) (push) Has been cancelled
test / test-backend (22.x) (push) Has been cancelled
test / backend (node env, api-test) (22.x) (push) Has been cancelled
test / puterjs (browser env, playwright) (22.x) (push) Has been cancelled
test / puterjs (node env, vitest) (22.x) (push) Has been cancelled
Docker Image CI / build-and-push-image (push) Has been cancelled
Maintain Release Merge PR / update-release-pr (push) Has been cancelled
release-please / release-please (push) Has been cancelled
test / test-backend (20.x) (push) Has been cancelled
test / test-backend (22.x) (push) Has been cancelled
test / backend (node env, api-test) (22.x) (push) Has been cancelled
test / puterjs (browser env, playwright) (22.x) (push) Has been cancelled
test / puterjs (node env, vitest) (22.x) (push) Has been cancelled
This commit is contained in:
@@ -7,7 +7,7 @@ on:
|
||||
branches: ["main"]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
test-backend:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
@@ -22,13 +22,13 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Build
|
||||
- name: Backend Tests
|
||||
run: |
|
||||
rm package-lock.json
|
||||
npm install -g npm@latest
|
||||
npm install
|
||||
npm run build
|
||||
npm run test
|
||||
npm run test:backend
|
||||
|
||||
api-test:
|
||||
name: backend (node env, api-test)
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@
|
||||
"scripts": {
|
||||
"test": "npx mocha src/phoenix/test && npx vitest run src/backend && node src/backend/tools/test.mjs",
|
||||
"test:puterjs-api": "vitest run tests/puterJsApiTests",
|
||||
"test:backend": "vitest run --config=src/backend/vitest.config.ts src/backend",
|
||||
"test:backend": "npm run build:ts; vitest run --config=src/backend/vitest.config.ts src/backend",
|
||||
"start=gui": "nodemon --exec \"node dev-server.js\" ",
|
||||
"start": "node ./tools/run-selfhosted.js",
|
||||
"prestart": "npm run build:ts",
|
||||
|
||||
@@ -156,14 +156,21 @@ class TogetherAIService extends BaseService {
|
||||
};
|
||||
}
|
||||
|
||||
// return completion.choices[0];
|
||||
const ret = completion.choices[0];
|
||||
|
||||
ret.usage = {
|
||||
input_tokens: completion.usage.prompt_tokens,
|
||||
output_tokens: completion.usage.completion_tokens,
|
||||
};
|
||||
|
||||
const trackedUsage = OpenAIUtil.extractMeteredUsage(completion.usage);
|
||||
const costOverrides = {
|
||||
prompt_tokens: trackedUsage.prompt_tokens * (modelDetails?.cost?.input ?? 0),
|
||||
completion_tokens: trackedUsage.completion_tokens * (modelDetails?.cost?.output ?? 0),
|
||||
};
|
||||
// Metering: record usage for non-streamed completion
|
||||
this.meteringService.utilRecordUsageObject(completion.usage, actor, modelId);
|
||||
this.meteringService.utilRecordUsageObject(completion.usage, actor, modelId, costOverrides);
|
||||
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
const { AnomalyService } = require('../../services/AnomalyService');
|
||||
const { GroupService } = require('../../services/auth/GroupService');
|
||||
const { PermissionService } = require('../../services/auth/PermissionService');
|
||||
const { CommandService } = require('../../services/CommandService');
|
||||
const { SqliteDatabaseAccessService } = require('../../services/database/SqliteDatabaseAccessService');
|
||||
const { DetailProviderService } = require('../../services/DetailProviderService');
|
||||
const { EventService } = require('../../services/EventService');
|
||||
const { GetUserService } = require('../../services/GetUserService');
|
||||
const { MeteringServiceWrapper } = require('../../services/MeteringService/MeteringServiceWrapper.mjs');
|
||||
const { DBKVServiceWrapper } = require('../../services/repositories/DBKVStore/index.mjs');
|
||||
const { SUService } = require('../../services/SUService');
|
||||
const { TraceService } = require('../../services/TraceService');
|
||||
const { AlarmService } = require('../core/AlarmService');
|
||||
@@ -18,6 +23,11 @@ class TestCoreModule {
|
||||
services.registerService('alarm', AlarmService);
|
||||
services.registerService('event', EventService);
|
||||
services.registerService('commands', CommandService);
|
||||
services.registerService('meteringService', MeteringServiceWrapper);
|
||||
services.registerService('puter-kvstore', DBKVServiceWrapper);
|
||||
services.registerService('permission', PermissionService);
|
||||
services.registerService('group', GroupService);
|
||||
services.registerService('anomaly', AnomalyService);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -223,5 +223,5 @@ describe('MeteringService', async () => {
|
||||
count: 1,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 10000);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,6 @@ import { describe, expect, it } from 'vitest';
|
||||
import { createTestKernel } from '../../../../tools/test.mjs';
|
||||
import * as config from '../../../config';
|
||||
import { Actor } from '../../auth/Actor';
|
||||
import { MeteringServiceWrapper } from '../../MeteringService/MeteringServiceWrapper.mjs';
|
||||
import { DBKVServiceWrapper } from './index.mjs';
|
||||
|
||||
describe('DBKVStore', async () => {
|
||||
@@ -18,10 +17,7 @@ describe('DBKVStore', async () => {
|
||||
});
|
||||
|
||||
const testKernel = await createTestKernel({
|
||||
serviceMap: {
|
||||
meteringService: MeteringServiceWrapper,
|
||||
'puter-kvstore': DBKVServiceWrapper,
|
||||
},
|
||||
serviceMap: {},
|
||||
initLevelString: 'init',
|
||||
testCore: true,
|
||||
});
|
||||
@@ -64,6 +60,29 @@ describe('DBKVStore', async () => {
|
||||
expect(fromTwo).toBe('two');
|
||||
});
|
||||
|
||||
it('retrieves single and multiple keys respecting app vs global scope', async () => {
|
||||
const userId = 12;
|
||||
const globalActor = makeActor(userId);
|
||||
const appActor = makeActor(userId, 'scoped-app');
|
||||
|
||||
await su.sudo(globalActor, () => kvStore.set({ key: 'shared', value: 'global-shared' }));
|
||||
await su.sudo(globalActor, () => kvStore.set({ key: 'global-only', value: 'global' }));
|
||||
await su.sudo(appActor, () => kvStore.set({ key: 'shared', value: 'app-shared' }));
|
||||
await su.sudo(appActor, () => kvStore.set({ key: 'app-only', value: 'app' }));
|
||||
|
||||
const globalSingle = await su.sudo(globalActor, () => kvStore.get({ key: 'shared' }));
|
||||
const appSingle = await su.sudo(appActor, () => kvStore.get({ key: 'shared' }));
|
||||
|
||||
expect(globalSingle).toBe('global-shared');
|
||||
expect(appSingle).toBe('app-shared');
|
||||
|
||||
const globalList = await su.sudo(globalActor, () => kvStore.get({ key: ['shared', 'app-only', 'global-only'] }));
|
||||
const appList = await su.sudo(appActor, () => kvStore.get({ key: ['shared', 'app-only', 'global-only'] }));
|
||||
|
||||
expect(globalList).toEqual(['global-shared', null, 'global']);
|
||||
expect(appList).toEqual(['app-shared', 'app', null]);
|
||||
});
|
||||
|
||||
it('increments nested numeric paths and persists the aggregated totals', async () => {
|
||||
const actor = makeActor(3);
|
||||
const key = 'counter-key';
|
||||
|
||||
@@ -53,10 +53,14 @@ export class DBKVStore implements IDBKVStore {
|
||||
if ( Array.isArray(key) ) {
|
||||
const keys = key;
|
||||
const key_hashes = keys.map((key: string) => murmurhash.v3(key));
|
||||
const placeholders = key_hashes.map(() => '?').join(',');
|
||||
const params = app
|
||||
? [user.id, app.uid, ...key_hashes]
|
||||
: [user.id, ...key_hashes];
|
||||
const rows = app
|
||||
? await this.#db.read('SELECT kkey, value, expireAt FROM kv WHERE user_id=? AND app=? AND kkey_hash IN (?)', [user.id, app.uid, key_hashes])
|
||||
: await this.#db.read(`SELECT kkey, value, expireAt FROM kv WHERE user_id=? AND (app IS NULL OR app = '${GLOBAL_APP_KEY}') AND kkey_hash IN (${key_hashes.map(() => '?').join(',')})`,
|
||||
[user.id, key_hashes]);
|
||||
? await this.#db.read(`SELECT kkey, value, expireAt FROM kv WHERE user_id=? AND app=? AND kkey_hash IN (${placeholders})`, params)
|
||||
: await this.#db.read(`SELECT kkey, value, expireAt FROM kv WHERE user_id=? AND (app IS NULL OR app = '${GLOBAL_APP_KEY}') AND kkey_hash IN (${placeholders})`,
|
||||
params);
|
||||
|
||||
const kvPairs: Record<string, unknown> = {};
|
||||
rows.forEach((row: { kkey: string, value: string }) => {
|
||||
@@ -82,7 +86,7 @@ export class DBKVStore implements IDBKVStore {
|
||||
deleteExpired(expiredKeys);
|
||||
}
|
||||
|
||||
return keys.map((key: string) => kvPairs[key]) as unknown[];
|
||||
return keys.map((key: string) => Object.prototype.hasOwnProperty.call(kvPairs, key) ? kvPairs[key] : null) as unknown[];
|
||||
}
|
||||
|
||||
const key_hash = murmurhash.v3(key);
|
||||
|
||||
Reference in New Issue
Block a user