Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add angular auth lib and add config key to angular-integration-interface #222

Merged
merged 12 commits into from
Apr 16, 2024
Merged
46 changes: 46 additions & 0 deletions libs/angular-auth/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"],
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "ocx",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "ocx",
"style": "kebab-case"
}
],
"no-restricted-syntax": [
"off",
{
"selector": "CallExpression[callee.object.name=\"console\"][callee.property.name=/^(debug|info|time|timeEnd|trace)$/]"
}
]
}
},
{
"files": ["*.html"],
"extends": ["plugin:@nx/angular-template"],
"rules": {}
},
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": "error"
}
}
]
}
7 changes: 7 additions & 0 deletions libs/angular-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# angular-auth

This library was generated with [Nx](https://nx.dev).

## Running unit tests

Run `nx test angular-auth` to execute the unit tests.
22 changes: 22 additions & 0 deletions libs/angular-auth/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* eslint-disable */
export default {
displayName: 'angular-auth',
preset: '../../jest.preset.js',
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
coverageDirectory: '../../coverage/libs/angular-auth',
transform: {
'^.+\\.(ts|mjs|js|html)$': [
'jest-preset-angular',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
},
],
},
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
'jest-preset-angular/build/serializers/ng-snapshot',
'jest-preset-angular/build/serializers/html-comment',
],
}
9 changes: 9 additions & 0 deletions libs/angular-auth/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/libs/angular-auth",
"lib": {
"entryFile": "src/index.ts"
},
"assets": ["CHANGELOG.md", "./assets/**"]
}

16 changes: 16 additions & 0 deletions libs/angular-auth/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@onecx/angular-auth",
"version": "4.13.2",
"peerDependencies": {
"@angular/common": ">=15.2.7",
"@angular/core": ">=15.2.7",
"@onecx/angular-integration-interface": "^4",
"@onecx/integration-interface": "^4",
"keycloak-angular": "^13.0.0",
"keycloak-js": "^18.0.0",
"rxjs": "~7.8.0"
},
"publishConfig": {
"access": "public"
}
}
63 changes: 63 additions & 0 deletions libs/angular-auth/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"name": "angular-auth",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/angular-auth/src",
"prefix": "ocx",
"tags": [],
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/angular:package",
"outputs": [
"{workspaceRoot}/dist/{projectRoot}"
],
"options": {
"project": "libs/angular-auth/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "libs/angular-auth/tsconfig.lib.prod.json"
},
"development": {
"tsConfig": "libs/angular-auth/tsconfig.lib.json"
}
},
"defaultConfiguration": "production"
},
"test": {
"executor": "@nx/jest:jest",
"outputs": [
"{workspaceRoot}/coverage/{projectRoot}"
],
"options": {
"jestConfig": "libs/angular-auth/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": [
"libs/angular-auth/**/*.ts",
"libs/angular-auth/**/*.html",
"libs/angular-auth/package.json"
]
}
},
"release": {
"executor": "nx-release:build-update-publish",
"options": {
"libName": "portal-integration-angular"
}
}
}
}
1 change: 1 addition & 0 deletions libs/angular-auth/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './lib/angular-auth.module'
33 changes: 33 additions & 0 deletions libs/angular-auth/src/lib/angular-auth.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { APP_INITIALIZER, NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { HTTP_INTERCEPTORS } from '@angular/common/http'
import { ConfigurationService } from '@onecx/angular-integration-interface'
import { TokenInterceptor } from './token.interceptor'
import { AuthService } from './auth.service'
import { AuthServiceWrapper } from './auth-service-wrapper'
import { KeycloakAuthService } from './auth_services/keycloak-auth.service'
import { KeycloakService } from 'keycloak-angular'

function appInitializer(configService: ConfigurationService, authService: AuthService) {
return async () => {
await configService.isInitialized
await authService.init()
}
}

@NgModule({
imports: [CommonModule],
providers: [
AuthServiceWrapper,
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true },
{
provide: APP_INITIALIZER,
useFactory: appInitializer,
deps: [ConfigurationService, AuthServiceWrapper],
multi: true,
},
KeycloakAuthService,
KeycloakService,
],
})
export class AngularAuthModule {}
51 changes: 51 additions & 0 deletions libs/angular-auth/src/lib/auth-service-wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { filter } from 'rxjs/internal/operators/filter'
import { AuthService } from './auth.service'
import { EventsTopic } from '@onecx/integration-interface'
import { AppStateService, CONFIG_KEY, ConfigurationService } from '@onecx/angular-integration-interface'
import { Injectable, Injector } from '@angular/core'
import { KeycloakAuthService } from './auth_services/keycloak-auth.service'
@Injectable()
export class AuthServiceWrapper {
private eventsTopic$ = new EventsTopic()
private authService: AuthService | undefined

constructor(
private configService: ConfigurationService,
private appStateService: AppStateService,
private injector: Injector
) {
this.eventsTopic$
.pipe(filter((e) => e.type === 'authentication#logoutButtonClicked'))
.subscribe(() => this.authService?.logout())
}
async init(): Promise<boolean | undefined> {
await this.configService.isInitialized

this.initializeAuthService()
const initResult = this.getInitResult()
return initResult
}
async getInitResult(): Promise<boolean | undefined> {
const initResult = await this.authService?.init()

if (initResult) {
await this.appStateService.isAuthenticated$.publish()
}
return initResult
}
getHeaderValues(): Record<string, string> {
return this.authService?.getHeaderValues() ?? {}
}

initializeAuthService(): void {
const serviceTypeConfig = this.configService.getProperty(CONFIG_KEY.AUTH_SERVICE) ?? 'keycloak'
switch (serviceTypeConfig) {
case 'keycloak':
this.authService = this.injector.get(KeycloakAuthService)
break
// TODO: Extend the other cases in the future
default:
throw new Error('Configured AuthService not found')
}
}
}
7 changes: 7 additions & 0 deletions libs/angular-auth/src/lib/auth.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface AuthService {
init(): Promise<boolean>

getHeaderValues(): Record<string, string>

logout(): void
}
Loading
Loading