diff --git a/backend/core/src/main/java/org/opencdmp/audit/AuditableAction.java b/backend/core/src/main/java/org/opencdmp/audit/AuditableAction.java index 085dedac1..c0c84243f 100644 --- a/backend/core/src/main/java/org/opencdmp/audit/AuditableAction.java +++ b/backend/core/src/main/java/org/opencdmp/audit/AuditableAction.java @@ -137,6 +137,7 @@ public class AuditableAction { public static final EventId Deposit_GetAccessToken = new EventId(18001, "Deposit_GetAccessToken"); public static final EventId Deposit_Deposit = new EventId(18002, "Deposit_Deposit"); public static final EventId Deposit_GetLogo = new EventId(18003, "Deposit_GetLogo"); + public static final EventId Deposit_GetRepository = new EventId(18004, "Deposit_GetRepository"); public static final EventId Tag_Query = new EventId(19000, "Tag_Query"); public static final EventId Tag_Lookup = new EventId(19001, "Tag_Lookup"); diff --git a/backend/core/src/main/java/org/opencdmp/commons/notification/NotificationProperties.java b/backend/core/src/main/java/org/opencdmp/commons/notification/NotificationProperties.java index 4da201dcf..f434964f5 100644 --- a/backend/core/src/main/java/org/opencdmp/commons/notification/NotificationProperties.java +++ b/backend/core/src/main/java/org/opencdmp/commons/notification/NotificationProperties.java @@ -23,7 +23,7 @@ public class NotificationProperties { private String contactSupportEmail; public UUID getDmpInvitationExternalUserType() { - return dmpInvitationExternalUserType; + return this.dmpInvitationExternalUserType; } public void setDmpInvitationExternalUserType(UUID dmpInvitationExternalUserType) { @@ -31,7 +31,7 @@ public class NotificationProperties { } public UUID getDmpInvitationExistingUserType() { - return dmpInvitationExistingUserType; + return this.dmpInvitationExistingUserType; } public void setDmpInvitationExistingUserType(UUID dmpInvitationExistingUserType) { @@ -39,7 +39,7 @@ public class NotificationProperties { } public UUID getDmpModifiedType() { - return dmpModifiedType; + return this.dmpModifiedType; } public void setDmpModifiedType(UUID dmpModifiedType) { @@ -47,7 +47,7 @@ public class NotificationProperties { } public UUID getDmpFinalisedType() { - return dmpFinalisedType; + return this.dmpFinalisedType; } public void setDmpFinalisedType(UUID dmpFinalisedType) { @@ -55,7 +55,7 @@ public class NotificationProperties { } public UUID getDescriptionModifiedType() { - return descriptionModifiedType; + return this.descriptionModifiedType; } public void setDescriptionModifiedType(UUID descriptionModifiedType) { @@ -63,7 +63,7 @@ public class NotificationProperties { } public UUID getDescriptionFinalisedType() { - return descriptionFinalisedType; + return this.descriptionFinalisedType; } public void setDescriptionFinalisedType(UUID descriptionFinalisedType) { @@ -71,7 +71,7 @@ public class NotificationProperties { } public UUID getMergeAccountConfirmationType() { - return mergeAccountConfirmationType; + return this.mergeAccountConfirmationType; } public void setMergeAccountConfirmationType(UUID mergeAccountConfirmationType) { @@ -79,7 +79,7 @@ public class NotificationProperties { } public UUID getRemoveCredentialConfirmationType() { - return removeCredentialConfirmationType; + return this.removeCredentialConfirmationType; } public void setRemoveCredentialConfirmationType(UUID removeCredentialConfirmationType) { @@ -87,7 +87,7 @@ public class NotificationProperties { } public UUID getDmpDepositType() { - return dmpDepositType; + return this.dmpDepositType; } public void setDmpDepositType(UUID dmpDepositType) { @@ -95,7 +95,7 @@ public class NotificationProperties { } public UUID getDescriptionTemplateInvitationType() { - return descriptionTemplateInvitationType; + return this.descriptionTemplateInvitationType; } public void setDescriptionTemplateInvitationType(UUID descriptionTemplateInvitationType) { @@ -103,7 +103,7 @@ public class NotificationProperties { } public int getEmailExpirationTimeSeconds() { - return emailExpirationTimeSeconds; + return this.emailExpirationTimeSeconds; } public void setEmailExpirationTimeSeconds(int emailExpirationTimeSeconds) { @@ -111,7 +111,7 @@ public class NotificationProperties { } public UUID getContactSupportType() { - return contactSupportType; + return this.contactSupportType; } public void setContactSupportType(UUID contactSupportType) { @@ -119,7 +119,7 @@ public class NotificationProperties { } public UUID getPublicContactSupportType() { - return publicContactSupportType; + return this.publicContactSupportType; } public void setPublicContactSupportType(UUID publicContactSupportType) { @@ -127,7 +127,7 @@ public class NotificationProperties { } public String getContactSupportEmail() { - return contactSupportEmail; + return this.contactSupportEmail; } public void setContactSupportEmail(String contactSupportEmail) { diff --git a/backend/core/src/main/java/org/opencdmp/model/persist/deposit/DepositRequest.java b/backend/core/src/main/java/org/opencdmp/model/persist/deposit/DepositRequest.java index b58cc2977..af25da4b2 100644 --- a/backend/core/src/main/java/org/opencdmp/model/persist/deposit/DepositRequest.java +++ b/backend/core/src/main/java/org/opencdmp/model/persist/deposit/DepositRequest.java @@ -1,10 +1,10 @@ package org.opencdmp.model.persist.deposit; -import org.opencdmp.commons.validation.BaseValidator; +import gr.cite.tools.fieldset.BaseFieldSet; import gr.cite.tools.validation.specification.Specification; +import org.opencdmp.commons.validation.BaseValidator; import org.opencdmp.convention.ConventionService; import org.opencdmp.errorcode.ErrorThesaurusProperties; -import gr.cite.tools.fieldset.BaseFieldSet; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Scope; @@ -30,7 +30,7 @@ public class DepositRequest { private BaseFieldSet project; public String getRepositoryId() { - return repositoryId; + return this.repositoryId; } public void setRepositoryId(String repositoryId) { @@ -38,7 +38,7 @@ public class DepositRequest { } public UUID getDmpId() { - return dmpId; + return this.dmpId; } public void setDmpId(UUID dmpId) { @@ -46,7 +46,7 @@ public class DepositRequest { } public String getAccessToken() { - return accessToken; + return this.accessToken; } public void setAccessToken(String accessToken) { @@ -54,7 +54,7 @@ public class DepositRequest { } public BaseFieldSet getProject() { - return project; + return this.project; } public void setProject(BaseFieldSet project) { @@ -84,10 +84,10 @@ public class DepositRequest { return Arrays.asList( this.spec() .must(() -> !this.isEmpty(item.getRepositoryId())) - .failOn(DepositRequest._repositoryId).failWith(messageSource.getMessage("Validation_Required", new Object[]{DepositRequest._repositoryId}, LocaleContextHolder.getLocale())), + .failOn(DepositRequest._repositoryId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DepositRequest._repositoryId}, LocaleContextHolder.getLocale())), this.spec() .must(() -> this.isValidGuid(item.getDmpId())) - .failOn(DepositRequest._dmpId).failWith(messageSource.getMessage("Validation_Required", new Object[]{DepositRequest._dmpId}, LocaleContextHolder.getLocale())) + .failOn(DepositRequest._dmpId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DepositRequest._dmpId}, LocaleContextHolder.getLocale())) ); } } diff --git a/backend/web/src/main/java/org/opencdmp/controllers/DepositController.java b/backend/web/src/main/java/org/opencdmp/controllers/DepositController.java index 6652df4f9..93c1c1394 100644 --- a/backend/web/src/main/java/org/opencdmp/controllers/DepositController.java +++ b/backend/web/src/main/java/org/opencdmp/controllers/DepositController.java @@ -1,7 +1,13 @@ package org.opencdmp.controllers; -import org.opencdmp.audit.AuditableAction; +import gr.cite.tools.auditing.AuditService; +import gr.cite.tools.data.censor.CensorFactory; +import gr.cite.tools.exception.MyNotFoundException; +import gr.cite.tools.fieldset.FieldSet; +import gr.cite.tools.logging.LoggerService; +import gr.cite.tools.logging.MapLogEntry; import gr.cite.tools.validation.ValidationFilterAnnotation; +import org.opencdmp.audit.AuditableAction; import org.opencdmp.model.EntityDoi; import org.opencdmp.model.censorship.EntityDoiCensor; import org.opencdmp.model.censorship.deposit.DepositConfigurationCensor; @@ -9,13 +15,10 @@ import org.opencdmp.model.deposit.DepositConfiguration; import org.opencdmp.model.persist.deposit.DepositAuthenticateRequest; import org.opencdmp.model.persist.deposit.DepositRequest; import org.opencdmp.service.deposit.DepositService; -import gr.cite.tools.auditing.AuditService; -import gr.cite.tools.data.censor.CensorFactory; -import gr.cite.tools.fieldset.FieldSet; -import gr.cite.tools.logging.LoggerService; -import gr.cite.tools.logging.MapLogEntry; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; @@ -32,7 +35,7 @@ import java.util.Map; @RestController @CrossOrigin -@RequestMapping(value = {"/api/deposit/"}) +@RequestMapping("/api/deposit/") public class DepositController { private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DepositController.class)); @@ -44,11 +47,14 @@ public class DepositController { private final AuditService auditService; + private final MessageSource messageSource; + @Autowired - public DepositController(DepositService depositService, CensorFactory censorFactory, AuditService auditService) { + public DepositController(DepositService depositService, CensorFactory censorFactory, AuditService auditService, MessageSource messageSource) { this.depositService = depositService; this.censorFactory = censorFactory; this.auditService = auditService; + this.messageSource = messageSource; } @GetMapping("/repositories/available") @@ -93,6 +99,24 @@ public class DepositController { return persisted; } + @GetMapping("/repositories/{repositoryId}") + public org.opencdmp.model.deposit.DepositConfiguration getRepository(@PathVariable("repositoryId") String repositoryId, FieldSet fieldSet) throws InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { + logger.debug(new MapLogEntry("retrieving" + DepositConfiguration.class.getSimpleName()).And("fields", fieldSet).And("repositoryId", repositoryId)); + + this.censorFactory.censor(DepositConfigurationCensor.class).censor(fieldSet, null); + + List models = this.depositService.getAvailableConfigurations(fieldSet); + org.opencdmp.model.deposit.DepositConfiguration model = models.stream().filter(x-> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null); + if (model == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{repositoryId, org.opencdmp.model.deposit.DepositConfiguration.class.getSimpleName()}, LocaleContextHolder.getLocale())); + + this.auditService.track(AuditableAction.Deposit_GetRepository, Map.ofEntries( + new AbstractMap.SimpleEntry("repositoryId", repositoryId), + new AbstractMap.SimpleEntry("fields", fieldSet) + )); + + return model; + } + @GetMapping("/repositories/{repositoryId}/logo") public String getLogo(@PathVariable("repositoryId") String repositoryId) throws InvalidApplicationException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { logger.debug(new MapLogEntry("get logo" + DepositConfiguration.class.getSimpleName()).And("repositoryId", repositoryId)); diff --git a/backend/web/src/main/resources/config/deposit-devel.yml b/backend/web/src/main/resources/config/deposit-devel.yml index 6eb01fe91..5266b1b75 100644 --- a/backend/web/src/main/resources/config/deposit-devel.yml +++ b/backend/web/src/main/resources/config/deposit-devel.yml @@ -1,7 +1,7 @@ deposit: sources: - url: http://dev04.local.cite.gr:55330/zenodo - repositoryId: Zenodo + repositoryId: zenodo pdfTransformerId: docx-file-transformer rdaTransformerId: rda-file-transformer issuer-url: ${IDP_ISSUER_URI_TOKEN} diff --git a/dmp-frontend/src/app/app-routing.module.ts b/dmp-frontend/src/app/app-routing.module.ts index 41a93bf18..f83680b2e 100644 --- a/dmp-frontend/src/app/app-routing.module.ts +++ b/dmp-frontend/src/app/app-routing.module.ts @@ -1,10 +1,9 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { Oauth2DialogComponent } from './ui/misc/oauth2-dialog/oauth2-dialog.component'; -import { AppComponent } from './app.component'; import { AppPermission } from './core/common/enum/permission.enum'; import { BreadcrumbService } from './ui/misc/breadcrumb/breadcrumb.service'; import { ReloadHelperComponent } from './ui/misc/reload-helper/reload-helper.component'; +import { DepositOauth2DialogComponent } from './ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component'; const appRoutes: Routes = [ { @@ -367,7 +366,9 @@ const appRoutes: Routes = [ }, { path: 'logout', loadChildren: () => import('./ui/auth/logout/logout.module').then(m => m.LogoutModule) }, { path: 'reload', component: ReloadHelperComponent }, - { path: 'oauth2', component: Oauth2DialogComponent }, + { path: 'oauth2', component: DepositOauth2DialogComponent }, + { path: 'login/external/zenodo', component: DepositOauth2DialogComponent }, + { path: 'deposit/oauth2', loadChildren: () => import('./ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.module').then(m => m.DepositOauth2DialogModule) } ]; @NgModule({ diff --git a/dmp-frontend/src/app/app.module.ts b/dmp-frontend/src/app/app.module.ts index d7916c359..e61742887 100644 --- a/dmp-frontend/src/app/app.module.ts +++ b/dmp-frontend/src/app/app.module.ts @@ -36,10 +36,10 @@ import { LanguageService } from './core/services/language/language.service'; import { TranslateServerLoader } from './core/services/language/server.loader'; import { MatomoService } from './core/services/matomo/matomo-service'; import { GuidedTourModule } from './library/guided-tour/guided-tour.module'; -import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module'; import { OpenDMPCustomTranslationCompiler } from './utilities/translate/opendmp-custom-translation-compiler'; import { CoreAnnotationServiceModule } from 'annotation-service/services/core-service.module'; import { CoreNotificationServiceModule } from '@notification-service/services/core-service.module'; +import { DepositOauth2DialogModule } from './ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.module'; // AoT requires an exported function for factories export function HttpLoaderFactory(languageHttpService: LanguageHttpService) { @@ -145,7 +145,7 @@ export function InstallationConfigurationFactory(appConfig: ConfigurationService NavbarModule, SidebarModule, NgcCookieConsentModule.forRoot(cookieConfig), - Oauth2DialogModule, + DepositOauth2DialogModule, GuidedTourModule.forRoot(), DragulaModule.forRoot(), NgxMatomoModule.forRoot({ diff --git a/dmp-frontend/src/app/core/services/deposit/deposit.service.ts b/dmp-frontend/src/app/core/services/deposit/deposit.service.ts index 4c8cf1803..2946397b0 100644 --- a/dmp-frontend/src/app/core/services/deposit/deposit.service.ts +++ b/dmp-frontend/src/app/core/services/deposit/deposit.service.ts @@ -30,9 +30,18 @@ export class DepositService { catchError((error: any) => throwError(error))); } - getAccessToken(item: DepositAuthenticateRequest): Observable { + getRepository(repositoryId: string, reqFields: string[] = []): Observable { + const url = `${this.apiBase}//repositories/${repositoryId}`; + const options = { params: { f: reqFields } }; + + return this.http + .get(url, options).pipe( + catchError((error: any) => throwError(error))); + } + + getAccessToken(item: DepositAuthenticateRequest): Observable { const url = `${this.apiBase}/get-access-token`; - return this.http.post(url, item).pipe(catchError((error: any) => throwError(error))); + return this.http.post(url, item).pipe(catchError((error: any) => throwError(error))); } deposit(item: DepositRequest): Observable { diff --git a/dmp-frontend/src/app/ui/auth/login/login.module.ts b/dmp-frontend/src/app/ui/auth/login/login.module.ts index 4cafdc86e..6546559d7 100644 --- a/dmp-frontend/src/app/ui/auth/login/login.module.ts +++ b/dmp-frontend/src/app/ui/auth/login/login.module.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'; import { LoginComponent } from '@app/ui/auth/login/login.component'; import { LoginRoutingModule } from '@app/ui/auth/login/login.routing'; import { LoginService } from '@app/ui/auth/login/utilities/login.service'; -import { Oauth2DialogModule } from '@app/ui/misc/oauth2-dialog/oauth2-dialog.module'; 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'; @@ -13,8 +12,7 @@ import { PostLoginComponent } from './post-login/post-login.component'; imports: [ CommonUiModule, CommonFormsModule, - LoginRoutingModule, - Oauth2DialogModule + LoginRoutingModule ], declarations: [ LoginComponent, diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dropdown/dmp-deposit-dropdown.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dropdown/dmp-deposit-dropdown.component.ts index 0d3647d2e..53192679a 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dropdown/dmp-deposit-dropdown.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dropdown/dmp-deposit-dropdown.component.ts @@ -11,7 +11,7 @@ import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; -import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service'; +import { DepositOauth2DialogService } from '@app/ui/misc/deposit-oauth2-dialog/service/deposit-oauth2-dialog.service'; import { BaseComponent } from '@common/base/base.component'; import { MultipleChoiceDialogComponent } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component'; import { TranslateService } from '@ngx-translate/core'; @@ -37,7 +37,7 @@ export class DmpDepositDropdown extends BaseComponent implements OnInit { private language: TranslateService, private translate: TranslateService, private uiNotificationService: UiNotificationService, - private oauth2DialogService: Oauth2DialogService, + private depositOauth2DialogService: DepositOauth2DialogService, private sanitizer: DomSanitizer ) { super(); @@ -75,9 +75,7 @@ export class DmpDepositDropdown extends BaseComponent implements OnInit { dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { switch (result) { case 0: - this.showOauth2Dialog(repo.repositoryAuthorizationUrl + '?client_id=' + repo.repositoryClientId - + '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri=' - + repo.redirectUri, repo, this.dmp); + this.showOauth2Dialog(this.depositOauth2DialogService.getLoginUrl(repo, this.dmp?.id), repo, this.dmp); break; case 1: const depositRequest: DepositRequest = { @@ -123,34 +121,25 @@ export class DmpDepositDropdown extends BaseComponent implements OnInit { } showOauth2Dialog(url: string, repo: DepositConfiguration, dmp: Dmp) { - this.oauth2DialogService.login(url) + this.depositOauth2DialogService.login(url) .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - if (result !== undefined) { - if (result.oauthCode !== undefined && result.oauthCode !== null && !this.oauthLock) { - const depositAuthenticateRequest: DepositAuthenticateRequest = { - repositoryId: repo.repositoryId, - code: result.oauthCode - }; - this.depositRepositoriesService.getAccessToken(depositAuthenticateRequest) - .pipe(takeUntil(this._destroyed)) - .subscribe(token => { - const depositRequest: DepositRequest = { - repositoryId: repo.repositoryId, - dmpId: dmp.id, - accessToken: token, - project: this.EntityDoiFields() - }; - this.depositRepositoriesService.deposit(depositRequest) - .pipe(takeUntil(this._destroyed)) - .subscribe(doi => { - this.onDOICallbackSuccess(); - this.outputRepos.push(doi); - this.outputReposEmitter.emit(this.outputRepos); - }, error => this.onDOICallbackError(error)); - }); - this.oauthLock = true; - } + .subscribe(token => { + if (token !== undefined) { + console.log(token); + // const depositRequest: DepositRequest = { + // repositoryId: repo.repositoryId, + // dmpId: dmp.id, + // accessToken: token, + // project: this.EntityDoiFields() + // }; + // this.depositRepositoriesService.deposit(depositRequest) + // .pipe(takeUntil(this._destroyed)) + // .subscribe(doi => { + // this.onDOICallbackSuccess(); + // this.outputRepos.push(doi); + // this.outputReposEmitter.emit(this.outputRepos); + // }, error => this.onDOICallbackError(error)); + this.oauthLock = true; } else { this.oauthLock = false; } diff --git a/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog-routing.module.ts b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog-routing.module.ts new file mode 100644 index 000000000..8c5350e64 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog-routing.module.ts @@ -0,0 +1,27 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { DepositOauth2DialogComponent } from './deposit-oauth2-dialog.component'; + +const routes: Routes = [ + { + path: ':id/:entityId', + component: DepositOauth2DialogComponent, + data: { + breadcrumb: true + }, + }, + { + path: 'code-callaback', + component: DepositOauth2DialogComponent, + data: { + breadcrumb: true + }, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [] +}) +export class DepositOauth2DialogRoutingModule { } diff --git a/dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.component.html b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component.html similarity index 100% rename from dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.component.html rename to dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component.html diff --git a/dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.component.scss b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component.scss similarity index 100% rename from dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.component.scss rename to dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component.scss diff --git a/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component.ts b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component.ts new file mode 100644 index 000000000..60ba4f18e --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.component.ts @@ -0,0 +1,103 @@ +import { Component, OnInit, Inject } from '@angular/core'; +import { ActivatedRoute, ParamMap, Params } from '@angular/router'; +import { BaseComponent } from '@common/base/base.component'; +import { takeUntil } from 'rxjs/operators'; +import { DepositOauth2DialogService } from './service/deposit-oauth2-dialog.service'; +import { DepositService } from '@app/core/services/deposit/deposit.service'; +import { DepositConfiguration } from '@app/core/model/deposit/deposit-configuration'; +import { nameof } from 'ts-simple-nameof'; +import { HttpErrorResponse } from '@angular/common/http'; +import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { DepositAuthenticateRequest, DepositRequest, DepositRequestFields } from '@app/core/model/deposit/deposit-request'; +import { EntityDoi } from '@app/core/model/entity-doi/entity-doi'; + +@Component({ + selector: 'app-deposit-oauth2-dialog', + templateUrl: './deposit-oauth2-dialog.component.html', + styleUrls: ['./deposit-oauth2-dialog.component.scss'] +}) +export class DepositOauth2DialogComponent extends BaseComponent implements OnInit{ + + constructor( + private route: ActivatedRoute, + private depositRepositoriesService: DepositService, + private uiNotificationService: UiNotificationService, + private httpErrorHandlingService: HttpErrorHandlingService, + private depositOauth2DialogService: DepositOauth2DialogService + ) { + super(); + } + + error: string = null; + + ngOnInit(): void { + this.route.paramMap.pipe(takeUntil(this._destroyed)).subscribe((paramMap: ParamMap) => { + let itemId = paramMap.get('id'); + let entityId = paramMap.get('entityId'); + + if (itemId && entityId) { + this.depositRepositoriesService.getRepository(itemId, [ + nameof(x => x.depositType), + nameof(x => x.repositoryId), + nameof(x => x.repositoryAuthorizationUrl), + nameof(x => x.repositoryRecordUrl), + nameof(x => x.repositoryClientId), + nameof(x => x.hasLogo), + nameof(x => x.redirectUri) + ]) + .pipe(takeUntil(this._destroyed)) + .subscribe( + repo => { + this.loadUrl(this.depositOauth2DialogService.getLoginUrl(repo, entityId)); + }, + error => this.onCallbackError(error)); + } else { + this.error = 'Repository id required' + } + }); + this.route.queryParams.pipe(takeUntil(this._destroyed)) + .subscribe((params: Params) => { + console.log(params) + if (params['url']) { + this.loadUrl(params['url']) + } else if (params['code']) { + if (!params['state']) { + this.error = 'State required' + + } else { + this.getAccessToken(params['code'], params['state']); + } + } else { + this.error = 'Repository id required' + } + }); + } + + private loadUrl(url: string ) { + window.location.href = url; + } + + private getAccessToken(code: string, state: string) { + const decoded = decodeURIComponent(state); + const stateParsed = JSON.parse(atob(decoded)); + if (!stateParsed) this.error = 'State required'; + if (!stateParsed.repositoryId) this.error = 'State repository id required'; + if (!stateParsed.entity) this.error = 'State entity required'; + + const depositAuthenticateRequest: DepositAuthenticateRequest = { + repositoryId: stateParsed.repositoryId, + code: code + }; + this.depositRepositoriesService.getAccessToken(depositAuthenticateRequest) + .pipe(takeUntil(this._destroyed)) + .subscribe(token => { + localStorage.setItem('repositoryOauthToken', token); + }, error => this.onCallbackError(error)); + } + + onCallbackError(errorResponse: HttpErrorResponse) { + const error: HttpError = this.httpErrorHandlingService.getError(errorResponse); + this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning); + } +} diff --git a/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.module.ts b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.module.ts new file mode 100644 index 000000000..b770e5de7 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/deposit-oauth2-dialog.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; + +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { DepositOauth2DialogComponent } from './deposit-oauth2-dialog.component'; +import { DepositOauth2DialogRoutingModule } from './deposit-oauth2-dialog-routing.module'; +import { DepositOauth2DialogService } from './service/deposit-oauth2-dialog.service'; + + +@NgModule({ + declarations: [DepositOauth2DialogComponent], + imports: [ + CommonUiModule, + DepositOauth2DialogRoutingModule, + ], + providers: [ + DepositOauth2DialogService + ] +}) +export class DepositOauth2DialogModule { } diff --git a/dmp-frontend/src/app/ui/misc/oauth2-dialog/service/oauth2-dialog.service.ts b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/service/deposit-oauth2-dialog.service.ts similarity index 55% rename from dmp-frontend/src/app/ui/misc/oauth2-dialog/service/oauth2-dialog.service.ts rename to dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/service/deposit-oauth2-dialog.service.ts index 8b556b63d..980498f76 100644 --- a/dmp-frontend/src/app/ui/misc/oauth2-dialog/service/oauth2-dialog.service.ts +++ b/dmp-frontend/src/app/ui/misc/deposit-oauth2-dialog/service/deposit-oauth2-dialog.service.ts @@ -4,9 +4,10 @@ import { BehaviorSubject, Observable, interval } from 'rxjs'; import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; import { isNullOrUndefined } from '@app/utilities/enhancers/utils'; import { takeUntil } from 'rxjs/operators'; +import { DepositConfiguration } from '@app/core/model/deposit/deposit-configuration'; @Injectable() -export class Oauth2DialogService extends BaseService{ +export class DepositOauth2DialogService extends BaseService{ private code: BehaviorSubject = new BehaviorSubject(undefined); @@ -14,8 +15,11 @@ export class Oauth2DialogService extends BaseService{ super(); } - public registerCode(code: string) { - this.code.next(code); + public getLoginUrl(repo: DepositConfiguration, entityId) { + return repo.repositoryAuthorizationUrl + '?client_id=' + repo.repositoryClientId + + '&state=' + encodeURIComponent(btoa(JSON.stringify({ repositoryId: repo.repositoryId, entity: entityId }))) + + '&response_type=code&scope=deposit:write+deposit:actions+user:email&redirect_uri=' + + repo.redirectUri } public login(url: string): Observable { @@ -23,24 +27,11 @@ export class Oauth2DialogService extends BaseService{ const sub = interval(300).pipe(takeUntil(this._destroyed)).subscribe(() => { if (windows.closed) { let oauthCode; - let oauthState; - let oauthToken; - let oauthVerifier; - if (localStorage.getItem('oauthCode')) { - oauthCode = localStorage.getItem('oauthCode'); - localStorage.removeItem('oauthCode'); + if (localStorage.getItem('repositoryOauthToken')) { + oauthCode = localStorage.getItem('repositoryOauthToken'); + localStorage.removeItem('repositoryOauthToken'); } - if (localStorage.getItem('oauthState')) { - oauthState = localStorage.getItem('oauthState'); - localStorage.removeItem('oauthState'); - } - if (localStorage.getItem('oauthObject')) { - const oauthObject = JSON.parse(localStorage.getItem('oauthObject')); - localStorage.removeItem('oauthObject'); - oauthToken = oauthObject.oauth_token; - oauthVerifier = oauthObject.oauth_verifier; - } - this.code.next({oauthCode: oauthCode, oauthState: oauthState, oauthToken: oauthToken, oauthVerifier: oauthVerifier}); + this.code.next(oauthCode); this.code.next(undefined); sub.unsubscribe(); } diff --git a/dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.component.ts b/dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.component.ts deleted file mode 100644 index 2ec574631..000000000 --- a/dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.component.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Component, OnInit, Inject } from '@angular/core'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -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'] && (!params['oauth_token'] && !params['oauth_verifier'])) { this.loadUrl(url) } else { this.sendCode(params); } - }); - } - - private loadUrl(url: string ) { - window.location.href = url; - } - - private sendCode(params: Params) { - if (params['code']) { - localStorage.setItem('oauthCode', params['code']); - } - if (params['state']) { - localStorage.setItem('oauthState', params['state']); - } - if (params['oauth_token'] && params['oauth_verifier']) { - localStorage.setItem('oauthObject', JSON.stringify({oauth_token: params['oauth_token'], oauth_verifier: params['oauth_verifier']})); - } - window.close(); - } - -} diff --git a/dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.module.ts b/dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.module.ts deleted file mode 100644 index 5bdefcec4..000000000 --- a/dmp-frontend/src/app/ui/misc/oauth2-dialog/oauth2-dialog.module.ts +++ /dev/null @@ -1,17 +0,0 @@ -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 { }