Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Bugfix/redirect before start #1233

Merged
merged 14 commits into from
May 13, 2021
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,6 @@ docs_for_site
jgiven-reports
logs
site/

# Disable test profiles
opba-embedded-starter/src/main/resources/test-profiles/
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public class BankProfile implements Serializable, CurrentBankProfile {
private Approach preferredApproach;
private boolean tryToUsePreferredApproach;
private boolean uniquePaymentPurpose;
private boolean xs2aSkipConsentAuthorization;

@OneToMany(mappedBy = "bankProfile", cascade = CascadeType.ALL, orphanRemoval = true)
@MapKey(name = "protocolAction")
Expand Down
1 change: 1 addition & 0 deletions opba-db/src/main/resources/migration/master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
<include relativeToChangelogFile="true" file="migrations/0001-init-protocol-facade.xml"/>
<include relativeToChangelogFile="true" file="migrations/0002-mock-data.xml"/>
<include relativeToChangelogFile="true" file="migrations/0003-add-staging-bank-configuration.xml"/>
<include relativeToChangelogFile="true" file="migrations/0004-add-skip-auth-for-deutsche-bank.xml"/>
</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
<column name="try_to_use_preferred_approach" type="BOOLEAN" defaultValue="false">
<constraints nullable="false"/>
</column>
<column name="xs2a_skip_consent_authorization" type="BOOLEAN" defaultValue="false">
<constraints nullable="false"/>
</column>
<column name="unique_payment_purpose" type="BOOLEAN" defaultValue="false">
<constraints nullable="false"/>
</column>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<databaseChangeLog logicalFilePath="db.changelog-1.0.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">

<changeSet author="vbeex@adorsys.com.ua" id="2021-05-12-23">
<comment>Updates xs2a_skip_consent_authorization for DeutscheBank</comment>
<update tableName="${table-prefix}bank_profile">
<column name="xs2a_skip_consent_authorization" value="true"/>
<where>
adapter_id = 'deutsche-bank-adapter'
</where>
</update>
</changeSet>

</databaseChangeLog>
49,742 changes: 24,871 additions & 24,871 deletions opba-db/src/main/resources/migration/migrations/bank_action_data.csv

Large diffs are not rendered by default.

7,106 changes: 3,553 additions & 3,553 deletions opba-db/src/main/resources/migration/migrations/bank_profile_data.csv

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private void writeXs2aBankActionData(String bankRecord) {
int authorizationId;

writelnToFile(BANK_ACTION_DESTINATION_PATH, String.format("%d,%s,LIST_ACCOUNTS,xs2aListAccounts,true", bankActionId++, bankUUID));
writelnToFile(BANK_ACTION_DESTINATION_PATH, String.format("%d,%s,LIST_TRANSACTIONS,xs2aSandboxListTransactions,true", bankActionId++, bankUUID));
writelnToFile(BANK_ACTION_DESTINATION_PATH, String.format("%d,%s,LIST_TRANSACTIONS,xs2aListTransactions,true", bankActionId++, bankUUID));
writelnToFile(BANK_ACTION_DESTINATION_PATH, String.format("%d,%s,AUTHORIZATION,,true", authorizationId = bankActionId++, bankUUID));
writelnToFile(BANK_ACTION_DESTINATION_PATH, String.format("%d,%s,SINGLE_PAYMENT,xs2aInitiateSinglePayment,true", bankActionId++, bankUUID));
writelnToFile(BANK_ACTION_DESTINATION_PATH, String.format("%d,%s,GET_PAYMENT_INFORMATION,xs2aGetPaymentInfoState,true", bankActionId++, bankUUID));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public interface CurrentBankProfile {
*/
boolean isUniquePaymentPurpose();

/**
* Whether to try to skip call to ConsentAuthorization action (startAuthorization)
*/
boolean isXs2aSkipConsentAuthorization();

/**
* Bank identification code.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import com.google.common.collect.ImmutableSet;
import de.adorsys.opba.protocol.bpmnshared.dto.messages.ProcessError;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableExceptionEvent;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.InvocationTargetException;

import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.JOB_EXECUTION_FAILURE;
import static org.flowable.common.engine.api.delegate.event.FlowableEngineEventType.PROCESS_COMPLETED_WITH_ERROR_END_EVENT;
Expand All @@ -33,9 +37,12 @@ protected void processCompletedWithErrorEnd(FlowableEngineEntityEvent event) {
handleError(event);
}

@SneakyThrows
private void handleError(FlowableEngineEntityEvent event) {
if (event instanceof FlowableExceptionEvent) {
log.error("Exception occurred for execution {} of process {}", event.getExecutionId(), event.getProcessInstanceId(), ((FlowableExceptionEvent) event).getCause());
var cause = ((FlowableExceptionEvent) event).getCause();
log.error("Exception occurred for execution {} of process {}", event.getExecutionId(), event.getProcessInstanceId(), cause);
handleXs2aAdapterError(cause);
}

ProcessError result = ProcessError.builder()
Expand All @@ -47,6 +54,15 @@ private void handleError(FlowableEngineEntityEvent event) {
applicationEventPublisher.publishEvent(result);
}

private void handleXs2aAdapterError(Throwable cause) throws IllegalAccessException, InvocationTargetException {
if (null != cause) {
var method = ReflectionUtils.findMethod(cause.getClass(), "getStatusCode");
if (null != method) {
log.error("Response status code: {}", method.invoke(cause));
}
}
}

private String exceptionMessage(FlowableEngineEntityEvent event) {
if (event instanceof FlowableExceptionEvent) {
return "An exception occurred";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.ImmutableMap;
import de.adorsys.opba.protocol.api.common.Approach;
import de.adorsys.opba.protocol.api.common.ProtocolAction;
import de.adorsys.opba.protocol.bpmnshared.dto.context.BaseContext;
import de.adorsys.opba.protocol.api.common.Approach;
import de.adorsys.opba.protocol.xs2a.domain.dto.forms.ScaMethod;
import de.adorsys.opba.protocol.xs2a.service.storage.TransientDataEntry;
import de.adorsys.xs2a.adapter.api.model.AuthenticationObject;
import de.adorsys.xs2a.adapter.api.model.ChallengeData;
import de.adorsys.xs2a.adapter.api.model.HrefType;
import de.adorsys.xs2a.adapter.api.model.StartScaprocessResponse;
import de.adorsys.xs2a.adapter.api.model.TokenResponse;
import lombok.Data;
Expand Down Expand Up @@ -57,6 +58,11 @@ public class Xs2aContext extends BaseContext {
*/
private String aspspScaApproach;

/**
* Consent/Payment create links response from ASPSP.
*/
private Map<String, HrefType> consentOrPaymentCreateLinks;

/**
* ASPSP response after consent authorization was initiated. Used to retrieve ASPSP redirection link for
* consent authorization for REDIRECT consent authorization.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
@RequiredArgsConstructor
public class Xs2aDoScaRedirectToAspspForScaChallenge extends ValidatedExecution<Xs2aContext> {

public static final String SCA_REDIRECT = "scaRedirect";

private final ProtocolUrlsConfiguration urlsConfiguration;
private final RuntimeService runtimeService;
private final Xs2aRedirectExecutor redirectExecutor;
Expand All @@ -33,7 +35,7 @@ protected void doRealExecution(DelegateExecution execution, Xs2aContext context)
execution,
context,
urlSet.getToAspsp(),
context.getStartScaProcessResponse().getLinks().get("scaRedirect").getHref(),
getRedirectToAspspUrl(context),
redirect -> new RedirectToAspsp(redirect.build())
);
}
Expand All @@ -44,4 +46,8 @@ protected void doMockedExecution(DelegateExecution execution, Xs2aContext contex

runtimeService.trigger(execution.getId());
}

protected String getRedirectToAspspUrl(Xs2aContext context) {
return context.getStartScaProcessResponse().getLinks().get(SCA_REDIRECT).getHref();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.adorsys.opba.protocol.xs2a.service.xs2a.authenticate.redirect;

import de.adorsys.opba.protocol.xs2a.config.protocol.ProtocolUrlsConfiguration;
import de.adorsys.opba.protocol.xs2a.context.Xs2aContext;
import de.adorsys.opba.protocol.xs2a.service.xs2a.Xs2aRedirectExecutor;
import org.flowable.engine.RuntimeService;
import org.springframework.stereotype.Service;

/**
* Performs redirection to the ASPSP by sending him to the page with redirection button (to ASPSP) for the redirect approach.
* But is specific as happens just after consent was created.
*/
@Service("xs2aDoScaRedirectToAspspForScaChallengeAfterCreate")
public class Xs2aDoScaRedirectToAspspForScaChallengeAfterCreate extends Xs2aDoScaRedirectToAspspForScaChallenge {

public Xs2aDoScaRedirectToAspspForScaChallengeAfterCreate(ProtocolUrlsConfiguration urlsConfiguration, RuntimeService runtimeService, Xs2aRedirectExecutor redirectExecutor) {
super(urlsConfiguration, runtimeService, redirectExecutor);
}

@Override
protected String getRedirectToAspspUrl(Xs2aContext context) {
return context.getConsentOrPaymentCreateLinks().get(SCA_REDIRECT).getHref();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package de.adorsys.opba.protocol.xs2a.service.xs2a.consent;

import de.adorsys.opba.protocol.bpmnshared.service.exec.ValidatedExecution;
import de.adorsys.opba.protocol.xs2a.context.Xs2aContext;
import de.adorsys.opba.protocol.xs2a.util.logresolver.Xs2aLogResolver;
import de.adorsys.xs2a.adapter.api.Response;
import de.adorsys.xs2a.adapter.api.model.ConsentsResponse201;
import org.apache.logging.log4j.util.Strings;
import org.flowable.engine.delegate.DelegateExecution;

import java.util.UUID;

import static de.adorsys.opba.protocol.bpmnshared.GlobalConst.CONTEXT;
import static de.adorsys.xs2a.adapter.api.ResponseHeaders.ASPSP_SCA_APPROACH;
import static de.adorsys.xs2a.adapter.impl.link.bg.template.LinksTemplate.SCA_OAUTH;

public abstract class BaseCreateAisConsentService<T extends Xs2aContext> extends ValidatedExecution<T> {

protected final Xs2aLogResolver logResolver = new Xs2aLogResolver(getClass());

@Override
protected void doMockedExecution(DelegateExecution execution, T context) {
logResolver.log("doMockedExecution: execution ({}) with context ({})", execution, context);

context.setConsentId("MOCK-" + UUID.randomUUID().toString());
execution.setVariable(CONTEXT, context);
}

protected void postHandleCreatedConsent(Response<ConsentsResponse201> consentInit, DelegateExecution execution, Xs2aContext context) {
context.setWrongAuthCredentials(false);
context.setConsentId(consentInit.getBody().getConsentId());
if (null != consentInit.getBody().getLinks() && consentInit.getBody().getLinks().containsKey(SCA_OAUTH)) {
context.setOauth2IntegratedNeeded(true);
context.setScaOauth2Link(consentInit.getBody().getLinks().get(SCA_OAUTH).getHref());
}

if (null != consentInit.getHeaders() && Strings.isNotBlank(consentInit.getHeaders().getHeader(ASPSP_SCA_APPROACH))) {
context.setAspspScaApproach(consentInit.getHeaders().getHeader(ASPSP_SCA_APPROACH));
if (null != consentInit.getBody()) {
context.setConsentOrPaymentCreateLinks(consentInit.getBody().getLinks());
}
}

execution.setVariable(CONTEXT, context);
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
package de.adorsys.opba.protocol.xs2a.service.xs2a.consent;

import de.adorsys.opba.protocol.bpmnshared.service.context.ContextUtil;
import de.adorsys.opba.protocol.bpmnshared.service.exec.ValidatedExecution;
import de.adorsys.opba.protocol.xs2a.config.protocol.ProtocolUrlsConfiguration;
import de.adorsys.opba.protocol.xs2a.context.ais.AccountListXs2aContext;
import de.adorsys.opba.protocol.xs2a.service.dto.ValidatedPathHeadersBody;
import de.adorsys.opba.protocol.xs2a.service.xs2a.dto.consent.ConsentInitiateHeaders;
import de.adorsys.opba.protocol.xs2a.service.xs2a.dto.consent.ConsentInitiateParameters;
import de.adorsys.opba.protocol.xs2a.service.xs2a.validation.Xs2aValidator;
import de.adorsys.opba.protocol.xs2a.util.logresolver.Xs2aLogResolver;
import de.adorsys.xs2a.adapter.api.AccountInformationService;
import de.adorsys.xs2a.adapter.api.model.Consents;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Service;

import java.util.UUID;

import static de.adorsys.opba.protocol.xs2a.constant.GlobalConst.CONTEXT;

/**
Expand All @@ -27,15 +23,14 @@
@Slf4j
@Service("xs2aAccountListConsentInitiate")
@RequiredArgsConstructor
public class CreateAisAccountListConsentService extends ValidatedExecution<AccountListXs2aContext> {
public class CreateAisAccountListConsentService extends BaseCreateAisConsentService<AccountListXs2aContext> {

private final AisConsentInitiateExtractor extractor;
private final AccountInformationService ais;
private final Xs2aValidator validator;
private final ProtocolUrlsConfiguration urlsConfiguration;
private final CreateConsentOrPaymentPossibleErrorHandler handler;
private final CreateAisConsentService createAisConsentService;
private final Xs2aLogResolver logResolver = new Xs2aLogResolver(getClass());

@Override
protected void doPrepareContext(DelegateExecution execution, AccountListXs2aContext context) {
Expand All @@ -59,14 +54,13 @@ protected void doRealExecution(DelegateExecution execution, AccountListXs2aConte
logResolver.log("doRealExecution: execution ({}) with context ({})", execution, context);

ValidatedPathHeadersBody<ConsentInitiateParameters, ConsentInitiateHeaders, Consents> params = extractor.forExecution(context);
handler.tryCreateAndHandleErrors(execution, () -> createAisConsentService.createConsent(ais, execution, context, params));
}

@Override
protected void doMockedExecution(DelegateExecution execution, AccountListXs2aContext context) {
logResolver.log("doMockedExecution: execution ({}) with context ({})", execution, context);
var result = handler.tryCreateAndHandleErrors(execution, () -> createAisConsentService.createConsent(ais, context, params));
if (null == result) {
execution.setVariable(CONTEXT, context);
log.warn("Consent creation failed");
return;
}

context.setConsentId("MOCK-" + UUID.randomUUID().toString());
execution.setVariable(CONTEXT, context);
postHandleCreatedConsent(result, execution, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@
import de.adorsys.xs2a.adapter.api.Response;
import de.adorsys.xs2a.adapter.api.model.Consents;
import de.adorsys.xs2a.adapter.api.model.ConsentsResponse201;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.stereotype.Service;

import static de.adorsys.opba.protocol.xs2a.constant.GlobalConst.CONTEXT;
import static de.adorsys.xs2a.adapter.impl.link.bg.template.LinksTemplate.SCA_OAUTH;

/**
* Calls Xs2a API to initiate AIS consent.
*/
Expand All @@ -24,9 +20,8 @@ public class CreateAisConsentService {

private final Xs2aLogResolver logResolver = new Xs2aLogResolver(getClass());

void createConsent(
Response<ConsentsResponse201> createConsent(
AccountInformationService ais,
DelegateExecution execution,
Xs2aAisContext context,
ValidatedPathHeadersBody<ConsentInitiateParameters, ConsentInitiateHeaders, Consents> params) {
logResolver.log("createConsent with parameters: {}", params.getPath(), params.getHeaders(), params.getBody());
Expand All @@ -36,13 +31,6 @@ void createConsent(
params.getBody()
);
logResolver.log("createConsent response: {}", consentInit);

context.setWrongAuthCredentials(false);
context.setConsentId(consentInit.getBody().getConsentId());
if (null != consentInit.getBody().getLinks() && consentInit.getBody().getLinks().containsKey(SCA_OAUTH)) {
context.setOauth2IntegratedNeeded(true);
context.setScaOauth2Link(consentInit.getBody().getLinks().get(SCA_OAUTH).getHref());
}
execution.setVariable(CONTEXT, context);
return consentInit;
}
}
Loading