From 1d9df66aad061cf8bfebf2a19c2374ea2d03971a Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 2 Nov 2020 13:02:29 +0100 Subject: [PATCH 1/3] MOBILE-3320 ci: Use production build in Travis --- .travis.yml | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index aba384359..64da6f723 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,4 @@ cache: npm script: - npm run lint - npm run test:ci - - npm run build + - npm run build:prod diff --git a/package.json b/package.json index 8e4d4db8a..c77787bb4 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "ng": "ng", "start": "ng serve", "build": "ng build", + "build:prod": "ng build --prod", "test": "jest --verbose", "test:ci": "jest -ci --runInBand --verbose", "test:watch": "jest --watch", From 7a3dd22189ca391afac468f72348d1da24b886c4 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 2 Nov 2020 15:16:40 +0100 Subject: [PATCH 2/3] MOBILE-3320 routes: Define dynamic mainmenu routes --- src/app/app.module.ts | 2 + .../core/mainmenu/mainmenu-routing.module.ts | 74 ++++++++++++------- src/app/core/mainmenu/pages/more/more.html | 20 ++--- src/app/core/settings/pages/about/about.html | 2 +- .../settings/pages/about/about.page.module.ts | 6 ++ src/app/core/settings/pages/app/app.page.ts | 2 +- src/app/core/settings/settings-init.module.ts | 31 ++++++++ .../core/settings/settings-routing.module.ts | 11 +-- 8 files changed, 101 insertions(+), 47 deletions(-) create mode 100644 src/app/core/settings/settings-init.module.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index daf0e9600..2c865e6c2 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -59,6 +59,7 @@ import { initCoreSyncDB } from '@services/sync.db'; import { CoreEmulatorModule } from '@core/emulator/emulator.module'; import { CoreLoginModule } from '@core/login/login.module'; import { CoreCoursesModule } from '@core/courses/courses.module'; +import { CoreSettingsInitModule } from '@core/settings/settings-init.module'; import { setSingletonsInjector } from '@singletons/core.singletons'; @@ -88,6 +89,7 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader { CoreEmulatorModule, CoreLoginModule, CoreCoursesModule, + CoreSettingsInitModule, ], providers: [ { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, diff --git a/src/app/core/mainmenu/mainmenu-routing.module.ts b/src/app/core/mainmenu/mainmenu-routing.module.ts index 9e45e3e5e..1afad8941 100644 --- a/src/app/core/mainmenu/mainmenu-routing.module.ts +++ b/src/app/core/mainmenu/mainmenu-routing.module.ts @@ -12,36 +12,60 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; +import { InjectionToken, Injector, ModuleWithProviders, NgModule } from '@angular/core'; +import { RouterModule, ROUTES, Routes } from '@angular/router'; + +import { CoreArray } from '@/app/singletons/array'; import { CoreMainMenuPage } from './pages/menu/menu.page'; import { CoreMainMenuMorePage } from './pages/more/more.page'; -const routes: Routes = [ - { - path: '', - component: CoreMainMenuPage, - children: [ - { - path: 'home', // @todo: Add this route dynamically. - loadChildren: () => import('./pages/home/home.page.module').then( m => m.CoreHomePageModule), - }, - { - path: 'more', - children: [ - { - path: '', - component: CoreMainMenuMorePage, - }, - ], - }, - ], - }, -]; +function buildMainMenuRoutes(injector: Injector): Routes { + const routes = CoreArray.flatten(injector.get(MAIN_MENU_ROUTES, [])); + + return [ + { + path: '', + component: CoreMainMenuPage, + children: [ + { + path: 'home', // @todo: Add this route dynamically. + loadChildren: () => import('./pages/home/home.page.module').then(m => m.CoreHomePageModule), + }, + { + path: 'more', + children: [ + { + path: '', + component: CoreMainMenuMorePage, + }, + ...routes, + ], + }, + ...routes, + // @todo handle 404. + ], + }, + ]; +} + +export const MAIN_MENU_ROUTES = new InjectionToken('MAIN_MENU_ROUTES'); @NgModule({ - imports: [RouterModule.forChild(routes)], + providers: [ + { provide: ROUTES, multi: true, useFactory: buildMainMenuRoutes, deps: [Injector] }, + ], exports: [RouterModule], }) -export class CoreMainMenuRoutingModule {} +export class CoreMainMenuRoutingModule { + + static forChild(routes: Routes): ModuleWithProviders { + return { + ngModule: CoreMainMenuRoutingModule, + providers: [ + { provide: MAIN_MENU_ROUTES, multi: true, useValue: routes }, + ], + }; + } + +} diff --git a/src/app/core/mainmenu/pages/more/more.html b/src/app/core/mainmenu/pages/more/more.html index 92ed80e86..96b7bbbd4 100644 --- a/src/app/core/mainmenu/pages/more/more.html +++ b/src/app/core/mainmenu/pages/more/more.html @@ -25,7 +25,7 @@ + (click)="openHandler(handler)" title="{{ handler.title | translate }}" detail="true" detail>

{{ handler.title | translate}}

@@ -36,55 +36,55 @@
+ [capture]="item.type == 'app'" [inApp]="item.type == 'inappbrowser'" class="core-moremenu-customitem" detail>

{{item.label}}

+ class="core-moremenu-customitem" detail>

{{item.label}}

- +

{{ 'core.scanqr' | translate }}

+ title="{{ 'core.mainmenu.website' | translate }}" detail>

{{ 'core.mainmenu.website' | translate }}

+ title="{{ 'core.mainmenu.help' | translate }}" detail>

{{ 'core.mainmenu.help' | translate }}

- +

{{ 'core.settings.preferences' | translate }}

- +

{{ logoutLabel | translate }}

- +

{{ 'core.settings.appsettings' | translate }}

diff --git a/src/app/core/settings/pages/about/about.html b/src/app/core/settings/pages/about/about.html index 8a47fbf42..081653499 100644 --- a/src/app/core/settings/pages/about/about.html +++ b/src/app/core/settings/pages/about/about.html @@ -21,7 +21,7 @@ {{ 'core.settings.privacypolicy' | translate }}
- + {{ 'core.settings.deviceinfo' | translate }} diff --git a/src/app/core/settings/pages/about/about.page.module.ts b/src/app/core/settings/pages/about/about.page.module.ts index b63096fc8..82fb94b64 100644 --- a/src/app/core/settings/pages/about/about.page.module.ts +++ b/src/app/core/settings/pages/about/about.page.module.ts @@ -28,6 +28,12 @@ const routes: Routes = [ path: '', component: CoreSettingsAboutPage, }, + { + path: 'deviceinfo', + loadChildren: () => + import('@core/settings/pages/deviceinfo/deviceinfo.page.module') + .then(m => m.CoreSettingsDeviceInfoPageModule), + }, ]; @NgModule({ diff --git a/src/app/core/settings/pages/app/app.page.ts b/src/app/core/settings/pages/app/app.page.ts index 01b9fd442..7caeb0245 100644 --- a/src/app/core/settings/pages/app/app.page.ts +++ b/src/app/core/settings/pages/app/app.page.ts @@ -59,7 +59,7 @@ export class CoreSettingsAppPage { openSettings(page: string, params?: Params): void { this.selectedPage = page; // this.splitviewCtrl!.push(page, params); - this.router.navigate(['../'+page], { relativeTo: this.route, queryParams: params }); + this.router.navigate([page], { relativeTo: this.route, queryParams: params }); } } diff --git a/src/app/core/settings/settings-init.module.ts b/src/app/core/settings/settings-init.module.ts new file mode 100644 index 000000000..6810084e2 --- /dev/null +++ b/src/app/core/settings/settings-init.module.ts @@ -0,0 +1,31 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { Routes } from '@angular/router'; + +import { CoreMainMenuRoutingModule } from '@core/mainmenu/mainmenu-routing.module'; + +const routes: Routes = [ + { + path: 'settings', + loadChildren: () => import('@core/settings/settings.module').then(m => m.CoreSettingsModule), + }, +]; + +@NgModule({ + imports: [CoreMainMenuRoutingModule.forChild(routes)], + exports: [CoreMainMenuRoutingModule], +}) +export class CoreSettingsInitModule {} diff --git a/src/app/core/settings/settings-routing.module.ts b/src/app/core/settings/settings-routing.module.ts index a391ebf1b..20554d6dd 100644 --- a/src/app/core/settings/settings-routing.module.ts +++ b/src/app/core/settings/settings-routing.module.ts @@ -20,18 +20,9 @@ const routes: Routes = [ path: 'about', loadChildren: () => import('./pages/about/about.page.module').then( m => m.CoreSettingsAboutPageModule), }, - { - path: 'deviceinfo', - loadChildren: () => import('./pages/deviceinfo/deviceinfo.page.module').then( m => m.CoreSettingsDeviceInfoPageModule), - }, - { - path: 'app', - loadChildren: () => import('./pages/app/app.page.module').then( m => m.CoreSettingsAppPageModule), - }, { path: '', - redirectTo: 'app', - pathMatch: 'full', + loadChildren: () => import('./pages/app/app.page.module').then( m => m.CoreSettingsAppPageModule), }, ]; From d8aca979060b1c568c26251d8524e0c4881e8bf0 Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 2 Nov 2020 13:58:18 +0100 Subject: [PATCH 3/3] MOBILE-3320 routes: Guard authenticated routes --- src/app/app-routing.module.ts | 11 ++++---- src/app/app.component.html | 2 ++ src/app/app.component.test.ts | 2 ++ src/app/core/login/services/helper.ts | 4 +-- src/app/guards/auth.guard.ts | 40 +++++++++++++++++++++++++++ tsconfig.app.json | 1 + tsconfig.json | 1 + tsconfig.test.json | 1 + 8 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 src/app/guards/auth.guard.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 388b3be63..2a8d0f660 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -15,12 +15,9 @@ import { NgModule } from '@angular/core'; import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; +import { AuthGuard } from '@guards/auth.guard'; + const routes: Routes = [ - { - path: '', - redirectTo: 'login', - pathMatch: 'full', - }, { path: 'login', loadChildren: () => import('./core/login/login.module').then( m => m.CoreLoginModule), @@ -30,8 +27,10 @@ const routes: Routes = [ loadChildren: () => import('./core/settings/settings.module').then( m => m.CoreSettingsModule), }, { - path: 'mainmenu', + path: '', loadChildren: () => import('./core/mainmenu/mainmenu.module').then( m => m.CoreMainMenuModule), + canActivate: [AuthGuard], + canLoad: [AuthGuard], }, ]; diff --git a/src/app/app.component.html b/src/app/app.component.html index 9b06aaff5..94c506c21 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,3 +1,5 @@ + + diff --git a/src/app/app.component.test.ts b/src/app/app.component.test.ts index 72baacfd2..9036f4b7b 100644 --- a/src/app/app.component.test.ts +++ b/src/app/app.component.test.ts @@ -54,4 +54,6 @@ describe('AppComponent', () => { expect(navController.navigateRoot).toHaveBeenCalledWith('/login/sites'); }); + it.todo('shows loading while app isn\'t ready'); + }); diff --git a/src/app/core/login/services/helper.ts b/src/app/core/login/services/helper.ts index 126f29958..abeee7248 100644 --- a/src/app/core/login/services/helper.ts +++ b/src/app/core/login/services/helper.ts @@ -720,7 +720,7 @@ export class CoreLoginHelperProvider { if (options?.redirectPage == CoreLoginHelperProvider.OPEN_COURSE) { // Load the main menu first, and then open the course. try { - await this.navCtrl.navigateRoot('/mainmenu'); + await this.navCtrl.navigateRoot('/'); } finally { // @todo: Open course. } @@ -729,7 +729,7 @@ export class CoreLoginHelperProvider { const queryParams: Params = Object.assign({}, options); delete queryParams.navigationOptions; - await this.navCtrl.navigateRoot('/mainmenu', { + await this.navCtrl.navigateRoot('/', { queryParams, ...options?.navigationOptions, }); diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts new file mode 100644 index 000000000..9319a4b36 --- /dev/null +++ b/src/app/guards/auth.guard.ts @@ -0,0 +1,40 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable } from '@angular/core'; +import { Router, CanLoad, CanActivate, UrlTree } from '@angular/router'; + +import { CoreInit } from '@services/init'; +import { CoreSites } from '@services/sites'; + +@Injectable({ providedIn: 'root' }) +export class AuthGuard implements CanLoad, CanActivate { + + constructor(private router: Router) {} + + canActivate(): Promise { + return this.guard(); + } + + canLoad(): Promise { + return this.guard(); + } + + private async guard(): Promise { + await CoreInit.instance.ready(); + + return CoreSites.instance.isLoggedIn() || this.router.parseUrl('/login'); + } + +} diff --git a/tsconfig.app.json b/tsconfig.app.json index ae7b6267b..72a9b5489 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -17,6 +17,7 @@ "@components/*": ["app/components/*"], "@core/*": ["app/core/*"], "@directives/*": ["app/directives/*"], + "@guards/*": ["app/guards/*"], "@pipes/*": ["app/pipes/*"], "@services/*": ["app/services/*"], "@singletons/*": ["app/singletons/*"] diff --git a/tsconfig.json b/tsconfig.json index b2401e638..1bc3663d1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,6 +36,7 @@ "@components/*": ["app/components/*"], "@core/*": ["app/core/*"], "@directives/*": ["app/directives/*"], + "@guards/*": ["app/guards/*"], "@pipes/*": ["app/pipes/*"], "@services/*": ["app/services/*"], "@singletons/*": ["app/singletons/*"], diff --git a/tsconfig.test.json b/tsconfig.test.json index 06e4ff33d..c62c89cf9 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -22,6 +22,7 @@ "@components/*": ["app/components/*"], "@core/*": ["app/core/*"], "@directives/*": ["app/directives/*"], + "@guards/*": ["app/guards/*"], "@pipes/*": ["app/pipes/*"], "@services/*": ["app/services/*"], "@singletons/*": ["app/singletons/*"],