You've already forked pigallery2
mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-11-25 22:32:52 +02:00
310 lines
12 KiB
TypeScript
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);
|
|
});
|
|
});
|
|
});
|