When selecting "login with zenodo" it will prompt and login with zenodo, and the access token will be registered to the current user instead of re-login you in with the zenodo account.
Also disable Zenodo user login
This commit is contained in:
parent
3fc5d68135
commit
a63ae3045e
|
@ -153,16 +153,6 @@ public class Login {
|
|||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Principal>().payload(this.nonVerifiedUserAuthenticationService.Touch(principal.getToken())).status(ApiMessageCode.NO_MESSAGE));
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = {"/hasDOIToken"}, consumes = "application/json", produces = "application/json")
|
||||
public @ResponseBody
|
||||
ResponseEntity<ResponseItem<Boolean>> hasDOIToken(Principal principal) throws NullEmailException {
|
||||
try {
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Boolean>().payload(this.userManager.isDOITokenValid(principal)).status(ApiMessageCode.NO_MESSAGE));
|
||||
} catch (NonValidTokenException | ExpiredTokenException | IOException e) {
|
||||
return ResponseEntity.status(460).body(new ResponseItem<Boolean>().payload(false).status(ApiMessageCode.ERROR_MESSAGE).message(e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@RequestMapping(method = RequestMethod.POST, value = {"/logout"}, consumes = "application/json", produces = "application/json")
|
||||
public @ResponseBody
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package eu.eudat.controllers;
|
||||
|
||||
import eu.eudat.data.query.items.table.userinfo.UserInfoTableRequestItem;
|
||||
import eu.eudat.exceptions.security.ExpiredTokenException;
|
||||
import eu.eudat.exceptions.security.NonValidTokenException;
|
||||
import eu.eudat.exceptions.security.NullEmailException;
|
||||
import eu.eudat.logic.managers.UserManager;
|
||||
import eu.eudat.logic.security.claims.ClaimedAuthorities;
|
||||
import eu.eudat.logic.services.ApiContext;
|
||||
import eu.eudat.models.data.doi.DOIRequest;
|
||||
import eu.eudat.models.data.helpers.common.DataTableData;
|
||||
import eu.eudat.models.data.helpers.responses.ResponseItem;
|
||||
import eu.eudat.models.data.security.Principal;
|
||||
|
@ -73,6 +77,24 @@ public class Users extends BaseController {
|
|||
DataTableData<UserListingModel> dataTable = userManager.getCollaboratorsPaged(userInfoTableRequestItem, principal);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DataTableData<UserListingModel>>().payload(dataTable).status(ApiMessageCode.NO_MESSAGE));
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = {"/hasDOIToken"}, consumes = "application/json", produces = "application/json")
|
||||
public @ResponseBody
|
||||
ResponseEntity<ResponseItem<Boolean>> hasDOIToken(Principal principal) throws NullEmailException {
|
||||
try {
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Boolean>().payload(this.userManager.isDOITokenValid(principal)).status(ApiMessageCode.NO_MESSAGE));
|
||||
} catch (NonValidTokenException | ExpiredTokenException | IOException e) {
|
||||
return ResponseEntity.status(460).body(new ResponseItem<Boolean>().payload(false).status(ApiMessageCode.ERROR_MESSAGE).message(e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@RequestMapping(method = RequestMethod.POST, value = {"/registerDOIToken"}, consumes = "application/json", produces = "application/json")
|
||||
public @ResponseBody
|
||||
ResponseEntity<ResponseItem<UserProfile>> registerDOIToken(@RequestBody DOIRequest doiRequest, Principal principal) throws NullEmailException, IOException {
|
||||
userManager.registerDOIToken(doiRequest, principal);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<UserProfile>().status(ApiMessageCode.NO_MESSAGE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,11 +13,14 @@ import eu.eudat.exceptions.security.NullEmailException;
|
|||
import eu.eudat.exceptions.security.UnauthorisedException;
|
||||
import eu.eudat.logic.builders.entity.UserRoleBuilder;
|
||||
import eu.eudat.logic.builders.model.models.DataTableDataBuilder;
|
||||
import eu.eudat.logic.security.customproviders.Zenodo.ZenodoCustomProvider;
|
||||
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoResponseToken;
|
||||
import eu.eudat.logic.services.ApiContext;
|
||||
import eu.eudat.logic.services.operations.authentication.AuthenticationService;
|
||||
import eu.eudat.logic.utilities.builders.XmlBuilder;
|
||||
import eu.eudat.models.HintedModelFactory;
|
||||
import eu.eudat.models.data.dmp.DataManagementPlan;
|
||||
import eu.eudat.models.data.doi.DOIRequest;
|
||||
import eu.eudat.models.data.helpers.common.DataTableData;
|
||||
import eu.eudat.models.data.login.Credentials;
|
||||
import eu.eudat.models.data.security.Principal;
|
||||
|
@ -26,6 +29,7 @@ import eu.eudat.models.data.userinfo.UserProfile;
|
|||
import eu.eudat.queryable.QueryableList;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
@ -39,10 +43,14 @@ import java.util.stream.Collectors;
|
|||
public class UserManager {
|
||||
|
||||
private ApiContext apiContext;
|
||||
private ZenodoCustomProvider zenodoCustomProvider;
|
||||
private Environment environment;
|
||||
|
||||
@Autowired
|
||||
public UserManager(ApiContext apiContext) {
|
||||
public UserManager(ApiContext apiContext, ZenodoCustomProvider zenodoCustomProvider, Environment environment) {
|
||||
this.apiContext = apiContext;
|
||||
this.zenodoCustomProvider = zenodoCustomProvider;
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public eu.eudat.models.data.user.composite.DatasetProfile generateDatasetProfileModel(eu.eudat.data.entities.DatasetProfile profile) {
|
||||
|
@ -127,4 +135,15 @@ public class UserManager {
|
|||
}
|
||||
throw new NonValidTokenException("This account has no Zenodo Token");
|
||||
}
|
||||
|
||||
public void registerDOIToken(DOIRequest doiRequest, Principal principal) throws IOException {
|
||||
ZenodoResponseToken responseToken = this.zenodoCustomProvider.getAccessToken(doiRequest.getZenodoRequest().getCode()
|
||||
, this.environment.getProperty("zenodo.login.client_id")
|
||||
, this.environment.getProperty("zenodo.login.client_secret")
|
||||
, doiRequest.getRedirectUri());
|
||||
Map<String, Object> settings = new HashMap<>();
|
||||
settings.put("zenodoToken", responseToken.getAccessToken());
|
||||
settings.put("expirationDate", Instant.now().plusSeconds(responseToken.getExpiresIn()).toEpochMilli());
|
||||
this.updateSettings(settings, principal);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package eu.eudat.models.data.doi;
|
||||
|
||||
import eu.eudat.logic.security.validators.zenodo.helpers.ZenodoRequest;
|
||||
|
||||
public class DOIRequest {
|
||||
|
||||
private ZenodoRequest zenodoRequest;
|
||||
private String redirectUri;
|
||||
|
||||
public ZenodoRequest getZenodoRequest() {
|
||||
return zenodoRequest;
|
||||
}
|
||||
|
||||
public void setZenodoRequest(ZenodoRequest zenodoRequest) {
|
||||
this.zenodoRequest = zenodoRequest;
|
||||
}
|
||||
|
||||
public String getRedirectUri() {
|
||||
return redirectUri;
|
||||
}
|
||||
|
||||
public void setRedirectUri(String redirectUri) {
|
||||
this.redirectUri = redirectUri;
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ import { NgModule } from '@angular/core';
|
|||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { ReloadHelperComponent } from '@app/ui/misc/reload-helper/reload-helper.component';
|
||||
import { B2AccessLoginComponent } from './ui/auth/login/b2access/b2access-login.component';
|
||||
import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module';
|
||||
import { Oauth2DialogComponent } from './ui/misc/oauth2-dialog/oauth2-dialog.component';
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
|
@ -219,7 +221,8 @@ const appRoutes: Routes = [
|
|||
data: {
|
||||
},
|
||||
},
|
||||
{ path: 'reload', component: ReloadHelperComponent }
|
||||
{ path: 'reload', component: ReloadHelperComponent },
|
||||
{ path: 'oauth2', component: Oauth2DialogComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -30,6 +30,7 @@ import { NgcCookieConsentConfig, NgcCookieConsentModule } from 'ngx-cookieconsen
|
|||
import { TranslateServerLoader } from './core/services/language/server.loader';
|
||||
import { BaseHttpService } from './core/services/http/base-http.service';
|
||||
import { ConfigurationService } from './core/services/configuration/configuration.service';
|
||||
import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module';
|
||||
|
||||
// AoT requires an exported function for factories
|
||||
export function HttpLoaderFactory(http: HttpClient, appConfig: ConfigurationService) {
|
||||
|
@ -97,7 +98,8 @@ const cookieConfig: NgcCookieConsentConfig = {
|
|||
DatasetCreateWizardModule,
|
||||
NavbarModule,
|
||||
SidebarModule,
|
||||
NgcCookieConsentModule.forRoot(cookieConfig)
|
||||
NgcCookieConsentModule.forRoot(cookieConfig),
|
||||
Oauth2DialogModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
|
|
|
@ -159,13 +159,4 @@ export class AuthService extends BaseService {
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
public hasDOIToken(): Observable<any> {
|
||||
this.actionUrl = this.configurationService.server + 'auth/';
|
||||
const url = this.actionUrl + '/hasDOIToken';
|
||||
const principal = this.current();
|
||||
let headers = this.headers;
|
||||
headers = headers.set('AuthToken', principal.token);
|
||||
return this.http.get(url, { headers: headers });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,4 +47,14 @@ export class UserService {
|
|||
getCollaboratorsPaged(dataTableRequest: DataTableRequest<UserCriteria>): Observable<DataTableData<UserListingModel>> {
|
||||
return this.http.post<DataTableData<UserListingModel>>(this.actionUrl + 'getCollaboratorsPaged', JSON.stringify(dataTableRequest), { headers: this.headers });
|
||||
}
|
||||
|
||||
public hasDOIToken(): Observable<any> {
|
||||
const url = this.actionUrl + 'hasDOIToken';
|
||||
return this.http.get(url, { headers: this.headers });
|
||||
}
|
||||
|
||||
public registerDOIToken(code: string, redirectUri: string): Observable<any> {
|
||||
const url = this.actionUrl + 'registerDOIToken';
|
||||
return this.http.post(url, {zenodoRequest: {code: code}, redirectUri: redirectUri}, { headers: this.headers });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@ import { Role } from "@app/core/common/enum/role";
|
|||
import { DmpInvitationDialogComponent } from '../invitation/dmp-invitation.component';
|
||||
import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
|
||||
import { MultipleChoiceDialogComponent } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component';
|
||||
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
|
||||
import { Oauth2DialogComponent } from '@app/ui/misc/oauth2-dialog/oauth2-dialog.component';
|
||||
import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { UserService } from '@app/core/services/user/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dmp-overview',
|
||||
|
@ -49,7 +54,10 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
private authentication: AuthService,
|
||||
private dialog: MatDialog,
|
||||
private language: TranslateService,
|
||||
private uiNotificationService: UiNotificationService
|
||||
private uiNotificationService: UiNotificationService,
|
||||
private configurationService: ConfigurationService,
|
||||
private oauth2DialogService: Oauth2DialogService,
|
||||
private userService: UserService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -323,8 +331,17 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
return dmp.doi == null ? true : false;
|
||||
}
|
||||
|
||||
getAccessUrl(): string {
|
||||
const redirectUri = this.configurationService.app + 'oauth2';
|
||||
const url = this.configurationService.loginProviders.zenodoConfiguration.oauthUrl
|
||||
+ '?client_id=' + this.configurationService.loginProviders.zenodoConfiguration.clientId
|
||||
+ '&response_type=code&scope=deposit:write+deposit:actions&state=astate&redirect_uri='
|
||||
+ redirectUri;
|
||||
return url;
|
||||
}
|
||||
|
||||
getDoi(dmp: DmpOverviewModel) {
|
||||
this.authentication.hasDOIToken().subscribe(response => {
|
||||
this.userService.hasDOIToken().subscribe(response => {
|
||||
this.showConfirmationDOIDialog(dmp);
|
||||
}, error => {
|
||||
this.showErrorConfirmationDOIDialog(error.error.message, dmp);
|
||||
|
@ -368,8 +385,9 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||
switch (result) {
|
||||
case 0:
|
||||
this.authentication.logout();
|
||||
this.router.navigate(['/login/external/zenodo']);
|
||||
// this.authentication.logout();
|
||||
// this.router.navigate(['/login/external/zenodo']);
|
||||
this.showOauth2Dialog(this.getAccessUrl(), dmp);
|
||||
break;
|
||||
case 1:
|
||||
this.showConfirmationDOIDialog(dmp);
|
||||
|
@ -378,6 +396,18 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
showOauth2Dialog(url: string, dmp: DmpOverviewModel) {
|
||||
this.oauth2DialogService.login(url)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(code => {
|
||||
if (!isNullOrUndefined(code)) {
|
||||
this.userService.registerDOIToken(code, this.configurationService.app + 'oauth2')
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(() => this.showConfirmationDOIDialog(dmp));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onDOICallbackSuccess(): void {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success);
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<p>oauth2-dialog works!</p>
|
|
@ -0,0 +1,41 @@
|
|||
import { Component, OnInit, Inject } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { BaseComponent } from '@common/base/base.component';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Oauth2DialogService } from './service/oauth2-dialog.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-oauth2-dialog',
|
||||
templateUrl: './oauth2-dialog.component.html',
|
||||
styleUrls: ['./oauth2-dialog.component.scss']
|
||||
})
|
||||
export class Oauth2DialogComponent extends BaseComponent implements OnInit{
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private oauth2dialogService: Oauth2DialogService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.route.queryParams.pipe(takeUntil(this._destroyed))
|
||||
.subscribe((params: Params) => {
|
||||
const url = params['url'];
|
||||
if (!params['code']) { this.loadUrl(url) } else { this.sendCode(params['code']); }
|
||||
});
|
||||
}
|
||||
|
||||
private loadUrl(url: string ) {
|
||||
console.log(url);
|
||||
window.location.href = url;
|
||||
}
|
||||
|
||||
private sendCode(code: string) {
|
||||
localStorage.setItem('oauthCode', code);
|
||||
window.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { Oauth2DialogComponent } from './oauth2-dialog.component';
|
||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||
import { Oauth2DialogService } from './service/oauth2-dialog.service';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [Oauth2DialogComponent],
|
||||
imports: [
|
||||
CommonUiModule
|
||||
],
|
||||
providers: [
|
||||
Oauth2DialogService
|
||||
]
|
||||
})
|
||||
export class Oauth2DialogModule { }
|
|
@ -0,0 +1,34 @@
|
|||
import { Injectable, Inject } from '@angular/core';
|
||||
import { BaseService } from '@common/base/base.service';
|
||||
import { BehaviorSubject, Observable, interval } from 'rxjs';
|
||||
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class Oauth2DialogService extends BaseService{
|
||||
|
||||
private code: BehaviorSubject<string> = new BehaviorSubject(undefined);
|
||||
|
||||
constructor(private configurationService: ConfigurationService) {
|
||||
super();
|
||||
}
|
||||
|
||||
public registerCode(code: string) {
|
||||
this.code.next(code);
|
||||
}
|
||||
|
||||
public login(url: string): Observable<string> {
|
||||
const windows = window.open(this.configurationService.app + 'oauth2?url=' + encodeURIComponent(url) ,'', 'height=500px,width=500px');
|
||||
const sub = interval(300).pipe(takeUntil(this._destroyed)).subscribe(() => {
|
||||
if (windows.closed) {
|
||||
const oauthCode = localStorage.getItem('oauthCode');
|
||||
localStorage.removeItem('oauthCode');
|
||||
this.code.next(oauthCode);
|
||||
sub.unsubscribe();
|
||||
}
|
||||
});
|
||||
return this.code.asObservable();
|
||||
}
|
||||
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"defaultCulture": "en-US",
|
||||
"loginProviders": {
|
||||
"enabled": [1, 2, 3, 4, 5, 6, 7, 8, 10],
|
||||
"enabled": [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
"facebookConfiguration": { "clientId": "" },
|
||||
"googleConfiguration": { "clientId": "" },
|
||||
"linkedInConfiguration": {
|
||||
|
|
Loading…
Reference in New Issue