@@ -689,6 +689,7 @@ | |||
<exclude>src/main/archiva-web/src/polyfills.ts</exclude> | |||
<exclude>src/main/archiva-web/e2e/protractor.conf.js</exclude> | |||
<exclude>src/main/archiva-web/e2e/tsconfig.json</exclude> | |||
<exclude>src/main/archiva-web/src/assets/i18n/*.json</exclude> | |||
</excludes> | |||
</configuration> | |||
</plugin> | |||
@@ -735,7 +736,7 @@ | |||
<webApp> | |||
<contextPath>/archiva</contextPath> | |||
</webApp> | |||
<jettyXml>${basedir}/src/test/jetty-env.xml</jettyXml> | |||
<jettyXml>${basedir}/src/test/resources/jetty-env.xml</jettyXml> | |||
<systemProperties> | |||
<systemProperty> | |||
<name>plexus.home</name> | |||
@@ -787,7 +788,7 @@ | |||
</systemProperty> | |||
<systemProperty> | |||
<name>log4j.configurationFile</name> | |||
<value>${basedir}/src/test/log4j2-test.xml</value> | |||
<value>${basedir}/src/test/resources/log4j2-test.xml</value> | |||
</systemProperty> | |||
<systemProperty> | |||
<name>AsyncLoggerConfig.WaitStrategy</name> | |||
@@ -801,8 +802,12 @@ | |||
<name>openjpa.Log</name> | |||
<value>${openjpa.Log}</value> | |||
</systemProperty> | |||
<systemProperty> | |||
<name>redback.admin.creation.file</name> | |||
<value>${basedir}/src/test/resources/auto-admin-creation.properties</value> | |||
</systemProperty> | |||
</systemProperties> | |||
<useTestScope>false</useTestScope> | |||
<useTestScope>true</useTestScope> | |||
</configuration> | |||
<dependencies> | |||
<dependency> |
@@ -2,26 +2,36 @@ | |||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.0.1. | |||
## Development server | |||
## Usage instructions | |||
### Development server | |||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. | |||
## Code scaffolding | |||
### Code scaffolding | |||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. | |||
## Build | |||
### Build | |||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. | |||
## Running unit tests | |||
### Running unit tests | |||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). | |||
## Running end-to-end tests | |||
### Running end-to-end tests | |||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). | |||
## Further help | |||
### Further help | |||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). | |||
## Information about used components | |||
### I18n-Support | |||
We are using the ngx-translate package for i18n, and not the builtin localization of angular 9.+ . Because, the builtin module | |||
does not allow runtime translations by keys. All keys must exist during compile phase. | |||
@@ -13,10 +13,14 @@ | |||
"root": "", | |||
"sourceRoot": "src", | |||
"prefix": "app", | |||
"i18n": { | |||
"sourceLocale": "en-US" | |||
}, | |||
"architect": { | |||
"build": { | |||
"builder": "@angular-devkit/build-angular:browser", | |||
"options": { | |||
"localize": false, | |||
"outputPath": "dist/archiva-web", | |||
"index": "src/index.html", | |||
"main": "src/main.ts", | |||
@@ -79,12 +83,6 @@ | |||
} | |||
} | |||
}, | |||
"extract-i18n": { | |||
"builder": "@angular-devkit/build-angular:extract-i18n", | |||
"options": { | |||
"browserTarget": "archiva-web:build" | |||
} | |||
}, | |||
"test": { | |||
"builder": "@angular-devkit/build-angular:karma", | |||
"options": { |
@@ -1,3 +1,21 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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. | |||
*/ | |||
// @ts-check | |||
// Protractor configuration file, see link for more information | |||
// https://github.com/angular/protractor/blob/master/lib/config.ts |
@@ -1,6 +1,6 @@ | |||
/* To learn more about this file see: https://angular.io/config/tsconfig. */ | |||
{ | |||
"extends": "../tsconfig.base.json", | |||
"extends": "../tsconfig.json", | |||
"compilerOptions": { | |||
"outDir": "../out-tsc/e2e", | |||
"module": "commonjs", |
@@ -1,3 +1,21 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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. | |||
*/ | |||
// Karma configuration file, see link for more information | |||
// https://karma-runner.github.io/1.0/config/configuration-file.html | |||
@@ -11,27 +11,30 @@ | |||
}, | |||
"private": true, | |||
"dependencies": { | |||
"@angular/animations": "~10.0.2", | |||
"@angular/common": "~10.0.2", | |||
"@angular/compiler": "~10.0.2", | |||
"@angular/core": "~10.0.2", | |||
"@angular/forms": "~10.0.2", | |||
"@angular/localize": "^10.0.2", | |||
"@angular/platform-browser": "~10.0.2", | |||
"@angular/platform-browser-dynamic": "~10.0.2", | |||
"@angular/router": "~10.0.2", | |||
"@angular/animations": "~10.2.0", | |||
"@angular/common": "~10.2.0", | |||
"@angular/compiler": "~10.2.0", | |||
"@angular/core": "~10.2.0", | |||
"@angular/forms": "~10.2.0", | |||
"@angular/platform-browser": "~10.2.0", | |||
"@angular/platform-browser-dynamic": "~10.2.0", | |||
"@angular/router": "~10.2.0", | |||
"@fortawesome/fontawesome-free": "^5.13.1", | |||
"@fortawesome/fontawesome-svg-core": "^1.2.29", | |||
"@ngx-translate/core": "^13.0.0", | |||
"@ngx-translate/http-loader": "^6.0.0", | |||
"bootstrap": "^4.5.0", | |||
"flag-icon-css": "^3.5.0", | |||
"jquery": "^3.5.1", | |||
"rxjs": "~6.5.5", | |||
"rxjs": "~6.6.3", | |||
"service": "^0.1.4", | |||
"tslib": "^2.0.0", | |||
"zone.js": "~0.10.3" | |||
}, | |||
"devDependencies": { | |||
"@angular-devkit/build-angular": "~0.1000.1", | |||
"@angular/cli": "~10.0.1", | |||
"@angular/compiler-cli": "~10.0.2", | |||
"@angular-devkit/build-angular": "~0.1002.0", | |||
"@angular/cli": "~10.2.0", | |||
"@angular/compiler-cli": "~10.2.0", | |||
"@types/node": "^12.11.1", | |||
"@types/jasmine": "~3.5.0", | |||
"@types/jasminewd2": "~2.0.3", |
@@ -22,8 +22,8 @@ import { Routes, RouterModule } from '@angular/router'; | |||
import { AboutComponent } from './modules/general/about/about.component'; | |||
import { ContactComponent } from './modules/general/contact/contact.component'; | |||
import { HomeComponent } from './modules/general/home/home.component'; | |||
import { LoginComponent } from './modules/general/login/login.component'; | |||
import { NotFoundComponent } from './modules/general/not-found/not-found.component'; | |||
import { LoginComponent } from "./modules/general/login/login.component"; | |||
const routes: Routes = [ | |||
{ path: '', component: HomeComponent, }, |
@@ -29,28 +29,35 @@ | |||
<div class="collapse navbar-collapse" id="navbarsDefault"> | |||
<ul class="navbar-nav ml-auto"> | |||
<li class="nav-item active"> | |||
<a i18n="navbar|" class="nav-link" routerLink="/"> | |||
<i class="fas fa-home mr-1"></i>Home | |||
<a class="nav-link" routerLink="/"> | |||
<i class="fas fa-home mr-1"></i>{{ 'menu.home' |translate }} | |||
</a> | |||
</li> | |||
<li class="nav-item active"> | |||
<a i18n="navbar|" class="nav-link" routerLink="/about"> | |||
<i class="far fa-question-circle mr-1"></i>About | |||
<a class="nav-link" routerLink="/login" data-toggle="modal" data-target="#loginModal"> | |||
<i class="fas fa-user mr-1"></i>{{'menu.login' | translate}} | |||
</a> | |||
</li> | |||
<li class="nav-item active dropdown"> | |||
<a class="nav-link dropdown-toggle" id="dropdown09" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="flag-icon {{langIcon()}}"></span></a> | |||
<div class="dropdown-menu" aria-labelledby="dropdown09"> | |||
<a class="dropdown-item" href="#en" (click)="switchLang('en')"><span class="flag-icon flag-icon-gb"> </span> English</a> | |||
<a class="dropdown-item" href="#de" (click)="switchLang('de')"><span class="flag-icon flag-icon-de"> </span> German</a> | |||
</div> | |||
</li> | |||
<li class="nav-item active"> | |||
<a i18n="navbar|" class="nav-link" routerLink="/contact"> | |||
<i class="fas fa-envelope mr-1"></i>Contact | |||
<a class="nav-link" routerLink="/about"> | |||
<i class="far fa-question-circle mr-1"></i>{{'menu.about' | translate}} | |||
</a> | |||
</li> | |||
<li class="nav-item active"> | |||
<a i18n="navbar|" class="nav-link" routerLink="/login"> | |||
<i class="fas fa-user mr-1"></i>Login | |||
<a class="nav-link" routerLink="/contact"> | |||
<i class="fas fa-envelope mr-1"></i>{{ 'menu.contact' | translate }} | |||
</a> | |||
</li> | |||
<li class="nav-item active"> | |||
<a class="nav-link" href="https://github.com/apache/archiva"> | |||
<i class="fab fa-github mr-1"></i>Github | |||
<i class="fab fa-github mr-1"></i> | |||
</a> | |||
</li> | |||
</ul> |
@@ -17,6 +17,7 @@ | |||
* under the License. | |||
*/ | |||
import { Component } from '@angular/core'; | |||
import { TranslateService } from '@ngx-translate/core'; | |||
@Component({ | |||
selector: 'app-root', | |||
@@ -26,4 +27,27 @@ import { Component } from '@angular/core'; | |||
export class AppComponent { | |||
title = 'archiva-web'; | |||
version = 'Angular version 10.0.2'; | |||
constructor( | |||
public translate: TranslateService | |||
) { | |||
translate.addLangs(['en', 'de']); | |||
translate.setDefaultLang('en'); | |||
translate.use('en'); | |||
} | |||
switchLang(lang: string) { | |||
this.translate.use(lang); | |||
} | |||
langIcon() : string { | |||
switch (this.translate.currentLang) { | |||
case "de": | |||
return "flag-icon-de"; | |||
case "en": | |||
return "flag-icon-gb"; | |||
default: | |||
return "flag-icon-" + this.translate.currentLang; | |||
} | |||
} | |||
} |
@@ -18,17 +18,19 @@ | |||
*/ | |||
import { BrowserModule } from '@angular/platform-browser'; | |||
import { NgModule } from '@angular/core'; | |||
import { HttpClientModule } from '@angular/common/http'; | |||
import { HttpClient, HttpClientModule } from '@angular/common/http'; | |||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; | |||
import { TranslateHttpLoader } from '@ngx-translate/http-loader'; | |||
import { AppRoutingModule } from './app-routing.module'; | |||
import { AppComponent } from './app.component'; | |||
import { HomeComponent } from './modules/general/home/home.component'; | |||
import { ContactComponent } from './modules/general/contact/contact.component'; | |||
import { AboutComponent } from './modules/general/about/about.component'; | |||
import { LoginComponent } from './modules/general/login/login.component'; | |||
import { NotFoundComponent } from './modules/general/not-found/not-found.component'; | |||
import { SidemenuComponent } from './modules/general/sidemenu/sidemenu.component'; | |||
import {FormsModule} from "@angular/forms"; | |||
import {FormsModule, ReactiveFormsModule} from "@angular/forms"; | |||
import { LoginComponent } from './modules/general/login/login.component'; | |||
@NgModule({ | |||
declarations: [ | |||
@@ -36,17 +38,29 @@ import {FormsModule} from "@angular/forms"; | |||
HomeComponent, | |||
ContactComponent, | |||
AboutComponent, | |||
LoginComponent, | |||
NotFoundComponent, | |||
SidemenuComponent, | |||
LoginComponent, | |||
], | |||
imports: [ | |||
BrowserModule, | |||
AppRoutingModule, | |||
FormsModule, | |||
ReactiveFormsModule, | |||
HttpClientModule, | |||
TranslateModule.forRoot({ | |||
loader: { | |||
provide: TranslateLoader, | |||
useFactory: httpTranslateLoader, | |||
deps: [HttpClient] | |||
} | |||
}) | |||
], | |||
providers: [], | |||
bootstrap: [AppComponent] | |||
}) | |||
export class AppModule { } | |||
export function httpTranslateLoader(http: HttpClient) { | |||
return new TranslateHttpLoader(http); | |||
} |
@@ -16,19 +16,11 @@ | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import { TestBed } from '@angular/core/testing'; | |||
import { LoginService } from './login.service'; | |||
import { AccessToken } from './access-token'; | |||
describe('LoginService', () => { | |||
let service: LoginService; | |||
beforeEach(() => { | |||
TestBed.configureTestingModule({}); | |||
service = TestBed.inject(LoginService); | |||
}); | |||
it('should be created', () => { | |||
expect(service).toBeTruthy(); | |||
describe('AccessToken', () => { | |||
it('should create an instance', () => { | |||
expect(new AccessToken()).toBeTruthy(); | |||
}); | |||
}); |
@@ -16,19 +16,11 @@ | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import { Injectable } from '@angular/core'; | |||
import { ArchivaRequestService } from "./archiva-request.service"; | |||
@Injectable({ | |||
providedIn: 'root' | |||
}) | |||
export class LoginService { | |||
login(username: string, password: string) { | |||
throw new Error("Method not implemented."); | |||
} | |||
constructor(private archiva : ArchivaRequestService) { } | |||
export class AccessToken { | |||
access_token: string; | |||
refresh_token: string; | |||
expires_in: number; | |||
token_type: string; | |||
scope: string; | |||
state: string; | |||
} |
@@ -0,0 +1,25 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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 { ErrorMessage } from './error-message'; | |||
describe('ErrorMessage', () => { | |||
it('should create an instance', () => { | |||
expect(new ErrorMessage()).toBeTruthy(); | |||
}); | |||
}); |
@@ -16,11 +16,8 @@ | |||
* under the License. | |||
*/ | |||
export class Logindata { | |||
constructor( | |||
public username: string, | |||
public password: string | |||
) { } | |||
} | |||
export class ErrorMessage { | |||
errorKey: string; | |||
args: string[]; | |||
message: string; | |||
} |
@@ -0,0 +1,27 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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 { ErrorResult } from './error-result'; | |||
import { ErrorMessage } from './error-message'; | |||
describe('ErrorResult', () => { | |||
it('should create an instance', () => { | |||
const resultArray = new ErrorMessage[0](); | |||
expect(resultArray).toBeTruthy(); | |||
}); | |||
}); |
@@ -0,0 +1,27 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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 {ErrorMessage} from "./error-message"; | |||
export class ErrorResult { | |||
errorMessages: Array<ErrorMessage> | |||
constructor(errorMessages: Array<ErrorMessage>) { | |||
this.errorMessages = errorMessages; | |||
} | |||
} |
@@ -16,36 +16,38 @@ | |||
~ specific language governing permissions and limitations | |||
~ under the License. | |||
--> | |||
<div class="container-md" > | |||
<div class="row"> | |||
<div class="col-6"> | |||
<form (ngSubmit)="onSubmit()" #loginForm="ngForm"> | |||
<div class="form-group"> | |||
<label for="username" i18n="loginform|">Username</label> | |||
<input type="text" class="form-control" id="username" aria-describedby="usernameHelp" | |||
required name="username" | |||
[(ngModel)]="model.username" #username="ngModel" | |||
> | |||
<small id="usernameHelp" class="form-text text-muted" i18n="inputhelp|">Enter your username.</small> | |||
<div [hidden]="username.valid || username.pristine" | |||
class="alert alert-danger" i18n> | |||
Username is required | |||
</div> | |||
<!-- Modal --> | |||
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-labelledby="loginModal" aria-hidden="true"> | |||
<div class="modal-dialog" role="document"> | |||
<form [formGroup]="loginForm" (ngSubmit)="login(loginForm.value)" > | |||
<div class="modal-content"> | |||
<div class="modal-header"> | |||
<h5 class="modal-title" id="loginModalLabel">{{'login.title'|translate}}</h5> | |||
<button type="button" #closebutton class="close" data-dismiss="modal" aria-label="Close" > | |||
<span aria-hidden="true">×</span> | |||
</button> | |||
</div> | |||
<div class="form-group"> | |||
<label for="password" i18n="loginform|">Password</label> | |||
<input type="password" class="form-control" id="password" name="password" | |||
required="required" [(ngModel)]="model.password" #password="ngModel" | |||
> | |||
<small id="passwordHelp" class="form-text text-muted" i18n="inputhelp|">Enter your password.</small> | |||
<div [hidden]="password.valid || password.pristine" | |||
class="alert alert-danger" i18n> | |||
Password is required | |||
<div class="modal-body"> | |||
<div class="form-group"> | |||
<label for="userid" id="userid-label" >{{'login.userid' | translate}}</label> | |||
<input id="userid" aria-labelledby="userid-label" class="form-control" placeholder="userid" formControlName="userid" /> | |||
</div> | |||
<div class="form-group"> | |||
<label for="password" id="password-label" >{{'login.password' | translate}}</label> | |||
<input id="password" aria-labelledby="password-label" class="form-control" type="password" formControlName="password" /> | |||
</div> | |||
</div> | |||
<button type="submit" class="btn btn-primary">Submit</button> | |||
<div class="modal-footer"> | |||
<button type="button" class="btn btn-secondary" data-dismiss="modal" >{{'modal.close'|translate}}</button> | |||
<button type="button" class="btn btn-primary" type="submit" >{{'login.submit'|translate}}</button> | |||
</div> | |||
</div> | |||
</form> | |||
<div *ngFor="let msg of errorMessages" class="alert alert-danger" > | |||
{{msg}} | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -15,4 +15,4 @@ | |||
* KIND, either express or implied. See the License for the | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
*/ |
@@ -16,7 +16,7 @@ | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | |||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
import { LoginComponent } from './login.component'; | |||
@@ -24,12 +24,12 @@ describe('LoginComponent', () => { | |||
let component: LoginComponent; | |||
let fixture: ComponentFixture<LoginComponent>; | |||
beforeEach(async(() => { | |||
TestBed.configureTestingModule({ | |||
beforeEach(async () => { | |||
await TestBed.configureTestingModule({ | |||
declarations: [ LoginComponent ] | |||
}) | |||
.compileComponents(); | |||
})); | |||
}); | |||
beforeEach(() => { | |||
fixture = TestBed.createComponent(LoginComponent); |
@@ -16,11 +16,13 @@ | |||
* specific language governing permissions and limitations | |||
* under the License. | |||
*/ | |||
import { Component, OnInit } from '@angular/core'; | |||
// noinspection ES6UnusedImports | |||
import { FormsModule } from "@angular/forms"; | |||
import { Logindata } from "../../../logindata"; | |||
import { LoginService } from "../../../services/login.service"; | |||
import {Component, OnInit, ViewChild} from '@angular/core'; | |||
import { FormBuilder } from '@angular/forms'; | |||
import { AuthenticationService } from "../../../services/authentication.service"; | |||
import {AccessToken} from "../../../model/access-token"; | |||
import {ErrorMessage} from "../../../model/error-message"; | |||
import {Router} from "@angular/router"; | |||
import {ArchivaRequestService} from "../../../services/archiva-request.service"; | |||
@Component({ | |||
selector: 'app-login', | |||
@@ -29,21 +31,47 @@ import { LoginService } from "../../../services/login.service"; | |||
}) | |||
export class LoginComponent implements OnInit { | |||
model = new Logindata('', ''); | |||
@ViewChild("closebutton") closebutton; | |||
submitted = false; | |||
loginForm; | |||
userid; | |||
password; | |||
errorMessages : string[]; | |||
onSubmit() { this.submitted = true; } | |||
constructor( private authenticationService: AuthenticationService, | |||
private formBuilder: FormBuilder, | |||
private router: Router, | |||
private archivaRequest : ArchivaRequestService ) { | |||
this.loginForm = this.formBuilder.group({ | |||
userid: '', | |||
password: '', | |||
}); | |||
this.errorMessages = []; | |||
get diagnostic() { return JSON.stringify(this.submitted); } | |||
login(): void { | |||
this.loginService.login(username, password); | |||
} | |||
constructor(private loginService: LoginService) { } | |||
ngOnInit(): void { | |||
} | |||
login(customerData) { | |||
this.errorMessages = []; | |||
let resultHandler = (result: string, err?: ErrorMessage[] ) => { | |||
if (result=="OK") { | |||
this.closebutton.nativeElement.click(); | |||
this.router.navigate(["/"]); | |||
} else if (result=="ERROR") { | |||
if (err != null) { | |||
this.errorMessages = []; | |||
for (let msg of err) { | |||
console.log("Error "+msg.errorKey); | |||
this.errorMessages.push(this.archivaRequest.translateError(msg)); | |||
} | |||
} | |||
} | |||
} | |||
// Process checkout data here | |||
this.loginForm.reset(); | |||
this.authenticationService.login(customerData.userid, customerData.password, resultHandler); | |||
} | |||
} |
@@ -18,51 +18,51 @@ | |||
--> | |||
<nav class="nav flex-column nav-pills " role="tablist" aria-orientation="vertical"> | |||
<a i18n="sidemenu|" class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Artifacts</a> | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Artifacts</a> | |||
<a i18n="sidemenu|" class="nav-link active my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link active my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-search" aria-selected="true">Search</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Browse</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Upload Artifact</a> | |||
<a i18n="sidemenu|" class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-home" aria-selected="false">Administration</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Repository Groups</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Repositories</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Proxy Connectors</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">ProxyConnector Rules</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Network Proxies</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Repository Scanning</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Runtime Configuration</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">System Status</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">UI Configuration</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Reports</a> | |||
<a i18n="sidemenu|" class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-home" aria-selected="false">Users</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Manage</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Roles</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">Users Runtime Configuration</a> | |||
<a i18n="sidemenu|" class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-home" aria-selected="false">Documentation</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">REST Api</a> | |||
<a i18n="sidemenu|" class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
<a class="nav-link my-0 py-0" href="#" data-toggle="pill" | |||
role="tab" aria-controls="v-pills-browse" aria-selected="false">User Documentation</a> | |||
</nav> |
@@ -17,24 +17,48 @@ | |||
* under the License. | |||
*/ | |||
import { Injectable } from '@angular/core'; | |||
import { HttpClient } from "@angular/common/http"; | |||
import {HttpClient, HttpEvent, HttpResponse} from "@angular/common/http"; | |||
import { environment } from "../../environments/environment"; | |||
import {Observable} from "rxjs"; | |||
import {ErrorMessage} from "../model/error-message"; | |||
import {TranslateService} from "@ngx-translate/core"; | |||
@Injectable({ | |||
providedIn: 'root' | |||
}) | |||
export class ArchivaRequestService { | |||
constructor(private http : HttpClient, private translator : TranslateService) { } | |||
executeRestCall(type: string, module: string, service: string, input: object, callback: (result: object) => void ) : void { | |||
executeRestCall<R>(type: string, module: string, service: string, input: object ) : Observable<R> { | |||
let modulePath = environment.application.servicePaths[module]; | |||
let url = environment.application.baseUrl + environment.application.restPath + "/"+modulePath+"/" + service + "Service"; | |||
let url = environment.application.baseUrl + environment.application.restPath + "/" + modulePath + "/" + service; | |||
let token = localStorage.getItem("access_token") | |||
let headers = null; | |||
if (token != null) { | |||
headers = { | |||
"Authorization": "Bearer " + localStorage.getItem("access_token") | |||
} | |||
} else { | |||
headers = {}; | |||
} | |||
if (type == "get") { | |||
this.http.get(url,) | |||
return this.http.get<R>(url, {"headers":headers}); | |||
} else if ( type == "post") { | |||
this.http.post(url); | |||
return this.http.post<R>(url, input, {"headers":headers}); | |||
} | |||
} | |||
constructor(private http : HttpClient) { } | |||
translateError(errorMsg : ErrorMessage) : string { | |||
if (errorMsg.errorKey!=null && errorMsg.errorKey!='') { | |||
let parms = {}; | |||
if (errorMsg.args!=null && errorMsg.args.length>0) { | |||
for ( let i=0; i<errorMsg.args.length; i++) { | |||
parms['arg' + i] = errorMsg.args[i]; | |||
} | |||
} | |||
return this.translator.instant('api.'+errorMsg.errorKey, parms); | |||
} | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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 { TestBed } from '@angular/core/testing'; | |||
import { AuthenticationService } from './authentication.service'; | |||
import {of, throwError} from 'rxjs'; | |||
import {ArchivaRequestService} from "./archiva-request.service"; | |||
import { ErrorMessage } from '../model/error-message'; | |||
import {HttpErrorResponse} from "@angular/common/http"; | |||
describe('AuthenticationService', () => { | |||
let service: AuthenticationService; | |||
let archivaRequestServiceSpy: jasmine.SpyObj<ArchivaRequestService>; | |||
beforeEach(() => { | |||
const spy = jasmine.createSpyObj('ArchivaRequestService', ['executeRestCall']); | |||
TestBed.configureTestingModule( { providers: [ | |||
AuthenticationService, | |||
{ provide: ArchivaRequestService, useValue: spy } | |||
]}); | |||
service = TestBed.inject(AuthenticationService); | |||
archivaRequestServiceSpy = TestBed.inject(ArchivaRequestService) as jasmine.SpyObj<ArchivaRequestService>; | |||
}); | |||
it('should be created', () => { | |||
expect(service).toBeTruthy(); | |||
}); | |||
it('#login should return success and set token', () => { | |||
const stubValue = {'access_token':'abcdefg','refresh_token':'hijklmnop','expires_in':1000}; | |||
archivaRequestServiceSpy.executeRestCall.and.returnValue(of(stubValue)); | |||
// resultHandler: (n: string, err?: ErrorMessage[]) => void | |||
let result:string; | |||
let handler = (n:string, err?:ErrorMessage[]) => { | |||
result = n; | |||
}; | |||
service.login('admin','pass123', handler); | |||
expect(result).toEqual("OK"); | |||
expect(archivaRequestServiceSpy.executeRestCall.calls.count()).toBe(1, 'one call'); | |||
expect(localStorage.getItem('access_token')).toEqual("abcdefg"); | |||
expect(localStorage.getItem('refresh_token')).toEqual("hijklmnop"); | |||
}); | |||
it('#login fails', () => { | |||
const stubValue = {'access_token':'abcdefg','refresh_token':'hijklmnop','expires_in':1000}; | |||
archivaRequestServiceSpy.executeRestCall.and.returnValue(throwError(new HttpErrorResponse({'status':404, error:{'errorMessages':[ | |||
new ErrorMessage() | |||
]}}))); | |||
// resultHandler: (n: string, err?: ErrorMessage[]) => void | |||
let result : string; | |||
let messages: ErrorMessage[]; | |||
let handler = (n:string, err?:ErrorMessage[]) => { | |||
result = n; | |||
messages = err; | |||
}; | |||
service.login('admin', 'test', handler); | |||
expect(result).toEqual("ERROR"); | |||
expect(messages).toBeTruthy(); | |||
expect(messages.length).toEqual(1); | |||
}); | |||
}); |
@@ -0,0 +1,76 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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 {ArchivaRequestService} from "./archiva-request.service"; | |||
import {AccessToken} from "../model/access-token"; | |||
import { environment } from "../../environments/environment"; | |||
import {ErrorMessage} from "../model/error-message"; | |||
import {ErrorResult} from "../model/error-result"; | |||
import {HttpErrorResponse} from "@angular/common/http"; | |||
@Injectable({ | |||
providedIn: 'root' | |||
}) | |||
export class AuthenticationService { | |||
constructor(private rest: ArchivaRequestService) { } | |||
login(userid:string, password:string, resultHandler: (n: string, err?: ErrorMessage[]) => void) { | |||
const data = { 'grant_type':'authorization_code', | |||
'client_id':environment.application.client_id, | |||
'user_id':userid, 'password':password | |||
}; | |||
let authObserver = this.rest.executeRestCall<AccessToken>('post','redback', 'auth/authenticate', data ); | |||
let tokenObserver = { | |||
next: (x: AccessToken) => { | |||
localStorage.setItem("access_token", x.access_token); | |||
localStorage.setItem("refresh_token", x.refresh_token); | |||
if (x.expires_in!=null) { | |||
let dt = new Date(); | |||
dt.setSeconds(dt.getSeconds() + x.expires_in); | |||
localStorage.setItem("token_expire", dt.toISOString()); | |||
} | |||
resultHandler("OK"); | |||
}, | |||
error: ( err: HttpErrorResponse) => { | |||
console.log("Error " + (JSON.stringify(err))); | |||
let result = err.error as ErrorResult | |||
if (result.errorMessages!=null) { | |||
for (let msg of result.errorMessages) { | |||
console.error('Observer got an error: ' + msg.errorKey) | |||
} | |||
resultHandler("ERROR", result.errorMessages); | |||
} else { | |||
resultHandler("ERROR", null); | |||
} | |||
}, | |||
// complete: () => console.log('Observer got a complete notification'), | |||
}; | |||
authObserver.subscribe(tokenObserver) | |||
} | |||
logout() { | |||
localStorage.removeItem("access_token"); | |||
localStorage.removeItem("refresh_token"); | |||
localStorage.removeItem("token_expire"); | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
{ | |||
"login": { | |||
"title": "Anmelden bei Archiva", | |||
"password": "Passwort", | |||
"userid": "User Id", | |||
"submit": "Anmelden" | |||
}, | |||
"modal" : { | |||
"close":"Schließen" | |||
}, | |||
"menu": { | |||
"home": "Home", | |||
"login": "Anmelden", | |||
"about": "Über", | |||
"contact": "Kontakt" | |||
}, | |||
"api" : { | |||
"rb.auth.invalid_credentials": "Anmeldedaten ungültig" | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
{ | |||
"login": { | |||
"title": "Login to Archiva", | |||
"password": "Password", | |||
"userid": "User Id", | |||
"submit": "Login" | |||
}, | |||
"modal" : { | |||
"close": "Close" | |||
}, | |||
"menu": { | |||
"home": "Home", | |||
"login": "Login", | |||
"about": "About", | |||
"contact": "Contact" | |||
}, | |||
"api" : { | |||
"rb.auth.invalid_credentials": "Invalid credentials given" | |||
} | |||
} |
@@ -25,15 +25,16 @@ export const environment = { | |||
production: false, | |||
application: | |||
{ | |||
client_id:'archiva_web_client', | |||
baseUrl: 'http://localhost:8080', | |||
restPath: '/restServices', | |||
restPath: '/archiva/api/v2', | |||
servicePaths: { | |||
archiva:"archivaServices", | |||
redback:"redbackServices", | |||
ui:"archivaUiServices" | |||
archiva:"archiva", | |||
redback:"redback", | |||
ui:"archivaUi" | |||
}, | |||
name: 'archiva-starter', | |||
angular: 'Angular 10.0.2', | |||
angular: 'Angular 10.2.0', | |||
bootstrap: 'Bootstrap 4.5.0', | |||
fontawesome: 'Font Awesome 5.13.1' | |||
} |
@@ -1,3 +1,21 @@ | |||
<!-- | |||
~ Licensed to the Apache Software Foundation (ASF) under one | |||
~ or more contributor license agreements. See the NOTICE file | |||
~ distributed with this work for additional information | |||
~ regarding copyright ownership. The ASF licenses this file | |||
~ to you 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. | |||
--> | |||
<!doctype html> | |||
<html lang="en"> | |||
<!-- |
@@ -1,102 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8" ?> | |||
<!-- | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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. | |||
*/ | |||
--> | |||
<xliff version="2.0" xmlns="urn:oasis:names:tc:xliff:document:2.0" srcLang="en-US"> | |||
<file original="ng.template" id="ngi18n"> | |||
<unit id="3533320232395919182"> | |||
<notes> | |||
<note category="meaning">sidenav</note> | |||
<note category="location">src/app/app.component.html:33,35</note> | |||
</notes> | |||
<segment> | |||
<source> | |||
<pc id="0" equivStart="START_ITALIC_TEXT" equivEnd="CLOSE_ITALIC_TEXT" type="fmt" dispStart="<i>" dispEnd="</i>"></pc>Home | |||
</source> | |||
</segment> | |||
</unit> | |||
<unit id="1283530642863181542"> | |||
<notes> | |||
<note category="meaning">sidenav</note> | |||
<note category="location">src/app/app.component.html:38,40</note> | |||
</notes> | |||
<segment> | |||
<source> | |||
<pc id="0" equivStart="START_ITALIC_TEXT" equivEnd="CLOSE_ITALIC_TEXT" type="fmt" dispStart="<i>" dispEnd="</i>"></pc>About | |||
</source> | |||
</segment> | |||
</unit> | |||
<unit id="4789449765292606242"> | |||
<notes> | |||
<note category="meaning">sidenav</note> | |||
<note category="location">src/app/app.component.html:43,45</note> | |||
</notes> | |||
<segment> | |||
<source> | |||
<pc id="0" equivStart="START_ITALIC_TEXT" equivEnd="CLOSE_ITALIC_TEXT" type="fmt" dispStart="<i>" dispEnd="</i>"></pc>Contact | |||
</source> | |||
</segment> | |||
</unit> | |||
<unit id="1912174959280479645"> | |||
<notes> | |||
<note category="meaning">sidenav</note> | |||
<note category="location">src/app/app.component.html:48,50</note> | |||
</notes> | |||
<segment> | |||
<source> | |||
<pc id="0" equivStart="START_ITALIC_TEXT" equivEnd="CLOSE_ITALIC_TEXT" type="fmt" dispStart="<i>" dispEnd="</i>"></pc>Login | |||
</source> | |||
</segment> | |||
</unit> | |||
<unit id="6511475824238507681"> | |||
<notes> | |||
<note category="location">src/app/modules/general/home/home.component.html:22</note> | |||
</notes> | |||
<segment> | |||
<source>Artifacts</source> | |||
</segment> | |||
</unit> | |||
<unit id="4580988005648117665"> | |||
<notes> | |||
<note category="location">src/app/modules/general/home/home.component.html:24</note> | |||
</notes> | |||
<segment> | |||
<source>Search</source> | |||
</segment> | |||
</unit> | |||
<unit id="787163983066183218"> | |||
<notes> | |||
<note category="location">src/app/modules/general/home/home.component.html:26</note> | |||
</notes> | |||
<segment> | |||
<source>Browse</source> | |||
</segment> | |||
</unit> | |||
<unit id="7844706011418789951"> | |||
<notes> | |||
<note category="location">src/app/modules/general/home/home.component.html:28</note> | |||
</notes> | |||
<segment> | |||
<source>Administration</source> | |||
</segment> | |||
</unit> | |||
</file> | |||
</xliff> |
@@ -1,7 +1,25 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one | |||
* or more contributor license agreements. See the NOTICE file | |||
* distributed with this work for additional information | |||
* regarding copyright ownership. The ASF licenses this file | |||
* to you 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. | |||
*/ | |||
/*************************************************************************************************** | |||
* Load `$localize` onto the global scope - used if i18n tags appear in Angular templates. | |||
*/ | |||
import '@angular/localize/init'; | |||
// import '@angular/localize/init'; | |||
/** | |||
* This file includes polyfills needed by Angular and is loaded before the app. | |||
* You can add your own extra polyfills to this file. |
@@ -43,6 +43,7 @@ body { | |||
} | |||
@import "~bootstrap/scss/bootstrap"; | |||
@import "~flag-icon-css/css/flag-icon.min.css"; | |||
@@ -1,6 +1,6 @@ | |||
/* To learn more about this file see: https://angular.io/config/tsconfig. */ | |||
{ | |||
"extends": "./tsconfig.base.json", | |||
"extends": "./tsconfig.json", | |||
"compilerOptions": { | |||
"outDir": "./out-tsc/app", | |||
"types": [] |
@@ -1,20 +0,0 @@ | |||
/* To learn more about this file see: https://angular.io/config/tsconfig. */ | |||
{ | |||
"compileOnSave": false, | |||
"compilerOptions": { | |||
"baseUrl": "./", | |||
"outDir": "./dist/out-tsc", | |||
"sourceMap": true, | |||
"declaration": false, | |||
"downlevelIteration": true, | |||
"experimentalDecorators": true, | |||
"moduleResolution": "node", | |||
"importHelpers": true, | |||
"target": "es2015", | |||
"module": "es2020", | |||
"lib": [ | |||
"es2018", | |||
"dom" | |||
] | |||
} | |||
} |
@@ -1,20 +1,20 @@ | |||
/* | |||
This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience. | |||
It is not intended to be used to perform a compilation. | |||
To learn more about this file see: https://angular.io/config/solution-tsconfig. | |||
*/ | |||
/* To learn more about this file see: https://angular.io/config/tsconfig. */ | |||
{ | |||
"files": [], | |||
"references": [ | |||
{ | |||
"path": "./tsconfig.app.json" | |||
}, | |||
{ | |||
"path": "./tsconfig.spec.json" | |||
}, | |||
{ | |||
"path": "./e2e/tsconfig.json" | |||
} | |||
] | |||
"compileOnSave": false, | |||
"compilerOptions": { | |||
"baseUrl": "./", | |||
"outDir": "./dist/out-tsc", | |||
"sourceMap": true, | |||
"declaration": false, | |||
"downlevelIteration": true, | |||
"experimentalDecorators": true, | |||
"moduleResolution": "node", | |||
"importHelpers": true, | |||
"target": "es2015", | |||
"module": "es2020", | |||
"lib": [ | |||
"es2018", | |||
"dom" | |||
] | |||
} | |||
} |
@@ -1,6 +1,6 @@ | |||
/* To learn more about this file see: https://angular.io/config/tsconfig. */ | |||
{ | |||
"extends": "./tsconfig.base.json", | |||
"extends": "./tsconfig.json", | |||
"compilerOptions": { | |||
"outDir": "./out-tsc/spec", | |||
"types": [ |
@@ -91,12 +91,6 @@ | |||
<logger name="net.sf.ehcache" level="warn"/> | |||
<!-- retained for Redback --> | |||
<logger name="JPOX" level="warn"/> | |||
<logger name="JPOX.MetaData" level="error"/> | |||
<logger name="JPOX.RDBMS.SQL" level="error"/> | |||
<logger name="SQL" level="error"/> | |||
<logger name="org.apache.commons.configuration.DefaultConfigurationBuilder" level="error"/> | |||
@@ -117,7 +111,9 @@ | |||
--> | |||
<root level="info" includeLocation="true"> | |||
<logger name="com.fasterxml" level="trace"/> | |||
<root level="debug" includeLocation="true"> | |||
<appender-ref ref="rolling"/> | |||
</root> | |||
</loggers> |
@@ -0,0 +1,32 @@ | |||
# | |||
# Licensed to the Apache Software Foundation (ASF) under one | |||
# or more contributor license agreements. See the NOTICE file | |||
# distributed with this work for additional information | |||
# regarding copyright ownership. The ASF licenses this file | |||
# to you 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. | |||
# | |||
# -------------------------------------------------------------------- | |||
# Email Settings | |||
# The subject line for the email message. | |||
email.validation.subject=Welcome to Archiva | |||
# Feedback page | |||
email.feedback.path=http://archiva.apache.org/mail-lists.html | |||
email.url.path=index.html | |||
rest.csrffilter.enabled=false |