mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2026-09-09 18:02:54 +00:00
ACS-11861 Sharable link redirects to Login Page (#5206)
* [ACS-11861]: adds publicUrl check * [ACS-11861]: UTs * [ACS-11861]: brings in minimatch dependency * [ACS-11861]: sonar fix
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
"katex": "^0.16.21",
|
||||
"material-icons": "^1.13.12",
|
||||
"mermaid": "^11.15.0",
|
||||
"minimatch": "^10.2.5",
|
||||
"minimatch-browser": "^1.0.0",
|
||||
"ngx-markdown": "19.1.1",
|
||||
"pdfjs-dist": "5.1.91",
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
import { AppService } from './app.service';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import {
|
||||
AppConfigService,
|
||||
AuthenticationService,
|
||||
NoopTranslateModule,
|
||||
NotificationService,
|
||||
@@ -43,15 +44,24 @@ import {
|
||||
SharedLinksApiService,
|
||||
UploadService
|
||||
} from '@alfresco/adf-content-services';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { RepositoryInfo, VersionInfo } from '@alfresco/js-api';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { ContentApiService } from './content-api.service';
|
||||
import { AppSettingsService, UserProfileService } from '@alfresco/aca-shared';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
|
||||
interface ApiUnauthorizedError {
|
||||
status: number;
|
||||
response: {
|
||||
req?: {
|
||||
url?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
describe('AppService', () => {
|
||||
let service: AppService;
|
||||
let auth: AuthenticationService;
|
||||
@@ -95,7 +105,9 @@ describe('AppService', () => {
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
snapshot: {}
|
||||
snapshot: {
|
||||
queryParams: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -222,6 +234,63 @@ describe('AppService', () => {
|
||||
expect(contentApi.getRepositoryInformation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('Init with unauthorized api error', () => {
|
||||
let appConfigService: AppConfigService;
|
||||
let router: Router;
|
||||
let matDialog: MatDialog;
|
||||
let alfrescoApiService: AlfrescoApiService;
|
||||
let navigateSpy: jasmine.Spy;
|
||||
let closeAllSpy: jasmine.Spy;
|
||||
let apiErrorListener: (error: ApiUnauthorizedError) => void;
|
||||
|
||||
const setupUnauthorizedErrorListener = (currentUrl: string): void => {
|
||||
spyOn(auth, 'isLoggedIn').and.returnValue(false);
|
||||
spyOn(alfrescoApiService, 'isExcludedErrorListener').and.returnValue(false);
|
||||
spyOn(appConfigService, 'get').and.callFake((key: string, defaultValue?: any) => (key === 'oauth2.publicUrls' ? ['/public/**'] : defaultValue));
|
||||
spyOnProperty(router, 'url', 'get').and.returnValue(currentUrl);
|
||||
closeAllSpy = spyOn(matDialog, 'closeAll');
|
||||
navigateSpy = spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
|
||||
|
||||
const apiInstance = alfrescoApiService.getInstance();
|
||||
spyOn(apiInstance, 'on').and.callFake((eventName: string | symbol, listener: (...args: unknown[]) => void) => {
|
||||
if (eventName === 'error') {
|
||||
apiErrorListener = listener;
|
||||
}
|
||||
|
||||
return apiInstance;
|
||||
});
|
||||
|
||||
service.init();
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
appConfigService = TestBed.inject(AppConfigService);
|
||||
router = TestBed.inject(Router);
|
||||
matDialog = TestBed.inject(MatDialog);
|
||||
alfrescoApiService = TestBed.inject(AlfrescoApiService);
|
||||
});
|
||||
|
||||
it('should navigate to login on 401 for non-public url when user is logged out', () => {
|
||||
setupUnauthorizedErrorListener('/private/page');
|
||||
|
||||
apiErrorListener({ status: 401, response: { req: { url: '/api/private' } } });
|
||||
|
||||
expect(closeAllSpy).toHaveBeenCalled();
|
||||
expect(navigateSpy).toHaveBeenCalledWith(['/login'], {
|
||||
queryParams: { redirectUrl: '/private/page' }
|
||||
});
|
||||
});
|
||||
|
||||
it('should not navigate to login on 401 for public url when user is logged out', () => {
|
||||
setupUnauthorizedErrorListener('/public/home');
|
||||
|
||||
apiErrorListener({ status: 401, response: { req: { url: '/api/public' } } });
|
||||
|
||||
expect(closeAllSpy).not.toHaveBeenCalled();
|
||||
expect(navigateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should load user profile on login', async () => {
|
||||
const person: any = { id: 'person' };
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ import { ShellAppService } from '@alfresco/adf-core/shell';
|
||||
import { AppSettingsService } from './app-settings.service';
|
||||
import { UserProfileService } from './user-profile.service';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { minimatch } from 'minimatch';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -133,7 +134,10 @@ export class AppService implements ShellAppService {
|
||||
init(): void {
|
||||
this.alfrescoApiService.getInstance().on('error', (error: { status: number; response: any }) => {
|
||||
if (error.status === 401 && !this.alfrescoApiService.isExcludedErrorListener(error?.response?.req?.url)) {
|
||||
if (!this.authenticationService.isLoggedIn()) {
|
||||
const publicUrls: string[] = this.config.get('oauth2.publicUrls', []);
|
||||
const isPublicUrl = publicUrls.some((pattern) => minimatch(this.router.url, pattern));
|
||||
|
||||
if (!this.authenticationService.isLoggedIn() && !isPublicUrl) {
|
||||
this.matDialog.closeAll();
|
||||
|
||||
let redirectUrl = this.activatedRoute.snapshot.queryParams['redirectUrl'];
|
||||
|
||||
Reference in New Issue
Block a user