task #9086 public urls support

This commit is contained in:
Efstratios Giannopoulos 2023-10-13 18:11:46 +03:00
parent 5976084473
commit d5c62539c5
24 changed files with 131 additions and 414 deletions

View File

@ -33,12 +33,6 @@ public class DashBoardController extends BaseController {
this.dashBoardManager = dashBoardManager;
}
@RequestMapping(method = RequestMethod.GET, value = {"/dashboard/getStatistics"}, produces = "application/json")
public ResponseEntity<ResponseItem<DashBoardStatistics>> getStatistics() {
DashBoardStatistics statistics = dashBoardManager.getStatistics();
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DashBoardStatistics>().status(ApiMessageCode.NO_MESSAGE).payload(statistics));
}
@RequestMapping(method = RequestMethod.GET, value = {"/dashboard/me/getStatistics"}, produces = "application/json")
public ResponseEntity<ResponseItem<DashBoardStatistics>> getStatistics(Principal principal) throws IOException {
DashBoardStatistics statistics = dashBoardManager.getMeStatistics(principal);

View File

@ -14,7 +14,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.*;
import java.util.UUID;
@RestController
@CrossOrigin
@ -28,26 +27,6 @@ public class LanguageController {
this.environment = environment;
}
@RequestMapping(value = "{lang}", method = RequestMethod.GET)
public ResponseEntity getLanguage(@PathVariable String lang) throws IOException {
String fileName = this.environment.getProperty("language.path") + lang + ".json";
InputStream is = new FileInputStream(fileName);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentLength(is.available());
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName);
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
byte[] content = new byte[is.available()];
is.read(content);
is.close();
return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK);
}
@RequestMapping(value = "update/{lang}", method = RequestMethod.POST)
public @ResponseBody
ResponseEntity<ResponseItem<String>> updateLang(@PathVariable String lang, @RequestBody String json, @ClaimedAuthorities(claims = {Authorities.ADMIN}) Principal principal) throws Exception {

View File

@ -0,0 +1,42 @@
package eu.eudat.controllers;
import eu.eudat.controllers.BaseController;
import eu.eudat.logic.managers.DashBoardManager;
import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.dashboard.recent.RecentActivity;
import eu.eudat.models.data.dashboard.recent.model.RecentActivityModel;
import eu.eudat.models.data.dashboard.recent.tablerequest.RecentActivityTableRequest;
import eu.eudat.models.data.dashboard.searchbar.SearchBarItem;
import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.security.Principal;
import eu.eudat.types.ApiMessageCode;
import eu.eudat.types.Authorities;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
@RestController
@CrossOrigin
@RequestMapping(value = {"/api/public/dashboard/"})
public class PublicDashBoardController extends BaseController {
private DashBoardManager dashBoardManager;
@Autowired
public PublicDashBoardController(ApiContext apiContext, DashBoardManager dashBoardManager) {
super(apiContext);
this.dashBoardManager = dashBoardManager;
}
@RequestMapping(method = RequestMethod.GET, value = {"getStatistics"}, produces = "application/json")
public ResponseEntity<ResponseItem<DashBoardStatistics>> getStatistics() {
DashBoardStatistics statistics = dashBoardManager.getStatistics();
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DashBoardStatistics>().status(ApiMessageCode.NO_MESSAGE).payload(statistics));
}
}

View File

@ -0,0 +1,44 @@
package eu.eudat.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.*;
@RestController
@CrossOrigin
@RequestMapping(value = {"/api/public/language/"})
public class PublicLanguageController {
private Environment environment;
@Autowired
public PublicLanguageController(Environment environment) {
this.environment = environment;
}
@RequestMapping(value = "{lang}", method = RequestMethod.GET)
public ResponseEntity getLanguage(@PathVariable String lang) throws IOException {
String fileName = this.environment.getProperty("language.path") + lang + ".json";
InputStream is = new FileInputStream(fileName);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentLength(is.available());
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName);
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
byte[] content = new byte[is.available()];
is.read(content);
is.close();
return new ResponseEntity<>(content, responseHeaders, HttpStatus.OK);
}
}

View File

@ -237,13 +237,6 @@ const appRoutes: Routes = [
breadcrumb: true
},
},
{
path: 'login/admin',
loadChildren: () => import('./ui/auth/admin-login/admin-login.module').then(m => m.AdminLoginModule),
data: {
breadcrumb: true
},
},
{
path: 'login',
loadChildren: () => import('./ui/auth/login/login.module').then(m => m.LoginModule),

View File

@ -1,4 +0,0 @@
export interface Credential {
username: string;
secret: string;
}

View File

@ -1,6 +0,0 @@
export class ConfigurableProvider {
configurableLoginId: string;
type: string;
name: string;
logoUrl: string;
}

View File

@ -1,9 +0,0 @@
import { ConfigurableProvider } from "./configurableProvider";
export class Oauth2ConfigurableProvider extends ConfigurableProvider{
clientId: string;
redirect_uri: string;
oauthUrl: string;
scope: string;
state: string;
}

View File

@ -1,8 +0,0 @@
import { ConfigurableProvider } from "./configurableProvider";
export class Saml2ConfigurableProvider extends ConfigurableProvider{
spEntityId: string;
idpUrl: string;
binding: string;
assertionConsumerServiceUrl: string;
}

View File

@ -1,5 +0,0 @@
export class OrcidUser {
orcidId: string;
name: string;
email: string;
}

View File

@ -1,6 +0,0 @@
export interface AuthnRequestModel {
authnRequestXml: string;
relayState: string;
algorithm: string;
signature: string;
}

View File

@ -1,23 +1,17 @@
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Router } from '@angular/router';
import { Credential } from '@app/core/model/auth/credential';
import { LoginInfo } from '@app/core/model/auth/login-info';
import { AppAccount } from '@app/core/model/auth/principal';
import { ConfigurableProvider } from '@app/core/model/configurable-provider/configurableProvider';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { BaseService } from '@common/base/base.service';
import { TranslateService } from '@ngx-translate/core';
import { Observable, Subject, forkJoin, from, of as observableOf, throwError as observableThrowError } from 'rxjs';
import { catchError, exhaustMap, map, takeUntil } from 'rxjs/operators';
import { Observable, Subject, forkJoin, from, of } from 'rxjs';
import { exhaustMap, map, takeUntil } from 'rxjs/operators';
import { ConfigurationService } from '../configuration/configuration.service';
import { CookieService } from 'ngx-cookie-service';
import { Guid } from '@common/types/guid';
import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
import { NgZone } from '@angular/core';
import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
import { PrincipalService } from '../http/principal.service';
import { AppRole } from '@app/core/common/enum/app-role';
@ -141,7 +135,7 @@ export class AuthService extends BaseService {
return observable.pipe(
map((x) => this.currentAuthenticationToken(x)),
exhaustMap(() => forkJoin([
this.principalService.me(httpParams)
this.accessToken ? this.principalService.me(httpParams) : of(null)
])),
map((item) => {
this.currentAccount(item[0]);

View File

@ -12,24 +12,25 @@ import { DataTableRequest, DataTableMultiTypeRequest } from '@app/core/model/dat
@Injectable()
export class DashboardService {
private actionUrl: string;
private headers: HttpHeaders;
private get apiBase(): string { return `${this.configurationService.server}dashboard`; }
private get publicApiBase(): string { return `${this.configurationService.server}public/dashboard`; }
constructor(private http: BaseHttpService,
private configurationService: ConfigurationService) {
this.actionUrl = configurationService.server + 'dashboard/';
}
getStatistics(): Observable<DashboardStatisticsModel> {
return this.http.get<DashboardStatisticsModel>(this.actionUrl + 'getStatistics', { headers: this.headers });
return this.http.get<DashboardStatisticsModel>(`${this.publicApiBase}/getStatistics`, { headers: this.headers });
}
getUserStatistics(): Observable<DashboardStatisticsModel> {
return this.http.get<DashboardStatisticsModel>(this.actionUrl + 'me/getStatistics', { headers: this.headers });
return this.http.get<DashboardStatisticsModel>(`${this.apiBase}/me/getStatistics`, { headers: this.headers });
}
getRecentActivity(request: DataTableMultiTypeRequest<RecentActivityCriteria>): Observable<RecentActivityModel[]> {
return this.http.post<RecentActivityModel[]>(this.actionUrl + 'recentActivity', request, {headers: this.headers});
return this.http.post<RecentActivityModel[]>(`${this.apiBase}/recentActivity`, request, {headers: this.headers});
}
// getRecentActivity(request: DataTableRequest<RecentActivityCriteria>): Observable<DataTableData<RecentActivityModel>> {

View File

@ -6,11 +6,14 @@ import { HttpResponse, HttpClient } from '@angular/common/http';
import { BaseHttpService } from '../http/base-http.service';
import { Language } from '@app/models/language/Language';
import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpParams } from '@common/http/base-http-params';
import { InterceptorType } from '@common/http/interceptors/interceptor-type';
@Injectable()
export class LanguageService {
private currentLanguage: string;
private languageUrl : string;
private get apiBase(): string { return `${this.configurationService.server}language`; }
private get publicApiBase(): string { return `${this.configurationService.server}public/language`; }
constructor(
private translate: TranslateService,
@ -18,7 +21,6 @@ export class LanguageService {
private baseHttp: BaseHttpService,
private configurationService: ConfigurationService
) {
this.languageUrl = `${configurationService.server}language`;
this.currentLanguage = this.configurationService.defaultLanguage || 'en';
}
@ -32,11 +34,17 @@ export class LanguageService {
}
public getCurrentLanguageJSON(): Observable<HttpResponse<Blob>> {
return this.http.get(`${this.languageUrl}/${this.currentLanguage}`, { responseType: 'blob', observe: 'response' });
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [
InterceptorType.AuthToken,
]
};
return this.http.get(`${this.publicApiBase}/${this.currentLanguage}`, { params: params, responseType: 'blob', observe: 'response' });
}
public updateLanguage(json: string): Observable<String> {
return this.baseHttp.post<string>(`${this.languageUrl}/update/${this.currentLanguage}`, json);
return this.baseHttp.post<string>(`${this.apiBase}/update/${this.currentLanguage}`, json);
}
public getCurrentLanguageName() {

View File

@ -3,9 +3,11 @@ import { Observable } from 'rxjs';
import { environment } from 'environments/environment';
import { HttpClient } from '@angular/common/http';
import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpParams } from '@common/http/base-http-params';
import { InterceptorType } from '@common/http/interceptors/interceptor-type';
export class TranslateServerLoader implements TranslateLoader{
private languageUrl: string;
private get apiBase(): string { return `${this.configurationService.server}public/language`; }
constructor(
private http: HttpClient,
@ -14,7 +16,12 @@ export class TranslateServerLoader implements TranslateLoader{
}
getTranslation(lang: string): Observable<any> {
this.languageUrl = `${this.configurationService.server}language`;
return this.http.get(`${this.languageUrl}/${lang}`);
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [
InterceptorType.AuthToken,
]
};
return this.http.get(`${this.apiBase}/${lang}`, { params: params });
}
}

View File

@ -1,35 +0,0 @@
import { HttpHeaders, HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ConfigurationService } from './configuration/configuration.service';
import { BaseHttpService } from './http/base-http.service';
import { Observable } from 'rxjs';
import { BaseComponent } from '@common/base/base.component';
import { AuthnRequestModel } from '../model/saml2/AuthnRequestModel';
@Injectable()
export class SamlLoginService extends BaseComponent {
private actionUrl: string;
private headers = new HttpHeaders();
constructor(private http: BaseHttpService, private httpClient: HttpClient, private configurationService: ConfigurationService) {
super();
this.actionUrl = configurationService.server + 'saml2/';
}
resolveConfigurableLoginId(relayState: string): string {
const decoded = decodeURIComponent(relayState);
const routeParams = new URLSearchParams(decoded);
return routeParams.has('configurableLoginId') ? routeParams.get('configurableLoginId') : undefined;
}
resolveSpId(relayState: string): string {
const decoded = decodeURIComponent(relayState);
const routeParams = new URLSearchParams(decoded);
return routeParams.has('spId') ? routeParams.get('spId') : '';
}
getAuthnRequest(configurableLoginId: string): Observable<AuthnRequestModel> {
return this.http.get<AuthnRequestModel>(this.actionUrl + 'authnRequest/' + configurableLoginId, { headers: this.headers });
}
}

View File

@ -1,34 +0,0 @@
<div class="container">
<div class="container">
<div class="row">
<div class="row col-md-6 col-sm-6 col-md-offset-3 col-sm-offset-3">
<div class="card col-md-8 col-md-offset-2">
<div class="card-header">
<h4>Admin Login</h4>
</div>
<!-- <div class="social-btns">
<div>
<div class="card-form">
<div class="form-row">
<i class="material-icons">person</i> -->
<mat-form-field color="accent">
<input type="text" [(ngModel)]="credential.username" matInput placeholder="Username" />
</mat-form-field>
<!-- </div>
<div class="form-row"> -->
<!-- <i class="material-icons">lock_outline</i> -->
<mat-form-field color="accent">
<input type="password" [(ngModel)]="credential.secret" matInput placeholder="Password" />
</mat-form-field>
<!-- </div>
</div> -->
<div>
<button mat-raised-button color="primary" (click)="nativeLogin()">LOGIN</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- </div>
</div> -->

View File

@ -1,148 +0,0 @@
.container {
padding: 15px 30px;
}
.card {
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.14);
border-radius: 6px;
color: rgba(0, 0, 0, 0.87);
background: #fff;
}
.card-raised {
box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.42), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2);
}
.page-title {
margin-top: 40px;
}
@media (min-width: 1200px) {
.container {
width: 100%;
}
}
@media (min-width: 992px) {
.container {
width: 100%;
}
}
@media (min-width: 768px) {
.container {
width: 100%;
}
}
.container {
height: 100%;
position: relative;
z-index: 1;
}
.card {
position: relative;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
margin-top: 90px;
top: -90px;
-webkit-animation-name: card;
-moz-animation-name: card;
-o-animation-name: card;
animation-name: card;
-webkit-animation-duration: 600ms;
-moz-animation-duration: 600ms;
-o-animation-duration: 600ms;
animation-duration: 600ms;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
-o-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@-webkit-keyframes card {
from {
top: -40px;
}
to {
top: 0;
}
}
@keyframes card {
from {
top: -40px;
}
to {
top: 0;
}
}
.card-header {
position: relative;
overflow: hidden;
top: -40px;
width: 100%;
padding: 25px;
border-radius: 3px;
background: linear-gradient(60deg, #ec407a, #d81b60);
box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(49, 46, 47, 0.4);
display: flex;
flex-direction: column;
align-items: center;
}
.card-header h4 {
font-weight: 400;
color: #fff;
margin-bottom: 25px;
margin-top: 5px;
}
.social-btns i {
font-size: 21px;
color: #fff;
}
.social-btns button {
margin: 0 8px;
}
.tip {
margin-top: -20px;
}
.form-row,
.card-form,
.mat-form-field {
width: 100%;
}
.card-form {
padding: 5px;
}
.form-row {
position: relative;
display: flex;
align-items: center;
margin-top: 13px;
}
.form-row i {
position: relative;
top: -5px;
margin-right: 15px;
color: #555;
}
.card-footer {
margin: 10px;
}
.card-footer button {
color: #e91e63;
}

View File

@ -1,63 +0,0 @@
import { Component, OnInit, HostListener } from '@angular/core';
import { Router } from '@angular/router';
import { Credential } from '@app/core/model/auth/credential';
import { AuthService } from '@app/core/services/auth/auth.service';
import { CultureService } from '@app/core/services/culture/culture-service';
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { BaseComponent } from '@common/base/base.component';
import { TranslateService } from '@ngx-translate/core';
import { takeUntil } from 'rxjs/operators';
import { TranslateServerLoader } from '@app/core/services/language/server.loader';
import { LanguageService } from '@app/core/services/language/language.service';
@Component({
selector: 'app-admin-login',
templateUrl: './admin-login.component.html',
styleUrls: ['./admin-login.component.scss']
})
export class AdminLoginComponent extends BaseComponent implements OnInit {
public auth2: any;
public credential: Credential;
@HostListener('document:keydown.enter', ['$event']) onKeydownHandler() {
this.nativeLogin();
}
constructor(
private authService: AuthService,
private uiNotificationService: UiNotificationService,
private translate: TranslateService,
private cultureService: CultureService,
private router: Router,
private language: LanguageService
) { super(); }
ngOnInit() {
this.credential = {
username: null,
secret: null
}
}
public nativeLogin() {
// this.authService.nativeLogin(this.credential)
// .pipe(takeUntil(this._destroyed))
// .subscribe(
// res => this.onLogInSuccess(res),
// error => this.onLogInError(error)
// );
}
public onLogInSuccess(loginResponse: any) {
this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Success);
if (this.authService.currentAccountIsAuthenticated() && this.authService.getUserProfileCulture()) { this.cultureService.cultureSelected(this.authService.getUserProfileCulture()); }
if (this.authService.currentAccountIsAuthenticated() && this.authService.getUserProfileLanguage()) { this.language.changeLanguage(this.authService.getUserProfileLanguage()); }
this.router.navigate(['/']);
}
public onLogInError(errorMessage: string) {
this.uiNotificationService.snackBarNotification(this.translate.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-LOGIN'), SnackBarNotificationLevel.Error);
}
}

View File

@ -1,17 +0,0 @@
import { NgModule } from '@angular/core';
import { AdminLoginComponent } from '@app/ui/auth/admin-login/admin-login.component';
import { AdminLoginRoutingModule } from '@app/ui/auth/admin-login/admin-login.routing';
import { CommonFormsModule } from '@common/forms/common-forms.module';
import { CommonUiModule } from '@common/ui/common-ui.module';
@NgModule({
imports: [
CommonUiModule,
CommonFormsModule,
AdminLoginRoutingModule
],
declarations: [
AdminLoginComponent
]
})
export class AdminLoginModule { }

View File

@ -1,16 +0,0 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AdminLoginComponent } from './admin-login.component';
const routes: Routes = [
{
path: '',
component: AdminLoginComponent,
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AdminLoginRoutingModule { }

View File

@ -8,7 +8,6 @@ import { CommonFormsModule } from '@common/forms/common-forms.module';
import { CommonUiModule } from '@common/ui/common-ui.module';
import { MergeEmailConfirmation } from './merge-email-confirmation/merge-email-confirmation.component';
import { MergeLoginService } from './utilities/merge-login.service';
import { SamlLoginService } from '@app/core/services/saml-login.service';
import { UnlinkEmailConfirmation } from './unlink-email-confirmation/unlink-email-confirmation.component';
@NgModule({
@ -27,6 +26,6 @@ import { UnlinkEmailConfirmation } from './unlink-email-confirmation/unlink-emai
exports: [
LoginComponent
],
providers: [LoginService, MergeLoginService, SamlLoginService]
providers: [LoginService, MergeLoginService]
})
export class LoginModule { }

View File

@ -52,12 +52,12 @@
],
"keycloak": {
"enabled": true,
"address": null,
"realm": null,
"address": "http://dev03.local.cite.gr:60201/auth",
"realm": "dmp-development",
"flow": "standard",
"clientId": null,
"clientId": "dmp_webapp",
"silentCheckSsoRedirectUri": "http://localhost:4200/assets/silent-check-sso.html",
"scope": "openid profile email address phone",
"scope": "openid profile email address phone dmp_web",
"clientSecret": null,
"grantType": "code"
},

View File

@ -0,0 +1,7 @@
<html>
<body>
<script>
parent.postMessage(location.href, location.origin);
</script>
</body>
</html>