1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-11-25 22:32:52 +02:00
Files
pigallery2/test/backend/unit/model/ObjectManagers.spec.ts
2025-08-17 23:20:13 +02:00

310 lines
12 KiB
TypeScript

/* eslint-disable no-unused-expressions,@typescript-eslint/no-unused-expressions */
import {expect} from 'chai';
import {ObjectManagers} from '../../../../src/backend/model/ObjectManagers';
import {UserEntity} from '../../../../src/backend/model/database/enitites/UserEntity';
import {ANDSearchQuery, SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes} from '../../../../src/common/entities/SearchQueryDTO';
import {UserRoles} from '../../../../src/common/entities/UserDTO';
import {Brackets} from 'typeorm';
import {DBTestHelper} from '../../DBTestHelper';
import {SharingEntity} from '../../../../src/backend/model/database/enitites/SharingEntity';
declare let describe: any;
declare const it: any;
declare const beforeEach: any;
declare const afterEach: any;
const tmpDescribe = describe;
describe = DBTestHelper.describe(); // fake it os IDE plays nicely (recognize the test)
describe('ObjectManagers', (sqlHelper: DBTestHelper) => {
describe = tmpDescribe;
describe('buildContext', () => {
// Reset ObjectManagers before each test
beforeEach(async () => {
await sqlHelper.initDB();
});
afterEach(sqlHelper.clearDB);
it('should create a basic context with user and no queries', async () => {
// Create a basic user with no queries
const user = new UserEntity();
user.id = 1;
user.name = 'testuser';
user.role = UserRoles.Admin;
// Create the context
const context = await ObjectManagers.getInstance().buildContext(user);
// Verify the context
expect(context).to.not.be.null;
expect(context.user).to.be.eql(user);
expect(context.projectionQuery).to.be.undefined;
});
it('should create a context with allowQuery and set projectionQuery', async () => {
// Create a user with allowQuery
const user = new UserEntity();
user.id = 2;
user.name = 'allowuser';
user.role = UserRoles.Admin;
user.overrideAllowBlockList = true;
user.allowQuery = {
type: SearchQueryTypes.directory,
text: '/allowed/path',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch;
// Mock the SearchManager.prepareAndBuildWhereQuery method
const mockProjectionQuery = new Brackets(qb => qb.where('directory.path = :path', {path: '/allowed/path'}));
ObjectManagers.getInstance().SearchManager = {
prepareAndBuildWhereQuery: (query: any) => {
// Verify the query is passed correctly
expect(query).to.be.eql(user.allowQuery);
return Promise.resolve(mockProjectionQuery);
}
} as any;
// Create the context
const context = await ObjectManagers.getInstance().buildContext(user);
// Verify the context
expect(context).to.not.be.null;
expect(context.user).to.be.eql(user);
expect(context.projectionQuery).to.be.eql(mockProjectionQuery);
expect(context.user.projectionKey).to.be.a('string').and.not.empty;
});
it('should create a context with blockQuery, negate it, and set projectionQuery', async () => {
// Create a user with blockQuery
const user = new UserEntity();
user.id = 3;
user.name = 'blockuser';
user.role = UserRoles.Admin;
user.overrideAllowBlockList = true;
user.blockQuery = {
type: SearchQueryTypes.directory,
text: '/blocked/path',
matchType: TextSearchQueryMatchTypes.exact_match,
negate: false
} as TextSearch;
// Clone the original blockQuery for later comparison
const originalBlockQuery = JSON.parse(JSON.stringify(user.blockQuery));
// Mock the SearchManager.prepareAndBuildWhereQuery method
const mockProjectionQuery = new Brackets(qb => qb.where('directory.path != :path', {path: '/blocked/path'}));
ObjectManagers.getInstance().SearchManager = {
prepareAndBuildWhereQuery: (query: any) => {
// Verify the query has been negated
expect(query).to.not.be.eql(originalBlockQuery);
expect(query.negate).to.be.true;
return Promise.resolve(mockProjectionQuery);
}
} as any;
// Create the context
const context = await ObjectManagers.getInstance().buildContext(user);
// Verify the context
expect(context).to.not.be.null;
expect(context.user).to.be.eql(user);
expect(context.projectionQuery).to.be.eql(mockProjectionQuery);
expect(context.user.projectionKey).to.be.a('string').and.not.empty;
// Verify the blockQuery was negated
expect((user.blockQuery as TextSearch).negate).to.be.true;
});
it('should create a context with both allowQuery and blockQuery, combine them with AND', async () => {
// Create a user with both allowQuery and blockQuery
const user = new UserEntity();
user.id = 4;
user.name = 'bothuser';
user.role = UserRoles.Admin;
user.overrideAllowBlockList = true;
user.allowQuery = {
type: SearchQueryTypes.AND,
list:[
{
type: SearchQueryTypes.directory,
text: '/allowed/path',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch,
{
type: SearchQueryTypes.file_name,
text: 'photo',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch
]
} as ANDSearchQuery;
user.blockQuery = {
type: SearchQueryTypes.directory,
text: '/blocked/path',
matchType: TextSearchQueryMatchTypes.exact_match,
negate: false
} as TextSearch;
// Clone the original queries for later comparison
const originalAllowQuery = JSON.parse(JSON.stringify(user.allowQuery));
const originalBlockQuery = JSON.parse(JSON.stringify(user.blockQuery));
// Mock the SearchManager.prepareAndBuildWhereQuery method
const mockProjectionQuery = new Brackets(qb => qb.where('complex combined query'));
ObjectManagers.getInstance().SearchManager = {
prepareAndBuildWhereQuery: (query: any) => {
// Verify the query is an AND combination of allowQuery and negated blockQuery
expect(query.type).to.be.eql(SearchQueryTypes.AND);
expect(query.list).to.have.lengthOf(2);
expect(query.list[0]).to.be.eql(originalAllowQuery);
expect(query.list[1].negate).to.be.true;
return Promise.resolve(mockProjectionQuery);
}
} as any;
// Create the context
const context = await ObjectManagers.getInstance().buildContext(user);
// Verify the context
expect(context).to.not.be.null;
expect(context.user).to.be.eql(user);
expect(context.projectionQuery).to.be.eql(mockProjectionQuery);
expect(context.user.projectionKey).to.be.a('string').and.not.empty;
// Verify the blockQuery was negated
expect((user.blockQuery as TextSearch).negate).to.be.true;
});
it('should generate consistent projectionKey for the same query', async () => {
// Create two identical users with the same query
const user1 = new UserEntity();
user1.id = 5;
user1.name = 'user1';
user1.role = UserRoles.Admin;
user1.overrideAllowBlockList = true;
user1.allowQuery = {
type: SearchQueryTypes.directory,
text: '/allowed/path',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch;
const user2 = new UserEntity();
user2.id = 6;
user2.name = 'user2';
user2.role = UserRoles.Admin;
user2.overrideAllowBlockList = true;
user2.allowQuery = {
type: SearchQueryTypes.directory,
text: '/allowed/path',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch;
// Mock the SearchManager.prepareAndBuildWhereQuery method
const mockProjectionQuery = new Brackets(qb => qb.where('directory.path = :path', {path: '/allowed/path'}));
/* ObjectManagers.getInstance().SearchManager = {
prepareAndBuildWhereQuery: (query: any) => {
return Promise.resolve(mockProjectionQuery);
}
} as any;*/
// Create the contexts
const context1 = await ObjectManagers.getInstance().buildContext(user1);
const context2 = await ObjectManagers.getInstance().buildContext(user2);
// Verify both users have the same projectionKey despite being different users
expect(context1.user.projectionKey).to.be.a('string').and.not.empty;
expect(context2.user.projectionKey).to.be.a('string').and.not.empty;
expect(context1.user.projectionKey).to.be.eql(context2.user.projectionKey);
});
});
describe('buildAllowListForSharing', () => {
// Reset ObjectManagers before each test
beforeEach(async () => {
await sqlHelper.initDB();
});
afterEach(sqlHelper.clearDB);
it('should return sharing.searchQuery unchanged when creator has no allow/block query', async () => {
const creator = new UserEntity();
creator.id = 10;
creator.name = 'creator1';
creator.role = UserRoles.Admin;
creator.overrideAllowBlockList = true; // use only user queries; none set
const sharing = new SharingEntity();
sharing.creator = creator as any;
sharing.searchQuery = {
type: SearchQueryTypes.directory,
text: '/shared/path',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch;
const result = ObjectManagers.getInstance().buildAllowListForSharing(sharing);
expect(result).to.be.eql(sharing.searchQuery);
});
it('should AND creator allowQuery with sharing.searchQuery', async () => {
const creator = new UserEntity();
creator.id = 11;
creator.name = 'creator2';
creator.role = UserRoles.Admin;
creator.overrideAllowBlockList = true;
creator.allowQuery = {
type: SearchQueryTypes.directory,
text: '/allowed/by/creator',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch;
const sharing = new SharingEntity();
sharing.creator = creator as any;
sharing.searchQuery = {
type: SearchQueryTypes.file_name,
text: 'holiday',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch;
const result = ObjectManagers.getInstance().buildAllowListForSharing(sharing) as ANDSearchQuery;
expect(result.type).to.be.eql(SearchQueryTypes.AND);
expect(result.list).to.have.lengthOf(2);
expect(result.list[0]).to.be.eql(creator.allowQuery);
expect(result.list[1]).to.be.eql(sharing.searchQuery);
});
it('should AND creator (allow AND negated block) with sharing.searchQuery', async () => {
const creator = new UserEntity();
creator.id = 12;
creator.name = 'creator3';
creator.role = UserRoles.Admin;
creator.overrideAllowBlockList = true;
creator.allowQuery = {
type: SearchQueryTypes.directory,
text: '/allowed',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch;
creator.blockQuery = {
type: SearchQueryTypes.file_name,
text: 'secret',
matchType: TextSearchQueryMatchTypes.exact_match,
negate: false
} as TextSearch;
const sharing = new SharingEntity();
sharing.creator = creator as any;
sharing.searchQuery = {
type: SearchQueryTypes.directory,
text: '/event/path',
matchType: TextSearchQueryMatchTypes.exact_match
} as TextSearch;
const result = ObjectManagers.getInstance().buildAllowListForSharing(sharing) as ANDSearchQuery;
expect(result.type).to.be.eql(SearchQueryTypes.AND);
expect(result.list).to.have.lengthOf(2);
const creatorQuery = result.list[0] as ANDSearchQuery;
expect(creatorQuery.type).to.be.eql(SearchQueryTypes.AND);
expect(creatorQuery.list).to.have.lengthOf(2);
expect(creatorQuery.list[0]).to.be.eql(creator.allowQuery);
expect((creatorQuery.list[1] as TextSearch).negate).to.be.true;
expect(result.list[1]).to.be.eql(sharing.searchQuery);
});
});
});