1 Commits

Author SHA1 Message Date
Willem Dantuma
8667001c01 Remove oauth 2026-03-25 21:08:18 +01:00
26 changed files with 85 additions and 2780 deletions

37
package-lock.json generated
View File

@@ -27,7 +27,6 @@
"@ngrx/router-store": "^21.0.1", "@ngrx/router-store": "^21.0.1",
"@ngrx/store": "^21.0.1", "@ngrx/store": "^21.0.1",
"@popperjs/core": "2.11.8", "@popperjs/core": "2.11.8",
"angular-oauth2-oidc": "^20.0.2",
"assert": "^2.1.0", "assert": "^2.1.0",
"bootstrap": "^5.3.8", "bootstrap": "^5.3.8",
"browserify-zlib": "^0.2.0", "browserify-zlib": "^0.2.0",
@@ -83,32 +82,31 @@
}, },
"dist/common": { "dist/common": {
"name": "@farmmaps/common", "name": "@farmmaps/common",
"version": "4.22.0-prerelease.2619", "version": "2.1.0",
"dependencies": { "dependencies": {
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },
"peerDependencies": { "peerDependencies": {
"@angular/common": "21.1.0", "@angular/common": "^21.1.0",
"@angular/core": "21.1.0", "@angular/core": "^21.1.0",
"@angular/forms": "21.1.0", "@angular/forms": "^21.1.0",
"@microsoft/signalr": "10.0.0", "@microsoft/signalr": "^10.0.0",
"@ng-bootstrap/ng-bootstrap": "^20.0.0", "@ng-bootstrap/ng-bootstrap": "^20.0.0",
"@ngrx/effects": "21.0.1", "@ngrx/effects": "^21.0.1",
"@ngrx/router-store": "21.0.1", "@ngrx/router-store": "^21.0.1",
"@ngrx/store": "21.0.1", "@ngrx/store": "^21.0.1",
"angular-oauth2-oidc": "20.0.2",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"moment": "^2.29.4", "moment": "^2.29.4",
"ngx-avatars": "1.10.1", "ngx-avatars": "^1.10.1",
"ngx-clipboard": "^16.0.0", "ngx-clipboard": "^16.0.0",
"ngx-image-cropper": "^7.0.0", "ngx-image-cropper": "^7.0.0",
"ngx-uploadx": "7.0.1", "ngx-uploadx": "^7.0.1",
"tassign": "^1.0.0" "tassign": "^1.0.0"
} }
}, },
"dist/common-map": { "dist/common-map": {
"name": "@farmmaps/common-map", "name": "@farmmaps/common-map",
"version": "4.22.0-prerelease.2620", "version": "2.0.0",
"dependencies": { "dependencies": {
"tslib": "^2.0.0" "tslib": "^2.0.0"
}, },
@@ -8897,19 +8895,6 @@
"node": ">= 14.0.0" "node": ">= 14.0.0"
} }
}, },
"node_modules/angular-oauth2-oidc": {
"version": "20.0.2",
"resolved": "https://registry.npmjs.org/angular-oauth2-oidc/-/angular-oauth2-oidc-20.0.2.tgz",
"integrity": "sha512-bMSXEQIuvgq8yqnsIatZggAvCJvY+pm7G8MK0tWCHR93UpFuNN+L5B6pY9CzRg8Ys+VVhkLIBx4zEHbJnv9icg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.5.2"
},
"peerDependencies": {
"@angular/common": ">=20.0.0",
"@angular/core": ">=20.0.0"
}
},
"node_modules/ansi-colors": { "node_modules/ansi-colors": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",

View File

@@ -30,7 +30,6 @@
"@ngrx/router-store": "^21.0.1", "@ngrx/router-store": "^21.0.1",
"@ngrx/store": "^21.0.1", "@ngrx/store": "^21.0.1",
"@popperjs/core": "2.11.8", "@popperjs/core": "2.11.8",
"angular-oauth2-oidc": "^20.0.2",
"assert": "^2.1.0", "assert": "^2.1.0",
"bootstrap": "^5.3.8", "bootstrap": "^5.3.8",
"browserify-zlib": "^0.2.0", "browserify-zlib": "^0.2.0",

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,6 @@
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"@microsoft/signalr": "^10.0.0", "@microsoft/signalr": "^10.0.0",
"ngx-uploadx": "^7.0.1", "ngx-uploadx": "^7.0.1",
"angular-oauth2-oidc": "^20.0.2",
"moment": "^2.29.4", "moment": "^2.29.4",
"ngx-avatars": "^1.10.1", "ngx-avatars": "^1.10.1",
"ngx-image-cropper": "^7.0.0", "ngx-image-cropper": "^7.0.0",

View File

@@ -4,7 +4,7 @@ import { IItemTypes } from '../models/item.types';
import { IListItem } from '../models/list.item'; import { IListItem } from '../models/list.item';
import { IUser } from '../models/user'; import { IUser } from '../models/user';
import { IItem } from '../models/item'; import { IItem } from '../models/item';
import { UserInfo } from 'angular-oauth2-oidc'; import { UserInfo } from '../models/user';
export const INITUSER = '[AppCommon] InitUser'; export const INITUSER = '[AppCommon] InitUser';
export const INITUSERSUCCESS = '[AppCommon] InitUserSuccess'; export const INITUSERSUCCESS = '[AppCommon] InitUserSuccess';

View File

@@ -1,8 +1,6 @@
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router'; import {RouterModule} from '@angular/router';
import {AuthCallbackComponent} from './components/auth-callback/auth-callback.component';
import {AuthCallbackGuard} from './components/auth-callback/auth-callback.guard';
import {NavBarGuard} from './services/nav-bar-guard.service'; import {NavBarGuard} from './services/nav-bar-guard.service';
import {FullScreenGuard} from './services/full-screen-guard.service'; import {FullScreenGuard} from './services/full-screen-guard.service';
import {SessionClearedComponent} from './components/session-cleared/session-cleared.component'; import {SessionClearedComponent} from './components/session-cleared/session-cleared.component';
@@ -11,10 +9,6 @@ import { ProductionGuard } from './services/production-guard.service';
const routes = [ const routes = [
{
path: 'cb',
component: AuthCallbackComponent
},
{ {
path: 'loggedout', path: 'loggedout',
component: SessionClearedComponent, component: SessionClearedComponent,

View File

@@ -3,9 +3,6 @@ import { NgModule, ModuleWithProviders, Injector, Optional, SkipSelf, inject, pr
import { DatePipe } from '@angular/common'; import { DatePipe } from '@angular/common';
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { HTTP_INTERCEPTORS } from '@angular/common/http';
// external modules
import { OAuthModule, OAuthService, OAuthStorage } from 'angular-oauth2-oidc';
//components //components
import { ItemTypeService } from './services/itemtype.service'; import { ItemTypeService } from './services/itemtype.service';
@@ -23,16 +20,13 @@ import { DownloadService } from './services/download.service';
import { GeolocatorService } from './services/geolocator.service'; import { GeolocatorService } from './services/geolocator.service';
import { WeatherService} from './services/weather.service'; import { WeatherService} from './services/weather.service';
import { AppConfig } from './shared/app.config'; import { AppConfig } from './shared/app.config';
import { AccessTokenInterceptor } from "./shared/accesstoken.interceptor";
import { appConfigFactory } from "./shared/app.config.factory"; import { appConfigFactory } from "./shared/app.config.factory";
import { AuthGuard } from './services/auth-guard.service'; import { AuthGuard } from './services/auth-guard.service';
import { NavBarGuard } from './services/nav-bar-guard.service'; import { NavBarGuard } from './services/nav-bar-guard.service';
import { PackageGuard } from './services/package-guard.service'; import { PackageGuard } from './services/package-guard.service';
import { FullScreenGuard } from './services/full-screen-guard.service'; import { FullScreenGuard } from './services/full-screen-guard.service';
import { AuthCallbackGuard } from './components/auth-callback/auth-callback.guard';
import { ResumableFileUploadService } from './components/resumable-file-upload/resumable-file-upload.service'; import { ResumableFileUploadService } from './components/resumable-file-upload/resumable-file-upload.service';
import { NgbDateNativeAdapter } from './services/date-adapter.service' import { NgbDateNativeAdapter } from './services/date-adapter.service'
import { AuthConfigFactory } from './shared/authconfigFactory';
import { StateSerializerService } from './services/state-serializer.service'; import { StateSerializerService } from './services/state-serializer.service';
import { PackageService } from './services/package.service'; import { PackageService } from './services/package.service';
import { PackagePreloadStrategy } from './services/package-preload-strategy.service'; import { PackagePreloadStrategy } from './services/package-preload-strategy.service';
@@ -58,12 +52,10 @@ export {
GeolocatorService, GeolocatorService,
WeatherService, WeatherService,
AppConfig, AppConfig,
AccessTokenInterceptor,
AuthGuard, AuthGuard,
NavBarGuard, NavBarGuard,
PackageGuard, PackageGuard,
FullScreenGuard, FullScreenGuard,
AuthCallbackGuard,
ResumableFileUploadService, ResumableFileUploadService,
NgbDateNativeAdapter, NgbDateNativeAdapter,
StateSerializerService, StateSerializerService,
@@ -79,9 +71,6 @@ export {
}; };
@NgModule({ @NgModule({
imports: [
OAuthModule.forRoot(),
]
}) })
export class AppCommonServiceModule { export class AppCommonServiceModule {
constructor(@Optional() @SkipSelf() parentModule: AppCommonServiceModule) { constructor(@Optional() @SkipSelf() parentModule: AppCommonServiceModule) {
@@ -97,14 +86,9 @@ export class AppCommonServiceModule {
AppConfig, AppConfig,
ItemTypeService, ItemTypeService,
provideAppInitializer(() => { provideAppInitializer(() => {
const initializerFn = (appConfigFactory)(inject(Injector), inject(AppConfig), inject(OAuthService), inject(AuthConfigFactory), inject(OAuthStorage), inject(ItemTypeService)); const initializerFn = (appConfigFactory)(inject(Injector), inject(AppConfig), inject(ItemTypeService));
return initializerFn(); return initializerFn();
}), }),
{
provide: HTTP_INTERCEPTORS,
useClass: AccessTokenInterceptor,
multi: true
},
DatePipe DatePipe
] ]
}; };

View File

@@ -8,7 +8,6 @@ import { FormsModule } from '@angular/forms';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { EffectsModule } from '@ngrx/effects'; import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store'; import { StoreModule } from '@ngrx/store';
import { OAuthModule } from 'angular-oauth2-oidc';
import { ClipboardModule } from 'ngx-clipboard'; import { ClipboardModule } from 'ngx-clipboard';
import { UploadxModule } from 'ngx-uploadx'; import { UploadxModule } from 'ngx-uploadx';
@@ -24,7 +23,6 @@ import { ImageCropperModule } from 'ngx-image-cropper';
import * as commonActions from './actions/app-common.actions'; import * as commonActions from './actions/app-common.actions';
import { AppMenuComponent } from './components/app-menu/app-menu.component'; import { AppMenuComponent } from './components/app-menu/app-menu.component';
import { AppComponent } from './components/app/app.component'; import { AppComponent } from './components/app/app.component';
import { AuthCallbackComponent } from './components/auth-callback/auth-callback.component';
import { AvatarComponent } from './components/avatar/avatar.component'; import { AvatarComponent } from './components/avatar/avatar.component';
import { BackButtonComponent } from './components/back-button/back-button.component'; import { BackButtonComponent } from './components/back-button/back-button.component';
import { EditImageModalComponent } from './components/edit-image-modal/edit-image-modal.component'; import { EditImageModalComponent } from './components/edit-image-modal/edit-image-modal.component';
@@ -71,25 +69,22 @@ import { IUrlType } from './models/url.type';
import { IUser } from './models/user'; import { IUser } from './models/user';
import { WeatherCurrentObservation } from './models/weatherCurrentObservation'; import { WeatherCurrentObservation } from './models/weatherCurrentObservation';
import * as commonReducers from './reducers/app-common.reducer'; import * as commonReducers from './reducers/app-common.reducer';
import { AuthConfigFactory, IAuthconfigFactory } from './shared/authconfigFactory';
import { SafePipe } from './shared/safe.pipe'; import { SafePipe } from './shared/safe.pipe';
import { SecureOAuthStorage } from './shared/secureOAuthStorage';
export const FM_COMMON_STARTPAGE = new InjectionToken<string>('fm-common-startpage'); export const FM_COMMON_STARTPAGE = new InjectionToken<string>('fm-common-startpage');
export { export {
Alert, AppComponent, AuthCallbackComponent, AuthConfigFactory, AvatarComponent, BackButtonComponent, commonActions, Alert, AppComponent, AvatarComponent, BackButtonComponent, commonActions,
commonReducers, EditImageModalComponent, commonReducers, EditImageModalComponent,
GradientComponent, GradientComponent,
GradientSelectComponent, HasClaimDirective, HasPackageDirective, HasRoleDirective, IAuthconfigFactory, IColor, IDataLayer, IEventMessage, IGradientstop, IItem, IItemLinkType, IItemTask, IItemType, IItemTypes, IJsonline, IListItem, IPackage, GradientSelectComponent, HasClaimDirective, HasPackageDirective, HasRoleDirective, IColor, IDataLayer, IEventMessage, IGradientstop, IItem, IItemLinkType, IItemTask, IItemType, IItemTypes, IJsonline, IListItem, IPackage,
IAclRights, IListItemAclRights, ISharedItem, IAclRights, IListItemAclRights, ISharedItem,
IPackages, IQueryState, ISenMLItem, Item, ItemLinkComponent, ItemTask, ITypeaheadItem, IUrlType, IUser, MenuBackgroundComponent, NotFoundComponent, IPackages, IQueryState, ISenMLItem, Item, ItemLinkComponent, ItemTask, ITypeaheadItem, IUrlType, IUser, MenuBackgroundComponent, NotFoundComponent,
NotImplementedComponent, PackageExistsDirective, ResumableFileUploadComponent, SafePipe, SecureOAuthStorage, SessionClearedComponent, SidePanelComponent, TagInputComponent, ThumbnailComponent, TimespanComponent, UserMenuComponent, WeatherCurrentObservation NotImplementedComponent, PackageExistsDirective, ResumableFileUploadComponent, SafePipe, SessionClearedComponent, SidePanelComponent, TagInputComponent, ThumbnailComponent, TimespanComponent, UserMenuComponent, WeatherCurrentObservation
}; };
@NgModule({ declarations: [ @NgModule({ declarations: [
AppComponent, AppComponent,
AuthCallbackComponent,
SidePanelComponent, SidePanelComponent,
SafePipe, SafePipe,
NotFoundComponent, NotFoundComponent,
@@ -123,7 +118,6 @@ export {
CommonModule, CommonModule,
AppComponent, AppComponent,
ResumableFileUploadComponent, ResumableFileUploadComponent,
AuthCallbackComponent,
SidePanelComponent, SidePanelComponent,
SafePipe, SafePipe,
NotFoundComponent, NotFoundComponent,
@@ -149,7 +143,6 @@ export {
AppCommonRoutingModule, AppCommonRoutingModule,
StoreModule.forFeature(MODULE_NAME, commonReducers.reducer), StoreModule.forFeature(MODULE_NAME, commonReducers.reducer),
EffectsModule.forFeature([commonEffects.AppCommonEffects]), EffectsModule.forFeature([commonEffects.AppCommonEffects]),
OAuthModule.forRoot(),
NgbModule, NgbModule,
FormsModule, FormsModule,
UploadxModule, UploadxModule,

View File

@@ -5,7 +5,6 @@ import { Subscription, Observable } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators'; import { distinctUntilChanged } from 'rxjs/operators';
import { Store, Action } from '@ngrx/store'; import { Store, Action } from '@ngrx/store';
import { IUser } from '../../models/user'; import { IUser } from '../../models/user';
import { OAuthService, OAuthErrorEvent } from 'angular-oauth2-oidc';
import { FM_COMMON_STARTPAGE } from '../../common.module'; import { FM_COMMON_STARTPAGE } from '../../common.module';
//AppCommon //AppCommon
@@ -19,13 +18,13 @@ import { AppConfig } from '../../shared/app.config';
import * as appReducers from '../../reducers/app-common.reducer'; import * as appReducers from '../../reducers/app-common.reducer';
@Component({ @Component({
selector: 'fm-app', selector: 'fm-app',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'], styleUrls: ['./app.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
standalone: false standalone: false
}) })
export class AppComponent implements OnInit, OnDestroy { export class AppComponent implements OnInit, OnDestroy {
@@ -64,7 +63,6 @@ export class AppComponent implements OnInit, OnDestroy {
private eventService$: EventService, private eventService$: EventService,
private healthCheckService$: HealthCheckService, private healthCheckService$: HealthCheckService,
private itemTypeService$: ItemTypeService, private itemTypeService$: ItemTypeService,
private oauthService$: OAuthService,
private appConfig$: AppConfig private appConfig$: AppConfig
) { ) {
} }
@@ -121,7 +119,6 @@ export class AppComponent implements OnInit, OnDestroy {
ngOnInit() { ngOnInit() {
this.InstallRouteEventHandler(); this.InstallRouteEventHandler();
this.InstallEventServiceEventHandler(); this.InstallEventServiceEventHandler();
this.InstallAuthenticationEventHandler();
this.InstallHealthCheck(); this.InstallHealthCheck();
} }
@@ -139,32 +136,6 @@ export class AppComponent implements OnInit, OnDestroy {
if (this.eventSub$) this.eventSub$.unsubscribe(); if (this.eventSub$) this.eventSub$.unsubscribe();
} }
private InstallAuthenticationEventHandler() {
// auth event handler
this.oauthService$.events.subscribe((event) => {
//console.debug(event.type);
if (event.type == 'token_error' || event.type == 'silent_refresh_timeout' || event.type == 'logout') {
const e = event as OAuthErrorEvent;
const p = e.params as any;
if (event.type == 'silent_refresh_timeout' || event.type == 'logout' || (p.error && p.error == 'login_required')) {
//console.debug("Session expired");
this.router.navigate(['loggedout'], { queryParams: { redirectTo: this.router.url } });
}
}
if (event.type == 'token_received') {
this.oauthService$.loadUserProfile();
this.store$.dispatch(new commonActions.InitUser());
}
});
if (this.oauthService$.hasValidAccessToken()) {
this.store$.dispatch(new commonActions.InitUser());
} else {
if (this.oauthService$.getRefreshToken() != null) {
this.oauthService$.refreshToken();
}
}
}
private InstallRouteEventHandler() { private InstallRouteEventHandler() {
const other = this; const other = this;
this.routerSub$ = this.router.events.subscribe(event => { this.routerSub$ = this.router.events.subscribe(event => {

View File

@@ -1,22 +0,0 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';
import { Location} from '@angular/common';
@Component({
selector: 'fm-auth-callback',
template: '<div></div>',
standalone: false
})
export class AuthCallbackComponent {
constructor(private router$: Router,private oauthService$:OAuthService) {
oauthService$.loadDiscoveryDocument().then(() => {
oauthService$.tryLoginCodeFlow().then(() => {
router$.navigateByUrl((oauthService$.state && oauthService$.state!="")?decodeURIComponent(oauthService$.state):"");
}).catch(() => {
router$.navigateByUrl("/");
});
})
}
}

View File

@@ -1,17 +0,0 @@
import { Router } from '@angular/router';
import { Injectable } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { } from '@angular/router';
@Injectable({
providedIn: 'root',
})
export class AuthCallbackGuard {
constructor(private router$: Router,private oauthService$:OAuthService) {}
canActivate() {
this.router$.navigateByUrl(this.oauthService$.state);
return false;
}
}

View File

@@ -1,15 +1,12 @@
import { Directive, ViewContainerRef,TemplateRef,OnInit,Input,OnDestroy } from '@angular/core'; import { Directive, ViewContainerRef,TemplateRef,OnInit,Input } from '@angular/core';
import { Store} from '@ngrx/store'; import { Store} from '@ngrx/store';
import * as appCommonReducer from '../../reducers/app-common.reducer' import * as appCommonReducer from '../../reducers/app-common.reducer'
import { IPackages } from '../../models/package'; import { Observable } from 'rxjs';
import { Observable, Subscription } from 'rxjs';
import { skip } from 'rxjs/operators';
import {OAuthService } from 'angular-oauth2-oidc';
import { IUser } from '../../models/user'; import { IUser } from '../../models/user';
@Directive({ @Directive({
selector: '[fm-hasclaim]', selector: '[fm-hasclaim]',
standalone: false standalone: false
}) })
export class HasClaimDirective implements OnInit{ export class HasClaimDirective implements OnInit{
@Input('fm-hasclaim') claim:string; @Input('fm-hasclaim') claim:string;

View File

@@ -1,5 +1,4 @@
import { Injectable, OnDestroy } from '@angular/core'; import { Injectable, OnDestroy } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { Subject , Subscription } from 'rxjs'; import { Subject , Subscription } from 'rxjs';
import { HttpClient } from "@angular/common/http"; import { HttpClient } from "@angular/common/http";
import { UploadxService, UploadState,UploadxOptions} from 'ngx-uploadx'; import { UploadxService, UploadState,UploadxOptions} from 'ngx-uploadx';
@@ -19,7 +18,7 @@ export class ResumableFileUploadService implements OnDestroy{
private _eventSub:Subscription; private _eventSub:Subscription;
private initialized = false; private initialized = false;
constructor(private httpClient: HttpClient,private oauthService: OAuthService,private uploadService: UploadxService,public appConfig: AppConfig) { constructor(private httpClient: HttpClient,private uploadService: UploadxService,public appConfig: AppConfig) {
} }
@@ -31,7 +30,6 @@ export class ResumableFileUploadService implements OnDestroy{
if(!this.initialized) { if(!this.initialized) {
this._eventSub=this.uploadService.init({ this._eventSub=this.uploadService.init({
endpoint:this.endPoint(), endpoint:this.endPoint(),
token:() => this.oauthService.getAccessToken(),
chunkSize: 2097152}).subscribe((uploadState:UploadState) => { chunkSize: 2097152}).subscribe((uploadState:UploadState) => {
this.handleState(uploadState); this.handleState(uploadState);
} ); } );

View File

@@ -1,5 +1,4 @@
import { Component, OnInit,Input } from '@angular/core'; import { Component, OnInit,Input } from '@angular/core';
import { OAuthService} from 'angular-oauth2-oidc'
import { IUser } from '../../models/user'; import { IUser } from '../../models/user';
import {Store} from '@ngrx/store'; import {Store} from '@ngrx/store';
import * as appReducers from '../../reducers/app-common.reducer'; import * as appReducers from '../../reducers/app-common.reducer';
@@ -16,13 +15,13 @@ export class UserMenuComponent implements OnInit {
@Input() user:IUser; @Input() user:IUser;
@Input() showMenu:boolean; @Input() showMenu:boolean;
constructor(private oauthService:OAuthService, private store: Store<appReducers.State>) { } constructor(private store: Store<appReducers.State>) { }
ngOnInit(): void { ngOnInit(): void {
} }
getProvider():string | null { getProvider():string | null {
const ownedClaims = this.oauthService.getIdentityClaims(); const ownedClaims = [];//TODO FIX THIS
if(ownedClaims) { if(ownedClaims) {
if (ownedClaims["idp"] != "local") { if (ownedClaims["idp"] != "local") {
return ownedClaims["idp"]; return ownedClaims["idp"];

View File

@@ -1,6 +1,5 @@
import { Injectable, Inject, LOCALE_ID } from '@angular/core'; import { Injectable, Inject, LOCALE_ID } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { OAuthService,UserInfo } from 'angular-oauth2-oidc';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Actions,ofType,createEffect } from '@ngrx/effects'; import { Actions,ofType,createEffect } from '@ngrx/effects';
import { of,from,zip } from 'rxjs'; import { of,from,zip } from 'rxjs';
@@ -13,27 +12,13 @@ import { UserService } from '../services/user.service';
import { IItemTypes } from '../models/item.types'; import { IItemTypes } from '../models/item.types';
import { IListItem } from '../models/list.item'; import { IListItem } from '../models/list.item';
import {StateSerializerService} from '../services/state-serializer.service'; import {StateSerializerService} from '../services/state-serializer.service';
import { IUser } from '../common.module';
import { UserInfo } from '../models/user';
@Injectable() @Injectable()
export class AppCommonEffects { export class AppCommonEffects {
locale: string; locale: string;
login$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.LOGIN),
withLatestFrom(this.store$.select(appCommonReducers.selectGetInitialized)),
mergeMap(([action, initialized]) => {
const a = (action as appCommonActions.Login);
this.oauthService$.initCodeFlow(a.url,{"prompt":"login"});
return [];
})),{dispatch:false});
logout$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.LOGOUT),
mergeMap((action) => {
this.oauthService$.revokeTokenAndLogout();
return [];
})),{dispatch:false});
loadItemTypes$ = createEffect(() => this.actions$.pipe( loadItemTypes$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.LOADITEMTYPES), ofType(appCommonActions.LOADITEMTYPES),
switchMap((action) => { switchMap((action) => {
@@ -43,21 +28,16 @@ export class AppCommonEffects {
} }
))); )));
//TODO FIX THIS
initUser$ = createEffect(() => this.actions$.pipe( initUser$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.INITUSER), ofType(appCommonActions.INITUSER),
first(), first(),
switchMap((action) => { switchMap((action) => {
return zip(this.userService$.getCurrentUser(),from(this.oauthService$.loadUserProfile())).pipe( let user :IUser = {claims:[],searchable:true}
switchMap(([user,userInfo]) => { let userInfo : UserInfo = {sub:"aabbccdd"}
if (location.hostname === 'localhost' || user.language === undefined || user.language === this.locale) return of(new appCommonActions.InitUserSuccess(user,userInfo))
{ }
return of(new appCommonActions.InitUserSuccess(user,userInfo as UserInfo)) )));
}
return of(new appCommonActions.SwitchLanguage(user.language))
}),
catchError(error => of(new appCommonActions.Fail(error))))
}
)));
switchLanguage$ = createEffect(() => this.actions$.pipe( switchLanguage$ = createEffect(() => this.actions$.pipe(
ofType(appCommonActions.SWITCHLANGUAGE), ofType(appCommonActions.SWITCHLANGUAGE),
@@ -213,19 +193,12 @@ export class AppCommonEffects {
ofType(appCommonActions.ONLINE), ofType(appCommonActions.ONLINE),
switchMap((action) => { switchMap((action) => {
//console.debug("Online: Check token"); //console.debug("Online: Check token");
if(!this.oauthService$.hasValidAccessToken()) {
//console.debug("No valid token, try to refresh");
if(this.oauthService$.getRefreshToken() != null ) {
//console.debug("We have a refresh token");
this.oauthService$.refreshToken();
}
}
return of(undefined); return of(undefined);
})),{dispatch:false}); })),{dispatch:false});
constructor(private actions$: Actions, private store$: Store<appCommonReducers.State>, private oauthService$: OAuthService, private itemService$: ItemService, private folderService$:FolderService, private userService$: UserService, private router$: Router, private stateSerializerService$:StateSerializerService, @Inject(LOCALE_ID) locale: string) { constructor(private actions$: Actions, private store$: Store<appCommonReducers.State>, private itemService$: ItemService, private folderService$:FolderService, private userService$: UserService, private router$: Router, private stateSerializerService$:StateSerializerService, @Inject(LOCALE_ID) locale: string) {
this.locale = locale; this.locale = locale;
store$.dispatch(new appCommonActions.LoadItemTypes()); store$.dispatch(new appCommonActions.LoadItemTypes());
} }

View File

@@ -16,4 +16,9 @@ export interface IUser {
searchable: boolean; searchable: boolean;
newsletter?: boolean; newsletter?: boolean;
language?: string; language?: string;
}
export interface UserInfo {
sub: string;
[key: string]: any;
} }

View File

@@ -3,7 +3,6 @@ import { Router, Route, ActivatedRouteSnapshot, RouterStateSnapshot, UrlSegment,
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
@@ -15,7 +14,7 @@ import * as appCommonReducer from '../reducers/app-common.reducer';
}) })
export class AuthGuard { export class AuthGuard {
constructor(private oauthService: OAuthService, private router: Router, private store: Store<appCommonReducer.State>) { } constructor(private router: Router, private store: Store<appCommonReducer.State>) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree | Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
//console.debug("AuthGuard->canActivate", route, state); //console.debug("AuthGuard->canActivate", route, state);
@@ -36,36 +35,38 @@ export class AuthGuard {
return this.checkLogin(route.path, null); return this.checkLogin(route.path, null);
} }
//TODO FIX THIS
checkLogin(url: string, route: ActivatedRouteSnapshot): boolean { checkLogin(url: string, route: ActivatedRouteSnapshot): boolean {
//console.debug("AuthGuard->checkLogin", url, route); //console.debug("AuthGuard->checkLogin", url, route);
if (!this.oauthService.hasValidAccessToken()) { // if (!this.oauthService.hasValidAccessToken()) {
//console.debug("No valid token"); // //console.debug("No valid token");
this.oauthService.initCodeFlow(url); // this.oauthService.initCodeFlow(url);
return false; // return false;
} else { // } else {
const requiredRoleClaim = route.data.role; // const requiredRoleClaim = route.data.role;
if (!requiredRoleClaim) { return true; } // if (!requiredRoleClaim) { return true; }
const ownedClaims = this.oauthService.getIdentityClaims(); // const ownedClaims = this.oauthService.getIdentityClaims();
if (!ownedClaims) { // if (!ownedClaims) {
//console.debug("No owned claims"); // //console.debug("No owned claims");
return false; // return false;
} // }
const ownedRoleClaims: string[] = ownedClaims['role']; // const ownedRoleClaims: string[] = ownedClaims['role'];
if (!ownedRoleClaims) { // if (!ownedRoleClaims) {
// console.debug("No owned role claims"); // // console.debug("No owned role claims");
return false; // return false;
} // }
if (Array.isArray(ownedRoleClaims)) { // if (Array.isArray(ownedRoleClaims)) {
if (ownedRoleClaims.findIndex(r => r === requiredRoleClaim) <= -1) { // if (ownedRoleClaims.findIndex(r => r === requiredRoleClaim) <= -1) {
//console.debug("No required role claim", ownedRoleClaims, requiredRoleClaim); // //console.debug("No required role claim", ownedRoleClaims, requiredRoleClaim);
return false; // return false;
} // }
} // }
else { // else {
if (ownedRoleClaims !== requiredRoleClaim) { console.debug("No required role claim", ownedRoleClaims, requiredRoleClaim); return false; } // if (ownedRoleClaims !== requiredRoleClaim) { console.debug("No required role claim", ownedRoleClaims, requiredRoleClaim); return false; }
} // }
//console.debug("Has required role claim", requiredRoleClaim); // //console.debug("Has required role claim", requiredRoleClaim);
return true; // return true;
} // }
return true;
} }
} }

View File

@@ -1,5 +1,4 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { Observable, ReplaySubject, Subscription, timer } from 'rxjs'; import { Observable, ReplaySubject, Subscription, timer } from 'rxjs';
import { catchError, take } from 'rxjs/operators'; import { catchError, take } from 'rxjs/operators';
import { IItem } from '../models/item'; import { IItem } from '../models/item';
@@ -12,7 +11,7 @@ export class CacheService {
private proxyCacheMap: { [key: string]: ReplaySubject<IItem[]> } = {}; private proxyCacheMap: { [key: string]: ReplaySubject<IItem[]> } = {};
private subscriptionMap: { [key: string]: Subscription } = {}; private subscriptionMap: { [key: string]: Subscription } = {};
constructor(private itemService: ItemService, public oauthService: OAuthService) { constructor(private itemService: ItemService) {
timer(0, REFRESH_INTERVAL).subscribe(() => { timer(0, REFRESH_INTERVAL).subscribe(() => {
this.subscriptionMap = {}; this.subscriptionMap = {};
}) })
@@ -23,7 +22,7 @@ export class CacheService {
this.proxyCacheMap[itemType] = new ReplaySubject(1); this.proxyCacheMap[itemType] = new ReplaySubject(1);
} }
if (this.oauthService.getAccessToken() != null && !this.subscriptionMap[itemType]) { if (!this.subscriptionMap[itemType]) {
this.subscriptionMap[itemType] = this.itemService.getItemList(itemType) this.subscriptionMap[itemType] = this.itemService.getItemList(itemType)
.pipe( .pipe(
catchError(error => { catchError(error => {

View File

@@ -1,7 +1,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { IEventMessage } from '../models/event.message'; import { IEventMessage } from '../models/event.message';
import { Subject, timer } from 'rxjs'; import { Subject, timer } from 'rxjs';
import { OAuthService } from 'angular-oauth2-oidc';
import { HubConnection, HubConnectionBuilder, LogLevel ,HttpTransportType,HubConnectionState} from '@microsoft/signalr'; import { HubConnection, HubConnectionBuilder, LogLevel ,HttpTransportType,HubConnectionState} from '@microsoft/signalr';
import { AppConfig } from "../shared/app.config"; import { AppConfig } from "../shared/app.config";
@@ -16,7 +15,7 @@ export class EventService {
private _apiEndPoint: string; private _apiEndPoint: string;
public authenticated = false; public authenticated = false;
constructor(private oauthService: OAuthService, private appConfig: AppConfig) { constructor(private appConfig: AppConfig) {
this._apiEndPoint = appConfig.getConfig("apiEndPoint"); this._apiEndPoint = appConfig.getConfig("apiEndPoint");
this._connection = new HubConnectionBuilder().withUrl(`${ this._apiEndPoint}/eventHub`, this._connection = new HubConnectionBuilder().withUrl(`${ this._apiEndPoint}/eventHub`,
{ transport: HttpTransportType.WebSockets, { transport: HttpTransportType.WebSockets,
@@ -41,17 +40,9 @@ export class EventService {
}); });
} }
private Authenticate() { private Authenticate() { //TODO FIX THIS
const accessToken = this.oauthService.getAccessToken(); this._connection.send('authenticate', "token");
if (this.oauthService.hasValidAccessToken()) {
this._connection.send('authenticate', this.oauthService.getAccessToken());
this.authenticated=true; this.authenticated=true;
} else {
//try again after half a second
setTimeout(() => {
this.Authenticate();
}, 800);
}
} }
Stop() { Stop() {

View File

@@ -1,40 +0,0 @@
import { Injectable, Injector, Inject, DOCUMENT } from '@angular/core';
import { AppConfig } from "./app.config";
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { OAuthService } from 'angular-oauth2-oidc';
import { Observable } from 'rxjs';
@Injectable()
export class AccessTokenInterceptor implements HttpInterceptor {
private oauthService: OAuthService = null;
private audience: string[] = [];
private base: string;
constructor(private injector: Injector, private appConfig: AppConfig, @Inject(DOCUMENT) private document: any) {
this.base = document.location.href;
}
hasAudience(url: string): boolean {
const u = new URL(url,this.base);
for (const audience of this.audience) {
if (u.href.startsWith(audience)) return true;
}
return false;
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.oauthService && this.hasAudience(request.url)) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.oauthService.getAccessToken()}`
}
});
} else {
this.oauthService = this.injector.get(OAuthService, null);
if(this.oauthService && this.oauthService.issuer) this.audience = (this.appConfig.getConfig("audience") as string).split(",");
}
return next.handle(request);
}
}

View File

@@ -1,23 +1,15 @@
import { Injector } from '@angular/core'; import { Injector } from '@angular/core';
import { Location} from '@angular/common';
import { Router,UrlSerializer } from '@angular/router';
import { AuthConfig, OAuthService, OAuthErrorEvent, OAuthStorage } from 'angular-oauth2-oidc';
import { AppConfig } from "./app.config"; import { AppConfig } from "./app.config";
import {ItemTypeService} from '../services/itemtype.service'; import {ItemTypeService} from '../services/itemtype.service';
import { IAuthconfigFactory } from './authconfigFactory';
export function appConfigFactory(injector:Injector, appConfig: AppConfig, oauthService: OAuthService, authconfigFactory:IAuthconfigFactory,authStorage:OAuthStorage,itemtypeService:ItemTypeService): () => Promise<any> { export function appConfigFactory(injector:Injector, appConfig: AppConfig, itemtypeService:ItemTypeService): () => Promise<any> {
return (): Promise<any> => { return (): Promise<any> => {
return new Promise<void>((resolve,reject) => { return new Promise<void>((resolve,reject) => {
appConfig.load().then(() => { appConfig.load().then(() => {
itemtypeService.load(appConfig); itemtypeService.load(appConfig);
oauthService.configure(authconfigFactory.getAuthConfig(appConfig)); }).then(() => resolve()).catch(() => reject());
oauthService.setStorage(authStorage);
oauthService.setupAutomaticSilentRefresh();
}).then(() => oauthService.loadDiscoveryDocument()
).then(() => resolve()).catch(() => reject());
}); });
} }
} }

View File

@@ -1,22 +0,0 @@
import { AuthConfig } from 'angular-oauth2-oidc';
import {AppConfig} from './app.config';
export interface IAuthconfigFactory {
getAuthConfig(appConfig: AppConfig): AuthConfig;
}
export class AuthConfigFactory implements IAuthconfigFactory {
getAuthConfig(appConfig: AppConfig): AuthConfig {
const authConfig: AuthConfig = new AuthConfig();
authConfig.issuer = appConfig.getConfig("issuer");
authConfig.redirectUri = window.location.origin + "/cb";
authConfig.silentRefreshRedirectUri = window.location.origin + "/silent-refresh.html";
authConfig.clientId = appConfig.getConfig("clientId");
authConfig.customQueryParams = { audience: appConfig.getConfig("audience") };
authConfig.scope = "openid profile email";
authConfig.oidc = true;
authConfig.disableAtHashCheck = true;
authConfig.requireHttps = appConfig.getConfig("requireHttps");
return authConfig;
}
}

View File

@@ -1,36 +0,0 @@
import {OAuthStorage} from 'angular-oauth2-oidc';
import {Inject, Injectable} from '@angular/core';
@Injectable()
export class SecureOAuthStorage extends OAuthStorage {
private storage = {};
secureKey(key:string): boolean {
if(key == "nonce") return false;
if(key == "PKCI_verifier") return false;
return true;
}
getItem(key: string): string {
if(this.secureKey(key)) {
return this.storage[key];
} else {
return window.sessionStorage.getItem(key);
}
}
removeItem(key: string): void {
if(this.secureKey(key)) {
delete this.storage[key];
} else {
window.sessionStorage.removeItem(key);
}
}
setItem(key: string, data: string): void {
if(this.secureKey(key)) {
this.storage[key]=data;
} else {
window.sessionStorage.setItem(key,data);
}
}
}

View File

@@ -6,7 +6,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { AppCommonModule,AppCommonServiceModule,AuthConfigFactory,FM_COMMON_STARTPAGE } from '@farmmaps/common'; import { AppCommonModule,AppCommonServiceModule,FM_COMMON_STARTPAGE } from '@farmmaps/common';
import {AppRootComponent} from './app.component'; import {AppRootComponent} from './app.component';
@@ -18,8 +18,6 @@ import {AppRoutingModule} from './app-routing.module';
import { LogoComponent } from './logo/logo.component'; import { LogoComponent } from './logo/logo.component';
import { MenuComponent } from './menu/menu.component'; import { MenuComponent } from './menu/menu.component';
import {RegisterDeviceComponent} from './registerdevice/registerdevice.component'; import {RegisterDeviceComponent} from './registerdevice/registerdevice.component';
import { SecureOAuthStorage} from '@farmmaps/common';
import { OAuthStorage } from 'angular-oauth2-oidc';
import {Id4AuthconfigFactory} from './id4AuthconfigFactory'; import {Id4AuthconfigFactory} from './id4AuthconfigFactory';
import { TestComponent } from './test/test.component'; import { TestComponent } from './test/test.component';
import { LandingpageComponent } from './landingpage/landingpage.component'; import { LandingpageComponent } from './landingpage/landingpage.component';
@@ -85,11 +83,6 @@ export const metaReducers: MetaReducer<any>[] = [debug];
EffectsModule.forRoot([]), EffectsModule.forRoot([]),
], ],
providers: [ providers: [
AuthConfigFactory,
{
provide:AuthConfigFactory,
useClass:Id4AuthconfigFactory
},
{ {
provide: FM_COMMON_STARTPAGE, provide: FM_COMMON_STARTPAGE,
useValue: '/map' useValue: '/map'

View File

@@ -1,23 +0,0 @@
import { IAuthconfigFactory, AppConfig } from '@farmmaps/common';
import { AuthConfig } from 'angular-oauth2-oidc';
import { Injectable } from "@angular/core";
@Injectable()
export class Id4AuthconfigFactory implements IAuthconfigFactory {
constructor() {
}
getAuthConfig(appConfig: AppConfig): AuthConfig {
const authConfig: AuthConfig = new AuthConfig();
authConfig.issuer = appConfig.getConfig("issuer");
authConfig.redirectUri = window.location.origin + "/cb";
authConfig.clientId = appConfig.getConfig("clientId");
authConfig.customQueryParams = { audience: appConfig.getConfig("audience") };
authConfig.scope = "openid profile api offline_access";
authConfig.disableAtHashCheck = true;
authConfig.responseType = "code";
authConfig.requireHttps = appConfig.getConfig("requireHttps");
return authConfig;
}
}

View File

@@ -1,22 +0,0 @@
import {IAuthconfigFactory,AppConfig} from '@farmmaps/common';
import {AuthConfig} from 'angular-oauth2-oidc';
export class LocalAuthconfigFactory implements IAuthconfigFactory {
getAuthConfig(appConfig:AppConfig): AuthConfig {
const authConfig: AuthConfig = new AuthConfig();
authConfig.issuer = appConfig.getConfig("issuer");
authConfig.redirectUri = window.location.origin + "/cb";
authConfig.silentRefreshRedirectUri = window.location.origin + "/silent-refresh.html";
authConfig.clientId = appConfig.getConfig("clientId");
authConfig.customQueryParams = { audience: appConfig.getConfig("audience") };
authConfig.scope = "openid profile email";
authConfig.oidc = true;
authConfig.disableAtHashCheck = true;
authConfig.openUri = uri => {
window.alert("OK "+uri);
}
authConfig.requireHttps = appConfig.getConfig("requireHttps");
return authConfig;
}
}