Commit 10d156dd authored by François Agneray's avatar François Agneray
Browse files

#53 => done

parent a2c0e5b5
Pipeline #4783 passed with stages
in 10 minutes and 4 seconds
......@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [3.6.0]
- In progress...
## Added
- #53: Authentication is optional (environment: authenticationEnabled)
### Changed
- #52: Update dependencies (Angular v11, ngrx v11, ...)
......
......@@ -13,11 +13,7 @@ list:
@echo " status > display $(NAME_APP) container status"
@echo " test > run $(NAME_APP) tests"
@echo " test-watch > run $(NAME_APP) tests on every file change"
@echo " report > open the code coverage report in a browser (only available for Linux)"
@echo " build > generate the angular dist application (html, css, js)"
@echo " build-sdb-lam > generate the angular dist application (SDB LAM Prod Version)"
@echo " build-sdb-lal > generate the angular dist application (SDB LAL Prod Version)"
@echo " build-sdb-cc > generate the angular dist application (SDB CC Prod Version)"
@echo " logs > display $(NAME_APP) container logs"
@echo " shell > shell into $(NAME_APP) container"
@echo ""
......@@ -48,29 +44,11 @@ test:
test-watch:
@docker exec -ti $(NAME_APP) ng test
report:
xdg-open coverage/client/index.html
build:
@docker build -t anis-node conf-dev && docker run --init -it --rm --user $(UID):$(GID) \
-v $(CURDIR):/project \
-w /project anis-node ng build --prod --base-href /admin/
build-sdb-lam:
@docker build -t anis-node conf-dev && docker run --init -it --rm --user $(UID):$(GID) \
-v $(CURDIR):/project \
-w /project anis-node ng build --configuration=sdb-lam --base-href /sdb/admin/
build-sdb-lal:
@docker build -t anis-node conf-dev && docker run --init -it --rm --user $(UID):$(GID) \
-v $(CURDIR):/project \
-w /project anis-node ng build --configuration=sdb-lal --base-href /sdb/admin/
build-sdb-cc:
@docker build -t anis-node conf-dev && docker run --init -it --rm --user $(UID):$(GID) \
-v $(CURDIR):/project \
-w /project anis-node ng build --configuration=sdb-cc --base-href /sdb/admin/
logs:
@docker logs -f -t $(NAME_APP)
......
......@@ -33,10 +33,11 @@ To list all operations availables just type `make` in your terminal at the root
- To install all dependancies : `make install`
- To start/stop/restart/status all services : `make start|stop|restart|status`
- To display logs for all services : `make logs`
- To open a shell command into anis-admin container : `make shell`
- To execute tests suite : `make test`
- To execute tests suite on every file change : `make test-watch`
- To generate anis-admin application : `make build`
- To display logs for all services : `make logs`
- To open a shell command into anis-admin container : `make shell`
## Web interface
......
......@@ -60,30 +60,6 @@
"maximumError": "10kb"
}
]
},
"sdb-lam": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.sdb-lam.ts"
}
]
},
"sdb-lal": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.sdb-lal.ts"
}
]
},
"sdb-cc": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.sdb-cc.ts"
}
]
}
}
},
......
......@@ -8,7 +8,7 @@ import { UnauthorizedComponent } from './core/containers/unauthorized.component'
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'unauthorized', component: UnauthorizedComponent },
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: '', redirectTo: 'instance-list', pathMatch: 'full' },
{ path: '**', component: NotFoundPageComponent }
];
......
......@@ -7,15 +7,16 @@ import { EffectsModule } from '@ngrx/effects';
import { initializeKeycloakAnis } from './init.keycloak';
import { reducer } from './auth.reducer';
import { AuthEffects } from './auth.effects';
import { environment } from 'src/environments/environment';
@NgModule({
imports: [
KeycloakAngularModule,
environment.authenticationEnabled ? KeycloakAngularModule : [],
StoreModule.forFeature('auth', reducer),
EffectsModule.forFeature([ AuthEffects ])
environment.authenticationEnabled ? EffectsModule.forFeature([ AuthEffects ]): []
],
providers: [
initializeKeycloakAnis
environment.authenticationEnabled ? initializeKeycloakAnis: []
]
})
export class AuthModule { }
......@@ -4,8 +4,11 @@ import {
Router,
RouterStateSnapshot,
} from '@angular/router';
import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root',
})
......@@ -21,28 +24,24 @@ export class AuthGuard extends KeycloakAuthGuard {
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
// If authorization is not enabled return true
if (!environment.authenticationEnabled) {
return true;
}
// Force the user to log in if currently unauthenticated.
if (!this.authenticated) {
this.router.navigateByUrl('/login');
return false;
}
// If authenticated but not admin go to unauthorized page.
if(!this.roles.includes('anis_admin')) {
this.router.navigateByUrl('/unauthorized');
return false;
}
// Else return true;
return true;
// Get the roles required from the route.
//const requiredRoles = route.data.roles;
// Allow the user to to proceed if no additional roles are required to access the route.
/* if (!(requiredRoles instanceof Array) || requiredRoles.length === 0) {
return true;
} */
// Allow the user to proceed if all the required roles are present.
//return requiredRoles.every((role) => this.roles.includes(role));
}
}
......@@ -23,7 +23,7 @@
</a>
</li>
</ul>
<span id="dropdown-menu" dropdown>
<span *ngIf="authenticationEnabled()" id="dropdown-menu" dropdown>
<button id="button-basic" dropdownToggle type="button" class="btn btn-light" aria-controls="dropdown-basic">
<span class="fa-stack theme-color">
<span class="fas fa-circle fa-2x"></span>
......@@ -60,10 +60,10 @@
</button>
<ul id="basic-link-dropdown" *dropdownMenu class="dropdown-menu dropdown-menu-right dropdown-up" role="menu"
aria-labelledby="basic-link">
<li role="menuitem">
<li *ngIf="authenticationEnabled()" role="menuitem">
<span class="dropdown-item font-italic">{{ userProfile.email }}</span>
</li>
<li class="divider dropdown-divider"></li>
<li *ngIf="authenticationEnabled()" class="divider dropdown-divider"></li>
<li role="menuitem">
<a class="dropdown-item" routerLink="/instance">
<span class="fas fa-home fa-fw"></span> Instances
......@@ -79,14 +79,14 @@
<span class="fas fa-wrench fa-fw"></span> Settings
</a>
</li>
<li class="divider dropdown-divider"></li>
<li role="menuitem">
<li *ngIf="authenticationEnabled()" class="divider dropdown-divider"></li>
<li *ngIf="authenticationEnabled()" role="menuitem">
<a class="dropdown-item pointer" (click)="emitOpenEditProfile()">
<span class="fas fa-id-card"></span> Edit profile
</a>
</li>
<li class="divider dropdown-divider"></li>
<li role="menuitem">
<li *ngIf="authenticationEnabled()" class="divider dropdown-divider"></li>
<li *ngIf="authenticationEnabled()" role="menuitem">
<a class="dropdown-item pointer text-danger" (click)="logout.emit()">
<span class="fas fa-sign-out-alt fa-fw"></span> Sign Out
</a>
......
......@@ -15,6 +15,10 @@ export class NavComponent {
isCollapsed = true;
baseHref: string = environment.baseHref;
authenticationEnabled(): boolean {
return environment.authenticationEnabled;
}
emitLogout() {
this.logout.emit();
}
......
<header>
<app-nav *ngIf="(isAuthenticated | async) && (isAnisAdmin() | async)" [userProfile]="userProfile | async" (logout)="logout()" (openEditProfile)="openEditProfile()">
<app-nav *ngIf="!authenticationEnabled() || (isAuthenticated | async) && (isAnisAdmin() | async)" [userProfile]="userProfile | async" (logout)="logout()" (openEditProfile)="openEditProfile()">
</app-nav>
</header>
<main role="main" class="pb-4">
<router-outlet></router-outlet>
</main>
<footer *ngIf="(isAuthenticated | async) && (isAnisAdmin() | async)" class="footer mt-auto bg-light">
<footer *ngIf="!authenticationEnabled() || (isAuthenticated | async) && (isAnisAdmin() | async)" class="footer mt-auto bg-light">
<div class="container my-3">
<div class="row justify-content-center mb-3">
<small>&copy; ANIS 2014 - {{ year }}</small>
......
......@@ -9,6 +9,7 @@ import * as authActions from '../../auth/auth.action';
import * as authSelector from '../../auth/auth.selector';
import { UserProfile } from '../../auth/user-profile.model';
import { VERSIONS } from '../../../settings/settings';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-root',
......@@ -31,6 +32,10 @@ export class AppComponent {
this.userRoles = store.select(authSelector.getUserRoles);
}
authenticationEnabled(): boolean {
return environment.authenticationEnabled;
}
logout(): void {
this.store.dispatch(new authActions.LogoutAction());
}
......
......@@ -19,33 +19,45 @@ import { GroupComponent } from './containers/group/group.component';
import { NewGroupComponent } from './containers/group/new-group.component';
import { EditGroupComponent } from './containers/group/edit-group.component';
import { AuthGuard } from '../core/auth.guard';
import { environment } from 'src/environments/environment';
const routes: Routes = [
{ path: 'instance-list', canActivate: [AuthGuard], component: InstanceComponent },
{ path: 'new-instance', canActivate: [AuthGuard], component: NewInstanceComponent },
{ path: 'edit-instance/:iname', canActivate: [AuthGuard], component: EditInstanceComponent },
{ path: 'configure-instance/:iname', canActivate: [AuthGuard], component: ConfigureInstanceComponent },
{ path: 'configure-instance/:iname/group', canActivate: [AuthGuard], component: GroupComponent },
{ path: 'configure-instance/:iname/new-group', canActivate: [AuthGuard], component: NewGroupComponent },
{ path: 'configure-instance/:iname/edit-group/:id', canActivate: [AuthGuard], component: EditGroupComponent },
{ path: 'configure-instance/:iname/new-dataset', canActivate: [AuthGuard], component: NewDatasetComponent },
{ path: 'configure-instance/:iname/edit-dataset/:dname', canActivate: [AuthGuard], component: EditDatasetComponent },
{ path: 'configure-instance/:iname/configure-dataset/:dname', canActivate: [AuthGuard], component: AttributeComponent },
{ path: 'instance-list', component: InstanceComponent },
{ path: 'new-instance', component: NewInstanceComponent },
{ path: 'edit-instance/:iname', component: EditInstanceComponent },
{ path: 'configure-instance/:iname', component: ConfigureInstanceComponent },
{ path: 'configure-instance/:iname/group', component: GroupComponent },
{ path: 'configure-instance/:iname/new-group', component: NewGroupComponent },
{ path: 'configure-instance/:iname/edit-group/:id', component: EditGroupComponent },
{ path: 'configure-instance/:iname/new-dataset', component: NewDatasetComponent },
{ path: 'configure-instance/:iname/edit-dataset/:dname', component: EditDatasetComponent },
{ path: 'configure-instance/:iname/configure-dataset/:dname', component: AttributeComponent },
{
path: 'project', component: ProjectPageComponent, canActivate: [AuthGuard], children: [
path: 'project', component: ProjectPageComponent, children: [
{ path: '', redirectTo: 'project-list', pathMatch: 'full' },
{ path: 'project-list', component: ProjectComponent },
{ path: 'database-list', component: DatabaseComponent }
]
},
{ path: 'new-project', canActivate: [AuthGuard], component: NewProjectComponent },
{ path: 'edit-project/:name', canActivate: [AuthGuard], component: EditProjectComponent },
{ path: 'new-database', canActivate: [AuthGuard], component: NewDatabaseComponent },
{ path: 'edit-database/:id', canActivate: [AuthGuard], component: EditDatabaseComponent }
{ path: 'new-project', component: NewProjectComponent },
{ path: 'edit-project/:name', component: EditProjectComponent },
{ path: 'new-database', component: NewDatabaseComponent },
{ path: 'edit-database/:id', component: EditDatabaseComponent }
];
const routesGuarded = routes.map(r=> {
if (environment.authenticationEnabled) {
return {
...r,
canActivate: [AuthGuard]
};
} else {
return r;
}
});
@NgModule({
imports: [RouterModule.forChild(routes)],
imports: [RouterModule.forChild(routesGuarded)],
exports: [RouterModule]
})
export class MetamodelRoutingModule { }
......
......@@ -2,7 +2,8 @@ export const environment = {
production: true,
apiUrl: '/server',
baseHref: '/admin',
ssoAuthUrl: 'https://anis-dev.lam.fr/auth',
authenticationEnabled: true,
ssoAuthUrl: 'https://keycloak.lam.fr/auth/',
ssoRealm: 'anis',
ssoClientId: 'anis-dev',
ssoLoginRedirectUri: '/',
......
export const environment = {
production: true,
apiUrl: '/sdb/server',
baseHref: '/sdb/admin',
ssoAuthUrl: 'https://admin.svom.eu/keycloak/',
ssoRealm: 'svom-fsc',
ssoClientId: 'FSC_SPA_WEB',
ssoLoginRedirectUri: '/',
ssoLogoutRedirectUri: '/login'
};
export const environment = {
production: true,
apiUrl: '/sdb/server',
baseHref: '/sdb/admin',
ssoAuthUrl: 'https://admin.svom.eu/keycloak/',
ssoRealm: 'svom-fsc',
ssoClientId: 'FSC_SPA_WEB_LAL',
ssoLoginRedirectUri: '/',
ssoLogoutRedirectUri: '/login'
};
export const environment = {
production: true,
apiUrl: '/sdb/server',
baseHref: '/sdb/admin',
ssoAuthUrl: 'https://keycloak.lam.fr/auth/',
ssoRealm: 'cesamsi',
ssoClientId: 'sdb-export',
ssoLoginRedirectUri: '/',
ssoLogoutRedirectUri: '/login'
};
......@@ -6,6 +6,7 @@ export const environment = {
production: false,
apiUrl: 'http://localhost:8080',
baseHref: '/',
authenticationEnabled: false,
ssoAuthUrl: 'http://localhost:8180/auth',
ssoRealm: 'anis',
ssoClientId: 'anis-admin',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment