@sync-in/server 1.3.8 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +3 -2
- package/environment/environment.dist.yaml +2 -0
- package/migrations/0001_square_mauler.sql +4 -0
- package/migrations/meta/0001_snapshot.json +2417 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +20 -2
- package/server/app.bootstrap.js +9 -0
- package/server/app.bootstrap.js.map +1 -1
- package/server/app.service.spec.js +48 -23
- package/server/app.service.spec.js.map +1 -1
- package/server/applications/files/constants/files.js +0 -23
- package/server/applications/files/constants/files.js.map +1 -1
- package/server/applications/files/constants/only-office.js +8 -0
- package/server/applications/files/constants/only-office.js.map +1 -1
- package/server/applications/files/files.config.js +5 -0
- package/server/applications/files/files.config.js.map +1 -1
- package/server/applications/files/guards/files-only-office.strategy.js +0 -1
- package/server/applications/files/guards/files-only-office.strategy.js.map +1 -1
- package/server/applications/spaces/guards/space.guard.spec.js +153 -18
- package/server/applications/spaces/guards/space.guard.spec.js.map +1 -1
- package/server/applications/spaces/services/spaces-browser.service.js +7 -7
- package/server/applications/spaces/services/spaces-browser.service.js.map +1 -1
- package/server/applications/spaces/services/spaces-manager.service.js +17 -17
- package/server/applications/spaces/services/spaces-manager.service.js.map +1 -1
- package/server/applications/sync/schemas/sync-clients.schema.js +4 -4
- package/server/applications/sync/schemas/sync-clients.schema.js.map +1 -1
- package/server/applications/sync/utils/routes.js +1 -1
- package/server/applications/sync/utils/routes.js.map +1 -1
- package/server/applications/users/guards/permissions.guard.js +4 -4
- package/server/applications/users/guards/permissions.guard.js.map +1 -1
- package/server/applications/users/guards/permissions.guard.spec.js +6 -6
- package/server/applications/users/guards/permissions.guard.spec.js.map +1 -1
- package/server/applications/users/guards/roles.guard.js +1 -1
- package/server/applications/users/guards/roles.guard.js.map +1 -1
- package/server/applications/users/models/user.model.js +1 -1
- package/server/applications/users/models/user.model.js.map +1 -1
- package/server/applications/users/schemas/users.schema.js +4 -4
- package/server/applications/users/schemas/users.schema.js.map +1 -1
- package/server/authentication/guards/auth-basic.guard.spec.js +38 -2
- package/server/authentication/guards/auth-basic.guard.spec.js.map +1 -1
- package/server/authentication/guards/auth-basic.strategy.js +0 -1
- package/server/authentication/guards/auth-basic.strategy.js.map +1 -1
- package/server/authentication/guards/auth-local.guard.spec.js +7 -5
- package/server/authentication/guards/auth-local.guard.spec.js.map +1 -1
- package/server/authentication/guards/auth-local.strategy.js +0 -1
- package/server/authentication/guards/auth-local.strategy.js.map +1 -1
- package/server/authentication/guards/auth-token-access.guard.spec.js +30 -0
- package/server/authentication/guards/auth-token-access.guard.spec.js.map +1 -1
- package/server/authentication/guards/auth-token-access.strategy.js +0 -1
- package/server/authentication/guards/auth-token-access.strategy.js.map +1 -1
- package/server/authentication/guards/auth-token-refresh.strategy.js +0 -1
- package/server/authentication/guards/auth-token-refresh.strategy.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-database.service.js +1 -1
- package/server/authentication/services/auth-methods/auth-method-database.service.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-database.service.spec.js +8 -6
- package/server/authentication/services/auth-methods/auth-method-database.service.spec.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-ldap.service.js +2 -2
- package/server/authentication/services/auth-methods/auth-method-ldap.service.js.map +1 -1
- package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js +500 -5
- package/server/authentication/services/auth-methods/auth-method-ldap.service.spec.js.map +1 -1
- package/server/configuration/config.constants.js +0 -4
- package/server/configuration/config.constants.js.map +1 -1
- package/server/configuration/config.loader.js +2 -5
- package/server/configuration/config.loader.js.map +1 -1
- package/server/infrastructure/context/services/context-manager.service.spec.js +98 -0
- package/server/infrastructure/context/services/context-manager.service.spec.js.map +1 -0
- package/server/infrastructure/database/configuration.js +1 -1
- package/server/infrastructure/database/configuration.js.map +1 -1
- package/server/infrastructure/database/constants.js +18 -5
- package/server/infrastructure/database/constants.js.map +1 -1
- package/server/infrastructure/database/scripts/seed/usersgroups.js +3 -3
- package/server/infrastructure/database/scripts/seed/usersgroups.js.map +1 -1
- package/server/infrastructure/mailer/mailer.service.js +20 -19
- package/server/infrastructure/mailer/mailer.service.js.map +1 -1
- package/server/infrastructure/mailer/mailer.service.spec.js +176 -0
- package/server/infrastructure/mailer/mailer.service.spec.js.map +1 -0
- package/static/{chunk-EVYNK2XG.js → chunk-3GC2BQZD.js} +1 -1
- package/static/{chunk-XN4TXQKE.js → chunk-5YKWZT33.js} +1 -1
- package/static/{chunk-VSBD6246.js → chunk-6F55D74O.js} +1 -1
- package/static/{chunk-MWPC5XQW.js → chunk-B2Y2RNFP.js} +1 -1
- package/static/{chunk-YTROXGRM.js → chunk-C23BPTJZ.js} +1 -1
- package/static/chunk-DGVNNICG.js +1 -0
- package/static/{chunk-WSVE6EWB.js → chunk-FQ4AFNGE.js} +1 -1
- package/static/{chunk-4YWOE6HM.js → chunk-GBCYYDCI.js} +1 -1
- package/static/{chunk-Z6S7RFGN.js → chunk-HZA7R43P.js} +1 -1
- package/static/{chunk-VO5W2VKC.js → chunk-KZQCFEPT.js} +1 -1
- package/static/{chunk-BLRDUWOI.js → chunk-LJIGRUEF.js} +1 -1
- package/static/chunk-MOVWEZ7J.js +1 -0
- package/static/{chunk-3UFSZ24R.js → chunk-MTRNPGS4.js} +1 -1
- package/static/{chunk-JM5PB2NQ.js → chunk-N2LYWNTC.js} +1 -1
- package/static/{chunk-L4F2K2VQ.js → chunk-PF4K7MVG.js} +1 -1
- package/static/{chunk-F2KKCIDO.js → chunk-PY3BGNJN.js} +1 -1
- package/static/chunk-RSNLYAN6.js +560 -0
- package/static/{chunk-VCXIQZT4.js → chunk-SH5EVL4E.js} +4 -4
- package/static/{chunk-BEJ62KA7.js → chunk-T55FAU2O.js} +1 -1
- package/static/{chunk-BEC2WQVF.js → chunk-TCFKH6K6.js} +1 -1
- package/static/{chunk-LATG3ZVP.js → chunk-TDQAEVZN.js} +1 -1
- package/static/{chunk-FNO4KAYG.js → chunk-TNW2CGK6.js} +1 -1
- package/static/{chunk-OWYD7F64.js → chunk-TTQ37MUV.js} +1 -1
- package/static/chunk-TXPODW5Q.js +7 -0
- package/static/chunk-VHYIXL7R.js +4 -0
- package/static/{chunk-UEN7RH33.js → chunk-VMQMD36Z.js} +1 -1
- package/static/{chunk-6E5YHOWA.js → chunk-VMUOUCEI.js} +1 -1
- package/static/{chunk-I6ACCGIM.js → chunk-W3QXNDI5.js} +1 -1
- package/static/chunk-WHMS3PJ3.js +24 -0
- package/static/{chunk-3PB73RWL.js → chunk-WWIC7UW3.js} +1 -1
- package/static/{chunk-6A5R4OPV.js → chunk-X43VWRFP.js} +1 -1
- package/static/chunk-XE5YHU5J.js +1 -0
- package/static/chunk-Y2CDUS4J.js +4 -0
- package/static/chunk-YCINY2YI.js +1 -0
- package/static/index.html +2 -2
- package/static/main-7LDKYVXO.js +10 -0
- package/static/{polyfills-GNKGQMRJ.js → polyfills-IA5XWQYN.js} +1 -1
- package/static/{scripts-263WP5VB.js → scripts-VZVAP2P4.js} +4 -4
- package/static/styles-FYUSO6OJ.css +1 -0
- package/sync-in-server.js +1 -1
- package/static/chunk-CIGVDQPA.js +0 -1
- package/static/chunk-CY3GGCEX.js +0 -7
- package/static/chunk-DJRILQTU.js +0 -1
- package/static/chunk-EDLO4Y5E.js +0 -4
- package/static/chunk-ENDRPUCI.js +0 -4
- package/static/chunk-HXRRMHEX.js +0 -1
- package/static/chunk-IJDFKCZM.js +0 -24
- package/static/chunk-J6YSVODR.js +0 -1
- package/static/chunk-JQOMI5VI.js +0 -560
- package/static/main-7LVJ2JSP.js +0 -10
- package/static/styles-3DONJ2Z4.css +0 -1
|
@@ -13,18 +13,22 @@ const _functions = require("../../../common/functions");
|
|
|
13
13
|
const _cacheservice = require("../../../infrastructure/cache/services/cache.service");
|
|
14
14
|
const _contextmanagerservice = require("../../../infrastructure/context/services/context-manager.service");
|
|
15
15
|
const _constants = require("../../../infrastructure/database/constants");
|
|
16
|
+
const _routes = require("../../files/constants/routes");
|
|
17
|
+
const _onlyofficeenvironmentdecorator = require("../../files/decorators/only-office-environment.decorator");
|
|
16
18
|
const _filesqueriesservice = require("../../files/services/files-queries.service");
|
|
17
19
|
const _linksqueriesservice = require("../../links/services/links-queries.service");
|
|
18
20
|
const _notificationsmanagerservice = require("../../notifications/services/notifications-manager.service");
|
|
19
21
|
const _shares = require("../../shares/constants/shares");
|
|
20
22
|
const _sharesmanagerservice = require("../../shares/services/shares-manager.service");
|
|
21
23
|
const _sharesqueriesservice = require("../../shares/services/shares-queries.service");
|
|
24
|
+
const _synccontextdecorator = require("../../sync/decorators/sync-context.decorator");
|
|
22
25
|
const _user = require("../../users/constants/user");
|
|
23
26
|
const _usermodel = require("../../users/models/user.model");
|
|
24
27
|
const _usersqueriesservice = require("../../users/services/users-queries.service");
|
|
25
28
|
const _test = require("../../users/utils/test");
|
|
26
29
|
const _webdavcontextdecorator = require("../../webdav/decorators/webdav-context.decorator");
|
|
27
30
|
const _spaces = require("../constants/spaces");
|
|
31
|
+
const _spaceskipguarddecorator = require("../decorators/space-skip-guard.decorator");
|
|
28
32
|
const _spaceskippermissionsdecorator = require("../decorators/space-skip-permissions.decorator");
|
|
29
33
|
const _spacesmanagerservice = require("../services/spaces-manager.service");
|
|
30
34
|
const _spacesqueriesservice = require("../services/spaces-queries.service");
|
|
@@ -399,15 +403,43 @@ describe(_spaceguard.SpaceGuard.name, ()=>{
|
|
|
399
403
|
'*': 'files/personal'
|
|
400
404
|
}
|
|
401
405
|
});
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
406
|
+
await expect(spacesGuard.canActivate(context)).rejects.toEqual(expect.objectContaining({
|
|
407
|
+
status: _common.HttpStatus.INSUFFICIENT_STORAGE
|
|
408
|
+
}));
|
|
409
|
+
});
|
|
410
|
+
it('should fail if request content-length header exceed the quota', async ()=>{
|
|
411
|
+
userTest.role = _user.USER_ROLE.USER;
|
|
412
|
+
const storageQuota = 12;
|
|
413
|
+
const storageUsage = 11;
|
|
414
|
+
spacesManager.spaceEnv = jest.fn().mockReturnValue({
|
|
415
|
+
enabled: true,
|
|
416
|
+
envPermissions: `${_spaces.SPACE_OPERATION.ADD}`,
|
|
417
|
+
storageQuota: storageQuota,
|
|
418
|
+
storageUsage: storageUsage,
|
|
419
|
+
willExceedQuota: (contentLength)=>contentLength > storageQuota - storageUsage
|
|
420
|
+
});
|
|
421
|
+
context.switchToHttp().getRequest.mockReturnValueOnce({
|
|
422
|
+
method: 'POST',
|
|
423
|
+
headers: {
|
|
424
|
+
'content-length': 13
|
|
425
|
+
},
|
|
426
|
+
user: userTest,
|
|
427
|
+
params: {
|
|
428
|
+
'*': 'files/personal'
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
await expect(spacesGuard.canActivate(context)).rejects.toEqual(expect.objectContaining({
|
|
432
|
+
status: _common.HttpStatus.INSUFFICIENT_STORAGE
|
|
433
|
+
}));
|
|
434
|
+
context.switchToHttp().getRequest.mockReturnValueOnce({
|
|
435
|
+
method: 'POST',
|
|
436
|
+
user: userTest,
|
|
437
|
+
headers: {},
|
|
438
|
+
params: {
|
|
439
|
+
'*': 'files/personal'
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
expect(await spacesGuard.canActivate(context)).toBe(true);
|
|
411
443
|
});
|
|
412
444
|
it('should fail with space disabled', async ()=>{
|
|
413
445
|
userTest.role = _user.USER_ROLE.USER;
|
|
@@ -421,21 +453,16 @@ describe(_spaceguard.SpaceGuard.name, ()=>{
|
|
|
421
453
|
'*': 'files/personal'
|
|
422
454
|
}
|
|
423
455
|
});
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
} catch (e) {
|
|
428
|
-
thrown = true;
|
|
429
|
-
expect(e).toBeInstanceOf(_common.HttpException);
|
|
430
|
-
expect(e.status).toBe(_common.HttpStatus.FORBIDDEN);
|
|
431
|
-
}
|
|
432
|
-
expect(thrown).toBe(true);
|
|
456
|
+
await expect(spacesGuard.canActivate(context)).rejects.toMatchObject({
|
|
457
|
+
status: _common.HttpStatus.FORBIDDEN
|
|
458
|
+
});
|
|
433
459
|
});
|
|
434
460
|
it('should validate (or not) the webdav routes', async ()=>{
|
|
435
461
|
userTest.role = _user.USER_ROLE.USER;
|
|
436
462
|
spacesManager.spaceEnv = jest.fn().mockReturnValue({
|
|
437
463
|
enabled: true
|
|
438
464
|
});
|
|
465
|
+
const spyUrlSegment = jest.spyOn(spacesGuard, 'urlSegmentsFromContext');
|
|
439
466
|
(0, _webdavcontextdecorator.WebDAVContext)()(context.getHandler());
|
|
440
467
|
context.switchToHttp().getRequest.mockReturnValueOnce({
|
|
441
468
|
user: userTest,
|
|
@@ -444,6 +471,10 @@ describe(_spaceguard.SpaceGuard.name, ()=>{
|
|
|
444
471
|
}
|
|
445
472
|
});
|
|
446
473
|
expect(await spacesGuard.canActivate(context)).toBe(true);
|
|
474
|
+
expect(spyUrlSegment.mock.results[0].value).toEqual([
|
|
475
|
+
'files',
|
|
476
|
+
'personal'
|
|
477
|
+
]);
|
|
447
478
|
context.switchToHttp().getRequest.mockReturnValueOnce({
|
|
448
479
|
user: userTest,
|
|
449
480
|
params: {
|
|
@@ -451,6 +482,110 @@ describe(_spaceguard.SpaceGuard.name, ()=>{
|
|
|
451
482
|
}
|
|
452
483
|
});
|
|
453
484
|
await expect(spacesGuard.canActivate(context)).rejects.toThrow(_common.HttpException);
|
|
485
|
+
// reset context
|
|
486
|
+
spyUrlSegment.mockRestore();
|
|
487
|
+
context = (0, _tsjest.createMock)();
|
|
488
|
+
});
|
|
489
|
+
it('should validate (or not) the sync routes', async ()=>{
|
|
490
|
+
userTest.role = _user.USER_ROLE.USER;
|
|
491
|
+
spacesManager.spaceEnv = jest.fn().mockReturnValue({
|
|
492
|
+
enabled: true
|
|
493
|
+
});
|
|
494
|
+
const spyUrlSegment = jest.spyOn(spacesGuard, 'urlSegmentsFromContext');
|
|
495
|
+
(0, _synccontextdecorator.SyncContext)()(context.getHandler());
|
|
496
|
+
context.switchToHttp().getRequest.mockReturnValueOnce({
|
|
497
|
+
user: userTest,
|
|
498
|
+
params: {
|
|
499
|
+
'*': 'personal/foo'
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
expect(await spacesGuard.canActivate(context)).toBe(true);
|
|
503
|
+
expect(spyUrlSegment.mock.results[0].value).toEqual([
|
|
504
|
+
'files',
|
|
505
|
+
'personal',
|
|
506
|
+
'foo'
|
|
507
|
+
]);
|
|
508
|
+
context.switchToHttp().getRequest.mockReturnValueOnce({
|
|
509
|
+
user: userTest,
|
|
510
|
+
params: {
|
|
511
|
+
'*': 'sync/files'
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
await expect(spacesGuard.canActivate(context)).rejects.toThrow(_common.HttpException);
|
|
515
|
+
// reset context
|
|
516
|
+
spyUrlSegment.mockRestore();
|
|
517
|
+
context = (0, _tsjest.createMock)();
|
|
518
|
+
});
|
|
519
|
+
it('should require the modify permission when using the POST method on the OnlyOffice callback URL', async ()=>{
|
|
520
|
+
userTest.role = _user.USER_ROLE.USER;
|
|
521
|
+
spacesManager.spaceEnv = jest.fn().mockReturnValue({
|
|
522
|
+
enabled: true,
|
|
523
|
+
envPermissions: `${_spaces.SPACE_OPERATION.MODIFY}`
|
|
524
|
+
});
|
|
525
|
+
(0, _onlyofficeenvironmentdecorator.OnlyOfficeContext)()(context.getHandler());
|
|
526
|
+
context.switchToHttp().getRequest.mockReturnValue({
|
|
527
|
+
method: 'POST',
|
|
528
|
+
user: userTest,
|
|
529
|
+
originalUrl: _routes.API_FILES_ONLY_OFFICE_CALLBACK,
|
|
530
|
+
params: {
|
|
531
|
+
'*': 'files/personal/root'
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
expect(await spacesGuard.canActivate(context)).toBe(true);
|
|
535
|
+
spacesManager.spaceEnv = jest.fn().mockReturnValue({
|
|
536
|
+
enabled: true,
|
|
537
|
+
envPermissions: `${_spaces.SPACE_OPERATION.ADD}`
|
|
538
|
+
});
|
|
539
|
+
await expect(spacesGuard.canActivate(context)).rejects.toThrow(_common.HttpException);
|
|
540
|
+
context.switchToHttp().getRequest.mockReturnValue({
|
|
541
|
+
method: 'POST',
|
|
542
|
+
user: userTest,
|
|
543
|
+
originalUrl: '',
|
|
544
|
+
params: {
|
|
545
|
+
'*': 'files/personal/root'
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
expect(await spacesGuard.canActivate(context)).toBe(true);
|
|
549
|
+
// reset context
|
|
550
|
+
context = (0, _tsjest.createMock)();
|
|
551
|
+
});
|
|
552
|
+
it('should pass if skipSpaceGuard context is enabled', async ()=>{
|
|
553
|
+
userTest.role = _user.USER_ROLE.USER;
|
|
554
|
+
userTest.applications = [
|
|
555
|
+
_user.USER_PERMISSION.PERSONAL_SPACE
|
|
556
|
+
];
|
|
557
|
+
spacesManager.spaceEnv = jest.fn().mockReturnValue({
|
|
558
|
+
enabled: true
|
|
559
|
+
});
|
|
560
|
+
context.switchToHttp().getRequest.mockReturnValue({
|
|
561
|
+
user: userTest,
|
|
562
|
+
params: {
|
|
563
|
+
'*': 'shares/personal'
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
await expect(spacesGuard.canActivate(context)).rejects.toMatchObject({
|
|
567
|
+
status: _common.HttpStatus.FORBIDDEN
|
|
568
|
+
});
|
|
569
|
+
(0, _spaceskipguarddecorator.SkipSpaceGuard)()(context.getHandler());
|
|
570
|
+
expect(await spacesGuard.canActivate(context)).toBe(true);
|
|
571
|
+
// reset context
|
|
572
|
+
context = (0, _tsjest.createMock)();
|
|
573
|
+
});
|
|
574
|
+
it('coverage only', async ()=>{
|
|
575
|
+
userTest.role = _user.USER_ROLE.USER;
|
|
576
|
+
userTest.applications = [
|
|
577
|
+
_user.USER_PERMISSION.PERSONAL_SPACE
|
|
578
|
+
];
|
|
579
|
+
spacesManager.spaceEnv = jest.fn().mockRejectedValueOnce(new Error('error'));
|
|
580
|
+
context.switchToHttp().getRequest.mockReturnValue({
|
|
581
|
+
user: userTest,
|
|
582
|
+
params: {
|
|
583
|
+
'*': 'files/personal'
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
await expect(spacesGuard.canActivate(context)).rejects.toMatchObject({
|
|
587
|
+
status: _common.HttpStatus.BAD_REQUEST
|
|
588
|
+
});
|
|
454
589
|
});
|
|
455
590
|
});
|
|
456
591
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/spaces/guards/space.guard.spec.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { createMock, DeepMocked } from '@golevelup/ts-jest'\nimport { ExecutionContext, HttpException, HttpStatus } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { intersectPermissions } from '../../../common/functions'\nimport { Cache } from '../../../infrastructure/cache/services/cache.service'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { FilesQueries } from '../../files/services/files-queries.service'\nimport { LinksQueries } from '../../links/services/links-queries.service'\nimport { NotificationsManager } from '../../notifications/services/notifications-manager.service'\nimport { SHARE_ALL_OPERATIONS } from '../../shares/constants/shares'\nimport { SharesManager } from '../../shares/services/shares-manager.service'\nimport { SharesQueries } from '../../shares/services/shares-queries.service'\nimport { USER_PERMISSION, USER_ROLE } from '../../users/constants/user'\nimport { UserModel } from '../../users/models/user.model'\nimport { UsersQueries } from '../../users/services/users-queries.service'\nimport { generateUserTest } from '../../users/utils/test'\nimport { WebDAVContext } from '../../webdav/decorators/webdav-context.decorator'\nimport { SPACE_ALIAS, SPACE_ALL_OPERATIONS, SPACE_OPERATION, SPACE_PERMS_SEP, SPACE_REPOSITORY } from '../constants/spaces'\nimport { SkipSpacePermissionsCheck } from '../decorators/space-skip-permissions.decorator'\nimport { SpaceEnv } from '../models/space-env.model'\nimport { SpacesManager } from '../services/spaces-manager.service'\nimport { SpacesQueries } from '../services/spaces-queries.service'\nimport { SpaceGuard } from './space.guard'\n\ndescribe(SpaceGuard.name, () => {\n let spacesGuard: SpaceGuard\n let spacesManager: SpacesManager\n let spacesQueries: SpacesQueries\n let userTest: UserModel\n let context: DeepMocked<ExecutionContext>\n\n beforeAll(async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n {\n provide: DB_TOKEN_PROVIDER,\n useValue: {}\n },\n {\n provide: Cache,\n useValue: {}\n },\n { provide: ContextManager, useValue: {} },\n {\n provide: NotificationsManager,\n useValue: {}\n },\n SpaceGuard,\n SpacesManager,\n SpacesQueries,\n SharesManager,\n SharesQueries,\n FilesQueries,\n UsersQueries,\n LinksQueries\n ]\n }).compile()\n\n spacesManager = module.get<SpacesManager>(SpacesManager)\n spacesQueries = module.get<SpacesQueries>(SpacesQueries)\n spacesGuard = module.get<SpaceGuard>(SpaceGuard)\n // mocks\n spacesManager['setQuotaExceeded'] = jest.fn()\n userTest = new UserModel(generateUserTest())\n context = createMock<ExecutionContext>()\n })\n\n it('should be defined', () => {\n expect(spacesGuard).toBeDefined()\n expect(spacesManager).toBeDefined()\n expect(userTest).toBeDefined()\n })\n\n it('should pass for a personal space', async () => {\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/personal/root/foo/bar' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(0)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.FILES)\n expect(req.space.alias).toBe(SPACE_ALIAS.PERSONAL)\n expect(req.space.name).toBe(SPACE_ALIAS.PERSONAL)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toBeUndefined()\n expect(req.space.dbFile).toMatchObject({ inTrash: false, ownerId: userTest.id, path: 'root/foo/bar' })\n expect(req.space.permissions).toBe(SPACE_ALL_OPERATIONS)\n expect(req.space.envPermissions).toBe(SPACE_ALL_OPERATIONS)\n expect(req.space.inFilesRepository).toBe(true)\n expect(req.space.inPersonalSpace).toBe(true)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(false)\n expect(req.space.inSharesList).toBe(false)\n expect(req.space.paths).toEqual(expect.arrayContaining(['root', 'foo', 'bar']))\n })\n\n it('should pass for a common space', async () => {\n const fakeSpace = {\n id: -1,\n alias: 'test',\n name: 'Test',\n enabled: true,\n permissions: ':a:d:m:so',\n role: 0\n }\n spacesQueries.permissions = jest.fn().mockReturnValueOnce(fakeSpace)\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/test' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(fakeSpace.id)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.FILES)\n expect(req.space.alias).toBe(fakeSpace.alias)\n expect(req.space.name).toBe(fakeSpace.name)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toMatchObject({ id: 0, alias: '', name: '', permissions: 'a:d:m:so' })\n expect(req.space.dbFile).toMatchObject({ inTrash: false, spaceId: fakeSpace.id, spaceExternalRootId: null, path: '.' })\n expect(req.space.permissions).toBe(SHARE_ALL_OPERATIONS)\n expect(req.space.envPermissions).not.toContain('d')\n expect(req.space.inFilesRepository).toBe(true)\n expect(req.space.inPersonalSpace).toBe(false)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(false)\n expect(req.space.inSharesList).toBe(false)\n expect(req.space.paths).toHaveLength(0)\n })\n\n it('should pass for a common space root', async () => {\n const fakeSpace = {\n id: -1,\n alias: 'test',\n name: 'Test',\n enabled: true,\n permissions: 'a:d:m:so',\n role: 1,\n root: {\n id: -2,\n alias: 'root',\n name: 'Root',\n permissions: 'a:d:so',\n owner: { id: -3, login: 'johaven' },\n file: { id: -4, path: 'code', inTrash: false },\n externalPath: null\n }\n }\n spacesQueries.permissions = jest.fn().mockReturnValueOnce(fakeSpace)\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/test/root' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(fakeSpace.id)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.FILES)\n expect(req.space.alias).toBe(fakeSpace.alias)\n expect(req.space.name).toBe(fakeSpace.name)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toMatchObject(fakeSpace.root)\n expect(req.space.dbFile).toMatchObject({ inTrash: false, ownerId: fakeSpace.root.owner.id, path: fakeSpace.root.file.path })\n expect(req.space.permissions).toBe(SPACE_ALL_OPERATIONS)\n expect(req.space.envPermissions).toBe(\n intersectPermissions(fakeSpace.permissions, fakeSpace.root.permissions)\n .split(SPACE_PERMS_SEP)\n .filter((p) => p !== SPACE_OPERATION.DELETE)\n .join(SPACE_PERMS_SEP)\n )\n expect(req.space.inFilesRepository).toBe(true)\n expect(req.space.inPersonalSpace).toBe(false)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(false)\n expect(req.space.inSharesList).toBe(false)\n expect(req.space.paths).toHaveLength(0)\n })\n\n it('should pass for a common space root with a path', async () => {\n const fakeSpace = {\n id: -1,\n alias: 'test',\n name: 'Test',\n enabled: true,\n permissions: 'a:d:m:so',\n role: 1,\n root: {\n id: -2,\n alias: 'root',\n name: 'Root',\n permissions: 'a:d:so',\n owner: { id: -3, login: 'johaven' },\n file: { id: -4, path: 'code', inTrash: false },\n externalPath: null\n }\n }\n spacesQueries.permissions = jest.fn().mockReturnValueOnce(fakeSpace)\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/test/root/path' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(fakeSpace.id)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.FILES)\n expect(req.space.alias).toBe(fakeSpace.alias)\n expect(req.space.name).toBe(fakeSpace.name)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toMatchObject(fakeSpace.root)\n expect(req.space.dbFile).toMatchObject({\n inTrash: false,\n ownerId: fakeSpace.root.owner.id,\n path: `${fakeSpace.root.file.path}/${req.space.paths[0]}`\n })\n expect(req.space.permissions).toBe(SPACE_ALL_OPERATIONS)\n expect(req.space.envPermissions).toBe(fakeSpace.root.permissions)\n expect(req.space.inFilesRepository).toBe(true)\n expect(req.space.inPersonalSpace).toBe(false)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(false)\n expect(req.space.inSharesList).toBe(false)\n expect(req.space.paths).toHaveLength(1)\n })\n\n it('should pass for a space in shares repository', async () => {\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'shares' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(0)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.SHARES)\n expect(req.space.alias).toBe(SPACE_REPOSITORY.SHARES)\n expect(req.space.name).toBe(SPACE_REPOSITORY.SHARES)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toBeUndefined()\n expect(req.space.dbFile).toBeUndefined()\n expect(req.space.permissions).toBe('')\n expect(req.space.envPermissions).toBe('')\n expect(req.space.inFilesRepository).toBe(false)\n expect(req.space.inPersonalSpace).toBe(false)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(true)\n expect(req.space.inSharesList).toBe(true)\n expect(req.space.paths).toHaveLength(0)\n })\n\n it('should not pass if the space is not found or not valid', async () => {\n const fakeSpace = null\n spacesQueries.permissions = jest.fn().mockReturnValueOnce(fakeSpace)\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/foo' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n })\n\n it('should validate (or not) the access to the space depending on the user permissions', async () => {\n // we only check the `spacesManager.checkAccessToSpace` function, ignores the `spacesManager.spaceEnv`\n userTest.applications = [USER_PERMISSION.PERSONAL_SPACE]\n for (const url of ['', 'shares/personal', 'shares/toto']) {\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': url }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n }\n // should pass because it is a standard user\n // should not pass because user is a guest (and dot not have the permission to access to a personal space)\n spacesManager.spaceEnv = jest.fn().mockReturnValueOnce({ enabled: true }) // only for user role\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/personal/root/foo/bar' }\n })\n for (const userRole of [USER_ROLE.USER, USER_ROLE.GUEST]) {\n userTest.role = userRole\n if (userRole === USER_ROLE.USER) {\n expect(await spacesGuard.canActivate(context)).toBe(true)\n } else {\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n }\n }\n })\n\n it('should check user permissions on route', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValue({\n enabled: true,\n envPermissions: `${SPACE_OPERATION.MODIFY}`\n } as Partial<SpaceEnv>)\n // does not allow creation (only modify)\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n\n // allows modification\n context.switchToHttp().getRequest.mockReturnValue({\n method: 'PATCH',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n\n // does not allow guest (on personal space)\n userTest.role = USER_ROLE.GUEST\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n\n // allow if SkipSpacePermissionsCheck is enabled\n userTest.role = USER_ROLE.USER\n SkipSpacePermissionsCheck()(context.getHandler())\n spacesManager.spaceEnv = jest.fn().mockReturnValue({\n enabled: true,\n envPermissions: `${SPACE_OPERATION.MODIFY}`\n } as Partial<SpaceEnv>)\n // does not allow creation but pass\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n // reset context\n context = createMock<ExecutionContext>()\n })\n\n it('should fail with quota exceeded', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValueOnce({\n enabled: true,\n envPermissions: `${SPACE_OPERATION.ADD}`,\n quotaIsExceeded: true\n } as Partial<SpaceEnv>)\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n let thrown = false\n try {\n await spacesGuard.canActivate(context)\n } catch (e) {\n thrown = true\n expect(e).toBeInstanceOf(HttpException)\n expect(e.status).toBe(HttpStatus.INSUFFICIENT_STORAGE)\n }\n expect(thrown).toBe(true)\n })\n\n it('should fail with space disabled', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValueOnce({\n enabled: false\n } as Partial<SpaceEnv>)\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n let thrown = false\n try {\n await spacesGuard.canActivate(context)\n } catch (e) {\n thrown = true\n expect(e).toBeInstanceOf(HttpException)\n expect(e.status).toBe(HttpStatus.FORBIDDEN)\n }\n expect(thrown).toBe(true)\n })\n\n it('should validate (or not) the webdav routes', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValue({ enabled: true })\n WebDAVContext()(context.getHandler())\n context.switchToHttp().getRequest.mockReturnValueOnce({\n user: userTest,\n params: { '*': 'webdav/personal' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n context.switchToHttp().getRequest.mockReturnValueOnce({\n user: userTest,\n params: { '*': 'webdav/files' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n })\n})\n"],"names":["describe","SpaceGuard","name","spacesGuard","spacesManager","spacesQueries","userTest","context","beforeAll","module","Test","createTestingModule","providers","provide","DB_TOKEN_PROVIDER","useValue","Cache","ContextManager","NotificationsManager","SpacesManager","SpacesQueries","SharesManager","SharesQueries","FilesQueries","UsersQueries","LinksQueries","compile","get","jest","fn","UserModel","generateUserTest","createMock","it","expect","toBeDefined","switchToHttp","getRequest","mockReturnValue","user","params","canActivate","toBe","req","space","id","repository","SPACE_REPOSITORY","FILES","alias","SPACE_ALIAS","PERSONAL","enabled","root","toBeUndefined","dbFile","toMatchObject","inTrash","ownerId","path","permissions","SPACE_ALL_OPERATIONS","envPermissions","inFilesRepository","inPersonalSpace","inTrashRepository","inSharesRepository","inSharesList","paths","toEqual","arrayContaining","fakeSpace","role","mockReturnValueOnce","spaceId","spaceExternalRootId","SHARE_ALL_OPERATIONS","not","toContain","toHaveLength","owner","login","file","externalPath","intersectPermissions","split","SPACE_PERMS_SEP","filter","p","SPACE_OPERATION","DELETE","join","SHARES","rejects","toThrow","HttpException","applications","USER_PERMISSION","PERSONAL_SPACE","url","spaceEnv","userRole","USER_ROLE","USER","GUEST","MODIFY","method","SkipSpacePermissionsCheck","getHandler","ADD","quotaIsExceeded","thrown","e","toBeInstanceOf","status","HttpStatus","INSUFFICIENT_STORAGE","FORBIDDEN","WebDAVContext"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/spaces/guards/space.guard.spec.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { createMock, DeepMocked } from '@golevelup/ts-jest'\nimport { ExecutionContext, HttpException, HttpStatus } from '@nestjs/common'\nimport { Test, TestingModule } from '@nestjs/testing'\nimport { intersectPermissions } from '../../../common/functions'\nimport { Cache } from '../../../infrastructure/cache/services/cache.service'\nimport { ContextManager } from '../../../infrastructure/context/services/context-manager.service'\nimport { DB_TOKEN_PROVIDER } from '../../../infrastructure/database/constants'\nimport { API_FILES_ONLY_OFFICE_CALLBACK } from '../../files/constants/routes'\nimport { OnlyOfficeContext } from '../../files/decorators/only-office-environment.decorator'\nimport { FilesQueries } from '../../files/services/files-queries.service'\nimport { LinksQueries } from '../../links/services/links-queries.service'\nimport { NotificationsManager } from '../../notifications/services/notifications-manager.service'\nimport { SHARE_ALL_OPERATIONS } from '../../shares/constants/shares'\nimport { SharesManager } from '../../shares/services/shares-manager.service'\nimport { SharesQueries } from '../../shares/services/shares-queries.service'\nimport { SyncContext } from '../../sync/decorators/sync-context.decorator'\nimport { USER_PERMISSION, USER_ROLE } from '../../users/constants/user'\nimport { UserModel } from '../../users/models/user.model'\nimport { UsersQueries } from '../../users/services/users-queries.service'\nimport { generateUserTest } from '../../users/utils/test'\nimport { WebDAVContext } from '../../webdav/decorators/webdav-context.decorator'\nimport { SPACE_ALIAS, SPACE_ALL_OPERATIONS, SPACE_OPERATION, SPACE_PERMS_SEP, SPACE_REPOSITORY } from '../constants/spaces'\nimport { SkipSpaceGuard } from '../decorators/space-skip-guard.decorator'\nimport { SkipSpacePermissionsCheck } from '../decorators/space-skip-permissions.decorator'\nimport { SpaceEnv } from '../models/space-env.model'\nimport { SpacesManager } from '../services/spaces-manager.service'\nimport { SpacesQueries } from '../services/spaces-queries.service'\nimport { SpaceGuard } from './space.guard'\n\ndescribe(SpaceGuard.name, () => {\n let spacesGuard: SpaceGuard\n let spacesManager: SpacesManager\n let spacesQueries: SpacesQueries\n let userTest: UserModel\n let context: DeepMocked<ExecutionContext>\n\n beforeAll(async () => {\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n {\n provide: DB_TOKEN_PROVIDER,\n useValue: {}\n },\n {\n provide: Cache,\n useValue: {}\n },\n { provide: ContextManager, useValue: {} },\n {\n provide: NotificationsManager,\n useValue: {}\n },\n SpaceGuard,\n SpacesManager,\n SpacesQueries,\n SharesManager,\n SharesQueries,\n FilesQueries,\n UsersQueries,\n LinksQueries\n ]\n }).compile()\n\n spacesManager = module.get<SpacesManager>(SpacesManager)\n spacesQueries = module.get<SpacesQueries>(SpacesQueries)\n spacesGuard = module.get<SpaceGuard>(SpaceGuard)\n // mocks\n spacesManager['setQuotaExceeded'] = jest.fn()\n userTest = new UserModel(generateUserTest())\n context = createMock<ExecutionContext>()\n })\n\n it('should be defined', () => {\n expect(spacesGuard).toBeDefined()\n expect(spacesManager).toBeDefined()\n expect(userTest).toBeDefined()\n })\n\n it('should pass for a personal space', async () => {\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/personal/root/foo/bar' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(0)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.FILES)\n expect(req.space.alias).toBe(SPACE_ALIAS.PERSONAL)\n expect(req.space.name).toBe(SPACE_ALIAS.PERSONAL)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toBeUndefined()\n expect(req.space.dbFile).toMatchObject({ inTrash: false, ownerId: userTest.id, path: 'root/foo/bar' })\n expect(req.space.permissions).toBe(SPACE_ALL_OPERATIONS)\n expect(req.space.envPermissions).toBe(SPACE_ALL_OPERATIONS)\n expect(req.space.inFilesRepository).toBe(true)\n expect(req.space.inPersonalSpace).toBe(true)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(false)\n expect(req.space.inSharesList).toBe(false)\n expect(req.space.paths).toEqual(expect.arrayContaining(['root', 'foo', 'bar']))\n })\n\n it('should pass for a common space', async () => {\n const fakeSpace = {\n id: -1,\n alias: 'test',\n name: 'Test',\n enabled: true,\n permissions: ':a:d:m:so',\n role: 0\n }\n spacesQueries.permissions = jest.fn().mockReturnValueOnce(fakeSpace)\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/test' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(fakeSpace.id)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.FILES)\n expect(req.space.alias).toBe(fakeSpace.alias)\n expect(req.space.name).toBe(fakeSpace.name)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toMatchObject({ id: 0, alias: '', name: '', permissions: 'a:d:m:so' })\n expect(req.space.dbFile).toMatchObject({ inTrash: false, spaceId: fakeSpace.id, spaceExternalRootId: null, path: '.' })\n expect(req.space.permissions).toBe(SHARE_ALL_OPERATIONS)\n expect(req.space.envPermissions).not.toContain('d')\n expect(req.space.inFilesRepository).toBe(true)\n expect(req.space.inPersonalSpace).toBe(false)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(false)\n expect(req.space.inSharesList).toBe(false)\n expect(req.space.paths).toHaveLength(0)\n })\n\n it('should pass for a common space root', async () => {\n const fakeSpace = {\n id: -1,\n alias: 'test',\n name: 'Test',\n enabled: true,\n permissions: 'a:d:m:so',\n role: 1,\n root: {\n id: -2,\n alias: 'root',\n name: 'Root',\n permissions: 'a:d:so',\n owner: { id: -3, login: 'johaven' },\n file: { id: -4, path: 'code', inTrash: false },\n externalPath: null\n }\n }\n spacesQueries.permissions = jest.fn().mockReturnValueOnce(fakeSpace)\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/test/root' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(fakeSpace.id)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.FILES)\n expect(req.space.alias).toBe(fakeSpace.alias)\n expect(req.space.name).toBe(fakeSpace.name)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toMatchObject(fakeSpace.root)\n expect(req.space.dbFile).toMatchObject({ inTrash: false, ownerId: fakeSpace.root.owner.id, path: fakeSpace.root.file.path })\n expect(req.space.permissions).toBe(SPACE_ALL_OPERATIONS)\n expect(req.space.envPermissions).toBe(\n intersectPermissions(fakeSpace.permissions, fakeSpace.root.permissions)\n .split(SPACE_PERMS_SEP)\n .filter((p) => p !== SPACE_OPERATION.DELETE)\n .join(SPACE_PERMS_SEP)\n )\n expect(req.space.inFilesRepository).toBe(true)\n expect(req.space.inPersonalSpace).toBe(false)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(false)\n expect(req.space.inSharesList).toBe(false)\n expect(req.space.paths).toHaveLength(0)\n })\n\n it('should pass for a common space root with a path', async () => {\n const fakeSpace = {\n id: -1,\n alias: 'test',\n name: 'Test',\n enabled: true,\n permissions: 'a:d:m:so',\n role: 1,\n root: {\n id: -2,\n alias: 'root',\n name: 'Root',\n permissions: 'a:d:so',\n owner: { id: -3, login: 'johaven' },\n file: { id: -4, path: 'code', inTrash: false },\n externalPath: null\n }\n }\n spacesQueries.permissions = jest.fn().mockReturnValueOnce(fakeSpace)\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/test/root/path' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(fakeSpace.id)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.FILES)\n expect(req.space.alias).toBe(fakeSpace.alias)\n expect(req.space.name).toBe(fakeSpace.name)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toMatchObject(fakeSpace.root)\n expect(req.space.dbFile).toMatchObject({\n inTrash: false,\n ownerId: fakeSpace.root.owner.id,\n path: `${fakeSpace.root.file.path}/${req.space.paths[0]}`\n })\n expect(req.space.permissions).toBe(SPACE_ALL_OPERATIONS)\n expect(req.space.envPermissions).toBe(fakeSpace.root.permissions)\n expect(req.space.inFilesRepository).toBe(true)\n expect(req.space.inPersonalSpace).toBe(false)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(false)\n expect(req.space.inSharesList).toBe(false)\n expect(req.space.paths).toHaveLength(1)\n })\n\n it('should pass for a space in shares repository', async () => {\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'shares' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n const req: any = context.switchToHttp().getRequest()\n expect(req.space.id).toBe(0)\n expect(req.space.repository).toBe(SPACE_REPOSITORY.SHARES)\n expect(req.space.alias).toBe(SPACE_REPOSITORY.SHARES)\n expect(req.space.name).toBe(SPACE_REPOSITORY.SHARES)\n expect(req.space.enabled).toBe(true)\n expect(req.space.root).toBeUndefined()\n expect(req.space.dbFile).toBeUndefined()\n expect(req.space.permissions).toBe('')\n expect(req.space.envPermissions).toBe('')\n expect(req.space.inFilesRepository).toBe(false)\n expect(req.space.inPersonalSpace).toBe(false)\n expect(req.space.inTrashRepository).toBe(false)\n expect(req.space.inSharesRepository).toBe(true)\n expect(req.space.inSharesList).toBe(true)\n expect(req.space.paths).toHaveLength(0)\n })\n\n it('should not pass if the space is not found or not valid', async () => {\n const fakeSpace = null\n spacesQueries.permissions = jest.fn().mockReturnValueOnce(fakeSpace)\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/foo' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n })\n\n it('should validate (or not) the access to the space depending on the user permissions', async () => {\n // we only check the `spacesManager.checkAccessToSpace` function, ignores the `spacesManager.spaceEnv`\n userTest.applications = [USER_PERMISSION.PERSONAL_SPACE]\n for (const url of ['', 'shares/personal', 'shares/toto']) {\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': url }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n }\n // should pass because it is a standard user\n // should not pass because user is a guest (and dot not have the permission to access to a personal space)\n spacesManager.spaceEnv = jest.fn().mockReturnValueOnce({ enabled: true }) // only for user role\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/personal/root/foo/bar' }\n })\n for (const userRole of [USER_ROLE.USER, USER_ROLE.GUEST]) {\n userTest.role = userRole\n if (userRole === USER_ROLE.USER) {\n expect(await spacesGuard.canActivate(context)).toBe(true)\n } else {\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n }\n }\n })\n\n it('should check user permissions on route', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValue({\n enabled: true,\n envPermissions: `${SPACE_OPERATION.MODIFY}`\n } as Partial<SpaceEnv>)\n // does not allow creation (only modify)\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n\n // allows modification\n context.switchToHttp().getRequest.mockReturnValue({\n method: 'PATCH',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n\n // does not allow guest (on personal space)\n userTest.role = USER_ROLE.GUEST\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n\n // allow if SkipSpacePermissionsCheck is enabled\n userTest.role = USER_ROLE.USER\n SkipSpacePermissionsCheck()(context.getHandler())\n spacesManager.spaceEnv = jest.fn().mockReturnValue({\n enabled: true,\n envPermissions: `${SPACE_OPERATION.MODIFY}`\n } as Partial<SpaceEnv>)\n // does not allow creation but pass\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n // reset context\n context = createMock<ExecutionContext>()\n })\n\n it('should fail with quota exceeded', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValueOnce({\n enabled: true,\n envPermissions: `${SPACE_OPERATION.ADD}`,\n quotaIsExceeded: true\n } as Partial<SpaceEnv>)\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toEqual(expect.objectContaining({ status: HttpStatus.INSUFFICIENT_STORAGE }))\n })\n\n it('should fail if request content-length header exceed the quota', async () => {\n userTest.role = USER_ROLE.USER\n const storageQuota = 12\n const storageUsage = 11\n spacesManager.spaceEnv = jest.fn().mockReturnValue({\n enabled: true,\n envPermissions: `${SPACE_OPERATION.ADD}`,\n storageQuota: storageQuota,\n storageUsage: storageUsage,\n willExceedQuota: (contentLength: number) => contentLength > storageQuota - storageUsage\n } as Partial<SpaceEnv>)\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n headers: { 'content-length': 13 },\n user: userTest,\n params: { '*': 'files/personal' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toEqual(expect.objectContaining({ status: HttpStatus.INSUFFICIENT_STORAGE }))\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n headers: {},\n params: { '*': 'files/personal' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n })\n\n it('should fail with space disabled', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValueOnce({\n enabled: false\n } as Partial<SpaceEnv>)\n context.switchToHttp().getRequest.mockReturnValueOnce({\n method: 'POST',\n user: userTest,\n params: { '*': 'files/personal' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toMatchObject({ status: HttpStatus.FORBIDDEN })\n })\n\n it('should validate (or not) the webdav routes', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValue({ enabled: true })\n const spyUrlSegment = jest.spyOn(spacesGuard as any, 'urlSegmentsFromContext')\n WebDAVContext()(context.getHandler())\n context.switchToHttp().getRequest.mockReturnValueOnce({\n user: userTest,\n params: { '*': 'webdav/personal' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n expect(spyUrlSegment.mock.results[0].value).toEqual(['files', 'personal'])\n context.switchToHttp().getRequest.mockReturnValueOnce({\n user: userTest,\n params: { '*': 'webdav/files' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n // reset context\n spyUrlSegment.mockRestore()\n context = createMock<ExecutionContext>()\n })\n\n it('should validate (or not) the sync routes', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValue({ enabled: true })\n const spyUrlSegment = jest.spyOn(spacesGuard as any, 'urlSegmentsFromContext')\n SyncContext()(context.getHandler())\n context.switchToHttp().getRequest.mockReturnValueOnce({\n user: userTest,\n params: { '*': 'personal/foo' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n expect(spyUrlSegment.mock.results[0].value).toEqual(['files', 'personal', 'foo'])\n context.switchToHttp().getRequest.mockReturnValueOnce({\n user: userTest,\n params: { '*': 'sync/files' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n // reset context\n spyUrlSegment.mockRestore()\n context = createMock<ExecutionContext>()\n })\n\n it('should require the modify permission when using the POST method on the OnlyOffice callback URL', async () => {\n userTest.role = USER_ROLE.USER\n spacesManager.spaceEnv = jest.fn().mockReturnValue({ enabled: true, envPermissions: `${SPACE_OPERATION.MODIFY}` })\n OnlyOfficeContext()(context.getHandler())\n context.switchToHttp().getRequest.mockReturnValue({\n method: 'POST',\n user: userTest,\n originalUrl: API_FILES_ONLY_OFFICE_CALLBACK,\n params: { '*': 'files/personal/root' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n spacesManager.spaceEnv = jest.fn().mockReturnValue({ enabled: true, envPermissions: `${SPACE_OPERATION.ADD}` })\n await expect(spacesGuard.canActivate(context)).rejects.toThrow(HttpException)\n context.switchToHttp().getRequest.mockReturnValue({\n method: 'POST',\n user: userTest,\n originalUrl: '',\n params: { '*': 'files/personal/root' }\n })\n expect(await spacesGuard.canActivate(context)).toBe(true)\n // reset context\n context = createMock<ExecutionContext>()\n })\n\n it('should pass if skipSpaceGuard context is enabled', async () => {\n userTest.role = USER_ROLE.USER\n userTest.applications = [USER_PERMISSION.PERSONAL_SPACE]\n spacesManager.spaceEnv = jest.fn().mockReturnValue({ enabled: true })\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'shares/personal' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toMatchObject({ status: HttpStatus.FORBIDDEN })\n SkipSpaceGuard()(context.getHandler())\n expect(await spacesGuard.canActivate(context)).toBe(true)\n // reset context\n context = createMock<ExecutionContext>()\n })\n\n it('coverage only', async () => {\n userTest.role = USER_ROLE.USER\n userTest.applications = [USER_PERMISSION.PERSONAL_SPACE]\n spacesManager.spaceEnv = jest.fn().mockRejectedValueOnce(new Error('error'))\n context.switchToHttp().getRequest.mockReturnValue({\n user: userTest,\n params: { '*': 'files/personal' }\n })\n await expect(spacesGuard.canActivate(context)).rejects.toMatchObject({ status: HttpStatus.BAD_REQUEST })\n })\n})\n"],"names":["describe","SpaceGuard","name","spacesGuard","spacesManager","spacesQueries","userTest","context","beforeAll","module","Test","createTestingModule","providers","provide","DB_TOKEN_PROVIDER","useValue","Cache","ContextManager","NotificationsManager","SpacesManager","SpacesQueries","SharesManager","SharesQueries","FilesQueries","UsersQueries","LinksQueries","compile","get","jest","fn","UserModel","generateUserTest","createMock","it","expect","toBeDefined","switchToHttp","getRequest","mockReturnValue","user","params","canActivate","toBe","req","space","id","repository","SPACE_REPOSITORY","FILES","alias","SPACE_ALIAS","PERSONAL","enabled","root","toBeUndefined","dbFile","toMatchObject","inTrash","ownerId","path","permissions","SPACE_ALL_OPERATIONS","envPermissions","inFilesRepository","inPersonalSpace","inTrashRepository","inSharesRepository","inSharesList","paths","toEqual","arrayContaining","fakeSpace","role","mockReturnValueOnce","spaceId","spaceExternalRootId","SHARE_ALL_OPERATIONS","not","toContain","toHaveLength","owner","login","file","externalPath","intersectPermissions","split","SPACE_PERMS_SEP","filter","p","SPACE_OPERATION","DELETE","join","SHARES","rejects","toThrow","HttpException","applications","USER_PERMISSION","PERSONAL_SPACE","url","spaceEnv","userRole","USER_ROLE","USER","GUEST","MODIFY","method","SkipSpacePermissionsCheck","getHandler","ADD","quotaIsExceeded","objectContaining","status","HttpStatus","INSUFFICIENT_STORAGE","storageQuota","storageUsage","willExceedQuota","contentLength","headers","FORBIDDEN","spyUrlSegment","spyOn","WebDAVContext","mock","results","value","mockRestore","SyncContext","OnlyOfficeContext","originalUrl","API_FILES_ONLY_OFFICE_CALLBACK","SkipSpaceGuard","mockRejectedValueOnce","Error","BAD_REQUEST"],"mappings":"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"}
|
|
@@ -15,11 +15,11 @@ Object.defineProperty(exports, "SpacesBrowser", {
|
|
|
15
15
|
const _common = require("@nestjs/common");
|
|
16
16
|
const _promises = /*#__PURE__*/ _interop_require_default(require("node:fs/promises"));
|
|
17
17
|
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
18
|
-
const
|
|
18
|
+
const _configenvironment = require("../../../configuration/config.environment");
|
|
19
19
|
const _fileslockmanagerservice = require("../../files/services/files-lock-manager.service");
|
|
20
20
|
const _filesqueriesservice = require("../../files/services/files-queries.service");
|
|
21
21
|
const _filesrecentsservice = require("../../files/services/files-recents.service");
|
|
22
|
-
const
|
|
22
|
+
const _files = require("../../files/utils/files");
|
|
23
23
|
const _sharesqueriesservice = require("../../shares/services/shares-queries.service");
|
|
24
24
|
const _user = require("../../users/constants/user");
|
|
25
25
|
const _webdav = require("../../webdav/constants/webdav");
|
|
@@ -122,14 +122,14 @@ let SpacesBrowser = class SpacesBrowser {
|
|
|
122
122
|
this.logger.log(`${this.parsePath.name} - ignore special file : ${element.name}`);
|
|
123
123
|
continue;
|
|
124
124
|
}
|
|
125
|
-
if (
|
|
125
|
+
if (!_configenvironment.configuration.applications.files.showHiddenFiles && element.name[0] === '.') {
|
|
126
126
|
this.logger.verbose(`${this.parsePath.name} - ignore filtered file : ${element.name}`);
|
|
127
127
|
continue;
|
|
128
128
|
}
|
|
129
129
|
const realPath = _nodepath.default.join(space.realPath, element.name);
|
|
130
130
|
const filePath = _nodepath.default.join(space.relativeUrl, element.name);
|
|
131
131
|
try {
|
|
132
|
-
yield await (0,
|
|
132
|
+
yield await (0, _files.getProps)(realPath, filePath, isDir);
|
|
133
133
|
} catch (e) {
|
|
134
134
|
this.logger.warn(`${this.parsePath.name} - unable get stats from ${realPath} : ${e}`);
|
|
135
135
|
}
|
|
@@ -143,7 +143,7 @@ let SpacesBrowser = class SpacesBrowser {
|
|
|
143
143
|
const realPath = (0, _paths.realPathFromRootFile)(f);
|
|
144
144
|
f.path = f.root.name;
|
|
145
145
|
try {
|
|
146
|
-
const fileProps = await (0,
|
|
146
|
+
const fileProps = await (0, _files.getProps)(realPath, f.path);
|
|
147
147
|
if (options.withShares) {
|
|
148
148
|
fileProps.shares = f.shares;
|
|
149
149
|
}
|
|
@@ -172,8 +172,8 @@ let SpacesBrowser = class SpacesBrowser {
|
|
|
172
172
|
this.logger.error(`${this.updateRootFile.name} - ${JSON.stringify(f)} - ${e}`);
|
|
173
173
|
return {
|
|
174
174
|
...f,
|
|
175
|
-
name: (0,
|
|
176
|
-
path: (0,
|
|
175
|
+
name: (0, _files.fileName)(f.path),
|
|
176
|
+
path: (0, _files.dirName)(f.path),
|
|
177
177
|
...{
|
|
178
178
|
root: {
|
|
179
179
|
...f.root,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/spaces/services/spaces-browser.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, Injectable, Logger } from '@nestjs/common'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { DEFAULT_FILTERS } from '../../files/constants/files'\nimport { FileLock } from '../../files/interfaces/file-lock.interface'\nimport { FileProps } from '../../files/interfaces/file-props.interface'\nimport { FilesLockManager } from '../../files/services/files-lock-manager.service'\nimport { FilesQueries } from '../../files/services/files-queries.service'\nimport { FilesRecents } from '../../files/services/files-recents.service'\nimport { dirName, fileName, getProps } from '../../files/utils/files'\nimport { SharesQueries } from '../../shares/services/shares-queries.service'\nimport { USER_PERMISSION } from '../../users/constants/user'\nimport { UserModel } from '../../users/models/user.model'\nimport { LOCK_SCOPE } from '../../webdav/constants/webdav'\nimport { SpaceFiles } from '../interfaces/space-files.interface'\nimport { SpaceEnv } from '../models/space-env.model'\nimport { realPathFromRootFile, IsRealPathIsDirAndExists } from '../utils/paths'\nimport { SpacesManager } from './spaces-manager.service'\nimport { SpacesQueries } from './spaces-queries.service'\n\n@Injectable()\nexport class SpacesBrowser {\n private readonly logger = new Logger(SpacesBrowser.name)\n\n constructor(\n private readonly spacesManager: SpacesManager,\n private readonly spacesQueries: SpacesQueries,\n private readonly sharesQueries: SharesQueries,\n private readonly filesQueries: FilesQueries,\n private readonly filesLockManager: FilesLockManager,\n private readonly filesRecents: FilesRecents\n ) {}\n\n async browse(\n user: UserModel,\n space: SpaceEnv,\n options: {\n withLocks?: boolean\n withSpacesAndShares?: boolean\n withSyncs?: boolean\n withHasComments?: boolean\n } = {}\n ): Promise<SpaceFiles> {\n // check sync permission\n options.withSyncs = options.withSyncs && user.havePermission(USER_PERMISSION.DESKTOP_APP) && user.havePermission(USER_PERMISSION.DESKTOP_APP_SYNC)\n const spaceFiles: SpaceFiles = { files: [], hasRoots: false, permissions: space.browsePermissions() }\n const [fsFiles, dbFiles, rootFiles] = await Promise.all([\n this.parseFS(space),\n this.parseDB(user.id, space, options),\n this.parseRootFiles(user, space, {\n withShares: options.withSpacesAndShares,\n withHasComments: options.withHasComments,\n withSyncs: options.withSyncs\n })\n ])\n this.updateDBFiles(user, space, dbFiles, fsFiles, options)\n if (space.inSharesList) {\n // the share space includes shares as root files\n spaceFiles.files = [...rootFiles, ...fsFiles]\n spaceFiles.hasRoots = true\n } else {\n await this.mergeSpaceRootFiles(space, rootFiles, fsFiles, spaceFiles)\n }\n if (options.withLocks && !space.inTrashRepository) {\n // locks were removed when files were moved to the trash, no need to parse locks\n await this.enrichWithLocks(space, spaceFiles.files)\n }\n // update recents files\n this.filesRecents.updateRecents(user, space, spaceFiles.files).catch((e: Error) => this.logger.error(`${this.browse.name} - ${e}`))\n return spaceFiles\n }\n\n private async parseRootFiles(\n user: UserModel,\n space: SpaceEnv,\n options: {\n withShares?: boolean\n withHasComments?: boolean\n withSyncs?: boolean\n }\n ): Promise<FileProps[]> {\n if (space.inFilesRepository && space.id && !space.root.alias) {\n // list roots in the space\n return Promise.all((await this.spacesQueries.spaceRootFiles(user.id, space.id, options)).map((f) => this.updateRootFile(f, options)))\n } else if (space.inSharesList) {\n // list shares as roots\n return Promise.all((await this.sharesQueries.shareRootFiles(user, options)).map((f) => this.updateRootFile(f, options)))\n }\n return []\n }\n\n private async parseDB(\n userId: number,\n space: SpaceEnv,\n options: {\n withSpacesAndShares?: boolean\n withSyncs?: boolean\n withHasComments?: boolean\n }\n ): Promise<FileProps[]> {\n if (space.inSharesList) return []\n const dbOptions = {\n withSpaces: options.withSpacesAndShares && space.inPersonalSpace,\n withShares: options.withSpacesAndShares,\n withSyncs: options.withSyncs,\n withHasComments: options.withHasComments,\n ignoreChildShares: !space.inSharesRepository\n }\n return this.filesQueries.browseFiles(userId, space.dbFile, dbOptions)\n }\n\n private async parseFS(space: SpaceEnv): Promise<FileProps[]> {\n if (space.inSharesList) return []\n const fsFiles: FileProps[] = []\n try {\n await IsRealPathIsDirAndExists(space.realPath)\n } catch (e) {\n this.logger.warn(`${this.parseFS.name} - ${space.realPath} : ${e.message}`)\n throw new HttpException(e.message, e.httpCode)\n }\n for await (const f of this.parsePath(space)) {\n fsFiles.push(f)\n }\n return fsFiles\n }\n\n private async *parsePath(space: SpaceEnv): AsyncGenerator<FileProps> {\n try {\n for (const element of await fs.readdir(space.realPath, { withFileTypes: true })) {\n const isDir = element.isDirectory()\n if (!isDir && !element.isFile()) {\n this.logger.log(`${this.parsePath.name} - ignore special file : ${element.name}`)\n continue\n }\n if (DEFAULT_FILTERS.has(element.name)) {\n this.logger.verbose(`${this.parsePath.name} - ignore filtered file : ${element.name}`)\n continue\n }\n const realPath = path.join(space.realPath, element.name)\n const filePath = path.join(space.relativeUrl, element.name)\n try {\n yield await getProps(realPath, filePath, isDir)\n } catch (e) {\n this.logger.warn(`${this.parsePath.name} - unable get stats from ${realPath} : ${e}`)\n }\n }\n } catch (e) {\n this.logger.error(`${this.parsePath.name} - unable to parse ${space.realPath} : ${e}`)\n }\n }\n\n private async updateRootFile(f: FileProps, options: { withShares?: boolean; withHasComments?: boolean; withSyncs?: boolean }): Promise<FileProps> {\n // get realpath\n const realPath = realPathFromRootFile(f)\n f.path = f.root.name\n try {\n const fileProps: FileProps = await getProps(realPath, f.path)\n if (options.withShares) {\n fileProps.shares = f.shares\n }\n if (options.withHasComments) {\n fileProps.hasComments = f.hasComments\n }\n if (options.withSyncs) {\n fileProps.syncs = f.syncs\n }\n if (f.id) {\n // f.id is null for external roots\n // todo: check if a db file referenced under external roots have an id and correctly parsed here\n this.filesQueries.compareAndUpdateFileProps(f, fileProps).catch((e: Error) => this.logger.error(`${this.updateRootFile.name} - ${e}`))\n fileProps.id = f.id\n }\n fileProps.root = {\n id: f.root.id,\n alias: f.root.alias,\n description: f.root.description,\n enabled: typeof f.root.enabled === 'undefined' ? true : f.root.enabled,\n permissions: f.root.permissions,\n owner: f.root.owner\n }\n return fileProps\n } catch (e) {\n this.logger.error(`${this.updateRootFile.name} - ${JSON.stringify(f)} - ${e}`)\n return { ...f, name: fileName(f.path), path: dirName(f.path), ...{ root: { ...f.root, enabled: false } } }\n }\n }\n\n private updateDBFiles(\n user: UserModel,\n space: SpaceEnv,\n dbFiles: FileProps[],\n fsFiles: FileProps[],\n options: {\n withSpacesAndShares?: boolean\n withSyncs?: boolean\n withHasComments?: boolean\n }\n ) {\n for (const dbFile of dbFiles) {\n const fsFile = fsFiles.find((f: FileProps) => dbFile.name === f.name)\n if (fsFile) {\n /* important: inherits from the file id in database */\n fsFile.id = dbFile.id\n if (options.withSpacesAndShares) {\n fsFile.spaces = dbFile.spaces\n fsFile.shares = dbFile.shares\n }\n if (options.withSyncs) {\n fsFile.syncs = dbFile.syncs\n }\n if (options.withHasComments) {\n fsFile.hasComments = dbFile.hasComments\n }\n this.filesQueries.compareAndUpdateFileProps(dbFile, fsFile).catch((e: Error) => this.logger.error(`${this.updateDBFiles.name} - ${e}`))\n } else {\n this.logger.warn(`${this.updateDBFiles.name} - missing ${dbFile.path}/${dbFile.name} (${dbFile.id}) from fs, delete it from db`)\n if (options.withSpacesAndShares) {\n if (dbFile.spaces) {\n for (const space of dbFile.spaces) {\n this.logger.warn(\n `${this.updateDBFiles.name} - ${dbFile.path}/${dbFile.name} (${dbFile.id}) will be removed from space : *${space.alias}* (${space.id})`\n )\n }\n }\n if (dbFile.shares) {\n for (const share of dbFile.shares) {\n this.logger.warn(\n `${this.updateDBFiles.name} - ${dbFile.path}/${dbFile.name} (${dbFile.id}) will be removed from share : *${share.alias}* (${share.id})`\n )\n }\n }\n }\n this.deleteDBFile(user, space, dbFile).catch((e: Error) => this.logger.error(`${this.updateDBFiles.name} - ${e}`))\n }\n }\n }\n\n private async deleteDBFile(user: UserModel, space: SpaceEnv, dbFile: FileProps) {\n const spaceEnv = await this.spacesManager.spaceEnv(user, path.join(space.url, dbFile.name).split('/'))\n this.filesQueries.deleteFiles(spaceEnv.dbFile, dbFile.isDir, true).catch((e: Error) => this.logger.error(`${this.deleteDBFile.name} - ${e}`))\n }\n\n private async mergeSpaceRootFiles(space: SpaceEnv, rootFiles: FileProps[], fsFiles: FileProps[], spaceFiles: SpaceFiles) {\n // merges root files in space files taking care of alias and name (file names must be unique)\n if (!rootFiles.length) {\n spaceFiles.files = fsFiles\n return\n }\n spaceFiles.hasRoots = true\n for (const f of rootFiles) {\n // check root alias (must be unique in the space)\n const newAlias: string = await this.spacesManager.uniqueRootAlias(\n space.id,\n f.root.alias,\n fsFiles.map((f) => f.name),\n true\n )\n if (newAlias) {\n this.logger.log(`${this.mergeSpaceRootFiles.name} - update space root alias (${f.root.id}) : ${f.root.alias} -> ${newAlias}`)\n // update in db\n this.spacesQueries\n .updateRoot({ alias: newAlias }, { id: f.root.id })\n .catch((e: Error) => this.logger.error(`${this.mergeSpaceRootFiles.name} - ${e}`))\n // cleanup cache\n this.spacesQueries\n .clearCachePermissions(space.alias, [f.root.alias, newAlias])\n .catch((e: Error) => this.logger.error(`${this.mergeSpaceRootFiles.name} - ${e}`))\n // assign\n f.root.alias = newAlias\n }\n // check root name (must be unique in the space)\n // f.name is equal to root name\n const newName: string = this.spacesManager.uniqueRootName(\n f.name,\n fsFiles.map((f) => f.name)\n )\n if (newName) {\n this.logger.log(`${this.mergeSpaceRootFiles.name} - update space root name (${f.root.id}) : ${f.name} -> ${newName}`)\n // update in db\n this.spacesQueries\n .updateRoot({ name: newName }, { id: f.root.id })\n .catch((e: Error) => this.logger.error(`${this.mergeSpaceRootFiles.name} - ${e}`))\n // assign\n f.name = newName\n }\n }\n spaceFiles.files = [...fsFiles, ...rootFiles]\n }\n\n private async enrichWithLocks(space: SpaceEnv, files: FileProps[]) {\n if (space.inSharesList) {\n return\n }\n const locks: Record<string, FileLock> = await this.filesLockManager.browseParentChildLocks(space.dbFile, false)\n if (!Object.keys(locks).length) return\n for (const f of files.filter((f) => (f.root && f.root.alias in locks) || (!f.root && f.name in locks))) {\n const lock: FileLock = f.root ? locks[f.root.alias] : locks[f.name]\n f.lock = {\n owner: lock?.davLock?.owner || `${lock.owner.fullName} (${lock.owner.email})`,\n ownerLogin: lock.owner.login,\n isExclusive: lock?.davLock?.lockscope ? lock?.davLock?.lockscope === LOCK_SCOPE.EXCLUSIVE : true\n }\n }\n }\n}\n"],"names":["SpacesBrowser","browse","user","space","options","withSyncs","havePermission","USER_PERMISSION","DESKTOP_APP","DESKTOP_APP_SYNC","spaceFiles","files","hasRoots","permissions","browsePermissions","fsFiles","dbFiles","rootFiles","Promise","all","parseFS","parseDB","id","parseRootFiles","withShares","withSpacesAndShares","withHasComments","updateDBFiles","inSharesList","mergeSpaceRootFiles","withLocks","inTrashRepository","enrichWithLocks","filesRecents","updateRecents","catch","e","logger","error","name","inFilesRepository","root","alias","spacesQueries","spaceRootFiles","map","f","updateRootFile","sharesQueries","shareRootFiles","userId","dbOptions","withSpaces","inPersonalSpace","ignoreChildShares","inSharesRepository","filesQueries","browseFiles","dbFile","IsRealPathIsDirAndExists","realPath","warn","message","HttpException","httpCode","parsePath","push","element","fs","readdir","withFileTypes","isDir","isDirectory","isFile","log","DEFAULT_FILTERS","has","verbose","path","join","filePath","relativeUrl","getProps","realPathFromRootFile","fileProps","shares","hasComments","syncs","compareAndUpdateFileProps","description","enabled","owner","JSON","stringify","fileName","dirName","fsFile","find","spaces","share","deleteDBFile","spaceEnv","spacesManager","url","split","deleteFiles","length","newAlias","uniqueRootAlias","updateRoot","clearCachePermissions","newName","uniqueRootName","locks","filesLockManager","browseParentChildLocks","Object","keys","filter","lock","davLock","fullName","email","ownerLogin","login","isExclusive","lockscope","LOCK_SCOPE","EXCLUSIVE","Logger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/spaces/services/spaces-browser.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, Injectable, Logger } from '@nestjs/common'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { configuration } from '../../../configuration/config.environment'\nimport { FileLock } from '../../files/interfaces/file-lock.interface'\nimport { FileProps } from '../../files/interfaces/file-props.interface'\nimport { FilesLockManager } from '../../files/services/files-lock-manager.service'\nimport { FilesQueries } from '../../files/services/files-queries.service'\nimport { FilesRecents } from '../../files/services/files-recents.service'\nimport { dirName, fileName, getProps } from '../../files/utils/files'\nimport { SharesQueries } from '../../shares/services/shares-queries.service'\nimport { USER_PERMISSION } from '../../users/constants/user'\nimport { UserModel } from '../../users/models/user.model'\nimport { LOCK_SCOPE } from '../../webdav/constants/webdav'\nimport { SpaceFiles } from '../interfaces/space-files.interface'\nimport { SpaceEnv } from '../models/space-env.model'\nimport { realPathFromRootFile, IsRealPathIsDirAndExists } from '../utils/paths'\nimport { SpacesManager } from './spaces-manager.service'\nimport { SpacesQueries } from './spaces-queries.service'\n\n@Injectable()\nexport class SpacesBrowser {\n private readonly logger = new Logger(SpacesBrowser.name)\n\n constructor(\n private readonly spacesManager: SpacesManager,\n private readonly spacesQueries: SpacesQueries,\n private readonly sharesQueries: SharesQueries,\n private readonly filesQueries: FilesQueries,\n private readonly filesLockManager: FilesLockManager,\n private readonly filesRecents: FilesRecents\n ) {}\n\n async browse(\n user: UserModel,\n space: SpaceEnv,\n options: {\n withLocks?: boolean\n withSpacesAndShares?: boolean\n withSyncs?: boolean\n withHasComments?: boolean\n } = {}\n ): Promise<SpaceFiles> {\n // check sync permission\n options.withSyncs = options.withSyncs && user.havePermission(USER_PERMISSION.DESKTOP_APP) && user.havePermission(USER_PERMISSION.DESKTOP_APP_SYNC)\n const spaceFiles: SpaceFiles = { files: [], hasRoots: false, permissions: space.browsePermissions() }\n const [fsFiles, dbFiles, rootFiles] = await Promise.all([\n this.parseFS(space),\n this.parseDB(user.id, space, options),\n this.parseRootFiles(user, space, {\n withShares: options.withSpacesAndShares,\n withHasComments: options.withHasComments,\n withSyncs: options.withSyncs\n })\n ])\n this.updateDBFiles(user, space, dbFiles, fsFiles, options)\n if (space.inSharesList) {\n // the share space includes shares as root files\n spaceFiles.files = [...rootFiles, ...fsFiles]\n spaceFiles.hasRoots = true\n } else {\n await this.mergeSpaceRootFiles(space, rootFiles, fsFiles, spaceFiles)\n }\n if (options.withLocks && !space.inTrashRepository) {\n // locks were removed when files were moved to the trash, no need to parse locks\n await this.enrichWithLocks(space, spaceFiles.files)\n }\n // update recents files\n this.filesRecents.updateRecents(user, space, spaceFiles.files).catch((e: Error) => this.logger.error(`${this.browse.name} - ${e}`))\n return spaceFiles\n }\n\n private async parseRootFiles(\n user: UserModel,\n space: SpaceEnv,\n options: {\n withShares?: boolean\n withHasComments?: boolean\n withSyncs?: boolean\n }\n ): Promise<FileProps[]> {\n if (space.inFilesRepository && space.id && !space.root.alias) {\n // list roots in the space\n return Promise.all((await this.spacesQueries.spaceRootFiles(user.id, space.id, options)).map((f) => this.updateRootFile(f, options)))\n } else if (space.inSharesList) {\n // list shares as roots\n return Promise.all((await this.sharesQueries.shareRootFiles(user, options)).map((f) => this.updateRootFile(f, options)))\n }\n return []\n }\n\n private async parseDB(\n userId: number,\n space: SpaceEnv,\n options: {\n withSpacesAndShares?: boolean\n withSyncs?: boolean\n withHasComments?: boolean\n }\n ): Promise<FileProps[]> {\n if (space.inSharesList) return []\n const dbOptions = {\n withSpaces: options.withSpacesAndShares && space.inPersonalSpace,\n withShares: options.withSpacesAndShares,\n withSyncs: options.withSyncs,\n withHasComments: options.withHasComments,\n ignoreChildShares: !space.inSharesRepository\n }\n return this.filesQueries.browseFiles(userId, space.dbFile, dbOptions)\n }\n\n private async parseFS(space: SpaceEnv): Promise<FileProps[]> {\n if (space.inSharesList) return []\n const fsFiles: FileProps[] = []\n try {\n await IsRealPathIsDirAndExists(space.realPath)\n } catch (e) {\n this.logger.warn(`${this.parseFS.name} - ${space.realPath} : ${e.message}`)\n throw new HttpException(e.message, e.httpCode)\n }\n for await (const f of this.parsePath(space)) {\n fsFiles.push(f)\n }\n return fsFiles\n }\n\n private async *parsePath(space: SpaceEnv): AsyncGenerator<FileProps> {\n try {\n for (const element of await fs.readdir(space.realPath, { withFileTypes: true })) {\n const isDir = element.isDirectory()\n if (!isDir && !element.isFile()) {\n this.logger.log(`${this.parsePath.name} - ignore special file : ${element.name}`)\n continue\n }\n if (!configuration.applications.files.showHiddenFiles && element.name[0] === '.') {\n this.logger.verbose(`${this.parsePath.name} - ignore filtered file : ${element.name}`)\n continue\n }\n const realPath = path.join(space.realPath, element.name)\n const filePath = path.join(space.relativeUrl, element.name)\n try {\n yield await getProps(realPath, filePath, isDir)\n } catch (e) {\n this.logger.warn(`${this.parsePath.name} - unable get stats from ${realPath} : ${e}`)\n }\n }\n } catch (e) {\n this.logger.error(`${this.parsePath.name} - unable to parse ${space.realPath} : ${e}`)\n }\n }\n\n private async updateRootFile(f: FileProps, options: { withShares?: boolean; withHasComments?: boolean; withSyncs?: boolean }): Promise<FileProps> {\n // get realpath\n const realPath = realPathFromRootFile(f)\n f.path = f.root.name\n try {\n const fileProps: FileProps = await getProps(realPath, f.path)\n if (options.withShares) {\n fileProps.shares = f.shares\n }\n if (options.withHasComments) {\n fileProps.hasComments = f.hasComments\n }\n if (options.withSyncs) {\n fileProps.syncs = f.syncs\n }\n if (f.id) {\n // f.id is null for external roots\n // todo: check if a db file referenced under external roots have an id and correctly parsed here\n this.filesQueries.compareAndUpdateFileProps(f, fileProps).catch((e: Error) => this.logger.error(`${this.updateRootFile.name} - ${e}`))\n fileProps.id = f.id\n }\n fileProps.root = {\n id: f.root.id,\n alias: f.root.alias,\n description: f.root.description,\n enabled: typeof f.root.enabled === 'undefined' ? true : f.root.enabled,\n permissions: f.root.permissions,\n owner: f.root.owner\n }\n return fileProps\n } catch (e) {\n this.logger.error(`${this.updateRootFile.name} - ${JSON.stringify(f)} - ${e}`)\n return { ...f, name: fileName(f.path), path: dirName(f.path), ...{ root: { ...f.root, enabled: false } } }\n }\n }\n\n private updateDBFiles(\n user: UserModel,\n space: SpaceEnv,\n dbFiles: FileProps[],\n fsFiles: FileProps[],\n options: {\n withSpacesAndShares?: boolean\n withSyncs?: boolean\n withHasComments?: boolean\n }\n ) {\n for (const dbFile of dbFiles) {\n const fsFile = fsFiles.find((f: FileProps) => dbFile.name === f.name)\n if (fsFile) {\n /* important: inherits from the file id in database */\n fsFile.id = dbFile.id\n if (options.withSpacesAndShares) {\n fsFile.spaces = dbFile.spaces\n fsFile.shares = dbFile.shares\n }\n if (options.withSyncs) {\n fsFile.syncs = dbFile.syncs\n }\n if (options.withHasComments) {\n fsFile.hasComments = dbFile.hasComments\n }\n this.filesQueries.compareAndUpdateFileProps(dbFile, fsFile).catch((e: Error) => this.logger.error(`${this.updateDBFiles.name} - ${e}`))\n } else {\n this.logger.warn(`${this.updateDBFiles.name} - missing ${dbFile.path}/${dbFile.name} (${dbFile.id}) from fs, delete it from db`)\n if (options.withSpacesAndShares) {\n if (dbFile.spaces) {\n for (const space of dbFile.spaces) {\n this.logger.warn(\n `${this.updateDBFiles.name} - ${dbFile.path}/${dbFile.name} (${dbFile.id}) will be removed from space : *${space.alias}* (${space.id})`\n )\n }\n }\n if (dbFile.shares) {\n for (const share of dbFile.shares) {\n this.logger.warn(\n `${this.updateDBFiles.name} - ${dbFile.path}/${dbFile.name} (${dbFile.id}) will be removed from share : *${share.alias}* (${share.id})`\n )\n }\n }\n }\n this.deleteDBFile(user, space, dbFile).catch((e: Error) => this.logger.error(`${this.updateDBFiles.name} - ${e}`))\n }\n }\n }\n\n private async deleteDBFile(user: UserModel, space: SpaceEnv, dbFile: FileProps) {\n const spaceEnv = await this.spacesManager.spaceEnv(user, path.join(space.url, dbFile.name).split('/'))\n this.filesQueries.deleteFiles(spaceEnv.dbFile, dbFile.isDir, true).catch((e: Error) => this.logger.error(`${this.deleteDBFile.name} - ${e}`))\n }\n\n private async mergeSpaceRootFiles(space: SpaceEnv, rootFiles: FileProps[], fsFiles: FileProps[], spaceFiles: SpaceFiles) {\n // merges root files in space files taking care of alias and name (file names must be unique)\n if (!rootFiles.length) {\n spaceFiles.files = fsFiles\n return\n }\n spaceFiles.hasRoots = true\n for (const f of rootFiles) {\n // check root alias (must be unique in the space)\n const newAlias: string = await this.spacesManager.uniqueRootAlias(\n space.id,\n f.root.alias,\n fsFiles.map((f) => f.name),\n true\n )\n if (newAlias) {\n this.logger.log(`${this.mergeSpaceRootFiles.name} - update space root alias (${f.root.id}) : ${f.root.alias} -> ${newAlias}`)\n // update in db\n this.spacesQueries\n .updateRoot({ alias: newAlias }, { id: f.root.id })\n .catch((e: Error) => this.logger.error(`${this.mergeSpaceRootFiles.name} - ${e}`))\n // cleanup cache\n this.spacesQueries\n .clearCachePermissions(space.alias, [f.root.alias, newAlias])\n .catch((e: Error) => this.logger.error(`${this.mergeSpaceRootFiles.name} - ${e}`))\n // assign\n f.root.alias = newAlias\n }\n // check root name (must be unique in the space)\n // f.name is equal to root name\n const newName: string = this.spacesManager.uniqueRootName(\n f.name,\n fsFiles.map((f) => f.name)\n )\n if (newName) {\n this.logger.log(`${this.mergeSpaceRootFiles.name} - update space root name (${f.root.id}) : ${f.name} -> ${newName}`)\n // update in db\n this.spacesQueries\n .updateRoot({ name: newName }, { id: f.root.id })\n .catch((e: Error) => this.logger.error(`${this.mergeSpaceRootFiles.name} - ${e}`))\n // assign\n f.name = newName\n }\n }\n spaceFiles.files = [...fsFiles, ...rootFiles]\n }\n\n private async enrichWithLocks(space: SpaceEnv, files: FileProps[]) {\n if (space.inSharesList) {\n return\n }\n const locks: Record<string, FileLock> = await this.filesLockManager.browseParentChildLocks(space.dbFile, false)\n if (!Object.keys(locks).length) return\n for (const f of files.filter((f) => (f.root && f.root.alias in locks) || (!f.root && f.name in locks))) {\n const lock: FileLock = f.root ? locks[f.root.alias] : locks[f.name]\n f.lock = {\n owner: lock?.davLock?.owner || `${lock.owner.fullName} (${lock.owner.email})`,\n ownerLogin: lock.owner.login,\n isExclusive: lock?.davLock?.lockscope ? lock?.davLock?.lockscope === LOCK_SCOPE.EXCLUSIVE : true\n }\n }\n }\n}\n"],"names":["SpacesBrowser","browse","user","space","options","withSyncs","havePermission","USER_PERMISSION","DESKTOP_APP","DESKTOP_APP_SYNC","spaceFiles","files","hasRoots","permissions","browsePermissions","fsFiles","dbFiles","rootFiles","Promise","all","parseFS","parseDB","id","parseRootFiles","withShares","withSpacesAndShares","withHasComments","updateDBFiles","inSharesList","mergeSpaceRootFiles","withLocks","inTrashRepository","enrichWithLocks","filesRecents","updateRecents","catch","e","logger","error","name","inFilesRepository","root","alias","spacesQueries","spaceRootFiles","map","f","updateRootFile","sharesQueries","shareRootFiles","userId","dbOptions","withSpaces","inPersonalSpace","ignoreChildShares","inSharesRepository","filesQueries","browseFiles","dbFile","IsRealPathIsDirAndExists","realPath","warn","message","HttpException","httpCode","parsePath","push","element","fs","readdir","withFileTypes","isDir","isDirectory","isFile","log","configuration","applications","showHiddenFiles","verbose","path","join","filePath","relativeUrl","getProps","realPathFromRootFile","fileProps","shares","hasComments","syncs","compareAndUpdateFileProps","description","enabled","owner","JSON","stringify","fileName","dirName","fsFile","find","spaces","share","deleteDBFile","spaceEnv","spacesManager","url","split","deleteFiles","length","newAlias","uniqueRootAlias","updateRoot","clearCachePermissions","newName","uniqueRootName","locks","filesLockManager","browseParentChildLocks","Object","keys","filter","lock","davLock","fullName","email","ownerLogin","login","isExclusive","lockscope","LOCK_SCOPE","EXCLUSIVE","Logger"],"mappings":"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"}
|