mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 17:37:00 +00:00
Merge branch 'develop' of github.com:OpenBankProject/OBP-API into develop
This commit is contained in:
commit
3fcda1e9c0
3
.github/workflows/build_package.yml
vendored
3
.github/workflows/build_package.yml
vendored
@ -21,8 +21,9 @@ jobs:
|
||||
cache: maven
|
||||
- name: Build with Maven
|
||||
run: |
|
||||
cp obp-api/src/main/resources/props/sample.props.template obp-api/src/main/resources/props/default.props
|
||||
echo connector=star > obp-api/src/main/resources/props/test.default.props
|
||||
echo starConnector_supported_types=mapped,internal > obp-api/src/main/resources/props/test.default.props
|
||||
echo starConnector_supported_types=mapped,internal >> obp-api/src/main/resources/props/test.default.props
|
||||
echo hostname=http://localhost:8016 >> obp-api/src/main/resources/props/test.default.props
|
||||
echo tests.port=8016 >> obp-api/src/main/resources/props/test.default.props
|
||||
echo End of minimum settings >> obp-api/src/main/resources/props/test.default.props
|
||||
|
||||
@ -62,7 +62,12 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<version>1.7.26</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>slf4j-ext</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<version>1.7.26</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
@ -110,12 +115,12 @@
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc8</artifactId>
|
||||
<version>21.4.0.0</version>
|
||||
<version>21.5.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.191</version>
|
||||
<version>2.1.214</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -138,7 +143,7 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -201,41 +206,27 @@
|
||||
<artifactId>amqp_3.1_${scala.version}</artifactId>
|
||||
<version>1.5.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tokbox</groupId>
|
||||
<artifactId>opentok-server-sdk</artifactId>
|
||||
<version>3.0.0-beta.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.tokbox</groupId>-->
|
||||
<!-- <artifactId>opentok-server-sdk</artifactId>-->
|
||||
<!-- <version>3.0.0-beta.2</version>-->
|
||||
<!-- <exclusions>-->
|
||||
<!-- <exclusion>-->
|
||||
<!-- <groupId>com.fasterxml.jackson.core</groupId>-->
|
||||
<!-- <artifactId>jackson-databind</artifactId>-->
|
||||
<!-- </exclusion>-->
|
||||
<!-- </exclusions>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.elasticsearch</groupId>
|
||||
<artifactId>elasticsearch</artifactId>
|
||||
<version>6.8.17</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.sksamuel.elastic4s/elastic4s-client-esjava -->
|
||||
<dependency>
|
||||
<groupId>com.sksamuel.elastic4s</groupId>
|
||||
<artifactId>elastic4s-http_${scala.version}</artifactId>
|
||||
<version>6.1.1</version>
|
||||
<!-- TODO try to switch to slf4j from log4j
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-1.2-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions> -->
|
||||
<artifactId>elastic4s-client-esjava_${scala.version}</artifactId>
|
||||
<version>8.2.1</version>
|
||||
</dependency>
|
||||
<!-- for LiftConsole -->
|
||||
<dependency>
|
||||
@ -356,10 +347,11 @@
|
||||
<version>0.5.7</version>
|
||||
</dependency>
|
||||
<!-- embeded kafka for unit test start -->
|
||||
<!-- https://mvnrepository.com/artifact/io.github.embeddedkafka/embedded-kafka -->
|
||||
<dependency>
|
||||
<groupId>net.manub</groupId>
|
||||
<artifactId>scalatest-embedded-kafka_2.12</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<groupId>io.github.embeddedkafka</groupId>
|
||||
<artifactId>embedded-kafka_2.12</artifactId>
|
||||
<version>2.4.1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- embeded kafka for unit test end -->
|
||||
@ -444,7 +436,7 @@
|
||||
<dependency>
|
||||
<groupId>sh.ory.hydra</groupId>
|
||||
<artifactId>hydra-client</artifactId>
|
||||
<version>1.7.0</version>
|
||||
<version>1.11.8</version>
|
||||
</dependency>
|
||||
|
||||
<!--json schema validation start-->
|
||||
|
||||
@ -1,84 +1,163 @@
|
||||
api.explorer = Explorador API
|
||||
introduction = Introducción
|
||||
# The main drawback here is that all application resources for a given locale must exist
|
||||
# in the same file, and that extended characters such as œ aren’t properly encoded by
|
||||
# default. This is due to Java properties bundles using ISO 8859-1 encoding and thus
|
||||
# requiring conversion to escaped format, such as \u0153. Fortunately this process can
|
||||
# be automated using tools like native2ascii
|
||||
# https://native2ascii.net/
|
||||
# This tool will allow you to convert national language characters to and from their Unicode equivalents in plain ASCII text.
|
||||
api.explorer = API Explorer
|
||||
api_explorer = API Explorer
|
||||
api_manager = Gestor API
|
||||
introduction = Introducci\u00f3n
|
||||
support = Soporte
|
||||
register = Registrarse
|
||||
logon = Ingresar
|
||||
terms_conditions = Terminos y condiciones
|
||||
privacy_policy = Pol\u00edtica de privacidad
|
||||
api_documentation = Documentaci\u00f3n API
|
||||
api_host = Host del API
|
||||
api_tester = Evaluador API
|
||||
view_api_explorer = Ver API Explorer
|
||||
get_api_key = Obten llave API
|
||||
welcome_to = Bienvenido a la instancia de prueba del API Sandbox del Open Bank Project!
|
||||
get_started_building_your_application = Empiece a crear su aplicaci\ufffdn
|
||||
for_banks = Para Bancos
|
||||
|
||||
invalid.email.address = Invalid email address
|
||||
password.must.be.set = Password must be set
|
||||
password.too.short = Password too short
|
||||
passwords.do.not.match = Passwords do not match
|
||||
number.required = A numeric value must be provided
|
||||
ajax.error=The server cannot be contacted at this time
|
||||
invalid.zip.code = Invalid ZIP code
|
||||
invalid.postal.code = Invalid postal code
|
||||
unique.email.address = The email address must be unique
|
||||
must.be.logged.in = You must be logged in
|
||||
already.logged.in = already logged in. Please logout first.
|
||||
login = Login
|
||||
logout = Logout
|
||||
log.in = Log In
|
||||
log.out = Log Out
|
||||
sign.up = Sign Up
|
||||
logged.in = Logged In
|
||||
logout.first = Please logout first.
|
||||
lost.password = Lost Password
|
||||
reset.password = Reset Password
|
||||
change.password = Change Password
|
||||
password.changed = Password Changed
|
||||
edit.user = Edit User
|
||||
validate.user = Validate User
|
||||
edit.profile = Edit Profile
|
||||
sign.up.confirmation = Sign up confirmation
|
||||
sign.up.message = You have signed up. A validation email message will be sent to you.
|
||||
sign.up.validation.link=Click on this link to complete signup:
|
||||
welcome = Welcome
|
||||
account.validated = Account Validated
|
||||
invalid.validation.link = Validation link invalid
|
||||
account.validation.error = Your account has not been validated. Please check your email for a validation link.
|
||||
invalid.credentials = Invalid Username/Password
|
||||
enter.email = Enter your email address and we'll email you a link to reset your password
|
||||
email.address = Email address
|
||||
reset.password.confirmation = Reset Password Confirmation
|
||||
dear = Dear
|
||||
click.reset.link = Click on this link to reset your password
|
||||
thank.you = Thank you
|
||||
reset.password.request = Reset Password Request
|
||||
password.reset.email.sent = Password Reset Email sent
|
||||
account.validation.resent = Account Validation Re-sent
|
||||
email.address.not.found = Email address not found
|
||||
send.it = Send It
|
||||
reset.your.password = Reset your password
|
||||
enter.your.new.password = Enter your new password
|
||||
repeat.your.new.password = Enter your new password (repeat)
|
||||
set.password = Set Password
|
||||
password.link.invalid = Password reset link invalid
|
||||
wrong.old.password = Wrong old password
|
||||
old.password = Old password
|
||||
new.password = New password
|
||||
repeat.password = New password (repeat)
|
||||
repeat = Repeat
|
||||
edit = Edit
|
||||
|
||||
Get_started = Empezar
|
||||
Create_an_account = Crea una cuenta
|
||||
Description_Create_an_account = En primer lugar, crea una cuenta de desarrollador gratuita en este sandbox y solicita una clave de desarrollador. En esta fase se te pedir\ufffd que env\ufffdes informaci\ufffdn b\ufffdsica sobre tu aplicaci\ufffdn.
|
||||
Connect_your_app = Conecta tu app
|
||||
Connect_your_app_description = Utiliza nuestros SDKs para conectar tu aplicaci\ufffdn a las APIs de Open Bank Project. Necesitar\ufffds tu clave de desarrollador, que deber\ufffdas tener desde que creaste tu cuenta. Consulta todas las APIs disponibles en el Explorador de APIs, pero aseg\ufffdrate de que est\ufffds utilizando la URL base correcta.
|
||||
Test_your_app = Pruebe su aplicaci\ufffdn con datos de clientes
|
||||
Test_your_app_description = una vez que su aplicaci\ufffdn est\ufffd conectada, puede probarla utilizando las credenciales del cliente de prueba.
|
||||
|
||||
|
||||
|
||||
register_for_an_account = Registrar una cuenta nueva
|
||||
|
||||
# Explore APIs Section
|
||||
explore_api_title = Explorar los titulos de las API
|
||||
explore_api_accounts_title = Cuentas
|
||||
explore_api_accounts = Acceso a cuentas (XS21) y tarjetas. Proporcionar acceso de grano fino a los invitados (auditor, contable o p\ufffdblico).
|
||||
explore_api_branches_title = Sucursales, cajeros y productos
|
||||
explore_api_branches = Acceda a los datos abiertos relacionados con los bancos, incluidas las sucursales y los cajeros autom\ufffdticos, as\ufffd como la geolocalizaci\ufffdn y los horarios de apertura.
|
||||
explore_api_transactions_title = Transacciones
|
||||
explore_api_transactions = Acceda al historial de transacciones y a los metadatos de las mismas.
|
||||
explore_api_metadata_title = Metadata
|
||||
explore_api_metadata = Enriquezca las transacciones y las contrapartes con metadatos que incluyan geolocalizaciones, comentarios, im\ufffdgenes y etiquetas (por ejemplo, categor\ufffda de gasto).
|
||||
explore_api_counterparties_title = Metadata
|
||||
explore_api_counterparties = Acceda a los pagadores y beneficiarios de una cuenta, incluyendo metadatos como sus alias, etiquetas, logotipos y p\ufffdginas de inicio.
|
||||
explore_api_webhooks_title = Webhooks
|
||||
explore_api_webhooks = Llamar a servicios web externos basados en eventos de la Cuenta.
|
||||
explore_api_customer_title = Incorporaci\ufffdn de clientes y KYC
|
||||
explore_api_customer = Realizar la creaci\ufffdn de usuarios, clientes y cuentas. Gestionar los documentos, los medios y el estado de Conozca a su Cliente (KYC). Crear reuniones y mensajes de clientes.
|
||||
explore_api_roles_title = Funciones, m\ufffdtricas y documentaci\ufffdn de la API
|
||||
explore_api_roles = Controle el acceso a los puntos finales, obtenga m\ufffdtricas y documentaci\ufffdn de la API.
|
||||
explore_api_payments_title = Pagos y transferencias
|
||||
explore_api_payments = Iniciar solicitudes de transacciones (transferencias y pagos). Ver y confirmar cargos (seg\ufffdn la PSD2). Responder a los retos de autenticaci\ufffdn fuerte del cliente (SCA).
|
||||
explore_api_warehouse_title = Buscar en el almac\ufffdn
|
||||
explore_api_warehouse = Realice b\ufffdsquedas avanzadas y consultas estad\ufffdsticas en el almac\ufffdn de datos.
|
||||
|
||||
# Get Started Section
|
||||
get_started_title = Empezar
|
||||
get_started_create_account_title = Crea una cuenta
|
||||
get_started_create_account = En primer lugar, crea una cuenta de desarrollador gratuita en este sandbox y solicita una clave de desarrollador. En esta fase se te pedir\u00e1 que env\u00edes informaci\u00f3n b\u00e1sica sobre tu aplicaci\u00f3n.
|
||||
get_started_create_account_sign_up = Register for an account
|
||||
get_started_connect_your_app_title = Conecta tu app
|
||||
get_started_connect_your_app = Utiliza nuestros SDKs para conectar tu aplicaci\u00f3n a las APIs de Open Bank Project. Necesitar\u00e1s tu clave de desarrollador, que deber\u00edas tener desde que creaste tu cuenta. Consulta todas las APIs disponibles en el Explorador de APIs, pero aseg\u00farate de que est\u00e1s utilizando la URL base correcta.
|
||||
get_started_test_your_app_title = Pruebe su aplicaci\u00f3n con datos de clientes
|
||||
get_started_test_your_app = Una vez que su aplicaci\u00f3n est\u00e9 conectada, puede probarla utilizando las credenciales del cliente de prueba.
|
||||
get_started_test_your_app_sandbox_date = View sandbox customer log ons.
|
||||
|
||||
username = Nombre de usuario
|
||||
logontext = Acceda a la API del Open Bank Project
|
||||
passwordlog = Contrase\ufffda
|
||||
Forgotten_password = \ufffdHas olvidado tu contrase\ufffda?
|
||||
don't_have_account = \ufffdNo Tienes una cuenta?
|
||||
or_login_with_openid = o con\ufffdctate con OpenID
|
||||
or = o
|
||||
|
||||
|
||||
invalid.email.address = Direcci\ufffdn de correo electr\ufffdnico no v\ufffdlida
|
||||
password.must.be.set = Hay que poner la contrase\ufffda
|
||||
password.too.short = Contrase\ufffda demasiado corta
|
||||
passwords.do.not.match = Las contrase\ufffdas no coinciden
|
||||
number.required = Se debe proporcionar un valor num\ufffdrico
|
||||
ajax.error=El servidor no puede ser contactado en este momento
|
||||
invalid.zip.code = C\ufffddigo postal inv\ufffdlido
|
||||
invalid.postal.code = C\ufffddigo postal inv\ufffdlido
|
||||
unique.email.address = La direcci\ufffdn de correo electr\ufffdnico debe ser \ufffdnica
|
||||
must.be.logged.in = Debe estar conectado
|
||||
already.logged.in = ya ha iniciado la sesi\ufffdn. Por favor, cierre la sesi\ufffdn primero.
|
||||
login = Ingresar
|
||||
logout = Salir
|
||||
log.in = Ingresar
|
||||
log.out = Salir
|
||||
sign.up = Registrarse
|
||||
logged.in = Ingresar
|
||||
logout.first = Por favor, cierre la sesi\ufffdn primero.
|
||||
lost.password = Contrase\ufffda perdida
|
||||
reset.password = Restablecer contrase\ufffda
|
||||
change.password = Cambiar la contrase\ufffda
|
||||
password.changed = Contrase\ufffda cambiada
|
||||
edit.user = Editar usuario
|
||||
validate.user = Validar usuario
|
||||
edit.profile = Editar perfil
|
||||
sign.up.confirmation = Confirmaci\ufffdn de inscripci\ufffdn
|
||||
sign.up.message = Se ha inscrito. Se le enviar\ufffd un mensaje de correo electr\ufffdnico de validaci\ufffdn.
|
||||
sign.up.validation.link=Haga clic en este enlace para completar la inscripci\ufffdn:
|
||||
welcome = Bienvenido
|
||||
account.validated = Cuenta validada
|
||||
invalid.validation.link = Enlace de validaci\ufffdn inv\ufffdlido
|
||||
account.validation.error = Su cuenta no ha sido validada. Por favor, compruebe su correo electr\ufffdnico para un enlace de validaci\ufffdn.
|
||||
invalid.credentials = Nombre de usuario/contrase\ufffda no v\ufffdlidos
|
||||
enter.email = Introduzca su direcci\ufffdn de correo electr\ufffdnico y le enviaremos un enlace para restablecer su contrase\ufffda
|
||||
email.address = Correo electr\ufffdnico
|
||||
reset.password.confirmation = Confirmacion para reestablecer la contrase\ufffda
|
||||
dear = Apreciable
|
||||
click.reset.link = Da click en el enlace para reestablecer tu contrase\ufffda
|
||||
thank.you = Gracias
|
||||
reset.password.request = Solicitud para reestablecer contrase\ufffda
|
||||
password.reset.email.sent = Contrase\ufffda para reestablecer el correo ha sido enviada
|
||||
account.validation.resent = Validaci\ufffdn de la cuenta enviado de nuevo
|
||||
email.address.not.found = Direcci\ufffdn de correo no encontrado
|
||||
send.it = Enviar
|
||||
reset.your.password = Resetea tu contrase\ufffda
|
||||
enter.your.new.password = Escribe tu contrase\ufffda
|
||||
repeat.your.new.password = Escribe tu contrase\ufffda (repitela)
|
||||
set.password = Establecer contrase\ufffda
|
||||
password.link.invalid = Enlace para cambio de contrase\ufffda invalido
|
||||
wrong.old.password = Contrase\ufffda equivocada
|
||||
old.password = Contrase\ufffda antigua
|
||||
new.password = Nueva contrase\ufffda
|
||||
repeat.password = Nueva contrase\ufffda (repetir)
|
||||
repeat = Repetir
|
||||
edit = Editar
|
||||
cancel = Cancel
|
||||
ok = OK
|
||||
change = Change
|
||||
password = Password
|
||||
recover.password = Recover Password
|
||||
profile.updated = You have updated your profile
|
||||
male = Male
|
||||
female = Female
|
||||
first.name = First name
|
||||
last.name = Last name
|
||||
locale = Locale
|
||||
time.zone = Time Zone
|
||||
msg.notice = Notice
|
||||
msg.warning = Warning
|
||||
change = Cambiar
|
||||
password = Contrase\ufffda
|
||||
recover.password = Recuperar contrase\ufffda
|
||||
profile.updated = Has actualizado tu perfil
|
||||
male = Masculino
|
||||
female = Femenino
|
||||
first.name = Primer Nombre
|
||||
last.name = Apellido
|
||||
locale = Localidad
|
||||
time.zone = Zona Horaria
|
||||
msg.notice = Advertencia
|
||||
msg.warning = Peligro
|
||||
msg.error = Error
|
||||
crudify.menu.view.displayName=View %s
|
||||
crudify.menu.edit.displayName=Edit %s
|
||||
crudify.menu.delete.displayName=Delete %s
|
||||
paginator.norecords = There are no records to display
|
||||
paginator.displayingrecords = Displaying %s-%s of %s
|
||||
crudify.menu.view.displayName=Ver %s
|
||||
crudify.menu.edit.displayName=Editar %s
|
||||
crudify.menu.delete.displayName=Borrar %s
|
||||
paginator.norecords = No hay informaci\ufffdn que mostrar
|
||||
paginator.displayingrecords = Mostrando %s-%s de %s
|
||||
|
||||
open_bank_project_is = Open Bank Project es
|
||||
and_commercial_licenses = TESOBE y licencias comerciales
|
||||
|
||||
# Country names
|
||||
country_1 = United States
|
||||
country_2 = Afghanistan
|
||||
@ -353,35 +432,37 @@ country_270 = Peter I Island
|
||||
country_271 = Queen Maud Land
|
||||
country_272 = British Antarctic Territory
|
||||
# LiftScreen + Wizard
|
||||
Next = Next
|
||||
Previous = Previous
|
||||
Finish = Finish
|
||||
Cancel = Cancel
|
||||
Next = Siguiente
|
||||
Previous = Anterior
|
||||
Finish = Terminado
|
||||
Cancel = Cancelado
|
||||
|
||||
# Crudify
|
||||
Create = Create
|
||||
Save = Save
|
||||
Edit = Edit
|
||||
Delete = Delete
|
||||
delete = delete
|
||||
View = View
|
||||
List = List %s
|
||||
Created = Created
|
||||
Edited = Edited
|
||||
Deleted = Deleted
|
||||
Create = Crear
|
||||
Save = Guardar
|
||||
Edit = Editar
|
||||
Delete = Borrar
|
||||
delete = borrar
|
||||
View = Ver
|
||||
List = lista %s
|
||||
Created = Creado
|
||||
Edited = Editado
|
||||
Deleted = Borrado
|
||||
|
||||
#OBP specific fields
|
||||
consumer.registration.nav.name=Obtener llave API
|
||||
invalid.login.credentials=Invalid Login Credentials
|
||||
invalid.username=Invalid Username: \
|
||||
1) The ONLY allowed characters in Usernames are: a-z A-Z 0-9 . _ \
|
||||
2) Usernames MUST be between 8 and 100 characters long \
|
||||
3) Usernames MUST NOT start with _ or . \
|
||||
4) Usernames MUST NOT contain __ or ._ or ._ or .. \
|
||||
5) Usernames MUST NOT end with _ or . \
|
||||
6) Any valid email address is allowed as the Username
|
||||
invalid.login.credentials= Credenciales invalidas
|
||||
invalid.username=Nombre de usuario invalido: \
|
||||
1) Los \ufffdnicos caracteres permitidos en los nombres de usuario son: a-z A-Z 0-9 . _ \
|
||||
2) Los nombres de usuario DEBEN tener entre 8 y 100 caracteres \
|
||||
3) Los nombres de usuario NO DEBEN empezar por _ o . \
|
||||
4) Los nombres de usuario NO DEBEN contener __ o ._ o ._ o .. \
|
||||
5) Los nombres de usuario NO DEBEN terminar con _ o . \
|
||||
6) Cualquier direcci\ufffdn de correo electr\ufffdnico v\ufffdlida est\ufffd permitida como nombre de usuario
|
||||
|
||||
your.username.is.not.unique = Your username is not unique. Please enter a different one.
|
||||
your.username.is.not.unique = Su nombre de usuario no es \ufffdnico. Por favor, introduzca uno diferente.
|
||||
# Those 2 messages must have the same output in order to prevent leakage of information
|
||||
user.invitation.is.already.finished = Looks like the invitation link is invalid. Still need help? Please send us a message using API Playground Support.
|
||||
your.secret.link.is.not.valid = Looks like the invitation link is invalid. Still need help? Please send us a message using API Playground Support.
|
||||
user.invitation.is.already.finished = Parece que el enlace de invitaci\ufffdn no es v\ufffdlido. \ufffdTodav\ufffda necesitas ayuda? Por favor, env\ufffdanos un mensaje usando el soporte de API Playground.
|
||||
your.secret.link.is.not.valid = Parece que el enlace de invitaci\ufffdn no es v\ufffdlido. \ufffdTodav\ufffda necesitas ayuda? Por favor, env\ufffdanos un mensaje usando el soporte de API Playground.
|
||||
|
||||
OBP-30001 = El usuario no ha iniciado sesi\u00c3\u00b3n. \u00c2\u00a1Se requiere autenticaci\u00c3\u00b3n!
|
||||
347
obp-api/src/main/resources/i18n/lift-core_zh_CN.properties
Normal file
347
obp-api/src/main/resources/i18n/lift-core_zh_CN.properties
Normal file
@ -0,0 +1,347 @@
|
||||
invalid.email.address = \u65e0\u6548\u7535\u5b50\u90ae\u7bb1\u5730\u5740
|
||||
password.must.be.set = \u5bc6\u7801\u4e0d\u80fd\u4e3a\u7a7a
|
||||
password.too.short = \u5bc6\u7801\u592a\u77ed
|
||||
passwords.do.not.match = \u5bc6\u7801\u4e0d\u5339\u914d
|
||||
number.required = \u53ea\u80fd\u63d0\u4f9b\u6570\u5b57\u503c
|
||||
ajax.error=\u8fde\u63a5\u670d\u52a1\u5668\u5931\u8d25
|
||||
invalid.zip.code = \u65e0\u6548\u90ae\u653f\u7f16\u7801
|
||||
invalid.postal.code = \u65e0\u6548\u90ae\u653f\u7f16\u7801
|
||||
unique.email.address = \u7535\u5b50\u90ae\u7bb1\u5730\u5740\u5df2\u5b58\u5728
|
||||
must.be.logged.in = \u8bf7\u5148\u767b\u5f55
|
||||
already.logged.in = \u5df2\u7ecf\u767b\u5f55\uff0c\u8bf7\u5148\u767b\u51fa
|
||||
login = \u767b\u5f55
|
||||
logout = \u767b\u51fa
|
||||
log.in = \u767b\u5f55
|
||||
log.out = \u767b\u51fa
|
||||
sign.up = \u6ce8\u518c
|
||||
logged.in = \u5df2\u767b\u5f55
|
||||
logout.first = \u8bf7\u5148\u767b\u51fa
|
||||
lost.password = \u5fd8\u8bb0\u5bc6\u7801
|
||||
reset.password = \u91cd\u7f6e\u5bc6\u7801
|
||||
change.password = \u4fee\u6539\u5bc6\u7801
|
||||
password.changed = \u5bc6\u7801\u5df2\u4fee\u6539
|
||||
edit.user = \u8bbe\u7f6e\u7528\u6237
|
||||
validate.user = \u6821\u9a8c\u7528\u6237
|
||||
edit.profile = \u4fee\u6539\u8d44\u6599
|
||||
sign.up.confirmation = \u6ce8\u518c\u4fe1\u606f\u786e\u8ba4
|
||||
sign.up.message = \u6ce8\u518c\u6210\u529f\uff0c\u7cfb\u7edf\u4f1a\u53d1\u9001\u4e00\u5c01\u5e10\u53f7\u9a8c\u8bc1\u90ae\u4ef6\u5230\u4f60\u7684\u7535\u5b50\u90ae\u7bb1
|
||||
sign.up.validation.link=\u70b9\u51fb\u6b64\u94fe\u63a5\u5b8c\u6210\u6ce8\u518c\uff1a
|
||||
welcome = \u6b22\u8fce
|
||||
account.validated = \u5e10\u53f7\u9a8c\u8bc1\u6210\u529f
|
||||
invalid.validation.link = \u9a8c\u8bc1\u94fe\u63a5\u65e0\u6548
|
||||
account.validation.error = \u60a8\u7684\u5e10\u53f7\u8fd8\u6ca1\u9a8c\u8bc1\uff0c\u8bf7\u68c0\u67e5\u60a8\u7684\u90ae\u7bb1\u83b7\u5f97\u9a8c\u8bc1\u94fe\u63a5
|
||||
invalid.credentials = \u7528\u6237\u540d/\u5bc6\u7801\u9519\u8bef
|
||||
enter.email = \u8f93\u5165\u4e00\u4e2a\u7535\u5b50\u90ae\u7bb1\u5730\u5740\uff0c\u6211\u4eec\u4f1a\u53d1\u9001\u4e00\u4e2a\u5bc6\u7801\u91cd\u7f6e\u94fe\u63a5\u5230\u8be5\u90ae\u7bb1
|
||||
email.address = \u7535\u5b50\u90ae\u7bb1\u5730\u5740
|
||||
reset.password.confirmation = \u91cd\u7f6e\u5bc6\u7801\u4fe1\u606f\u786e\u8ba4
|
||||
dear = \u5c0a\u656c\u7684
|
||||
click.reset.link = \u70b9\u51fb\u6b64\u94fe\u63a5\u91cd\u7f6e\u60a8\u7684\u5bc6\u7801
|
||||
thank.you = \u8c22\u8c22
|
||||
reset.password.request = \u8bf7\u6c42\u5bc6\u7801\u91cd\u7f6e
|
||||
password.reset.email.sent = \u5bc6\u7801\u91cd\u7f6e\u90ae\u4ef6\u5df2\u53d1\u9001
|
||||
account.validation.resent = \u91cd\u53d1\u5e10\u53f7\u9a8c\u8bc1\u90ae\u4ef6
|
||||
email.address.not.found = \u7535\u5b50\u90ae\u7bb1\u5730\u5740\u4e0d\u5b58\u5728
|
||||
send.it = \u53d1\u9001
|
||||
reset.your.password = \u91cd\u7f6e\u5bc6\u7801
|
||||
enter.your.new.password = \u8f93\u5165\u65b0\u5bc6\u7801
|
||||
repeat.your.new.password = \u8f93\u5165\u65b0\u5bc6\u7801\uff08\u786e\u8ba4\uff09
|
||||
set.password = \u8bbe\u7f6e\u5bc6\u7801
|
||||
password.link.invalid = \u5bc6\u7801\u91cd\u7f6e\u94fe\u7ed3\u65e0\u6548
|
||||
wrong.old.password = \u539f\u5bc6\u7801\u9519\u8bef
|
||||
old.password = \u539f\u5bc6\u7801
|
||||
new.password = \u65b0\u5bc6\u7801
|
||||
repeat.password = \u65b0\u5bc6\u7801\u786e\u8ba4
|
||||
repeat = \u786e\u8ba4
|
||||
edit = \u4fee\u6539
|
||||
cancel = \u53d6\u6d88
|
||||
ok = \u786e\u5b9a
|
||||
change = \u4fee\u6539
|
||||
password = \u5bc6\u7801
|
||||
recover.password = \u6062\u590d\u5bc6\u7801
|
||||
profile.updated = \u60a8\u7684\u8d44\u6599\u4fee\u6539\u6210\u529f
|
||||
male = \u7537
|
||||
female = \u5973
|
||||
first.name = \u540d
|
||||
last.name = \u59d3
|
||||
locale = \u533a\u57df
|
||||
time.zone = \u65f6\u533a
|
||||
msg.notice = \u4fe1\u606f
|
||||
msg.warning = \u8b66\u544a
|
||||
msg.error = \u9519\u8bef
|
||||
crudify.menu.view.displayName=\u67e5\u770b %s
|
||||
crudify.menu.edit.displayName=\u8bbe\u7f6e %s
|
||||
crudify.menu.delete.displayName=\u5220\u9664 %s
|
||||
country_1 = \u7f8e\u56fd
|
||||
country_2 = \u963f\u5bcc\u6c57
|
||||
country_3 = \u963f\u5c14\u5df4\u5c3c\u4e9a
|
||||
country_4 = \u963f\u5c14\u53ca\u5229\u4e9a
|
||||
country_5 = \u5b89\u9053\u5c14
|
||||
country_6 = \u5b89\u54e5\u62c9
|
||||
country_7 = \u5b89\u63d0\u74dc\u548c\u5df4\u5e03\u8fbe
|
||||
country_8 = \u963f\u6839\u5ef7
|
||||
country_9 = \u4e9a\u7f8e\u5c3c\u4e9a
|
||||
country_10 = \u6fb3\u5927\u5229\u4e9a
|
||||
country_11 = \u5965\u5730\u5229
|
||||
country_12 = \u963f\u585e\u62dc\u7586
|
||||
country_13 = \u5df4\u54c8\u9a6c
|
||||
country_14 = \u5df4\u6797
|
||||
country_15 = \u5b5f\u52a0\u62c9\u56fd
|
||||
country_16 = \u5df4\u5df4\u591a\u65af
|
||||
country_17 = \u767d\u4fc4\u7f57\u65af
|
||||
country_18 = \u6bd4\u5229\u65f6
|
||||
country_19 = \u4f2f\u5229\u5179
|
||||
country_20 = \u8d1d\u5b81
|
||||
country_21 = \u4e0d\u4e39
|
||||
country_22 = \u73bb\u5229\u7ef4\u4e9a
|
||||
country_23 = \u6ce2\u65af\u5c3c\u4e9a\u548c\u9ed1\u585e\u54e5\u7ef4
|
||||
country_24 = \u535a\u8328\u74e6\u7eb3
|
||||
country_25 = \u5df4\u897f
|
||||
country_26 = \u6587\u83b1
|
||||
country_27 = \u4fdd\u52a0\u5229\u4e9a
|
||||
country_28 = \u5e03\u57fa\u7eb3\u6cd5\u7d22
|
||||
country_29 = \u5e03\u9686\u8fea
|
||||
country_30 = \u67ec\u57d4\u5be8
|
||||
country_31 = \u5580\u9ea6\u9686
|
||||
country_32 = \u52a0\u62ff\u5927
|
||||
country_33 = \u4f5b\u5f97\u89d2
|
||||
country_34 = \u4e2d\u975e\u5171\u548c\u56fd
|
||||
country_35 = \u4e4d\u5f97
|
||||
country_36 = \u667a\u5229
|
||||
country_37 = \u4e2d\u56fd
|
||||
country_38 = \u54e5\u4f26\u6bd4\u4e9a
|
||||
country_39 = \u79d1\u6469\u7f57
|
||||
country_40 = \u521a\u679c\u6c11\u4e3b\u5171\u548c\u56fd
|
||||
country_41 = \u521a\u679c\u5171\u548c\u56fd
|
||||
country_42 = \u54e5\u65af\u8fbe\u9ece\u52a0
|
||||
country_43 = \u79d1\u7279\u8fea\u74e6
|
||||
country_44 = \u514b\u7f57\u5730\u4e9a
|
||||
country_45 = \u53e4\u5df4
|
||||
country_46 = \u585e\u6d66\u8def\u65af
|
||||
country_47 = \u6377\u514b\u5171\u548c\u56fd
|
||||
country_48 = \u4e39\u9ea6
|
||||
country_49 = \u5409\u5e03\u63d0
|
||||
country_50 = \u591a\u7c73\u5c3c\u52a0
|
||||
country_51 = \u591a\u7c73\u5c3c\u52a0\u5171\u548c\u56fd
|
||||
country_52 = \u5384\u74dc\u591a\u5c14
|
||||
country_53 = \u57c3\u53ca
|
||||
country_54 = \u8428\u5c14\u74e6\u591a
|
||||
country_55 = \u8d64\u9053\u51e0\u5185\u4e9a
|
||||
country_56 = \u5384\u7acb\u7279\u91cc\u4e9a
|
||||
country_57 = \u7231\u6c99\u5c3c\u4e9a
|
||||
country_58 = \u57c3\u585e\u4fc4\u6bd4\u4e9a
|
||||
country_59 = \u6590\u6d4e
|
||||
country_60 = \u82ac\u5170
|
||||
country_61 = \u6cd5\u56fd
|
||||
country_62 = \u52a0\u84ec
|
||||
country_63 = \u5188\u6bd4\u4e9a\uff0c
|
||||
country_64 = \u683c\u9c81\u5409\u4e9a
|
||||
country_65 = \u5fb7\u56fd
|
||||
country_66 = \u52a0\u7eb3
|
||||
country_67 = \u5e0c\u814a
|
||||
country_68 = \u683c\u6797\u7eb3\u8fbe
|
||||
country_69 = \u5371\u5730\u9a6c\u62c9
|
||||
country_70 = \u51e0\u5185\u4e9a
|
||||
country_71 = \u51e0\u5185\u4e9a\u6bd4\u7ecd
|
||||
country_72 = \u572d\u4e9a\u90a3
|
||||
country_73 = \u6d77\u5730
|
||||
country_74 = \u6d2a\u90fd\u62c9\u65af
|
||||
country_75 = \u5308\u7259\u5229
|
||||
country_76 = \u51b0\u5c9b
|
||||
country_77 = \u5370\u5ea6
|
||||
country_78 = \u5370\u5ea6\u5c3c\u897f\u4e9a
|
||||
country_79 = \u4f0a\u6717
|
||||
country_80 = \u4f0a\u62c9\u514b
|
||||
country_81 = \u7231\u5c14\u5170
|
||||
country_82 = \u4ee5\u8272\u5217
|
||||
country_83 = \u610f\u5927\u5229
|
||||
country_84 = \u7259\u4e70\u52a0
|
||||
country_85 = \u65e5\u672c
|
||||
country_86 = \u7ea6\u65e6
|
||||
country_87 = \u54c8\u8428\u514b\u65af\u5766
|
||||
country_88 = \u80af\u5c3c\u4e9a
|
||||
country_89 = \u57fa\u91cc\u5df4\u65af
|
||||
country_90 = \u671d\u9c9c
|
||||
country_91 = \u97e9\u56fd
|
||||
country_92 = \u79d1\u5a01\u7279
|
||||
country_93 = \u5409\u5c14\u5409\u65af\u65af\u5766
|
||||
country_94 = \u8001\u631d
|
||||
country_95 = \u62c9\u8131\u7ef4\u4e9a
|
||||
country_96 = \u9ece\u5df4\u5ae9
|
||||
country_97 = \u83b1\u7d22\u6258
|
||||
country_98 = \u5229\u6bd4\u91cc\u4e9a
|
||||
country_99 = \u5229\u6bd4\u4e9a
|
||||
country_100 = \u5217\u652f\u6566\u58eb\u767b
|
||||
country_101 = \u7acb\u9676\u5b9b
|
||||
country_102 = \u5362\u68ee\u5821
|
||||
country_103 = \u9a6c\u5176\u987f
|
||||
country_104 = \u9a6c\u8fbe\u52a0\u65af\u52a0
|
||||
country_105 = \u9a6c\u62c9\u7ef4
|
||||
country_106 = \u9a6c\u6765\u897f\u4e9a
|
||||
country_107 = \u9a6c\u5c14\u4ee3\u592b
|
||||
country_108 = \u9a6c\u91cc
|
||||
country_109 = \u9a6c\u8033\u4ed6
|
||||
country_110 = \u9a6c\u7ecd\u5c14\u7fa4\u5c9b
|
||||
country_111 = \u6bdb\u91cc\u5854\u5c3c\u4e9a
|
||||
country_112 = \u6bdb\u91cc\u6c42\u65af
|
||||
country_113 = \u58a8\u897f\u54e5
|
||||
country_114 = \u5bc6\u514b\u7f57\u5c3c\u897f\u4e9a
|
||||
country_115 = \u6469\u5c14\u591a\u74e6
|
||||
country_116 = \u6469\u7eb3\u54e5
|
||||
country_117 = \u8499\u53e4
|
||||
country_118 = \u9ed1\u5c71
|
||||
country_119 = \u6469\u6d1b\u54e5
|
||||
country_120 = \u83ab\u6851\u6bd4\u514b
|
||||
country_121 = \u7f05\u7538
|
||||
country_122 = \u7eb3\u7c73\u6bd4\u4e9a
|
||||
country_123 = \u7459\u9c81
|
||||
country_124 = \u5c3c\u6cca\u5c14
|
||||
country_125 = \u8377\u5170
|
||||
country_126 = \u65b0\u897f\u5170
|
||||
country_127 = \u5c3c\u52a0\u62c9\u74dc
|
||||
country_128 = \u5c3c\u65e5\u5c14
|
||||
country_129 = \u5c3c\u65e5\u5229\u4e9a
|
||||
country_130 = \u632a\u5a01
|
||||
country_131 = \u963f\u66fc
|
||||
country_132 = \u5df4\u57fa\u65af\u5766
|
||||
country_133 = \u5e15\u52b3
|
||||
country_134 = \u5df4\u62ff\u9a6c
|
||||
country_135 = \u5df4\u5e03\u4e9a\u65b0\u51e0\u5185\u4e9a
|
||||
country_136 = \u5df4\u62c9\u572d
|
||||
country_137 = \u79d8\u9c81
|
||||
country_138 = \u83f2\u5f8b\u5bbe
|
||||
country_139 = \u6ce2\u5170
|
||||
country_140 = \u8461\u8404\u7259
|
||||
country_141 = \u5361\u5854\u5c14
|
||||
country_142 = \u7f57\u9a6c\u5c3c\u4e9a
|
||||
country_143 = \u4fc4\u7f57\u65af
|
||||
country_144 = \u5362\u65fa\u8fbe
|
||||
country_145 = \u5723\u57fa\u8328\u548c\u5c3c\u7ef4\u65af
|
||||
country_146 = \u5723\u5362\u897f\u4e9a
|
||||
country_147 = \u5723\u6587\u68ee\u7279\u548c\u683c\u6797\u7eb3\u4e01\u65af
|
||||
country_148 = \u8428\u6469\u4e9a
|
||||
country_149 = \u5723\u9a6c\u529b\u8bfa
|
||||
country_150 = \u5723\u591a\u7f8e\u548c\u666e\u6797\u897f\u6bd4
|
||||
country_151 = \u6c99\u7279\u963f\u62c9\u4f2f
|
||||
country_152 = \u585e\u5185\u52a0\u5c14
|
||||
country_153 = \u585e\u5c14\u7ef4\u4e9a
|
||||
country_154 = \u585e\u820c\u5c14
|
||||
country_155 = \u585e\u62c9\u5229\u6602
|
||||
country_156 = \u65b0\u52a0\u5761
|
||||
country_157 = \u65af\u6d1b\u4f10\u514b
|
||||
country_158 = \u65af\u6d1b\u6587\u5c3c\u4e9a
|
||||
country_159 = \u6240\u7f57\u95e8\u7fa4\u5c9b
|
||||
country_160 = \u7d22\u9a6c\u91cc
|
||||
country_161 = \u5357\u975e
|
||||
country_162 = \u897f\u73ed\u7259
|
||||
country_163 = \u65af\u91cc\u5170\u5361
|
||||
country_164 = \u82cf\u4e39
|
||||
country_165 = \u82cf\u91cc\u5357
|
||||
country_166 = \u65af\u5a01\u58eb\u5170
|
||||
country_167 = \u745e\u5178
|
||||
country_168 = \u745e\u58eb
|
||||
country_169 = \u53d9\u5229\u4e9a
|
||||
country_170 = \u5854\u5409\u514b\u65af\u5766
|
||||
country_171 = \u5766\u6851\u5c3c\u4e9a
|
||||
country_172 = \u6cf0\u56fd
|
||||
country_173 = \u4e1c\u5e1d\u6c76
|
||||
country_174 = \u591a\u54e5
|
||||
country_175 = \u6c64\u52a0
|
||||
country_176 = \u7279\u7acb\u5c3c\u8fbe\u548c\u591a\u5df4\u54e5
|
||||
country_177 = \u7a81\u5c3c\u65af
|
||||
country_178 = \u571f\u8033\u5176
|
||||
country_179 = \u571f\u5e93\u66fc\u65af\u5766
|
||||
country_180 = \u56fe\u74e6\u5362
|
||||
country_181 = \u4e4c\u5e72\u8fbe
|
||||
country_182 = \u4e4c\u514b\u5170
|
||||
country_183 = \u963f\u62c9\u4f2f\u8054\u5408\u914b\u957f\u56fd
|
||||
country_184 = \u82f1\u56fd
|
||||
country_185 = \u4e4c\u62c9\u572d
|
||||
country_186 = \u4e4c\u5179\u522b\u514b\u65af\u5766
|
||||
country_187 = \u74e6\u52aa\u963f\u56fe
|
||||
country_188 = \u68b5\u8482\u5188\u57ce
|
||||
country_189 = \u59d4\u5185\u745e\u62c9
|
||||
country_190 = \u8d8a\u5357
|
||||
country_191 = \u4e5f\u95e8
|
||||
country_192 = \u8d5e\u6bd4\u4e9a
|
||||
country_193 = \u6d25\u5df4\u5e03\u97e6
|
||||
country_194 = \u963f\u5e03\u54c8\u5179
|
||||
country_195 = \u53f0\u6e7e
|
||||
country_196 = \u7eb3\u5361
|
||||
country_197 = \u5317\u585e\u6d66\u8def\u65af
|
||||
country_198 = \u5fb7\u6d85\u65af\u7279\u6cb3\u6cbf\u5cb8\u5171\u548c\u56fd
|
||||
country_199 = \u7d22\u9a6c\u91cc\u5170
|
||||
country_200 = \u5357\u5965\u585e\u68af
|
||||
country_201 = \u963f\u4ec0\u83ab\u5c14\u548c\u5361\u6377\u5c9b
|
||||
country_202 = \u5723\u8bde\u5c9b
|
||||
country_203 = \u79d1\u79d1\u65af\uff08\u57fa\u6797\uff09\u7fa4\u5c9b
|
||||
country_204 = \u73ca\u745a\u6d77\u7fa4\u5c9b
|
||||
country_205 = \u8d6b\u5fb7\u5c9b\u548c\u9ea6\u5f53\u52b3\u7fa4\u5c9b
|
||||
country_206 = \u8bfa\u798f\u514b\u5c9b
|
||||
country_207 = \u65b0\u5580\u91cc\u591a\u5c3c\u4e9a
|
||||
country_208 = \u6cd5\u5c5e\u6ce2\u5229\u5c3c\u897f\u4e9a
|
||||
country_209 = \u9a6c\u7ea6\u7279
|
||||
country_210 = \u5723\u5df4\u6cf0\u52d2\u7c73
|
||||
country_211 = \u5723\u9a6c\u4e01
|
||||
country_212 = \u5723\u76ae\u57c3\u5c14\u548c\u5bc6\u514b\u9686
|
||||
country_213 = \u74e6\u5229\u65af\u7fa4\u5c9b\u548c\u5bcc\u56fe\u7eb3\u7fa4\u5c9b
|
||||
country_214 = \u6cd5\u56fd\u5357\u90e8\u548c\u5357\u6781\u9886\u5730
|
||||
country_215 = \u514b\u5229\u73c0\u987f\u5c9b
|
||||
country_216 = \u5e03\u7ef4\u5c9b
|
||||
country_217 = \u5e93\u514b\u7fa4\u5c9b
|
||||
country_218 = \u7ebd\u57c3
|
||||
country_219 = \u6258\u514b\u52b3
|
||||
country_220 = \u6839\u897f\u5c9b
|
||||
country_221 = \u9a6c\u6069\u5c9b
|
||||
country_222 = \u6cfd\u897f
|
||||
country_223 = \u5b89\u572d\u62c9
|
||||
country_224 = \u767e\u6155\u5927
|
||||
country_225 = \u82f1\u5c5e\u5370\u5ea6\u6d0b\u9886\u5730
|
||||
country_226 = \u82f1\u56fd\u4e3b\u6743\u57fa\u5730\u533a
|
||||
country_227 = \u82f1\u5c5e\u7ef4\u5c14\u4eac\u7fa4\u5c9b
|
||||
country_228 = \u5f00\u66fc\u7fa4\u5c9b
|
||||
country_229 = \u798f\u514b\u5170\u7fa4\u5c9b
|
||||
country_230 = \u76f4\u5e03\u7f57\u9640
|
||||
country_231 = \u8499\u7279\u585e\u62c9\u7279
|
||||
country_232 = \u76ae\u7279\u51ef\u6069\u7fa4\u5c9b
|
||||
country_233 = \u5723\u6d77\u4f26\u5a1c
|
||||
country_234 = \u5357\u4e54\u6cbb\u4e9a\u5c9b\u548c\u5357\u6851\u5a01\u5947\u7fa4\u5c9b
|
||||
country_235 = \u7279\u514b\u65af\u548c\u51ef\u79d1\u65af\u7fa4\u5c9b
|
||||
country_236 = \u5317\u9a6c\u91cc\u4e9a\u7eb3\u7fa4\u5c9b
|
||||
country_237 = \u6ce2\u591a\u9ece\u5404
|
||||
country_238 = \u7f8e\u5c5e\u8428\u6469\u4e9a
|
||||
country_239 = \u8d1d\u514b\u5c9b
|
||||
country_240 = \u5173\u5c9b
|
||||
country_241 = \u8c6a\u5170\u5c9b
|
||||
country_242 = \u8d3e\u7ef4\u65af\u5c9b
|
||||
country_243 = \u7ea6\u7ff0\u65af\u987f\u73af\u7901
|
||||
country_244 = \u91d1\u66fc\u7901
|
||||
country_245 = \u4e2d\u9014\u5c9b
|
||||
country_246 = \u7eb3\u74e6\u8428\u5c9b
|
||||
country_247 = \u5df4\u5c14\u7c73\u62c9\u73af\u7901
|
||||
country_248 = \u7f8e\u56fd\u7ef4\u5c14\u4eac\u7fa4\u5c9b
|
||||
country_249 = \u5a01\u514b\u5c9b
|
||||
country_250 = \u9999\u6e2f
|
||||
country_251 = \u6fb3\u95e8
|
||||
country_252 = \u6cd5\u7f57\u7fa4\u5c9b
|
||||
country_253 = \u683c\u9675\u5170
|
||||
country_254 = \u6cd5\u5c5e\u572d\u4e9a\u90a3
|
||||
country_255 = \u74dc\u5fb7\u7f57\u666e\u5c9b
|
||||
country_256 = \u9a6c\u63d0\u5c3c\u514b
|
||||
country_257 = \u7559\u5c3c\u6c6a
|
||||
country_258 = \u5965\u5170
|
||||
country_259 = \u963f\u9c81\u5df4
|
||||
country_260 = \u8377\u5c5e\u5b89\u7684\u5217\u65af
|
||||
country_261 = \u65af\u74e6\u5c14\u5df4\u5fb7
|
||||
country_262 = \u963f\u68ee\u677e
|
||||
country_263 = \u7279\u91cc\u65af\u5766\u8fbe\u5e93\u5c3c\u4e9a
|
||||
country_264 = \u5357\u6781\u6d32
|
||||
country_265 = \u79d1\u7d22\u6c83
|
||||
country_266 = \u5df4\u52d2\u65af\u5766\u9886\u571f
|
||||
country_267 = \u897f\u6492\u54c8\u62c9
|
||||
country_268 = \u6fb3\u5927\u5229\u4e9a\u5357\u6781\u9886\u5730
|
||||
country_269 = \u7f57\u65af\u5c5e\u5730
|
||||
country_270 = \u5f7c\u5f97\u4e00\u4e16\u5c9b
|
||||
country_271 = \u6bdb\u5fb7\u7687\u540e\u5730
|
||||
country_272 = \u82f1\u5c5e\u5357\u6781\u9886\u5730
|
||||
|
||||
OBP-30001 = \u627e\u4e0d\u5230\u94f6\u884c\u3002\u0020\u8bf7\u4e3a\u0020\u0042\u0041\u004e\u004b\u005f\u0049\u0044\u0020\u6307\u5b9a\u4e00\u4e2a\u6709\u6548\u503c
|
||||
@ -243,7 +243,14 @@ mail.smtp.port=25
|
||||
token_expiration_weeks=4
|
||||
|
||||
## payment challenge answer timeout,default is 600 seconds/10 minutes
|
||||
transaction_request_challenge_ttl=600
|
||||
transactionRequest.challenge.ttl.seconds=600
|
||||
|
||||
## auth context update request challenge answer timeout,default is 600 seconds/10 minutes
|
||||
userAuthContextUpdateRequest.challenge.ttl.seconds=600
|
||||
|
||||
# the allowed attempts to answer the same transactionRequest Challenge, default is 3 times
|
||||
#answer_transactionRequest_challenge_allowed_attempts=3
|
||||
|
||||
|
||||
|
||||
|
||||
@ -283,14 +290,6 @@ transactionRequests_challenge_threshold_SEPA=1000
|
||||
# To set a currency for the above value:
|
||||
#transactionRequests_challenge_currency=KRW
|
||||
|
||||
|
||||
## For video conference meetings (createMeeting)
|
||||
meeting.tokbox_enabled=false
|
||||
meeting.tokbox_api_key=changeme
|
||||
meeting.tokbox_api_secret=changeme
|
||||
|
||||
|
||||
|
||||
### Management modules
|
||||
|
||||
## RabbitMQ settings (used to communicate with HBCI project)
|
||||
|
||||
@ -66,10 +66,11 @@ tests.port=8016
|
||||
End of minimum settings
|
||||
####################################
|
||||
|
||||
#if connector is mapped, set a database backend. If not set, this will be set to an in-memory h2 database by default
|
||||
#you can use a no config needed h2 database by setting db.driver=org.h2.Driver and not including db.url
|
||||
# if connector is mapped, set a database backend. If not set, this will be set to an in-memory h2 database by default
|
||||
# you can use a no config needed h2 database by setting db.driver=org.h2.Driver and not including db.url
|
||||
# Please note that since update o version 2.1.214 we use NON_KEYWORDS=VALUE to bypass reserved word issue in SQL statements
|
||||
#db.driver=org.h2.Driver
|
||||
#db.url=jdbc:h2:./lift_proto.db;DB_CLOSE_ON_EXIT=FALSE
|
||||
#db.url=jdbc:h2:./lift_proto.db;NON_KEYWORDS=VALUE;DB_CLOSE_ON_EXIT=FALSE
|
||||
|
||||
#set this to false if you don't want the api payments call to work
|
||||
payments_enabled=false
|
||||
|
||||
@ -55,7 +55,7 @@ import code.bankconnectors.{Connector, ConnectorEndpoints}
|
||||
import code.branches.MappedBranch
|
||||
import code.cardattribute.MappedCardAttribute
|
||||
import code.cards.{MappedPhysicalCard, PinReset}
|
||||
import code.consent.MappedConsent
|
||||
import code.consent.{ConsentRequest, MappedConsent}
|
||||
import code.consumer.Consumers
|
||||
import code.context.{MappedConsentAuthContext, MappedUserAuthContext, MappedUserAuthContextUpdate}
|
||||
import code.crm.MappedCrmEvent
|
||||
@ -246,14 +246,14 @@ class Boot extends MdcLoggable {
|
||||
case Props.RunModes.Test =>
|
||||
new StandardDBVendor(
|
||||
driver,
|
||||
APIUtil.getPropsValue("db.url") openOr "jdbc:h2:mem:OBPTest;DB_CLOSE_DELAY=-1",
|
||||
APIUtil.getPropsValue("db.url") openOr Constant.h2DatabaseDefaultUrlValue,
|
||||
APIUtil.getPropsValue("db.user").orElse(Empty),
|
||||
APIUtil.getPropsValue("db.password").orElse(Empty)
|
||||
)
|
||||
case _ =>
|
||||
new StandardDBVendor(
|
||||
driver,
|
||||
"jdbc:h2:mem:OBPTest;DB_CLOSE_DELAY=-1",
|
||||
h2DatabaseDefaultUrlValue,
|
||||
Empty, Empty)
|
||||
}
|
||||
|
||||
@ -1004,6 +1004,7 @@ object ToSchemify {
|
||||
MappedCustomerIdMapping,
|
||||
MappedProductAttribute,
|
||||
MappedConsent,
|
||||
ConsentRequest,
|
||||
MigrationScriptLog,
|
||||
MethodRouting,
|
||||
EndpointMapping,
|
||||
|
||||
@ -31,12 +31,13 @@ import java.net.URLDecoder
|
||||
import code.api.Constant._
|
||||
import code.api.OAuthHandshake._
|
||||
import code.api.builder.AccountInformationServiceAISApi.APIMethods_AccountInformationServiceAISApi
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.APIUtil.{getClass, _}
|
||||
import code.api.util.ErrorMessages.{InvalidDAuthHeaderToken, UserIsDeleted, UsernameHasBeenLocked, attemptedToOpenAnEmptyBox}
|
||||
import code.api.util._
|
||||
import code.api.v3_0_0.APIMethods300
|
||||
import code.api.v3_1_0.APIMethods310
|
||||
import code.api.v4_0_0.APIMethods400
|
||||
import code.api.v4_0_0.{APIMethods400, OBPAPI4_0_0}
|
||||
import code.api.v5_0_0.OBPAPI5_0_0
|
||||
import code.loginattempts.LoginAttempt
|
||||
import code.model.dataAccess.AuthUser
|
||||
import code.util.Helper.MdcLoggable
|
||||
@ -45,15 +46,18 @@ import com.openbankproject.commons.model.ErrorMessage
|
||||
import com.openbankproject.commons.util.{ApiVersion, ReflectUtils, ScannedApiVersion}
|
||||
import net.liftweb.common.{Box, Full, _}
|
||||
import net.liftweb.http.rest.RestHelper
|
||||
import net.liftweb.http.{JsonResponse, LiftResponse, Req, S}
|
||||
import net.liftweb.http.{JsonResponse, LiftResponse, LiftRules, Req, S, TransientRequestMemoize}
|
||||
import net.liftweb.json.Extraction
|
||||
import net.liftweb.json.JsonAST.JValue
|
||||
import net.liftweb.util.Helpers
|
||||
import net.liftweb.util.{Helpers, NamedPF, Props, ThreadGlobal}
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
import java.util.{Locale, ResourceBundle}
|
||||
import scala.collection.immutable.List
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import scala.math.Ordering
|
||||
import scala.util.control.NoStackTrace
|
||||
import scala.xml.{Node, NodeSeq}
|
||||
|
||||
trait APIFailure{
|
||||
val msg : String
|
||||
@ -72,7 +76,76 @@ object APIFailure {
|
||||
case class APIFailureNewStyle(failMsg: String,
|
||||
failCode: Int = 400,
|
||||
ccl: Option[CallContextLight] = None
|
||||
)
|
||||
){
|
||||
def translatedErrorMessage = {
|
||||
|
||||
val errorCode = extractErrorMessageCode(failMsg)
|
||||
val errorBody = extractErrorMessageBody(failMsg)
|
||||
|
||||
val localeUrlParameter = getHttpRequestUrlParam(ccl.map(_.url).getOrElse(""),"Locale")
|
||||
val locale = I18NUtil.computeLocale(localeUrlParameter)
|
||||
|
||||
val liftCoreResourceBundle = tryo(ResourceBundle.getBundle(LiftRules.liftCoreResourceName, locale)).toList
|
||||
|
||||
val _resBundle = new ThreadGlobal[List[ResourceBundle]]
|
||||
object resourceValueCache extends TransientRequestMemoize[(String, Locale), String]
|
||||
|
||||
def resourceBundles(loc: Locale): List[ResourceBundle] = {
|
||||
_resBundle.box match {
|
||||
case Full(bundles) => bundles
|
||||
case _ => {
|
||||
_resBundle.set(
|
||||
LiftRules.resourceForCurrentLoc.vend() :::
|
||||
LiftRules.resourceNames.flatMap(name => tryo{
|
||||
if (Props.devMode) {
|
||||
tryo{
|
||||
val clz = this.getClass.getClassLoader.loadClass("java.util.ResourceBundle")
|
||||
val meth = clz.getDeclaredMethods.
|
||||
filter{m => m.getName == "clearCache" && m.getParameterTypes.length == 0}.
|
||||
toList.head
|
||||
meth.invoke(null)
|
||||
}
|
||||
}
|
||||
List(ResourceBundle.getBundle(name, loc))
|
||||
}.openOr(
|
||||
NamedPF.applyBox((name, loc), LiftRules.resourceBundleFactories.toList).map(List(_)) openOr Nil
|
||||
)))
|
||||
_resBundle.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def resourceBundleList: List[ResourceBundle] = resourceBundles(locale) ++ liftCoreResourceBundle
|
||||
|
||||
def ?!(str: String, resBundle: List[ResourceBundle]): String =
|
||||
resBundle.flatMap(
|
||||
r => tryo(
|
||||
r.getObject(str) match {
|
||||
case s: String => Full(s)
|
||||
case n: Node => Full(n.text)
|
||||
case ns: NodeSeq => Full(ns.text)
|
||||
case _ => Empty
|
||||
})
|
||||
.flatMap(s => s)).find(s => true) getOrElse {
|
||||
LiftRules.localizationLookupFailureNotice.foreach(_ (str, locale));
|
||||
str
|
||||
}
|
||||
|
||||
def ?(str: String, locale: Locale): String = resourceValueCache.get(
|
||||
str ->
|
||||
locale,
|
||||
if(?!(str, resourceBundleList)==str) //If can not find the value from props, then return the default error body.
|
||||
errorBody
|
||||
else
|
||||
?!(str, resourceBundleList)
|
||||
|
||||
)
|
||||
|
||||
val translatedErrorBody = ?(errorCode, locale)
|
||||
s"$errorCode$translatedErrorBody"
|
||||
}
|
||||
}
|
||||
|
||||
//if you change this, think about backwards compatibility! All existing
|
||||
//versions of the API return this failure message, so if you change it, make sure
|
||||
@ -586,8 +659,9 @@ trait OBPRestHelper extends RestHelper with MdcLoggable {
|
||||
apiPrefix:OBPEndpoint => OBPEndpoint,
|
||||
autoValidateAll: Boolean = false): Unit = {
|
||||
|
||||
def isAutoValidate(doc: ResourceDoc): Boolean =
|
||||
doc.isValidateEnabled || (autoValidateAll && !doc.isValidateDisabled && doc.implementedInApiVersion == version)
|
||||
def isAutoValidate(doc: ResourceDoc): Boolean = { //note: only support v5.0.0 and v4.0.0 at the moment.
|
||||
doc.isValidateEnabled || (autoValidateAll && !doc.isValidateDisabled && List(OBPAPI5_0_0.version,OBPAPI4_0_0.version).contains(doc.implementedInApiVersion))
|
||||
}
|
||||
|
||||
for(route <- routes) {
|
||||
// one endpoint can have multiple ResourceDocs, so here use filter instead of find, e.g APIMethods400.Implementations400.createTransactionRequest
|
||||
|
||||
@ -248,7 +248,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth
|
||||
Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getStaticResourceDocsTTL second) {
|
||||
logger.debug(s"Generating OBP Resource Docs requestedApiVersion is $requestedApiVersion")
|
||||
|
||||
val resourceDocJson = resourceDocsToResourceDocJson(getResourceDocsList(requestedApiVersion), resourceDocTags, partialFunctionNames, isVersion4OrHigher)
|
||||
val resourceDocJson = resourceDocsToResourceDocJson(getResourceDocsList(requestedApiVersion), resourceDocTags, partialFunctionNames, isVersion4OrHigher, languageParam)
|
||||
resourceDocJson.map(resourceDocsJsonToJsonResponse)
|
||||
}
|
||||
}
|
||||
@ -309,7 +309,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth
|
||||
|
||||
val allDocs = staticDocs.map( _ ++ filteredDocs)
|
||||
|
||||
val resourceDocJson = resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames, isVersion4OrHigher)
|
||||
val resourceDocJson = resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames, isVersion4OrHigher, languageParam)
|
||||
resourceDocJson.map(resourceDocsJsonToJsonResponse)
|
||||
}
|
||||
}
|
||||
@ -353,25 +353,27 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth
|
||||
case None => dynamicDocs
|
||||
}
|
||||
|
||||
val resourceDocJson = resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames, isVersion4OrHigher)
|
||||
val resourceDocJson = resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames, isVersion4OrHigher, languageParam)
|
||||
resourceDocJson.map(resourceDocsJsonToJsonResponse)
|
||||
}}}
|
||||
|
||||
|
||||
|
||||
private def resourceDocsToResourceDocJson(rd: Option[List[ResourceDoc]],
|
||||
resourceDocTags: Option[List[ResourceDocTag]],
|
||||
partialFunctionNames: Option[List[String]],
|
||||
isVersion4OrHigher:Boolean): Option[ResourceDocsJson] =
|
||||
resourceDocTags: Option[List[ResourceDocTag]],
|
||||
partialFunctionNames: Option[List[String]],
|
||||
isVersion4OrHigher:Boolean,
|
||||
languageParam: Option[LanguageParam]): Option[ResourceDocsJson] = {
|
||||
for {
|
||||
resourceDocs <- rd
|
||||
} yield {
|
||||
// Filter
|
||||
val rdFiltered = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, resourceDocTags, partialFunctionNames)
|
||||
// Format the data as json
|
||||
JSONFactory1_4_0.createResourceDocsJson(rdFiltered, isVersion4OrHigher)
|
||||
JSONFactory1_4_0.createResourceDocsJson(rdFiltered, isVersion4OrHigher, languageParam)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val getChineseVersionResourceDocs : Box[JsonResponse] = {
|
||||
val stream = getClass().getClassLoader().getResourceAsStream("ResourceDocs/ResourceDocs-Chinese.json")
|
||||
val chineseVersion = try {
|
||||
@ -402,9 +404,9 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth
|
||||
List(apiTagDocumentation))
|
||||
|
||||
|
||||
val exampleResourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(List(exampleResourceDoc), false)
|
||||
val exampleResourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(List(exampleResourceDoc), false, None)
|
||||
|
||||
val exampleResourceDocsJsonV400 = JSONFactory1_4_0.createResourceDocsJson(List(exampleResourceDoc), true)
|
||||
val exampleResourceDocsJsonV400 = JSONFactory1_4_0.createResourceDocsJson(List(exampleResourceDoc), true, None)
|
||||
|
||||
|
||||
|
||||
@ -578,7 +580,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth
|
||||
case _ if (apiCollectionIdParam.isDefined) =>
|
||||
val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId)
|
||||
val resourceDocs = ResourceDoc.getResourceDocs(operationIds)
|
||||
val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher)
|
||||
val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher, languageParam)
|
||||
val resourceDocsJsonJValue = Full(resourceDocsJsonToJsonResponse(resourceDocsJson))
|
||||
Future(resourceDocsJsonJValue.map(successJsonResponse(_)))
|
||||
case _ =>
|
||||
@ -918,6 +920,7 @@ object ResourceDocsAPIMethodsUtil extends MdcLoggable{
|
||||
def stringToLanguageParam (x: String) : Option[LanguageParam] = x.toLowerCase match {
|
||||
case "en" => Some(EN)
|
||||
case "zh" => Some(ZH)
|
||||
case "es" | "es_ES" => Some(ES)
|
||||
case _ => Empty
|
||||
}
|
||||
|
||||
|
||||
@ -3745,6 +3745,7 @@ object SwaggerDefinitionsJSON {
|
||||
valid_from = Some(new Date()),
|
||||
time_to_live = Some(3600)
|
||||
)
|
||||
val postConsentRequestJsonV310 = postConsentPhoneJsonV310.copy(consumer_id = None)
|
||||
|
||||
val consentsJsonV310 = ConsentsJsonV310(List(consentJsonV310))
|
||||
|
||||
@ -4658,6 +4659,33 @@ object SwaggerDefinitionsJSON {
|
||||
consumer_id = consumerIdExample.value
|
||||
)
|
||||
|
||||
val consentRequestResponseJson = ConsentRequestResponseJson(
|
||||
consent_request_id = consentRequestIdExample.value,
|
||||
payload = json.parse(consentRequestPayloadExample.value),
|
||||
consumer_id = consumerIdExample.value
|
||||
)
|
||||
|
||||
val consentJsonV500 = ConsentJsonV500(
|
||||
consent_id = "9d429899-24f5-42c8-8565-943ffa6a7945",
|
||||
jwt = "eyJhbGciOiJIUzI1NiJ9.eyJlbnRpdGxlbWVudHMiOltdLCJjcmVhdGVkQnlVc2VySWQiOiJhYjY1MzlhOS1iMTA1LTQ0ODktYTg4My0wYWQ4ZDZjNjE2NTciLCJzdWIiOiIyMWUxYzhjYy1mOTE4LTRlYWMtYjhlMy01ZTVlZWM2YjNiNGIiLCJhdWQiOiJlanpuazUwNWQxMzJyeW9tbmhieDFxbXRvaHVyYnNiYjBraWphanNrIiwibmJmIjoxNTUzNTU0ODk5LCJpc3MiOiJodHRwczpcL1wvd3d3Lm9wZW5iYW5rcHJvamVjdC5jb20iLCJleHAiOjE1NTM1NTg0OTksImlhdCI6MTU1MzU1NDg5OSwianRpIjoiMDlmODhkNWYtZWNlNi00Mzk4LThlOTktNjYxMWZhMWNkYmQ1Iiwidmlld3MiOlt7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAxIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifSx7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAyIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifV19.8cc7cBEf2NyQvJoukBCmDLT7LXYcuzTcSYLqSpbxLp4",
|
||||
status = ConsentStatus.INITIATED.toString,
|
||||
consent_request_id = Some(consentRequestIdExample.value)
|
||||
)
|
||||
|
||||
val postConsentRequestJsonV500 = PostConsentRequestJsonV500(
|
||||
everything = false,
|
||||
account_access = List(AccountAccessV500(
|
||||
account_routing = accountRoutingJsonV121,
|
||||
view_id = viewIdExample.value
|
||||
)),
|
||||
entitlements = Some(List(PostConsentEntitlementJsonV310(bankIdExample.value, "CanGetCustomer"))),
|
||||
consumer_id = Some(consumerIdExample.value),
|
||||
phone_number = Some(mobileNumberExample.value),
|
||||
email = Some(emailExample.value),
|
||||
valid_from = Some(new Date()),
|
||||
time_to_live = Some(3600)
|
||||
)
|
||||
|
||||
//The common error or success format.
|
||||
//Just some helper format to use in Json
|
||||
case class NotSupportedYet()
|
||||
|
||||
@ -8,6 +8,8 @@ import com.openbankproject.commons.util.ApiStandards
|
||||
// Note: Import this with: import code.api.Constant._
|
||||
object Constant extends MdcLoggable {
|
||||
logger.info("Instantiating Constants")
|
||||
|
||||
final val h2DatabaseDefaultUrlValue = "jdbc:h2:mem:OBPTest_H2_v2.1.214;NON_KEYWORDS=VALUE;DB_CLOSE_DELAY=10"
|
||||
|
||||
final val HostName = APIUtil.getPropsValue("hostname").openOrThrowException(ErrorMessages.HostnameNotSpecified)
|
||||
def localIdentityProvider = APIUtil.getPropsValue("local_identity_provider", HostName)
|
||||
|
||||
@ -202,7 +202,7 @@ object DirectLogin extends RestHelper with MdcLoggable {
|
||||
case "username" =>
|
||||
checkUsernameString(parameterValue)
|
||||
case "password" =>
|
||||
validatePasswordOnUsage(parameterValue)
|
||||
basicPasswordValidation(parameterValue)
|
||||
case "consumer_key" =>
|
||||
checkMediumAlphaNumeric(parameterValue)
|
||||
case "token" =>
|
||||
|
||||
@ -33,6 +33,7 @@ import java.nio.charset.Charset
|
||||
import java.text.{ParsePosition, SimpleDateFormat}
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.{Calendar, Date, UUID}
|
||||
|
||||
import code.UserRefreshes.UserRefreshes
|
||||
import code.accountholders.AccountHolders
|
||||
import code.api.Constant._
|
||||
@ -65,7 +66,7 @@ import code.scope.Scope
|
||||
import code.usercustomerlinks.UserCustomerLink
|
||||
import code.util.Helper.{MdcLoggable, SILENCE_IS_GOLDEN}
|
||||
import code.util.{Helper, JsonSchemaUtil}
|
||||
import code.views.Views
|
||||
import code.views.{MapperViews, Views}
|
||||
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
|
||||
import com.alibaba.ttl.internal.javassist.CannotCompileException
|
||||
import com.github.dwickern.macros.NameOf.{nameOf, nameOfType}
|
||||
@ -105,8 +106,8 @@ import javassist.{ClassPool, LoaderClassPath}
|
||||
import javassist.expr.{ExprEditor, MethodCall}
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
|
||||
import java.security.AccessControlException
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
|
||||
import scala.concurrent.Future
|
||||
@ -130,10 +131,10 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
val DateWithMsFormat = new SimpleDateFormat(DateWithMs)
|
||||
val DateWithMsRollbackFormat = new SimpleDateFormat(DateWithMsRollback)
|
||||
|
||||
val DateWithDayExampleString: String = "2017-09-19"
|
||||
val DateWithSecondsExampleString: String = "2017-09-19T02:31:05Z"
|
||||
val DateWithMsExampleString: String = "2017-09-19T02:31:05.000Z"
|
||||
val DateWithMsRollbackExampleString: String = "2017-09-19T02:31:05.000+0000"
|
||||
val DateWithDayExampleString: String = "1100-01-01"
|
||||
val DateWithSecondsExampleString: String = "1100-01-01T01:01:01Z"
|
||||
val DateWithMsExampleString: String = "1100-01-01T01:01:01.000Z"
|
||||
val DateWithMsRollbackExampleString: String = "1100-01-01T01:01:01.000+0000"
|
||||
|
||||
// Use a fixed date far into the future (rather than current date/time so that cache keys are more static)
|
||||
// (Else caching is invalidated by constantly changing date)
|
||||
@ -611,14 +612,14 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
|
||||
def errorJsonResponse(message : String = "error", httpCode : Int = 400, callContextLight: Option[CallContextLight] = None)(implicit headers: CustomResponseHeaders = CustomResponseHeaders(Nil)) : JsonResponse = {
|
||||
def check403(message: String): Boolean = {
|
||||
message.contains(UserHasMissingRoles) ||
|
||||
message.contains(UserNoPermissionAccessView) ||
|
||||
message.contains(UserHasMissingRoles) ||
|
||||
message.contains(UserNotSuperAdminOrMissRole) ||
|
||||
message.contains(ConsumerHasMissingRoles)
|
||||
message.contains(extractErrorMessageCode(UserHasMissingRoles)) ||
|
||||
message.contains(extractErrorMessageCode(UserNoPermissionAccessView)) ||
|
||||
message.contains(extractErrorMessageCode(UserHasMissingRoles)) ||
|
||||
message.contains(extractErrorMessageCode(UserNotSuperAdminOrMissRole)) ||
|
||||
message.contains(extractErrorMessageCode(ConsumerHasMissingRoles))
|
||||
}
|
||||
def check401(message: String): Boolean = {
|
||||
message.contains(UserNotLoggedIn)
|
||||
message.contains(extractErrorMessageCode(UserNotLoggedIn))
|
||||
}
|
||||
val (code, responseHeaders) =
|
||||
message match {
|
||||
@ -677,7 +678,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
* 1) length is >16 characters without validations but max length <= 512
|
||||
* 2) or Min 10 characters with mixed numbers + letters + upper+lower case + at least one special character.
|
||||
* */
|
||||
def validatePasswordOnCreation(password: String): Boolean = {
|
||||
def fullPasswordValidation(password: String): Boolean = {
|
||||
/**
|
||||
* (?=.*\d) //should contain at least one digit
|
||||
* (?=.*[a-z]) //should contain at least one lower case
|
||||
@ -688,9 +689,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
val regex =
|
||||
"""^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!"#$%&'\(\)*+,-./:;<=>?@\\[\\\\]^_\\`{|}~])([A-Za-z0-9!"#$%&'\(\)*+,-./:;<=>?@\\[\\\\]^_\\`{|}~]{10,16})$""".r
|
||||
password match {
|
||||
case password if(validatePasswordOnUsage(password) ==SILENCE_IS_GOLDEN) => true
|
||||
case password if(password.length > 16 && password.length <= 512) => true
|
||||
case regex(password) => true
|
||||
case password if(password.length > 16 && password.length <= 512 && basicPasswordValidation(password) ==SILENCE_IS_GOLDEN) => true
|
||||
case regex(password) if(basicPasswordValidation(password) ==SILENCE_IS_GOLDEN) => true
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
@ -725,7 +725,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
|
||||
/** only A-Z, a-z, 0-9, all allowed characters for password and max length <= 512 */
|
||||
/** also support space now */
|
||||
def validatePasswordOnUsage(value:String): String ={
|
||||
def basicPasswordValidation(value:String): String ={
|
||||
val valueLength = value.length
|
||||
val regex = """^([A-Za-z0-9!"#$%&'\(\)*+,-./:;<=>?@\\[\\\\]^_\\`{|}~ ]+)$""".r
|
||||
value match {
|
||||
@ -3038,8 +3038,10 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
throw new Exception("Empty Box not allowed")
|
||||
case obj1@ParamFailure(m,e,c,af: APIFailureNewStyle) =>
|
||||
val obj = (m,e, c) match {
|
||||
case ("", Empty, Empty) => Empty ?~! af.failMsg
|
||||
case _ => Failure (m, e, c) ?~! af.failMsg
|
||||
case ("", Empty, Empty) =>
|
||||
Empty ?~! af.translatedErrorMessage
|
||||
case _ =>
|
||||
Failure (m, e, c) ?~! af.translatedErrorMessage
|
||||
}
|
||||
val failuresMsg = filterMessage(obj)
|
||||
val callContext = af.ccl.map(_.copy(httpCode = Some(af.failCode)))
|
||||
@ -3326,7 +3328,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
* Note: The public views means you can use anonymous access which implies that the user is an optional value
|
||||
*/
|
||||
final def checkViewAccessAndReturnView(viewId : ViewId, bankIdAccountId: BankIdAccountId, user: Option[User], consumerId: Option[String] = None): Box[View] = {
|
||||
val customView = Views.views.vend.customView(viewId, bankIdAccountId)
|
||||
val customView = MapperViews.customView(viewId, bankIdAccountId)
|
||||
customView match { // CHECK CUSTOM VIEWS
|
||||
// 1st: View is Pubic and Public views are NOT allowed on this instance.
|
||||
case Full(v) if(v.isPublic && !allowPublicViews) => Failure(PublicViewsNotAllowedOnThisInstance)
|
||||
@ -3336,7 +3338,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
case Full(v) if(user.isDefined && user.get.hasAccountAccess(v, bankIdAccountId, consumerId)) => customView
|
||||
// The user has NO account access via custom view
|
||||
case _ =>
|
||||
val systemView = Views.views.vend.systemView(viewId)
|
||||
val systemView = MapperViews.systemView(viewId)
|
||||
systemView match { // CHECK SYSTEM VIEWS
|
||||
// 1st: View is Pubic and Public views are NOT allowed on this instance.
|
||||
case Full(v) if(v.isPublic && !allowPublicViews) => Failure(PublicViewsNotAllowedOnThisInstance)
|
||||
@ -4200,5 +4202,25 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
|
|
||||
""".stripMargin
|
||||
|
||||
val transactionRequestChallengeTtl = APIUtil.getPropsAsLongValue("transaction_request_challenge_ttl", 600)
|
||||
val transactionRequestChallengeTtl = APIUtil.getPropsAsLongValue("transactionRequest.challenge.ttl.seconds", 600)
|
||||
val userAuthContextUpdateRequestChallengeTtl = APIUtil.getPropsAsLongValue("userAuthContextUpdateRequest.challenge.ttl.seconds", 600)
|
||||
|
||||
val obpErrorMessageCodeRegex = "^(OBP-\\d+):"
|
||||
|
||||
//eg: UserHasMissingRoles = "OBP-20006: User is missing one or more roles:" -->
|
||||
// errorCode = "OBP-20006:"
|
||||
// So far we support the i180n, we need to separate the errorCode and errorBody
|
||||
def extractErrorMessageCode (errorMessage: String) = {
|
||||
val regex = obpErrorMessageCodeRegex.r
|
||||
regex.findFirstIn(errorMessage).mkString
|
||||
}
|
||||
//eg: UserHasMissingRoles = "OBP-20006: User is missing one or more roles:" -->
|
||||
// errorBody = " User is missing one or more roles:"
|
||||
// So far we support the i180n, we need to separate the errorCode and errorBody
|
||||
def extractErrorMessageBody(errorMessage: String) = {
|
||||
|
||||
errorMessage.replaceFirst(obpErrorMessageCodeRegex,"")
|
||||
}
|
||||
|
||||
val allowedAnswerTransactionRequestChallengeAttempts = APIUtil.getPropsAsIntValue("answer_transactionRequest_challenge_allowed_attempts").openOr(3)
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ object ErrorMessages {
|
||||
val FXCurrencyCodeCombinationsNotSupported = "OBP-10004: ISO Currency code combination not supported for FX. Please modify the FROM_CURRENCY_CODE or TO_CURRENCY_CODE. "
|
||||
val InvalidDateFormat = "OBP-10005: Invalid Date Format. Could not convert value to a Date."
|
||||
val InvalidCurrency = "OBP-10006: Invalid Currency Value."
|
||||
val IncorrectRoleName = "OBP-10007: Incorrect Role name: "
|
||||
val IncorrectRoleName = "OBP-10007: Incorrect Role name:"
|
||||
val CouldNotTransformJsonToInternalModel = "OBP-10008: Could not transform Json to internal model."
|
||||
val CountNotSaveOrUpdateResource = "OBP-10009: Could not save or update resource."
|
||||
val NotImplemented = "OBP-10010: Not Implemented "
|
||||
@ -77,7 +77,7 @@ object ErrorMessages {
|
||||
val maximumLimitExceeded = "OBP-10012: Invalid value. Maximum number is 10000."
|
||||
val attemptedToOpenAnEmptyBox = "OBP-10013: Attempted to open an empty Box."
|
||||
val cannotDecryptValueOfProperty = "OBP-10014: Could not decrypt value of property "
|
||||
val AllowedValuesAre = "OBP-10015: Allowed values are: "
|
||||
val AllowedValuesAre = "OBP-10015: Allowed values are:"
|
||||
val InvalidFilterParameterFormat = "OBP-10016: Incorrect filter Parameters in URL. "
|
||||
val InvalidUrl = "OBP-10017: Incorrect URL Format. "
|
||||
val TooManyRequests = "OBP-10018: Too Many Requests."
|
||||
@ -106,7 +106,7 @@ object ErrorMessages {
|
||||
val FilterIsDeletedFormatError = s"OBP-10036: is_deleted parameter can only take two values: TRUE or FALSE!"
|
||||
|
||||
val InvalidApiVersionString = "OBP-00027: Invalid API Version string. We could not find the version specified."
|
||||
val IncorrectTriggerName = "OBP-10028: Incorrect Trigger name: "
|
||||
val IncorrectTriggerName = "OBP-10028: Incorrect Trigger name:"
|
||||
|
||||
val ScaMethodNotDefined = "OBP-10030: Strong customer authentication method is not defined at this instance."
|
||||
|
||||
@ -114,11 +114,11 @@ object ErrorMessages {
|
||||
|
||||
// Authentication / Authorisation / User messages (OBP-20XXX)
|
||||
val UserNotLoggedIn = "OBP-20001: User not logged in. Authentication is required!"
|
||||
val DirectLoginMissingParameters = "OBP-20002: These DirectLogin parameters are missing: "
|
||||
val DirectLoginInvalidToken = "OBP-20003: This DirectLogin token is invalid or expired: "
|
||||
val DirectLoginMissingParameters = "OBP-20002: These DirectLogin parameters are missing:"
|
||||
val DirectLoginInvalidToken = "OBP-20003: This DirectLogin token is invalid or expired:"
|
||||
val InvalidLoginCredentials = "OBP-20004: Invalid login credentials. Check username/password."
|
||||
val UserNotFoundById = "OBP-20005: User not found. Please specify a valid value for USER_ID."
|
||||
val UserHasMissingRoles = "OBP-20006: User is missing one or more roles: "
|
||||
val UserHasMissingRoles = "OBP-20006: User is missing one or more roles:"
|
||||
val UserNotFoundByEmail = "OBP-20007: User not found by email."
|
||||
|
||||
val InvalidConsumerKey = "OBP-20008: Invalid Consumer Key."
|
||||
@ -146,13 +146,13 @@ object ErrorMessages {
|
||||
val SystemViewsCanNotBeModified = "OBP-20021: System Views can not be modified. Only the created views can be modified."
|
||||
val ViewDoesNotPermitAccess = "OBP-20022: View does not permit the access."
|
||||
|
||||
val ConsumerHasMissingRoles = "OBP-20023: Consumer is missing one or more roles: "
|
||||
val ConsumerHasMissingRoles = "OBP-20023: Consumer is missing one or more roles:"
|
||||
val ConsumerNotFoundById = "OBP-20024: Consumer not found. Please specify a valid value for CONSUMER_ID."
|
||||
val ScopeNotFound = "OBP-20025: Scope not found. Please specify a valid value for SCOPE_ID."
|
||||
val ConsumerDoesNotHaveScope = "OBP-20026: CONSUMER_ID does not have the SCOPE_ID "
|
||||
|
||||
val UserNotFoundByUsername = "OBP-20027: User not found by username."
|
||||
val GatewayLoginMissingParameters = "OBP-20028: These GatewayLogin parameters are missing: "
|
||||
val GatewayLoginMissingParameters = "OBP-20028: These GatewayLogin parameters are missing:"
|
||||
val GatewayLoginUnknownError = "OBP-20029: Unknown Gateway login error."
|
||||
val GatewayLoginHostPropertyMissing = "OBP-20030: Property gateway.host is not defined."
|
||||
val GatewayLoginWhiteListAddresses = "OBP-20031: Gateway login can be done only from allowed addresses."
|
||||
@ -172,7 +172,7 @@ object ErrorMessages {
|
||||
val NotEnoughtSearchStatisticsResults = "OBP-20052: Result set too small. Will not be displayed for reasons of privacy."
|
||||
val ElasticSearchEmptyQueryBody = "OBP-20053: The Elasticsearch query body cannot be empty"
|
||||
val InvalidAmount = "OBP-20054: Invalid amount. Please specify a valid value for amount."
|
||||
val MissingQueryParams = "OBP-20055: These query parameters are missing: "
|
||||
val MissingQueryParams = "OBP-20055: These query parameters are missing:"
|
||||
val ElasticSearchDisabled = "OBP-20056: Elasticsearch is disabled for this API instance."
|
||||
val UserNotFoundByUserId = "OBP-20057: User not found by userId."
|
||||
val ConsumerIsDisabled = "OBP-20058: Consumer is disabled."
|
||||
@ -185,7 +185,7 @@ object ErrorMessages {
|
||||
val UserIsDeleted = "OBP-20064: The user is deleted!"
|
||||
|
||||
val DAuthCannotGetOrCreateUser = "OBP-20065: Cannot get or create user during DAuth process."
|
||||
val DAuthMissingParameters = "OBP-20066: These DAuth parameters are missing: "
|
||||
val DAuthMissingParameters = "OBP-20066: These DAuth parameters are missing:"
|
||||
val DAuthUnknownError = "OBP-20067: Unknown DAuth login error."
|
||||
val DAuthHostPropertyMissing = "OBP-20068: Property dauth.host is not defined."
|
||||
val DAuthWhiteListAddresses = "OBP-20069: DAuth login can be done only from allowed addresses."
|
||||
@ -198,7 +198,7 @@ object ErrorMessages {
|
||||
val UserAttributeNotFound = "OBP-20081: User Attribute not found by USER_ATTRIBUTE_ID."
|
||||
|
||||
|
||||
val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements: "
|
||||
val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements:"
|
||||
val CannotGetOrCreateUser = "OBP-20102: Cannot get or create user."
|
||||
val InvalidUserProvider = "OBP-20103: Invalid DAuth User Provider."
|
||||
|
||||
@ -267,7 +267,7 @@ object ErrorMessages {
|
||||
|
||||
val CreateBankError = "OBP-30020: Could not create the Bank"
|
||||
val UpdateBankError = "OBP-30021: Could not update the Bank"
|
||||
val NoViewPermission = "OBP-30022: The current view does not have the permission: "
|
||||
val NoViewPermission = "OBP-30022: The current view does not have the permission:"
|
||||
val UpdateConsumerError = "OBP-30023: Cannot update Consumer "
|
||||
val CreateConsumerError = "OBP-30024: Could not create Consumer "
|
||||
val CreateOAuth2ConsumerError = "OBP-30077: Could not create OAuth2 Consumer."
|
||||
@ -467,7 +467,7 @@ object ErrorMessages {
|
||||
val ConsentDisabled = "OBP-35007: Consents are not allowed at this instance. "
|
||||
val ConsentHeaderNotFound = "OBP-35008: Cannot get Consent-Id. "
|
||||
val ConsentAllowedScaMethods = "OBP-35009: Only SMS and EMAIL are supported as SCA methods. "
|
||||
val SmsServerNotResponding = "OBP-35010: SMS server is not working or SMS server can not send the message to the phone number: "
|
||||
val SmsServerNotResponding = "OBP-35010: SMS server is not working or SMS server can not send the message to the phone number:"
|
||||
val AuthorizationNotFound = "OBP-35011: Resource identification of the related Consent authorisation sub-resource not found by AUTHORIZATION_ID. "
|
||||
val ConsentAlreadyRevoked = "OBP-35012: Consent is already revoked. "
|
||||
val RolesAllowedInConsent = "OBP-35013: Consents can only contain Roles that you already have access to."
|
||||
@ -485,6 +485,8 @@ object ErrorMessages {
|
||||
val ConsentUpdateStatusError = "OBP-35025: The Consent's status cannot be updated."
|
||||
val ConsentUserCannotBeAdded = "OBP-35026: The Consent's User cannot be added."
|
||||
val ConsentUserAuthContextCannotBeAdded = "OBP-35027: The Consent's User Auth Context cannot be added."
|
||||
val ConsentRequestNotFound = "OBP-35028: Consent Request not found by CONSENT_REQUEST_ID. "
|
||||
val ConsentRequestAlreadyUsed = "OBP-35029: The CONSENT_REQUEST_ID is used to create Consent. "
|
||||
|
||||
//Authorisations
|
||||
val AuthorisationNotFound = "OBP-36001: Authorisation not found. Please specify valid values for PAYMENT_ID and AUTHORISATION_ID. "
|
||||
|
||||
@ -1456,7 +1456,35 @@ object ExampleValue {
|
||||
glossaryItems += makeGlossaryItem("direct_debit_id", directDebitIdExample)
|
||||
|
||||
lazy val consentIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
|
||||
glossaryItems += makeGlossaryItem("consent_id", consentIdExample)
|
||||
glossaryItems += makeGlossaryItem("consent_id", consentIdExample)
|
||||
|
||||
lazy val consentRequestPayloadExample = ConnectorField(
|
||||
"""{
|
||||
| "everything": false,
|
||||
| "account_access": [
|
||||
| {
|
||||
| "account_routing": {
|
||||
| "scheme": "AccountNumber",
|
||||
| "address": "4930396"
|
||||
| },
|
||||
| "view_id": "owner"
|
||||
| }
|
||||
| ],
|
||||
| "phone_number": "+44 07972 444 876",
|
||||
| "valid_from": "2022-06-14T12:42:00Z",
|
||||
| "time_to_live": 3600
|
||||
|}""".stripMargin,
|
||||
"The whole create consent request json body."
|
||||
)
|
||||
|
||||
glossaryItems += makeGlossaryItem("payload", consentRequestPayloadExample)
|
||||
|
||||
lazy val consentRequestIdExample = ConnectorField (
|
||||
"8ca8a7e4-6d02-40e3-a129-0b2bf89de9f0",
|
||||
s"A string that MUST uniquely identify the Consent Request on this OBP instance."
|
||||
)
|
||||
|
||||
glossaryItems += makeGlossaryItem("consent_request_id", consentRequestIdExample)
|
||||
|
||||
lazy val line2Example = ConnectorField(NoExampleProvided,NoDescriptionProvided)
|
||||
glossaryItems += makeGlossaryItem("line2", line2Example)
|
||||
|
||||
@ -993,7 +993,7 @@ object Glossary extends MdcLoggable {
|
||||
|
|
||||
|Body:
|
||||
|
|
||||
| { "legal_name":"Eveline Tripman", "mobile_phone_number":"+44 07972 444 876", "email":"eveline@example.com", "face_image":{ "url":"www.openbankproject", "date":"2017-09-19T00:00:00Z" }, "date_of_birth":"2017-09-19T00:00:00Z", "relationship_status":"single", "dependants":10, "dob_of_dependants":["2017-09-19T00:00:00Z"], "credit_rating":{ "rating":"OBP", "source":"OBP" }, "credit_limit":{ "currency":"EUR", "amount":"10" }, "highest_education_attained":"Master", "employment_status":"worker", "kyc_status":true, "last_ok_date":"2017-09-19T00:00:00Z", "title":"Dr.", "branch_id":"DERBY6", "name_suffix":"Sr"}
|
||||
| { "legal_name":"Eveline Tripman", "mobile_phone_number":"+44 07972 444 876", "email":"eveline@example.com", "face_image":{ "url":"www.openbankproject", "date":"1100-01-01T00:00:00Z" }, "date_of_birth":"1100-01-01T00:00:00Z", "relationship_status":"single", "dependants":10, "dob_of_dependants":["1100-01-01T00:00:00Z"], "credit_rating":{ "rating":"OBP", "source":"OBP" }, "credit_limit":{ "currency":"EUR", "amount":"10" }, "highest_education_attained":"Master", "employment_status":"worker", "kyc_status":true, "last_ok_date":"1100-01-01T00:00:00Z", "title":"Dr.", "branch_id":"DERBY6", "name_suffix":"Sr"}
|
||||
|
|
||||
|Headers:
|
||||
|
|
||||
|
||||
@ -2,6 +2,8 @@ package code.api.util
|
||||
|
||||
import java.util.{Date, Locale}
|
||||
|
||||
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
|
||||
import com.openbankproject.commons.model.enums.LanguageParam
|
||||
import net.liftweb.http.S
|
||||
import net.liftweb.util.Props
|
||||
|
||||
@ -31,5 +33,27 @@ object I18NUtil {
|
||||
case Array(lang, country) => new Locale(lang, country)
|
||||
case Array(lang, country, variant) => new Locale(lang, country, variant)
|
||||
}
|
||||
|
||||
object ResourceDocTranslation {
|
||||
def summary(operationId: String, language: Option[LanguageParam], default: String): String = {
|
||||
language match {
|
||||
case Some(value) =>
|
||||
val webUiKey = s"webui_resource_doc_operation_id_${operationId}_summary_${value}"
|
||||
getWebUiPropsValue(webUiKey, default)
|
||||
case None =>
|
||||
default
|
||||
}
|
||||
}
|
||||
def description(operationId: String, language: Option[LanguageParam], default: String): String = {
|
||||
language match {
|
||||
case Some(value) =>
|
||||
val webUiKey = s"webui_resource_doc_operation_id_${operationId}_description_${value}"
|
||||
getWebUiPropsValue(webUiKey, default)
|
||||
case None =>
|
||||
default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -148,6 +148,7 @@ object JwsUtil extends MdcLoggable {
|
||||
val pathOfStandard = HashMap(
|
||||
"BGv1.3"->"berlin-group/v1.3",
|
||||
"OBPv4.0.0"->"obp/v4.0.0",
|
||||
"OBPv5.0.0"->"obp/v5.0.0",
|
||||
"OBPv3.1.0"->"obp/v3.1.0",
|
||||
"UKv1.3"->"open-banking/v3.1"
|
||||
).withDefaultValue("{Not found any standard to match}")
|
||||
|
||||
@ -64,15 +64,15 @@ object Migration extends MdcLoggable {
|
||||
addAccountAccessConsumerId()
|
||||
populateTableViewDefinition()
|
||||
populateTableAccountAccess()
|
||||
generateAndPopulateMissingCustomerUUIDs()
|
||||
generateAndPopulateMissingConsumersUUIDs()
|
||||
generateAndPopulateMissingCustomerUUIDs(startedBeforeSchemifier)
|
||||
generateAndPopulateMissingConsumersUUIDs(startedBeforeSchemifier)
|
||||
populateTableRateLimiting()
|
||||
updateTableViewDefinition()
|
||||
bankAccountHoldersAndOwnerViewAccessInfo()
|
||||
alterTableMappedConsent()
|
||||
alterColumnChallengeAtTableMappedConsent()
|
||||
alterTableOpenIDConnectToken()
|
||||
alterTableMappedUserAuthContext()
|
||||
alterTableMappedUserAuthContext(startedBeforeSchemifier)
|
||||
alterTableMappedUserAuthContextUpdate()
|
||||
populateNameAndAppTypeFieldsAtConsumerTable()
|
||||
populateAzpAndSubFieldsAtConsumerTable()
|
||||
@ -80,7 +80,7 @@ object Migration extends MdcLoggable {
|
||||
populateSettlementBankAccounts()
|
||||
alterColumnStatusAtTableMappedConsent()
|
||||
alterColumnDetailsAtTableTransactionRequest()
|
||||
deleteDuplicatedRowsInTheTableUserAuthContext()
|
||||
deleteDuplicatedRowsInTheTableUserAuthContext(startedBeforeSchemifier)
|
||||
populateTheFieldDeletedAtResourceUser(startedBeforeSchemifier)
|
||||
populateTheFieldIsActiveAtProductAttribute(startedBeforeSchemifier)
|
||||
alterColumnUsernameProviderFirstnameAndLastnameAtAuthUser(startedBeforeSchemifier)
|
||||
@ -94,6 +94,7 @@ object Migration extends MdcLoggable {
|
||||
alterWebhookColumnUrlLength()
|
||||
dropConsentAuthContextDropIndex()
|
||||
alterMappedExpectedChallengeAnswerChallengeTypeLength()
|
||||
alterTransactionRequestChallengeChallengeTypeLength()
|
||||
}
|
||||
|
||||
private def dummyScript(): Boolean = {
|
||||
@ -123,36 +124,47 @@ object Migration extends MdcLoggable {
|
||||
}
|
||||
}
|
||||
|
||||
private def generateAndPopulateMissingCustomerUUIDs(): Boolean = {
|
||||
val name = nameOf(generateAndPopulateMissingCustomerUUIDs)
|
||||
runOnce(name) {
|
||||
val startDate = System.currentTimeMillis()
|
||||
val commitId: String = APIUtil.gitCommit
|
||||
val isSuccessful = CustomerX.customerProvider.vend.populateMissingUUIDs()
|
||||
val endDate = System.currentTimeMillis()
|
||||
private def generateAndPopulateMissingCustomerUUIDs(startedBeforeSchemifier: Boolean): Boolean = {
|
||||
if(startedBeforeSchemifier == true) {
|
||||
logger.warn(s"Migration.database.generateAndPopulateMissingCustomerUUIDs(true) cannot be run before Schemifier.")
|
||||
true
|
||||
} else {
|
||||
val name = nameOf(generateAndPopulateMissingCustomerUUIDs(startedBeforeSchemifier))
|
||||
runOnce(name) {
|
||||
val startDate = System.currentTimeMillis()
|
||||
val commitId: String = APIUtil.gitCommit
|
||||
val isSuccessful = CustomerX.customerProvider.vend.populateMissingUUIDs()
|
||||
val endDate = System.currentTimeMillis()
|
||||
|
||||
val comment: String =
|
||||
s"""Execute `generateAndPopulateMissingCustomerUUIDs`
|
||||
|Duration: ${endDate - startDate} ms;
|
||||
val comment: String =
|
||||
s"""Execute `generateAndPopulateMissingCustomerUUIDs`
|
||||
|Duration: ${endDate - startDate} ms;
|
||||
""".stripMargin
|
||||
saveLog(name, commitId, isSuccessful, startDate, endDate, comment)
|
||||
isSuccessful
|
||||
saveLog(name, commitId, isSuccessful, startDate, endDate, comment)
|
||||
isSuccessful
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private def generateAndPopulateMissingConsumersUUIDs(): Boolean = {
|
||||
val name = nameOf(generateAndPopulateMissingConsumersUUIDs)
|
||||
runOnce(name) {
|
||||
val startDate = System.currentTimeMillis()
|
||||
val commitId: String = APIUtil.gitCommit
|
||||
val isSuccessful = Consumers.consumers.vend.populateMissingUUIDs()
|
||||
val endDate = System.currentTimeMillis()
|
||||
val comment: String =
|
||||
s"""Execute `generateAndPopulateMissingConsumersUUIDs`
|
||||
|Duration: ${endDate - startDate} ms;
|
||||
private def generateAndPopulateMissingConsumersUUIDs(startedBeforeSchemifier: Boolean): Boolean = {
|
||||
if(startedBeforeSchemifier == true) {
|
||||
logger.warn(s"Migration.database.generateAndPopulateMissingConsumersUUIDs(true) cannot be run before Schemifier.")
|
||||
true
|
||||
} else {
|
||||
val name = nameOf(generateAndPopulateMissingConsumersUUIDs(startedBeforeSchemifier))
|
||||
runOnce(name) {
|
||||
val startDate = System.currentTimeMillis()
|
||||
val commitId: String = APIUtil.gitCommit
|
||||
val isSuccessful = Consumers.consumers.vend.populateMissingUUIDs()
|
||||
val endDate = System.currentTimeMillis()
|
||||
val comment: String =
|
||||
s"""Execute `generateAndPopulateMissingConsumersUUIDs`
|
||||
|Duration: ${endDate - startDate} ms;
|
||||
""".stripMargin
|
||||
saveLog(name, commitId, isSuccessful, startDate, endDate, comment)
|
||||
isSuccessful
|
||||
saveLog(name, commitId, isSuccessful, startDate, endDate, comment)
|
||||
isSuccessful
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,10 +219,15 @@ object Migration extends MdcLoggable {
|
||||
MigrationOfConsumer.populateAzpAndSub(name)
|
||||
}
|
||||
}
|
||||
private def alterTableMappedUserAuthContext(): Boolean = {
|
||||
val name = nameOf(alterTableMappedUserAuthContext)
|
||||
runOnce(name) {
|
||||
MigrationOfMappedUserAuthContext.dropUniqueIndex(name)
|
||||
private def alterTableMappedUserAuthContext(startedBeforeSchemifier: Boolean): Boolean = {
|
||||
if(startedBeforeSchemifier == true) {
|
||||
logger.warn(s"Migration.database.alterTableMappedUserAuthContext(true) cannot be run before Schemifier.")
|
||||
true
|
||||
} else {
|
||||
val name = nameOf(alterTableMappedUserAuthContext(startedBeforeSchemifier))
|
||||
runOnce(name) {
|
||||
MigrationOfMappedUserAuthContext.dropUniqueIndex(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
private def alterTableMappedUserAuthContextUpdate(): Boolean = {
|
||||
@ -243,10 +260,15 @@ object Migration extends MdcLoggable {
|
||||
MigrationOfTransactionRequerst.alterColumnDetails(name)
|
||||
}
|
||||
}
|
||||
private def deleteDuplicatedRowsInTheTableUserAuthContext(): Boolean = {
|
||||
val name = nameOf(deleteDuplicatedRowsInTheTableUserAuthContext)
|
||||
runOnce(name) {
|
||||
MigrationOfUserAuthContext.removeDuplicates(name)
|
||||
private def deleteDuplicatedRowsInTheTableUserAuthContext(startedBeforeSchemifier: Boolean): Boolean = {
|
||||
if(startedBeforeSchemifier == true) {
|
||||
logger.warn(s"Migration.database.deleteDuplicatedRowsInTheTableUserAuthContext(true) cannot be run before Schemifier.")
|
||||
true
|
||||
} else {
|
||||
val name = nameOf(deleteDuplicatedRowsInTheTableUserAuthContext(startedBeforeSchemifier))
|
||||
runOnce(name) {
|
||||
MigrationOfUserAuthContext.removeDuplicates(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
private def populateTheFieldDeletedAtResourceUser(startedBeforeSchemifier: Boolean): Boolean = {
|
||||
@ -386,6 +408,13 @@ object Migration extends MdcLoggable {
|
||||
}
|
||||
}
|
||||
|
||||
private def alterTransactionRequestChallengeChallengeTypeLength(): Boolean = {
|
||||
val name = nameOf(alterTransactionRequestChallengeChallengeTypeLength)
|
||||
runOnce(name) {
|
||||
MigrationOfTransactionRequestChallengeChallengeTypeLength.alterColumnChallengeChallengeTypeLength(name)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -8,10 +8,11 @@ import net.liftweb.mapper.{DB, Schemifier}
|
||||
import net.liftweb.util.DefaultConnectionIdentifier
|
||||
import scalikejdbc.DB.CPContext
|
||||
import scalikejdbc._
|
||||
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.{ZoneId, ZonedDateTime}
|
||||
|
||||
import code.api.Constant
|
||||
|
||||
object MigrationOfConsentAuthContextDropIndex {
|
||||
|
||||
val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1)
|
||||
@ -19,7 +20,7 @@ object MigrationOfConsentAuthContextDropIndex {
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'")
|
||||
|
||||
private lazy val getDbConnectionParameters: (String, String, String) = {
|
||||
val dbUrl = APIUtil.getPropsValue("db.url") openOr "jdbc:h2:mem:OBPTest;DB_CLOSE_DELAY=-1"
|
||||
val dbUrl = APIUtil.getPropsValue("db.url") openOr Constant.h2DatabaseDefaultUrlValue
|
||||
val username = dbUrl.split(";").filter(_.contains("user")).toList.headOption.map(_.split("=")(1))
|
||||
val password = dbUrl.split(";").filter(_.contains("password")).toList.headOption.map(_.split("=")(1))
|
||||
val dbUser = APIUtil.getPropsValue("db.user").orElse(username)
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
package code.api.util.migration
|
||||
|
||||
import code.api.util.APIUtil
|
||||
import code.api.util.migration.Migration.{DbFunction, saveLog}
|
||||
import code.transactionrequests.MappedTransactionRequest
|
||||
import net.liftweb.common.Full
|
||||
import net.liftweb.mapper.{DB, Schemifier}
|
||||
import net.liftweb.util.DefaultConnectionIdentifier
|
||||
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.{ZoneId, ZonedDateTime}
|
||||
|
||||
object MigrationOfTransactionRequestChallengeChallengeTypeLength {
|
||||
|
||||
val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1)
|
||||
val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1)
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'")
|
||||
|
||||
def alterColumnChallengeChallengeTypeLength(name: String): Boolean = {
|
||||
DbFunction.tableExists(MappedTransactionRequest, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match {
|
||||
case true =>
|
||||
val startDate = System.currentTimeMillis()
|
||||
val commitId: String = APIUtil.gitCommit
|
||||
var isSuccessful = false
|
||||
|
||||
val executedSql =
|
||||
DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) {
|
||||
APIUtil.getPropsValue("db.driver") match {
|
||||
case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") =>
|
||||
() => "ALTER TABLE mappedtransactionrequest ALTER COLUMN mChallenge_ChallengeType varchar(100);"
|
||||
case _ =>
|
||||
() => "ALTER TABLE mappedtransactionrequest ALTER COLUMN mChallenge_ChallengeType TYPE character varying(100);"
|
||||
}
|
||||
}
|
||||
|
||||
val endDate = System.currentTimeMillis()
|
||||
val comment: String =
|
||||
s"""Executed SQL:
|
||||
|$executedSql
|
||||
|""".stripMargin
|
||||
isSuccessful = true
|
||||
saveLog(name, commitId, isSuccessful, startDate, endDate, comment)
|
||||
isSuccessful
|
||||
|
||||
case false =>
|
||||
val startDate = System.currentTimeMillis()
|
||||
val commitId: String = APIUtil.gitCommit
|
||||
val isSuccessful = false
|
||||
val endDate = System.currentTimeMillis()
|
||||
val comment: String =
|
||||
s"""${MappedTransactionRequest._dbTableNameLC} table does not exist""".stripMargin
|
||||
saveLog(name, commitId, isSuccessful, startDate, endDate, comment)
|
||||
isSuccessful
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,6 +3,7 @@ package code.api.util.migration
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.{ZoneId, ZonedDateTime}
|
||||
|
||||
import code.api.Constant
|
||||
import code.api.util.APIUtil
|
||||
import code.api.util.migration.Migration.{DbFunction, saveLog}
|
||||
import code.context.MappedUserAuthContext
|
||||
@ -20,7 +21,7 @@ object MigrationOfUserAuthContext {
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'")
|
||||
|
||||
private lazy val getDbConnectionParameters: (String, String, String) = {
|
||||
val dbUrl = APIUtil.getPropsValue("db.url") openOr "jdbc:h2:mem:OBPTest;DB_CLOSE_DELAY=-1"
|
||||
val dbUrl = APIUtil.getPropsValue("db.url") openOr Constant.h2DatabaseDefaultUrlValue
|
||||
val username = dbUrl.split(";").filter(_.contains("user")).toList.headOption.map(_.split("=")(1))
|
||||
val password = dbUrl.split(";").filter(_.contains("password")).toList.headOption.map(_.split("=")(1))
|
||||
val dbUser = APIUtil.getPropsValue("db.user").orElse(username)
|
||||
@ -51,6 +52,8 @@ object MigrationOfUserAuthContext {
|
||||
// Make back up
|
||||
DbFunction.makeBackUpOfTable(MappedUserAuthContext)
|
||||
|
||||
MappedUserAuthContext.findAll()
|
||||
|
||||
val startDate = System.currentTimeMillis()
|
||||
val commitId: String = APIUtil.gitCommit
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
package code.api.v1_4_0
|
||||
|
||||
import code.api.berlin.group.v1_3.JvalueCaseClass
|
||||
|
||||
import java.util.Date
|
||||
|
||||
import code.api.util.APIUtil.{EmptyBody, PrimaryDataBody, ResourceDoc}
|
||||
import code.api.util.ApiTag.ResourceDocTag
|
||||
import code.api.util.Glossary.glossaryItems
|
||||
import code.api.util.{APIUtil, ApiRole, ConnectorField, CustomJsonFormats, ExampleValue, PegdownOptions}
|
||||
import code.api.util.{APIUtil, ApiRole, ConnectorField, CustomJsonFormats, ExampleValue, I18NUtil, PegdownOptions}
|
||||
import code.bankconnectors.LocalMappedConnector.getAllEndpointTagsBox
|
||||
import com.openbankproject.commons.model.ListResult
|
||||
import code.crm.CrmEvent.CrmEvent
|
||||
@ -21,10 +21,11 @@ import net.liftweb.json.JsonAST.{JArray, JBool, JNothing, JObject, JValue}
|
||||
import net.liftweb.util.StringHelpers
|
||||
import code.util.Helper.MdcLoggable
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import com.openbankproject.commons.model.enums.LanguageParam
|
||||
|
||||
object JSONFactory1_4_0 extends MdcLoggable{
|
||||
implicit def formats: Formats = CustomJsonFormats.formats
|
||||
case class PostCustomerJson(
|
||||
@ -452,7 +453,7 @@ object JSONFactory1_4_0 extends MdcLoggable{
|
||||
|
||||
private val createResourceDocJsonMemo = new ConcurrentHashMap[ResourceDoc, ResourceDocJson]
|
||||
|
||||
def createResourceDocJson(rd: ResourceDoc, isVersion4OrHigher:Boolean) : ResourceDocJson = {
|
||||
def createResourceDocJson(rd: ResourceDoc, isVersion4OrHigher:Boolean, languageParam: Option[LanguageParam]) : ResourceDocJson = {
|
||||
// if this calculate conversion already happened before, just return that value
|
||||
// if not calculated before, just do conversion
|
||||
val endpointTags = getAllEndpointTagsBox(rd.operationId).map(endpointTag =>ResourceDocTag(endpointTag.tagName))
|
||||
@ -489,13 +490,20 @@ object JSONFactory1_4_0 extends MdcLoggable{
|
||||
urlParametersDescription ++ exampleRequestBodyFieldsDescription ++ responseFieldsDescription
|
||||
}
|
||||
|
||||
val description = resourceDocUpdatedTags.description.stripMargin.trim ++ fieldsDescription
|
||||
val resourceDocDescription = I18NUtil.ResourceDocTranslation.description(
|
||||
resourceDocUpdatedTags.operationId,
|
||||
languageParam,
|
||||
resourceDocUpdatedTags.description.stripMargin.trim
|
||||
)
|
||||
val description = resourceDocDescription ++ fieldsDescription
|
||||
val summary = resourceDocUpdatedTags.summary.replaceFirst("""\.(\s*)$""", "$1") // remove the ending dot in summary
|
||||
val translatedSummary = I18NUtil.ResourceDocTranslation.summary(resourceDocUpdatedTags.operationId, languageParam, summary)
|
||||
|
||||
ResourceDocJson(
|
||||
operation_id = resourceDocUpdatedTags.operationId,
|
||||
request_verb = resourceDocUpdatedTags.requestVerb,
|
||||
request_url = resourceDocUpdatedTags.requestUrl,
|
||||
summary = resourceDocUpdatedTags.summary.replaceFirst("""\.(\s*)$""", "$1"), // remove the ending dot in summary
|
||||
summary = translatedSummary,
|
||||
// Strip the margin character (|) and line breaks and convert from markdown to html
|
||||
description = PegdownOptions.convertPegdownToHtmlTweaked(description), //.replaceAll("\n", ""),
|
||||
description_markdown = description,
|
||||
@ -516,14 +524,14 @@ object JSONFactory1_4_0 extends MdcLoggable{
|
||||
})
|
||||
}
|
||||
|
||||
def createResourceDocsJson(resourceDocList: List[ResourceDoc], isVersion4OrHigher:Boolean) : ResourceDocsJson = {
|
||||
def createResourceDocsJson(resourceDocList: List[ResourceDoc], isVersion4OrHigher:Boolean, languageParam: Option[LanguageParam]) : ResourceDocsJson = {
|
||||
if(isVersion4OrHigher){
|
||||
ResourceDocsJson(
|
||||
resourceDocList.map(createResourceDocJson(_,isVersion4OrHigher)),
|
||||
resourceDocList.map(createResourceDocJson(_,isVersion4OrHigher, languageParam)),
|
||||
meta=Some(ResourceDocMeta(new Date(), resourceDocList.length))
|
||||
)
|
||||
} else {
|
||||
ResourceDocsJson(resourceDocList.map(createResourceDocJson(_,false)))
|
||||
ResourceDocsJson(resourceDocList.map(createResourceDocJson(_,false, languageParam)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1477,7 +1477,7 @@ trait APIMethods200 {
|
||||
cc =>
|
||||
for {
|
||||
postedData <- tryo {json.extract[CreateUserJson]} ?~! ErrorMessages.InvalidJsonFormat
|
||||
_ <- tryo(assert(validatePasswordOnCreation(postedData.password))) ?~! ErrorMessages.InvalidStrongPasswordFormat
|
||||
_ <- tryo(assert(fullPasswordValidation(postedData.password))) ?~! ErrorMessages.InvalidStrongPasswordFormat
|
||||
} yield {
|
||||
if (AuthUser.find(By(AuthUser.username, postedData.username)).isEmpty) {
|
||||
val userCreated = AuthUser.create
|
||||
@ -1511,180 +1511,180 @@ trait APIMethods200 {
|
||||
|
||||
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
createMeeting,
|
||||
apiVersion,
|
||||
"createMeeting",
|
||||
"POST",
|
||||
"/banks/BANK_ID/meetings",
|
||||
"Create Meeting (video conference/call)",
|
||||
"""Create Meeting: Initiate a video conference/call with the bank.
|
||||
|
|
||||
|The Meetings resource contains meta data about video/other conference sessions, not the video/audio/chat itself.
|
||||
|
|
||||
|The actual conferencing is handled by external providers. Currently OBP supports tokbox video conferences (WIP).
|
||||
|
|
||||
|This is not a recomendation of tokbox per se.
|
||||
|
|
||||
|provider_id determines the provider of the meeting / video chat service. MUST be url friendly (no spaces).
|
||||
|
|
||||
|purpose_id explains the purpose of the chat. onboarding | mortgage | complaint etc. MUST be url friendly (no spaces).
|
||||
|
|
||||
|Login is required.
|
||||
|
|
||||
|This call is **experimental**. Currently staff_user_id is not set. Further calls will be needed to correctly set this.
|
||||
""".stripMargin,
|
||||
CreateMeetingJson("tokbox", "onboarding"),
|
||||
meetingJson,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
MeetingApiKeyNotConfigured,
|
||||
MeetingApiSecretNotConfigured,
|
||||
InvalidBankIdFormat,
|
||||
BankNotFound,
|
||||
InvalidJsonFormat,
|
||||
MeetingsNotSupported,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagMeeting, apiTagCustomer, apiTagExperimental))
|
||||
|
||||
|
||||
lazy val createMeeting: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "meetings" :: Nil JsonPost json -> _ => {
|
||||
cc =>
|
||||
if (APIUtil.getPropsAsBoolValue("meeting.tokbox_enabled", false)) {
|
||||
for {
|
||||
// TODO use these keys to get session and tokens from tokbox
|
||||
_ <- APIUtil.getPropsValue("meeting.tokbox_api_key") ~> APIFailure(MeetingApiKeyNotConfigured, 403)
|
||||
_ <- APIUtil.getPropsValue("meeting.tokbox_api_secret") ~> APIFailure(MeetingApiSecretNotConfigured, 403)
|
||||
u <- cc.user ?~! UserNotLoggedIn
|
||||
_ <- tryo(assert(isValidID(bankId.value)))?~! InvalidBankIdFormat
|
||||
(bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
postedData <- tryo {json.extract[CreateMeetingJson]} ?~! InvalidJsonFormat
|
||||
now = Calendar.getInstance().getTime()
|
||||
sessionId <- tryo{code.opentok.OpenTokUtil.getSession.getSessionId()}
|
||||
customerToken <- tryo{code.opentok.OpenTokUtil.generateTokenForPublisher(60)}
|
||||
staffToken <- tryo{code.opentok.OpenTokUtil.generateTokenForModerator(60)}
|
||||
meeting <- Meetings.meetingProvider.vend.createMeeting(bank.bankId, u, u, postedData.provider_id, postedData.purpose_id, now, sessionId, customerToken, staffToken
|
||||
,null,null)//These two are used from V310
|
||||
} yield {
|
||||
// Format the data as V2.0.0 json
|
||||
val json = JSONFactory200.createMeetingJSON(meeting)
|
||||
successJsonResponse(Extraction.decompose(json), 201)
|
||||
}
|
||||
} else {
|
||||
Full(errorJsonResponse(MeetingsNotSupported))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
getMeetings,
|
||||
apiVersion,
|
||||
"getMeetings",
|
||||
"GET",
|
||||
"/banks/BANK_ID/meetings",
|
||||
"Get Meetings",
|
||||
"""Meetings contain meta data about, and are used to facilitate, video conferences / chats etc.
|
||||
|
|
||||
|The actual conference/chats are handled by external services.
|
||||
|
|
||||
|Login is required.
|
||||
|
|
||||
|This call is **experimental** and will require further authorisation in the future.
|
||||
""".stripMargin,
|
||||
emptyObjectJson,
|
||||
meetingsJson,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
MeetingApiKeyNotConfigured,
|
||||
MeetingApiSecretNotConfigured,
|
||||
BankNotFound,
|
||||
MeetingsNotSupported,
|
||||
UnknownError),
|
||||
List(apiTagMeeting, apiTagCustomer, apiTagExperimental))
|
||||
|
||||
|
||||
lazy val getMeetings: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "meetings" :: Nil JsonGet _ => {
|
||||
cc =>
|
||||
if (APIUtil.getPropsAsBoolValue("meeting.tokbox_enabled", false)) {
|
||||
for {
|
||||
_ <- cc.user ?~! ErrorMessages.UserNotLoggedIn
|
||||
(bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
_ <- APIUtil.getPropsValue("meeting.tokbox_api_key") ~> APIFailure(ErrorMessages.MeetingApiKeyNotConfigured, 403)
|
||||
_ <- APIUtil.getPropsValue("meeting.tokbox_api_secret") ~> APIFailure(ErrorMessages.MeetingApiSecretNotConfigured, 403)
|
||||
u <- cc.user ?~! ErrorMessages.UserNotLoggedIn
|
||||
(bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
// now = Calendar.getInstance().getTime()
|
||||
meetings <- Meetings.meetingProvider.vend.getMeetings(bank.bankId, u)
|
||||
}
|
||||
yield {
|
||||
// Format the data as V2.0.0 json
|
||||
val json = JSONFactory200.createMeetingJSONs(meetings)
|
||||
successJsonResponse(Extraction.decompose(json))
|
||||
}
|
||||
} else {
|
||||
Full(errorJsonResponse(MeetingsNotSupported))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
getMeeting,
|
||||
apiVersion,
|
||||
"getMeeting",
|
||||
"GET",
|
||||
"/banks/BANK_ID/meetings/MEETING_ID",
|
||||
"Get Meeting",
|
||||
"""Get Meeting specified by BANK_ID / MEETING_ID
|
||||
|Meetings contain meta data about, and are used to facilitate, video conferences / chats etc.
|
||||
|
|
||||
|The actual conference/chats are handled by external services.
|
||||
|
|
||||
|Login is required.
|
||||
|
|
||||
|This call is **experimental** and will require further authorisation in the future.
|
||||
""".stripMargin,
|
||||
emptyObjectJson,
|
||||
meetingJson,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
BankNotFound,
|
||||
MeetingApiKeyNotConfigured,
|
||||
MeetingApiSecretNotConfigured,
|
||||
MeetingNotFound,
|
||||
MeetingsNotSupported,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagMeeting, apiTagKyc, apiTagCustomer, apiTagExperimental))
|
||||
|
||||
|
||||
lazy val getMeeting: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "meetings" :: meetingId :: Nil JsonGet _ => {
|
||||
cc =>
|
||||
if (APIUtil.getPropsAsBoolValue("meeting.tokbox_enabled", false)) {
|
||||
for {
|
||||
u <- cc.user ?~! UserNotLoggedIn
|
||||
(bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
_ <- APIUtil.getPropsValue("meeting.tokbox_api_key") ~> APIFailure(ErrorMessages.MeetingApiKeyNotConfigured, 403)
|
||||
_ <- APIUtil.getPropsValue("meeting.tokbox_api_secret") ~> APIFailure(ErrorMessages.MeetingApiSecretNotConfigured, 403)
|
||||
(bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
meeting <- Meetings.meetingProvider.vend.getMeeting(bank.bankId, u, meetingId) ?~! {ErrorMessages.MeetingNotFound}
|
||||
}
|
||||
yield {
|
||||
// Format the data as V2.0.0 json
|
||||
val json = JSONFactory200.createMeetingJSON(meeting)
|
||||
successJsonResponse(Extraction.decompose(json))
|
||||
}
|
||||
} else {
|
||||
Full(errorJsonResponse(ErrorMessages.MeetingsNotSupported))
|
||||
}
|
||||
}
|
||||
}
|
||||
// resourceDocs += ResourceDoc(
|
||||
// createMeeting,
|
||||
// apiVersion,
|
||||
// "createMeeting",
|
||||
// "POST",
|
||||
// "/banks/BANK_ID/meetings",
|
||||
// "Create Meeting (video conference/call)",
|
||||
// """Create Meeting: Initiate a video conference/call with the bank.
|
||||
// |
|
||||
// |The Meetings resource contains meta data about video/other conference sessions, not the video/audio/chat itself.
|
||||
// |
|
||||
// |The actual conferencing is handled by external providers. Currently OBP supports tokbox video conferences (WIP).
|
||||
// |
|
||||
// |This is not a recomendation of tokbox per se.
|
||||
// |
|
||||
// |provider_id determines the provider of the meeting / video chat service. MUST be url friendly (no spaces).
|
||||
// |
|
||||
// |purpose_id explains the purpose of the chat. onboarding | mortgage | complaint etc. MUST be url friendly (no spaces).
|
||||
// |
|
||||
// |Login is required.
|
||||
// |
|
||||
// |This call is **experimental**. Currently staff_user_id is not set. Further calls will be needed to correctly set this.
|
||||
// """.stripMargin,
|
||||
// CreateMeetingJson("tokbox", "onboarding"),
|
||||
// meetingJson,
|
||||
// List(
|
||||
// UserNotLoggedIn,
|
||||
// MeetingApiKeyNotConfigured,
|
||||
// MeetingApiSecretNotConfigured,
|
||||
// InvalidBankIdFormat,
|
||||
// BankNotFound,
|
||||
// InvalidJsonFormat,
|
||||
// MeetingsNotSupported,
|
||||
// UnknownError
|
||||
// ),
|
||||
// List(apiTagMeeting, apiTagCustomer, apiTagExperimental))
|
||||
//
|
||||
//
|
||||
// lazy val createMeeting: OBPEndpoint = {
|
||||
// case "banks" :: BankId(bankId) :: "meetings" :: Nil JsonPost json -> _ => {
|
||||
// cc =>
|
||||
// if (APIUtil.getPropsAsBoolValue("meeting.tokbox_enabled", false)) {
|
||||
// for {
|
||||
// // TODO use these keys to get session and tokens from tokbox
|
||||
// _ <- APIUtil.getPropsValue("meeting.tokbox_api_key") ~> APIFailure(MeetingApiKeyNotConfigured, 403)
|
||||
// _ <- APIUtil.getPropsValue("meeting.tokbox_api_secret") ~> APIFailure(MeetingApiSecretNotConfigured, 403)
|
||||
// u <- cc.user ?~! UserNotLoggedIn
|
||||
// _ <- tryo(assert(isValidID(bankId.value)))?~! InvalidBankIdFormat
|
||||
// (bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
// postedData <- tryo {json.extract[CreateMeetingJson]} ?~! InvalidJsonFormat
|
||||
// now = Calendar.getInstance().getTime()
|
||||
// sessionId <- tryo{code.opentok.OpenTokUtil.getSession.getSessionId()}
|
||||
// customerToken <- tryo{code.opentok.OpenTokUtil.generateTokenForPublisher(60)}
|
||||
// staffToken <- tryo{code.opentok.OpenTokUtil.generateTokenForModerator(60)}
|
||||
// meeting <- Meetings.meetingProvider.vend.createMeeting(bank.bankId, u, u, postedData.provider_id, postedData.purpose_id, now, sessionId, customerToken, staffToken
|
||||
// ,null,null)//These two are used from V310
|
||||
// } yield {
|
||||
// // Format the data as V2.0.0 json
|
||||
// val json = JSONFactory200.createMeetingJSON(meeting)
|
||||
// successJsonResponse(Extraction.decompose(json), 201)
|
||||
// }
|
||||
// } else {
|
||||
// Full(errorJsonResponse(MeetingsNotSupported))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// resourceDocs += ResourceDoc(
|
||||
// getMeetings,
|
||||
// apiVersion,
|
||||
// "getMeetings",
|
||||
// "GET",
|
||||
// "/banks/BANK_ID/meetings",
|
||||
// "Get Meetings",
|
||||
// """Meetings contain meta data about, and are used to facilitate, video conferences / chats etc.
|
||||
// |
|
||||
// |The actual conference/chats are handled by external services.
|
||||
// |
|
||||
// |Login is required.
|
||||
// |
|
||||
// |This call is **experimental** and will require further authorisation in the future.
|
||||
// """.stripMargin,
|
||||
// emptyObjectJson,
|
||||
// meetingsJson,
|
||||
// List(
|
||||
// UserNotLoggedIn,
|
||||
// MeetingApiKeyNotConfigured,
|
||||
// MeetingApiSecretNotConfigured,
|
||||
// BankNotFound,
|
||||
// MeetingsNotSupported,
|
||||
// UnknownError),
|
||||
// List(apiTagMeeting, apiTagCustomer, apiTagExperimental))
|
||||
//
|
||||
//
|
||||
// lazy val getMeetings: OBPEndpoint = {
|
||||
// case "banks" :: BankId(bankId) :: "meetings" :: Nil JsonGet _ => {
|
||||
// cc =>
|
||||
// if (APIUtil.getPropsAsBoolValue("meeting.tokbox_enabled", false)) {
|
||||
// for {
|
||||
// _ <- cc.user ?~! ErrorMessages.UserNotLoggedIn
|
||||
// (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
// _ <- APIUtil.getPropsValue("meeting.tokbox_api_key") ~> APIFailure(ErrorMessages.MeetingApiKeyNotConfigured, 403)
|
||||
// _ <- APIUtil.getPropsValue("meeting.tokbox_api_secret") ~> APIFailure(ErrorMessages.MeetingApiSecretNotConfigured, 403)
|
||||
// u <- cc.user ?~! ErrorMessages.UserNotLoggedIn
|
||||
// (bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
// // now = Calendar.getInstance().getTime()
|
||||
// meetings <- Meetings.meetingProvider.vend.getMeetings(bank.bankId, u)
|
||||
// }
|
||||
// yield {
|
||||
// // Format the data as V2.0.0 json
|
||||
// val json = JSONFactory200.createMeetingJSONs(meetings)
|
||||
// successJsonResponse(Extraction.decompose(json))
|
||||
// }
|
||||
// } else {
|
||||
// Full(errorJsonResponse(MeetingsNotSupported))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// resourceDocs += ResourceDoc(
|
||||
// getMeeting,
|
||||
// apiVersion,
|
||||
// "getMeeting",
|
||||
// "GET",
|
||||
// "/banks/BANK_ID/meetings/MEETING_ID",
|
||||
// "Get Meeting",
|
||||
// """Get Meeting specified by BANK_ID / MEETING_ID
|
||||
// |Meetings contain meta data about, and are used to facilitate, video conferences / chats etc.
|
||||
// |
|
||||
// |The actual conference/chats are handled by external services.
|
||||
// |
|
||||
// |Login is required.
|
||||
// |
|
||||
// |This call is **experimental** and will require further authorisation in the future.
|
||||
// """.stripMargin,
|
||||
// emptyObjectJson,
|
||||
// meetingJson,
|
||||
// List(
|
||||
// UserNotLoggedIn,
|
||||
// BankNotFound,
|
||||
// MeetingApiKeyNotConfigured,
|
||||
// MeetingApiSecretNotConfigured,
|
||||
// MeetingNotFound,
|
||||
// MeetingsNotSupported,
|
||||
// UnknownError
|
||||
// ),
|
||||
// List(apiTagMeeting, apiTagKyc, apiTagCustomer, apiTagExperimental))
|
||||
//
|
||||
//
|
||||
// lazy val getMeeting: OBPEndpoint = {
|
||||
// case "banks" :: BankId(bankId) :: "meetings" :: meetingId :: Nil JsonGet _ => {
|
||||
// cc =>
|
||||
// if (APIUtil.getPropsAsBoolValue("meeting.tokbox_enabled", false)) {
|
||||
// for {
|
||||
// u <- cc.user ?~! UserNotLoggedIn
|
||||
// (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
// _ <- APIUtil.getPropsValue("meeting.tokbox_api_key") ~> APIFailure(ErrorMessages.MeetingApiKeyNotConfigured, 403)
|
||||
// _ <- APIUtil.getPropsValue("meeting.tokbox_api_secret") ~> APIFailure(ErrorMessages.MeetingApiSecretNotConfigured, 403)
|
||||
// (bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound
|
||||
// meeting <- Meetings.meetingProvider.vend.getMeeting(bank.bankId, u, meetingId) ?~! {ErrorMessages.MeetingNotFound}
|
||||
// }
|
||||
// yield {
|
||||
// // Format the data as V2.0.0 json
|
||||
// val json = JSONFactory200.createMeetingJSON(meeting)
|
||||
// successJsonResponse(Extraction.decompose(json))
|
||||
// }
|
||||
// } else {
|
||||
// Full(errorJsonResponse(ErrorMessages.MeetingsNotSupported))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
|
||||
@ -169,9 +169,9 @@ object OBPAPI2_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations2_0_0.createAccount,
|
||||
Implementations2_0_0.getTransactionTypes,
|
||||
Implementations2_0_0.createUser,
|
||||
Implementations2_0_0.createMeeting,
|
||||
Implementations2_0_0.getMeetings,
|
||||
Implementations2_0_0.getMeeting,
|
||||
// Implementations2_0_0.createMeeting,
|
||||
// Implementations2_0_0.getMeetings,
|
||||
// Implementations2_0_0.getMeeting,
|
||||
Implementations2_0_0.createCustomer,
|
||||
Implementations2_0_0.getCurrentUser,
|
||||
Implementations2_0_0.getUser,
|
||||
|
||||
@ -140,7 +140,7 @@ object OBPAPI2_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations2_0_0.addSocialMediaHandle ::
|
||||
Implementations2_0_0.getPrivateAccountsAtOneBank ::
|
||||
Implementations2_0_0.createAccount ::
|
||||
Implementations2_0_0.createMeeting ::
|
||||
// Implementations2_0_0.createMeeting ::
|
||||
Implementations2_0_0.createUser ::
|
||||
Implementations2_0_0.createUserCustomerLinks ::
|
||||
Implementations2_0_0.deleteEntitlement ::
|
||||
@ -155,8 +155,8 @@ object OBPAPI2_1_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations2_0_0.getKycDocuments ::
|
||||
Implementations2_0_0.getKycMedia ::
|
||||
Implementations2_0_0.getKycStatuses ::
|
||||
Implementations2_0_0.getMeeting ::
|
||||
Implementations2_0_0.getMeetings ::
|
||||
// Implementations2_0_0.getMeeting ::
|
||||
// Implementations2_0_0.getMeetings ::
|
||||
Implementations2_0_0.getPermissionForUserForBankAccount ::
|
||||
Implementations2_0_0.getPermissionsForBankAccount ::
|
||||
Implementations2_0_0.getSocialMediaHandles ::
|
||||
|
||||
@ -115,7 +115,7 @@ object OBPAPI2_2_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations2_0_0.getPrivateAccountsAtOneBank ::
|
||||
//now in V220
|
||||
//Implementations2_0_0.createAccount ::
|
||||
Implementations2_0_0.createMeeting ::
|
||||
// Implementations2_0_0.createMeeting ::
|
||||
Implementations2_0_0.createUser ::
|
||||
Implementations2_0_0.createUserCustomerLinks ::
|
||||
Implementations2_0_0.deleteEntitlement ::
|
||||
@ -130,8 +130,8 @@ object OBPAPI2_2_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations2_0_0.getKycDocuments ::
|
||||
Implementations2_0_0.getKycMedia ::
|
||||
Implementations2_0_0.getKycStatuses ::
|
||||
Implementations2_0_0.getMeeting ::
|
||||
Implementations2_0_0.getMeetings ::
|
||||
// Implementations2_0_0.getMeeting ::
|
||||
// Implementations2_0_0.getMeetings ::
|
||||
Implementations2_0_0.getPermissionForUserForBankAccount ::
|
||||
Implementations2_0_0.getPermissionsForBankAccount ::
|
||||
Implementations2_0_0.getSocialMediaHandles ::
|
||||
|
||||
@ -151,7 +151,7 @@ object OBPAPI3_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations2_0_0.getPrivateAccountsAtOneBank ::
|
||||
//now in V220
|
||||
//Implementations2_0_0.createAccount ::
|
||||
Implementations2_0_0.createMeeting ::
|
||||
// Implementations2_0_0.createMeeting ::
|
||||
Implementations2_0_0.createUser ::
|
||||
Implementations2_0_0.createUserCustomerLinks ::
|
||||
Implementations2_0_0.deleteEntitlement ::
|
||||
@ -166,8 +166,8 @@ object OBPAPI3_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
Implementations2_0_0.getKycDocuments ::
|
||||
Implementations2_0_0.getKycMedia ::
|
||||
Implementations2_0_0.getKycStatuses ::
|
||||
Implementations2_0_0.getMeeting ::
|
||||
Implementations2_0_0.getMeetings ::
|
||||
// Implementations2_0_0.getMeeting ::
|
||||
// Implementations2_0_0.getMeetings ::
|
||||
Implementations2_0_0.getPermissionsForBankAccount ::
|
||||
Implementations2_0_0.getSocialMediaHandles ::
|
||||
Implementations2_0_0.getTransactionTypes ::
|
||||
|
||||
@ -3,7 +3,6 @@ package code.api.v3_1_0
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.UUID
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
|
||||
import code.api.ResourceDocs1_4_0.{MessageDocsSwaggerDefinitions, ResourceDocsAPIMethodsUtil, SwaggerDefinitionsJSON, SwaggerJSONFactory}
|
||||
import code.api.util.APIUtil.{getWebUIPropsPairs, _}
|
||||
@ -22,7 +21,7 @@ import code.api.v3_0_0.JSONFactory300.createAdapterInfoJson
|
||||
import code.api.v3_1_0.JSONFactory310._
|
||||
import code.bankconnectors.rest.RestConnector_vMar2019
|
||||
import code.bankconnectors.{Connector, LocalMappedConnector}
|
||||
import code.consent.{ConsentStatus, Consents}
|
||||
import code.consent.{ConsentRequests, ConsentStatus, Consents}
|
||||
import code.consumer.Consumers
|
||||
import code.context.UserAuthContextUpdateProvider
|
||||
import code.entitlement.Entitlement
|
||||
@ -1425,7 +1424,7 @@ trait APIMethods310 {
|
||||
json.extract[PostUserAuthContextJson]
|
||||
}
|
||||
(user, callContext) <- NewStyle.function.findByUserId(userId, callContext)
|
||||
(userAuthContext, callContext) <- NewStyle.function.createUserAuthContext(user, postedData.key, postedData.value, callContext)
|
||||
(userAuthContext, callContext) <- NewStyle.function.createUserAuthContext(user, postedData.key.trim, postedData.value.trim, callContext)
|
||||
} yield {
|
||||
(JSONFactory310.createUserAuthContextJson(userAuthContext), HttpCode.`201`(callContext))
|
||||
}
|
||||
@ -3507,11 +3506,13 @@ trait APIMethods310 {
|
||||
}
|
||||
case None => Future(None, "Any application")
|
||||
}
|
||||
|
||||
|
||||
challengeAnswer = Props.mode match {
|
||||
case Props.RunModes.Test => Consent.challengeAnswerAtTestEnvironment
|
||||
case _ => Random.nextInt(99999999).toString()
|
||||
}
|
||||
createdConsent <- Future(Consents.consentProvider.vend.createConsent(user, challengeAnswer)) map {
|
||||
createdConsent <- Future(Consents.consentProvider.vend.createObpConsent(user, challengeAnswer, None)) map {
|
||||
i => connectorEmptyResponse(i, callContext)
|
||||
}
|
||||
consentJWT =
|
||||
|
||||
@ -529,6 +529,7 @@ case class PostConsentBodyCommonJson(
|
||||
views: List[PostConsentViewJsonV310],
|
||||
entitlements: List[PostConsentEntitlementJsonV310],
|
||||
consumer_id: Option[String],
|
||||
consent_request_id: Option[String],
|
||||
valid_from: Option[Date],
|
||||
time_to_live: Option[Long]
|
||||
) extends PostConsentCommonBody
|
||||
|
||||
@ -3,6 +3,7 @@ package code.api.v4_0_0
|
||||
import java.net.URLEncoder
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.{Calendar, Date}
|
||||
|
||||
import code.DynamicData.{DynamicData, DynamicDataProvider}
|
||||
import code.DynamicEndpoint.DynamicEndpointSwagger
|
||||
import code.accountattribute.AccountAttributeX
|
||||
@ -42,7 +43,7 @@ import code.apicollectionendpoint.MappedApiCollectionEndpointsProvider
|
||||
import code.authtypevalidation.JsonAuthTypeValidation
|
||||
import code.bankconnectors.{Connector, DynamicConnector, InternalConnector}
|
||||
import code.connectormethod.{JsonConnectorMethod, JsonConnectorMethodMethodBody}
|
||||
import code.consent.{ConsentStatus, Consents}
|
||||
import code.consent.{ConsentRequests, ConsentStatus, Consents}
|
||||
import code.dynamicEntity.{DynamicEntityCommons, ReferenceType}
|
||||
import code.dynamicMessageDoc.JsonDynamicMessageDoc
|
||||
import code.dynamicResourceDoc.JsonDynamicResourceDoc
|
||||
@ -909,379 +910,421 @@ trait APIMethods400 {
|
||||
Some(List(canCreateAnyTransactionRequest)))
|
||||
|
||||
|
||||
// Different Transaction Request approaches:
|
||||
lazy val createTransactionRequestAccount = createTransactionRequest
|
||||
lazy val createTransactionRequestAccountOtp = createTransactionRequest
|
||||
lazy val createTransactionRequestSepa = createTransactionRequest
|
||||
lazy val createTransactionRequestCounterparty = createTransactionRequest
|
||||
lazy val createTransactionRequestRefund = createTransactionRequest
|
||||
lazy val createTransactionRequestFreeForm = createTransactionRequest
|
||||
lazy val createTransactionRequestSimple = createTransactionRequest
|
||||
def createTransactionRequest(bankId: BankId, accountId: AccountId, viewId: ViewId, transactionRequestType: TransactionRequestType, json: JValue): Future[(TransactionRequestWithChargeJSON400, Option[CallContext])] = {
|
||||
for {
|
||||
(Full(u), fromAccount, callContext) <- SS.userAccount
|
||||
_ <- NewStyle.function.isEnabledTransactionRequests(callContext)
|
||||
_ <- Helper.booleanToFuture(InvalidAccountIdFormat, cc=callContext) {
|
||||
isValidID(accountId.value)
|
||||
}
|
||||
_ <- Helper.booleanToFuture(InvalidBankIdFormat, cc=callContext) {
|
||||
isValidID(bankId.value)
|
||||
}
|
||||
|
||||
// This handles the above cases
|
||||
lazy val createTransactionRequest: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transaction-request-types" ::
|
||||
TransactionRequestType(transactionRequestType) :: "transaction-requests" :: Nil JsonPost json -> _ => {
|
||||
cc =>
|
||||
for {
|
||||
(Full(u), fromAccount, callContext) <- SS.userAccount
|
||||
_ <- NewStyle.function.isEnabledTransactionRequests(callContext)
|
||||
_ <- Helper.booleanToFuture(InvalidAccountIdFormat, cc=callContext) {
|
||||
isValidID(accountId.value)
|
||||
}
|
||||
_ <- Helper.booleanToFuture(InvalidBankIdFormat, cc=callContext) {
|
||||
isValidID(bankId.value)
|
||||
}
|
||||
account = BankIdAccountId(bankId, accountId)
|
||||
_ <- NewStyle.function.checkAuthorisationToCreateTransactionRequest(viewId, account, u, callContext)
|
||||
|
||||
account = BankIdAccountId(bankId, accountId)
|
||||
_ <- NewStyle.function.checkAuthorisationToCreateTransactionRequest(viewId, account, u, callContext)
|
||||
_ <- Helper.booleanToFuture(s"${InvalidTransactionRequestType}: '${transactionRequestType.value}'. Current Sandbox does not support it. ", cc=callContext) {
|
||||
APIUtil.getPropsValue("transactionRequests_supported_types", "").split(",").contains(transactionRequestType.value)
|
||||
}
|
||||
|
||||
_ <- Helper.booleanToFuture(s"${InvalidTransactionRequestType}: '${transactionRequestType.value}'. Current Sandbox does not support it. ", cc=callContext) {
|
||||
APIUtil.getPropsValue("transactionRequests_supported_types", "").split(",").contains(transactionRequestType.value)
|
||||
}
|
||||
transactionRequestTypeValue <- NewStyle.function.tryons(s"$InvalidTransactionRequestType: '${transactionRequestType.value}'. OBP does not support it.", 400, callContext) {
|
||||
TransactionRequestTypes.withName(transactionRequestType.value)
|
||||
}
|
||||
|
||||
transactionRequestTypeValue <- NewStyle.function.tryons(s"$InvalidTransactionRequestType: '${transactionRequestType.value}'. OBP does not support it.", 400, callContext) {
|
||||
TransactionRequestTypes.withName(transactionRequestType.value)
|
||||
}
|
||||
// Check the input JSON format, here is just check the common parts of all four types
|
||||
transDetailsJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $TransactionRequestBodyCommonJSON ", 400, callContext) {
|
||||
json.extract[TransactionRequestBodyCommonJSON]
|
||||
}
|
||||
|
||||
// Check the input JSON format, here is just check the common parts of all four types
|
||||
transDetailsJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $TransactionRequestBodyCommonJSON ", 400, callContext) {
|
||||
json.extract[TransactionRequestBodyCommonJSON]
|
||||
}
|
||||
transactionAmountNumber <- NewStyle.function.tryons(s"$InvalidNumber Current input is ${transDetailsJson.value.amount} ", 400, callContext) {
|
||||
BigDecimal(transDetailsJson.value.amount)
|
||||
}
|
||||
|
||||
transactionAmountNumber <- NewStyle.function.tryons(s"$InvalidNumber Current input is ${transDetailsJson.value.amount} ", 400, callContext) {
|
||||
BigDecimal(transDetailsJson.value.amount)
|
||||
}
|
||||
_ <- Helper.booleanToFuture(s"${NotPositiveAmount} Current input is: '${transactionAmountNumber}'", cc=callContext) {
|
||||
transactionAmountNumber > BigDecimal("0")
|
||||
}
|
||||
|
||||
_ <- Helper.booleanToFuture(s"${NotPositiveAmount} Current input is: '${transactionAmountNumber}'", cc=callContext) {
|
||||
transactionAmountNumber > BigDecimal("0")
|
||||
}
|
||||
_ <- Helper.booleanToFuture(s"${InvalidISOCurrencyCode} Current input is: '${transDetailsJson.value.currency}'", cc=callContext) {
|
||||
isValidCurrencyISOCode(transDetailsJson.value.currency)
|
||||
}
|
||||
|
||||
_ <- Helper.booleanToFuture(s"${InvalidISOCurrencyCode} Current input is: '${transDetailsJson.value.currency}'", cc=callContext) {
|
||||
isValidCurrencyISOCode(transDetailsJson.value.currency)
|
||||
}
|
||||
// Prevent default value for transaction request type (at least).
|
||||
_ <- Helper.booleanToFuture(s"${InvalidISOCurrencyCode} Current input is: '${transDetailsJson.value.currency}'", cc=callContext) {
|
||||
isValidCurrencyISOCode(transDetailsJson.value.currency)
|
||||
}
|
||||
|
||||
// Prevent default value for transaction request type (at least).
|
||||
_ <- Helper.booleanToFuture(s"${InvalidISOCurrencyCode} Current input is: '${transDetailsJson.value.currency}'", cc=callContext) {
|
||||
isValidCurrencyISOCode(transDetailsJson.value.currency)
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- transactionRequestTypeValue match {
|
||||
case REFUND => {
|
||||
for {
|
||||
transactionRequestBodyRefundJson <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $ACCOUNT json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodyRefundJsonV400]
|
||||
}
|
||||
|
||||
(createdTransactionRequest, callContext) <- transactionRequestTypeValue match {
|
||||
case REFUND => {
|
||||
for {
|
||||
transactionRequestBodyRefundJson <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $ACCOUNT json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodyRefundJsonV400]
|
||||
}
|
||||
transactionId = TransactionId(transactionRequestBodyRefundJson.refund.transaction_id)
|
||||
|
||||
transactionId = TransactionId(transactionRequestBodyRefundJson.refund.transaction_id)
|
||||
(fromAccount, toAccount, transaction, callContext) <- transactionRequestBodyRefundJson.to match {
|
||||
case Some(refundRequestTo) if refundRequestTo.account_id.isDefined && refundRequestTo.bank_id.isDefined =>
|
||||
val toBankId = BankId(refundRequestTo.bank_id.get)
|
||||
val toAccountId = AccountId(refundRequestTo.account_id.get)
|
||||
for {
|
||||
(transaction, callContext) <- NewStyle.function.getTransaction(fromAccount.bankId, fromAccount.accountId, transactionId, callContext)
|
||||
(toAccount, callContext) <- NewStyle.function.checkBankAccountExists(toBankId, toAccountId, callContext)
|
||||
} yield (fromAccount, toAccount, transaction, callContext)
|
||||
|
||||
(fromAccount, toAccount, transaction, callContext) <- transactionRequestBodyRefundJson.to match {
|
||||
case Some(refundRequestTo) if refundRequestTo.account_id.isDefined && refundRequestTo.bank_id.isDefined =>
|
||||
val toBankId = BankId(refundRequestTo.bank_id.get)
|
||||
val toAccountId = AccountId(refundRequestTo.account_id.get)
|
||||
for {
|
||||
(transaction, callContext) <- NewStyle.function.getTransaction(fromAccount.bankId, fromAccount.accountId, transactionId, callContext)
|
||||
(toAccount, callContext) <- NewStyle.function.checkBankAccountExists(toBankId, toAccountId, callContext)
|
||||
} yield (fromAccount, toAccount, transaction, callContext)
|
||||
case Some(refundRequestTo) if refundRequestTo.counterparty_id.isDefined =>
|
||||
val toCounterpartyId = CounterpartyId(refundRequestTo.counterparty_id.get)
|
||||
for {
|
||||
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(toCounterpartyId, callContext)
|
||||
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, isOutgoingAccount = true, callContext)
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
toCounterparty.isBeneficiary
|
||||
}
|
||||
(transaction, callContext) <- NewStyle.function.getTransaction(fromAccount.bankId, fromAccount.accountId, transactionId, callContext)
|
||||
} yield (fromAccount, toAccount, transaction, callContext)
|
||||
|
||||
case Some(refundRequestTo) if refundRequestTo.counterparty_id.isDefined =>
|
||||
val toCounterpartyId = CounterpartyId(refundRequestTo.counterparty_id.get)
|
||||
for {
|
||||
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(toCounterpartyId, callContext)
|
||||
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, isOutgoingAccount = true, callContext)
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
toCounterparty.isBeneficiary
|
||||
}
|
||||
(transaction, callContext) <- NewStyle.function.getTransaction(fromAccount.bankId, fromAccount.accountId, transactionId, callContext)
|
||||
} yield (fromAccount, toAccount, transaction, callContext)
|
||||
case None if transactionRequestBodyRefundJson.from.isDefined =>
|
||||
val fromCounterpartyId = CounterpartyId(transactionRequestBodyRefundJson.from.get.counterparty_id)
|
||||
val toAccount = fromAccount
|
||||
for {
|
||||
(fromCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(fromCounterpartyId, callContext)
|
||||
fromAccount <- NewStyle.function.getBankAccountFromCounterparty(fromCounterparty, isOutgoingAccount = false, callContext)
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
fromCounterparty.isBeneficiary
|
||||
}
|
||||
(transaction, callContext) <- NewStyle.function.getTransaction(toAccount.bankId, toAccount.accountId, transactionId, callContext)
|
||||
} yield (fromAccount, toAccount, transaction, callContext)
|
||||
}
|
||||
|
||||
case None if transactionRequestBodyRefundJson.from.isDefined =>
|
||||
val fromCounterpartyId = CounterpartyId(transactionRequestBodyRefundJson.from.get.counterparty_id)
|
||||
val toAccount = fromAccount
|
||||
for {
|
||||
(fromCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(fromCounterpartyId, callContext)
|
||||
fromAccount <- NewStyle.function.getBankAccountFromCounterparty(fromCounterparty, isOutgoingAccount = false, callContext)
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
fromCounterparty.isBeneficiary
|
||||
}
|
||||
(transaction, callContext) <- NewStyle.function.getTransaction(toAccount.bankId, toAccount.accountId, transactionId, callContext)
|
||||
} yield (fromAccount, toAccount, transaction, callContext)
|
||||
}
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodyRefundJson)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodyRefundJson)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
_ <- Helper.booleanToFuture(s"${RefundedTransaction} Current input amount is: '${transDetailsJson.value.amount}'. It can not be more than the original amount(${(transaction.amount).abs})", cc=callContext) {
|
||||
(transaction.amount).abs >= transactionAmountNumber
|
||||
}
|
||||
//TODO, we need additional field to guarantee the transaction is refunded...
|
||||
// _ <- Helper.booleanToFuture(s"${RefundedTransaction}") {
|
||||
// !((transaction.description.toString contains(" Refund to ")) && (transaction.description.toString contains(" and transaction_id(")))
|
||||
// }
|
||||
|
||||
_ <- Helper.booleanToFuture(s"${RefundedTransaction} Current input amount is: '${transDetailsJson.value.amount}'. It can not be more than the original amount(${(transaction.amount).abs})", cc=callContext) {
|
||||
(transaction.amount).abs >= transactionAmountNumber
|
||||
}
|
||||
//TODO, we need additional field to guarantee the transaction is refunded...
|
||||
// _ <- Helper.booleanToFuture(s"${RefundedTransaction}") {
|
||||
// !((transaction.description.toString contains(" Refund to ")) && (transaction.description.toString contains(" and transaction_id(")))
|
||||
// }
|
||||
//we add the extra info (counterparty name + transaction_id) for this special Refund endpoint.
|
||||
newDescription = s"${transactionRequestBodyRefundJson.description} - Refund for transaction_id: (${transactionId.value}) to ${transaction.otherAccount.counterpartyName}"
|
||||
|
||||
//we add the extra info (counterparty name + transaction_id) for this special Refund endpoint.
|
||||
newDescription = s"${transactionRequestBodyRefundJson.description} - Refund for transaction_id: (${transactionId.value}) to ${transaction.otherAccount.counterpartyName}"
|
||||
//This is the refund endpoint, the original fromAccount is the `toAccount` which will receive money.
|
||||
refundToAccount = fromAccount
|
||||
//This is the refund endpoint, the original toAccount is the `fromAccount` which will lose money.
|
||||
refundFromAccount = toAccount
|
||||
|
||||
//This is the refund endpoint, the original fromAccount is the `toAccount` which will receive money.
|
||||
refundToAccount = fromAccount
|
||||
//This is the refund endpoint, the original toAccount is the `fromAccount` which will lose money.
|
||||
refundFromAccount = toAccount
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
refundFromAccount,
|
||||
refundToAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodyRefundJson.copy(description = newDescription),
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext) //in ACCOUNT, ChargePolicy set default "SHARED"
|
||||
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
refundFromAccount,
|
||||
refundToAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodyRefundJson.copy(description = newDescription),
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext) //in ACCOUNT, ChargePolicy set default "SHARED"
|
||||
_ <- NewStyle.function.createOrUpdateTransactionRequestAttribute(
|
||||
bankId = bankId,
|
||||
transactionRequestId = createdTransactionRequest.id,
|
||||
transactionRequestAttributeId = None,
|
||||
name = "original_transaction_id",
|
||||
attributeType = TransactionRequestAttributeType.withName("STRING"),
|
||||
value = transactionId.value,
|
||||
callContext = callContext
|
||||
)
|
||||
|
||||
_ <- NewStyle.function.createOrUpdateTransactionRequestAttribute(
|
||||
refundReasonCode = transactionRequestBodyRefundJson.refund.reason_code
|
||||
_ <- if (refundReasonCode.nonEmpty) {
|
||||
NewStyle.function.createOrUpdateTransactionRequestAttribute(
|
||||
bankId = bankId,
|
||||
transactionRequestId = createdTransactionRequest.id,
|
||||
transactionRequestAttributeId = None,
|
||||
name = "original_transaction_id",
|
||||
name = "refund_reason_code",
|
||||
attributeType = TransactionRequestAttributeType.withName("STRING"),
|
||||
value = transactionId.value,
|
||||
callContext = callContext
|
||||
)
|
||||
value = refundReasonCode,
|
||||
callContext = callContext)
|
||||
} else Future.successful()
|
||||
|
||||
refundReasonCode = transactionRequestBodyRefundJson.refund.reason_code
|
||||
_ <- if (refundReasonCode.nonEmpty) {
|
||||
NewStyle.function.createOrUpdateTransactionRequestAttribute(
|
||||
bankId = bankId,
|
||||
transactionRequestId = createdTransactionRequest.id,
|
||||
transactionRequestAttributeId = None,
|
||||
name = "refund_reason_code",
|
||||
attributeType = TransactionRequestAttributeType.withName("STRING"),
|
||||
value = refundReasonCode,
|
||||
callContext = callContext)
|
||||
} else Future.successful()
|
||||
(newTransactionRequestStatus, callContext) <- NewStyle.function.notifyTransactionRequest(refundFromAccount, refundToAccount, createdTransactionRequest, callContext)
|
||||
_ <- Future(Connector.connector.vend.saveTransactionRequestStatusImpl(createdTransactionRequest.id, newTransactionRequestStatus.toString))
|
||||
createdTransactionRequest <- Future(createdTransactionRequest.copy(status = newTransactionRequestStatus.toString))
|
||||
|
||||
(newTransactionRequestStatus, callContext) <- NewStyle.function.notifyTransactionRequest(refundFromAccount, refundToAccount, createdTransactionRequest, callContext)
|
||||
_ <- Future(Connector.connector.vend.saveTransactionRequestStatusImpl(createdTransactionRequest.id, newTransactionRequestStatus.toString))
|
||||
createdTransactionRequest <- Future(createdTransactionRequest.copy(status = newTransactionRequestStatus.toString))
|
||||
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
}
|
||||
case ACCOUNT | SANDBOX_TAN => {
|
||||
for {
|
||||
transactionRequestBodySandboxTan <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $ACCOUNT json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodySandBoxTanJSON]
|
||||
}
|
||||
|
||||
toBankId = BankId(transactionRequestBodySandboxTan.to.bank_id)
|
||||
toAccountId = AccountId(transactionRequestBodySandboxTan.to.account_id)
|
||||
(toAccount, callContext) <- NewStyle.function.checkBankAccountExists(toBankId, toAccountId, callContext)
|
||||
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodySandboxTan)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodySandboxTan,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext) //in ACCOUNT, ChargePolicy set default "SHARED"
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
}
|
||||
case ACCOUNT_OTP => {
|
||||
for {
|
||||
transactionRequestBodySandboxTan <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $ACCOUNT json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodySandBoxTanJSON]
|
||||
}
|
||||
|
||||
toBankId = BankId(transactionRequestBodySandboxTan.to.bank_id)
|
||||
toAccountId = AccountId(transactionRequestBodySandboxTan.to.account_id)
|
||||
(toAccount, callContext) <- NewStyle.function.checkBankAccountExists(toBankId, toAccountId, callContext)
|
||||
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodySandboxTan)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodySandboxTan,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext) //in ACCOUNT, ChargePolicy set default "SHARED"
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
}
|
||||
case COUNTERPARTY => {
|
||||
for {
|
||||
//For COUNTERPARTY, Use the counterpartyId to find the toCounterparty and set up the toAccount
|
||||
transactionRequestBodyCounterparty <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $COUNTERPARTY json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodyCounterpartyJSON]
|
||||
}
|
||||
toCounterpartyId = transactionRequestBodyCounterparty.to.counterparty_id
|
||||
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(CounterpartyId(toCounterpartyId), callContext)
|
||||
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
|
||||
// Check we can send money to it.
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
toCounterparty.isBeneficiary
|
||||
}
|
||||
chargePolicy = transactionRequestBodyCounterparty.charge_policy
|
||||
_ <- Helper.booleanToFuture(s"$InvalidChargePolicy", cc=callContext) {
|
||||
ChargePolicy.values.contains(ChargePolicy.withName(chargePolicy))
|
||||
}
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodyCounterparty)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodyCounterparty,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext)
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
|
||||
}
|
||||
case SIMPLE => {
|
||||
for {
|
||||
//For SAMPLE, we will create/get toCounterparty on site and set up the toAccount
|
||||
transactionRequestBodySimple <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $SIMPLE json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodySimpleJsonV400]
|
||||
}
|
||||
(toCounterparty, callContext) <- NewStyle.function.getOrCreateCounterparty(
|
||||
name = transactionRequestBodySimple.to.name,
|
||||
description = transactionRequestBodySimple.to.description,
|
||||
currency = transactionRequestBodySimple.value.currency,
|
||||
createdByUserId = u.userId,
|
||||
thisBankId = bankId.value,
|
||||
thisAccountId = accountId.value,
|
||||
thisViewId = viewId.value,
|
||||
otherBankRoutingScheme = transactionRequestBodySimple.to.other_bank_routing_scheme,
|
||||
otherBankRoutingAddress = transactionRequestBodySimple.to.other_bank_routing_address,
|
||||
otherBranchRoutingScheme = transactionRequestBodySimple.to.other_branch_routing_scheme,
|
||||
otherBranchRoutingAddress = transactionRequestBodySimple.to.other_branch_routing_address,
|
||||
otherAccountRoutingScheme = transactionRequestBodySimple.to.other_account_routing_scheme,
|
||||
otherAccountRoutingAddress = transactionRequestBodySimple.to.other_account_routing_address,
|
||||
otherAccountSecondaryRoutingScheme = transactionRequestBodySimple.to.other_account_secondary_routing_scheme,
|
||||
otherAccountSecondaryRoutingAddress = transactionRequestBodySimple.to.other_account_secondary_routing_address,
|
||||
callContext: Option[CallContext],
|
||||
)
|
||||
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
|
||||
// Check we can send money to it.
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
toCounterparty.isBeneficiary
|
||||
}
|
||||
chargePolicy = transactionRequestBodySimple.charge_policy
|
||||
_ <- Helper.booleanToFuture(s"$InvalidChargePolicy", cc=callContext) {
|
||||
ChargePolicy.values.contains(ChargePolicy.withName(chargePolicy))
|
||||
}
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodySimple)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodySimple,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext)
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
|
||||
}
|
||||
case SEPA => {
|
||||
for {
|
||||
//For SEPA, Use the iban to find the toCounterparty and set up the toAccount
|
||||
transDetailsSEPAJson <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $SEPA json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodySEPAJsonV400]
|
||||
}
|
||||
toIban = transDetailsSEPAJson.to.iban
|
||||
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByIbanAndBankAccountId(toIban, fromAccount.bankId, fromAccount.accountId, callContext)
|
||||
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
toCounterparty.isBeneficiary
|
||||
}
|
||||
chargePolicy = transDetailsSEPAJson.charge_policy
|
||||
_ <- Helper.booleanToFuture(s"$InvalidChargePolicy", cc=callContext) {
|
||||
ChargePolicy.values.contains(ChargePolicy.withName(chargePolicy))
|
||||
}
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transDetailsSEPAJson)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transDetailsSEPAJson,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
transDetailsSEPAJson.reasons.map(_.map(_.transform)),
|
||||
None,
|
||||
callContext)
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
}
|
||||
case FREE_FORM => {
|
||||
for {
|
||||
transactionRequestBodyFreeForm <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $FREE_FORM json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodyFreeFormJSON]
|
||||
}
|
||||
// Following lines: just transfer the details body, add Bank_Id and Account_Id in the Detail part. This is for persistence and 'answerTransactionRequestChallenge'
|
||||
transactionRequestAccountJSON = TransactionRequestAccountJsonV140(bankId.value, accountId.value)
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodyFreeForm)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
fromAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodyFreeForm,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext)
|
||||
} yield
|
||||
(createdTransactionRequest, callContext)
|
||||
}
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
}
|
||||
case ACCOUNT | SANDBOX_TAN => {
|
||||
for {
|
||||
transactionRequestBodySandboxTan <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $ACCOUNT json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodySandBoxTanJSON]
|
||||
}
|
||||
|
||||
toBankId = BankId(transactionRequestBodySandboxTan.to.bank_id)
|
||||
toAccountId = AccountId(transactionRequestBodySandboxTan.to.account_id)
|
||||
(toAccount, callContext) <- NewStyle.function.checkBankAccountExists(toBankId, toAccountId, callContext)
|
||||
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodySandboxTan)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodySandboxTan,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext) //in ACCOUNT, ChargePolicy set default "SHARED"
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
}
|
||||
case ACCOUNT_OTP => {
|
||||
for {
|
||||
transactionRequestBodySandboxTan <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $ACCOUNT json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodySandBoxTanJSON]
|
||||
}
|
||||
|
||||
toBankId = BankId(transactionRequestBodySandboxTan.to.bank_id)
|
||||
toAccountId = AccountId(transactionRequestBodySandboxTan.to.account_id)
|
||||
(toAccount, callContext) <- NewStyle.function.checkBankAccountExists(toBankId, toAccountId, callContext)
|
||||
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodySandboxTan)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodySandboxTan,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext) //in ACCOUNT, ChargePolicy set default "SHARED"
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
}
|
||||
case COUNTERPARTY => {
|
||||
for {
|
||||
//For COUNTERPARTY, Use the counterpartyId to find the toCounterparty and set up the toAccount
|
||||
transactionRequestBodyCounterparty <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $COUNTERPARTY json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodyCounterpartyJSON]
|
||||
}
|
||||
toCounterpartyId = transactionRequestBodyCounterparty.to.counterparty_id
|
||||
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByCounterpartyId(CounterpartyId(toCounterpartyId), callContext)
|
||||
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
|
||||
// Check we can send money to it.
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
toCounterparty.isBeneficiary
|
||||
}
|
||||
chargePolicy = transactionRequestBodyCounterparty.charge_policy
|
||||
_ <- Helper.booleanToFuture(s"$InvalidChargePolicy", cc=callContext) {
|
||||
ChargePolicy.values.contains(ChargePolicy.withName(chargePolicy))
|
||||
}
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodyCounterparty)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodyCounterparty,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext)
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
|
||||
}
|
||||
case SIMPLE => {
|
||||
for {
|
||||
//For SAMPLE, we will create/get toCounterparty on site and set up the toAccount
|
||||
transactionRequestBodySimple <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $SIMPLE json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodySimpleJsonV400]
|
||||
}
|
||||
(toCounterparty, callContext) <- NewStyle.function.getOrCreateCounterparty(
|
||||
name = transactionRequestBodySimple.to.name,
|
||||
description = transactionRequestBodySimple.to.description,
|
||||
currency = transactionRequestBodySimple.value.currency,
|
||||
createdByUserId = u.userId,
|
||||
thisBankId = bankId.value,
|
||||
thisAccountId = accountId.value,
|
||||
thisViewId = viewId.value,
|
||||
otherBankRoutingScheme = transactionRequestBodySimple.to.other_bank_routing_scheme,
|
||||
otherBankRoutingAddress = transactionRequestBodySimple.to.other_bank_routing_address,
|
||||
otherBranchRoutingScheme = transactionRequestBodySimple.to.other_branch_routing_scheme,
|
||||
otherBranchRoutingAddress = transactionRequestBodySimple.to.other_branch_routing_address,
|
||||
otherAccountRoutingScheme = transactionRequestBodySimple.to.other_account_routing_scheme,
|
||||
otherAccountRoutingAddress = transactionRequestBodySimple.to.other_account_routing_address,
|
||||
otherAccountSecondaryRoutingScheme = transactionRequestBodySimple.to.other_account_secondary_routing_scheme,
|
||||
otherAccountSecondaryRoutingAddress = transactionRequestBodySimple.to.other_account_secondary_routing_address,
|
||||
callContext: Option[CallContext],
|
||||
)
|
||||
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
|
||||
// Check we can send money to it.
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
toCounterparty.isBeneficiary
|
||||
}
|
||||
chargePolicy = transactionRequestBodySimple.charge_policy
|
||||
_ <- Helper.booleanToFuture(s"$InvalidChargePolicy", cc=callContext) {
|
||||
ChargePolicy.values.contains(ChargePolicy.withName(chargePolicy))
|
||||
}
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodySimple)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodySimple,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext)
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
|
||||
}
|
||||
case SEPA => {
|
||||
for {
|
||||
//For SEPA, Use the iban to find the toCounterparty and set up the toAccount
|
||||
transDetailsSEPAJson <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $SEPA json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodySEPAJsonV400]
|
||||
}
|
||||
toIban = transDetailsSEPAJson.to.iban
|
||||
(toCounterparty, callContext) <- NewStyle.function.getCounterpartyByIbanAndBankAccountId(toIban, fromAccount.bankId, fromAccount.accountId, callContext)
|
||||
toAccount <- NewStyle.function.getBankAccountFromCounterparty(toCounterparty, true, callContext)
|
||||
_ <- Helper.booleanToFuture(s"$CounterpartyBeneficiaryPermit", cc=callContext) {
|
||||
toCounterparty.isBeneficiary
|
||||
}
|
||||
chargePolicy = transDetailsSEPAJson.charge_policy
|
||||
_ <- Helper.booleanToFuture(s"$InvalidChargePolicy", cc=callContext) {
|
||||
ChargePolicy.values.contains(ChargePolicy.withName(chargePolicy))
|
||||
}
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transDetailsSEPAJson)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
toAccount,
|
||||
transactionRequestType,
|
||||
transDetailsSEPAJson,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
transDetailsSEPAJson.reasons.map(_.map(_.transform)),
|
||||
None,
|
||||
callContext)
|
||||
} yield (createdTransactionRequest, callContext)
|
||||
}
|
||||
case FREE_FORM => {
|
||||
for {
|
||||
transactionRequestBodyFreeForm <- NewStyle.function.tryons(s"${InvalidJsonFormat}, it should be $FREE_FORM json format", 400, callContext) {
|
||||
json.extract[TransactionRequestBodyFreeFormJSON]
|
||||
}
|
||||
// Following lines: just transfer the details body, add Bank_Id and Account_Id in the Detail part. This is for persistence and 'answerTransactionRequestChallenge'
|
||||
transactionRequestAccountJSON = TransactionRequestAccountJsonV140(bankId.value, accountId.value)
|
||||
transDetailsSerialized <- NewStyle.function.tryons(UnknownError, 400, callContext) {
|
||||
write(transactionRequestBodyFreeForm)(Serialization.formats(NoTypeHints))
|
||||
}
|
||||
(createdTransactionRequest, callContext) <- NewStyle.function.createTransactionRequestv400(u,
|
||||
viewId,
|
||||
fromAccount,
|
||||
fromAccount,
|
||||
transactionRequestType,
|
||||
transactionRequestBodyFreeForm,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OBP_TRANSACTION_REQUEST_CHALLENGE),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
callContext)
|
||||
} yield
|
||||
(createdTransactionRequest, callContext)
|
||||
}
|
||||
(challenges, callContext) <- NewStyle.function.getChallengesByTransactionRequestId(createdTransactionRequest.id.value, callContext)
|
||||
} yield {
|
||||
(JSONFactory400.createTransactionRequestWithChargeJSON(createdTransactionRequest, challenges), HttpCode.`201`(callContext))
|
||||
}
|
||||
}
|
||||
(challenges, callContext) <- NewStyle.function.getChallengesByTransactionRequestId(createdTransactionRequest.id.value, callContext)
|
||||
} yield {
|
||||
(JSONFactory400.createTransactionRequestWithChargeJSON(createdTransactionRequest, challenges), HttpCode.`201`(callContext))
|
||||
}
|
||||
}
|
||||
|
||||
lazy val createTransactionRequestAccount: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transaction-request-types" ::
|
||||
"ACCOUNT" :: "transaction-requests" :: Nil JsonPost json -> _ =>
|
||||
cc =>
|
||||
val transactionRequestType = TransactionRequestType("ACCOUNT")
|
||||
createTransactionRequest(bankId, accountId, viewId , transactionRequestType, json)
|
||||
}
|
||||
|
||||
lazy val createTransactionRequestAccountOtp: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transaction-request-types" ::
|
||||
"ACCOUNT_OTP" :: "transaction-requests" :: Nil JsonPost json -> _ =>
|
||||
cc =>
|
||||
val transactionRequestType = TransactionRequestType("ACCOUNT_OTP")
|
||||
createTransactionRequest(bankId, accountId, viewId , transactionRequestType, json)
|
||||
}
|
||||
|
||||
lazy val createTransactionRequestSepa: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transaction-request-types" ::
|
||||
"SEPA" :: "transaction-requests" :: Nil JsonPost json -> _ =>
|
||||
cc =>
|
||||
val transactionRequestType = TransactionRequestType("SEPA")
|
||||
createTransactionRequest(bankId, accountId, viewId , transactionRequestType, json)
|
||||
}
|
||||
|
||||
lazy val createTransactionRequestCounterparty: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transaction-request-types" ::
|
||||
"COUNTERPARTY" :: "transaction-requests" :: Nil JsonPost json -> _ =>
|
||||
cc =>
|
||||
val transactionRequestType = TransactionRequestType("COUNTERPARTY")
|
||||
createTransactionRequest(bankId, accountId, viewId , transactionRequestType, json)
|
||||
}
|
||||
|
||||
lazy val createTransactionRequestRefund: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transaction-request-types" ::
|
||||
"REFUND" :: "transaction-requests" :: Nil JsonPost json -> _ =>
|
||||
cc =>
|
||||
val transactionRequestType = TransactionRequestType("REFUND")
|
||||
createTransactionRequest(bankId, accountId, viewId , transactionRequestType, json)
|
||||
}
|
||||
|
||||
lazy val createTransactionRequestFreeForm: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transaction-request-types" ::
|
||||
"FREE_FORM" :: "transaction-requests" :: Nil JsonPost json -> _ =>
|
||||
cc =>
|
||||
val transactionRequestType = TransactionRequestType("FREE_FORM")
|
||||
createTransactionRequest(bankId, accountId, viewId , transactionRequestType, json)
|
||||
}
|
||||
|
||||
lazy val createTransactionRequestSimple: OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transaction-request-types" ::
|
||||
"SIMPLE" :: "transaction-requests" :: Nil JsonPost json -> _ =>
|
||||
cc =>
|
||||
val transactionRequestType = TransactionRequestType("SIMPLE")
|
||||
createTransactionRequest(bankId, accountId, viewId , transactionRequestType, json)
|
||||
}
|
||||
|
||||
|
||||
@ -8322,7 +8365,7 @@ trait APIMethods400 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
addConsentUser,
|
||||
implementedInApiVersion,
|
||||
@ -11471,8 +11514,7 @@ trait APIMethods400 {
|
||||
EmptyBody,
|
||||
atmsJsonV400,
|
||||
List(
|
||||
$UserNotLoggedIn,
|
||||
InvalidJsonFormat,
|
||||
$BankNotFound,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagATM, apiTagNewStyle)
|
||||
@ -12435,7 +12477,7 @@ trait APIMethods400 {
|
||||
DynamicEndpointHelper.getRoles(dynamicEndpointInfo)
|
||||
}
|
||||
_ <- NewStyle.function.tryons(InvalidJsonFormat+"Can not generate OBP external Resource Docs", 400, cc.callContext) {
|
||||
JSONFactory1_4_0.createResourceDocsJson(dynamicEndpointInfo.resourceDocs.toList, false)
|
||||
JSONFactory1_4_0.createResourceDocsJson(dynamicEndpointInfo.resourceDocs.toList, false, None)
|
||||
}
|
||||
(dynamicEndpoint, callContext) <- NewStyle.function.createDynamicEndpoint(bankId, cc.userId, postedJson.swaggerString, cc.callContext)
|
||||
_ <- NewStyle.function.tryons(InvalidJsonFormat+s"Can not grant these roles ${roles.toString} ", 400, cc.callContext) {
|
||||
|
||||
@ -69,7 +69,6 @@ import scala.collection.immutable.List
|
||||
import scala.math.BigDecimal
|
||||
import scala.util.Try
|
||||
|
||||
|
||||
case class CallLimitPostJsonV400(
|
||||
from_date : Date,
|
||||
to_date : Date,
|
||||
|
||||
@ -51,7 +51,7 @@ object OBPAPI4_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
|
||||
val version : ApiVersion = ApiVersion.v4_0_0
|
||||
|
||||
val versionStatus = "BLEEDING-EDGE" // TODO this should be a property of ApiVersion.
|
||||
val versionStatus = "DRAFT" // TODO this should be a property of ApiVersion.
|
||||
|
||||
// Possible Endpoints from 4.0.0, exclude one endpoint use - method,exclude multiple endpoints use -- method,
|
||||
// e.g getEndpoints(Implementations4_0_0) -- List(Implementations4_0_0.genericEndpoint, Implementations4_0_0.root)
|
||||
@ -81,7 +81,7 @@ object OBPAPI4_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
|
||||
// register v4.0.0 apis first, Make them available for use!
|
||||
registerRoutes(routes, allResourceDocs, apiPrefix, true)
|
||||
|
||||
logger.info(s"version $version has been run! There are ${routes.length} routes.")
|
||||
logger.info(s"version $version has been run! There are ${routes.length} routes, ${allResourceDocs.length} allResourceDocs.")
|
||||
|
||||
// specified response for OPTIONS request.
|
||||
private val corsResponse: Box[LiftResponse] = Full{
|
||||
|
||||
@ -5,28 +5,51 @@ import code.api.util.APIUtil._
|
||||
import code.api.util.ApiRole.{CanCreateUserAuthContextUpdate, canCreateUserAuthContext, canGetUserAuthContext}
|
||||
import code.api.util.ApiTag._
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.util.{ApiRole, NewStyle}
|
||||
import code.api.util.{APIUtil, ApiRole, Consent, NewStyle}
|
||||
import code.api.util.NewStyle.HttpCode
|
||||
import code.api.v3_1_0.{PostUserAuthContextJson, PostUserAuthContextUpdateJsonV310}
|
||||
import code.api.v3_1_0.{PostConsentBodyCommonJson, PostConsentEmailJsonV310, PostConsentEntitlementJsonV310, PostConsentPhoneJsonV310, PostConsentViewJsonV310, PostUserAuthContextJson, PostUserAuthContextUpdateJsonV310}
|
||||
import code.bankconnectors.Connector
|
||||
import code.consent.{ConsentRequests, Consents}
|
||||
import code.entitlement.Entitlement
|
||||
import code.transactionrequests.TransactionRequests.TransactionRequestTypes.{apply => _}
|
||||
import code.util.Helper
|
||||
import code.views.Views
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
import com.openbankproject.commons.ExecutionContext.Implicits.global
|
||||
import com.openbankproject.commons.model.{BankId, UserAuthContextUpdateStatus}
|
||||
import com.openbankproject.commons.model.enums.StrongCustomerAuthentication
|
||||
import com.openbankproject.commons.util.ApiVersion
|
||||
import net.liftweb.common.Full
|
||||
import net.liftweb.common.{Full}
|
||||
import net.liftweb.http.{Req}
|
||||
import net.liftweb.http.rest.RestHelper
|
||||
import net.liftweb.json
|
||||
import net.liftweb.json.compactRender
|
||||
import net.liftweb.util.Props
|
||||
|
||||
import scala.collection.immutable.{List, Nil}
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import scala.concurrent.Future
|
||||
import scala.util.Random
|
||||
|
||||
trait APIMethods500 {
|
||||
self: RestHelper =>
|
||||
|
||||
val Implementations5_0_0 = new Implementations500()
|
||||
|
||||
protected trait TestHead {
|
||||
/**
|
||||
* Test to see if the request is a GET and expecting JSON in the response.
|
||||
* The path and the Req instance are extracted.
|
||||
*/
|
||||
def unapply(r: Req): Option[(List[String], Req)] =
|
||||
if (r.requestType.head_? && testResponse_?(r))
|
||||
Some(r.path.partPath -> r) else None
|
||||
|
||||
def testResponse_?(r: Req): Boolean
|
||||
}
|
||||
|
||||
lazy val JsonHead = new TestHead with JsonTest
|
||||
|
||||
class Implementations500 {
|
||||
|
||||
val implementedInApiVersion = ApiVersion.v5_0_0
|
||||
@ -69,7 +92,7 @@ trait APIMethods500 {
|
||||
json.extract[PostUserAuthContextJson]
|
||||
}
|
||||
(user, callContext) <- NewStyle.function.findByUserId(userId, callContext)
|
||||
(userAuthContext, callContext) <- NewStyle.function.createUserAuthContext(user, postedData.key, postedData.value, callContext)
|
||||
(userAuthContext, callContext) <- NewStyle.function.createUserAuthContext(user, postedData.key.trim, postedData.value.trim, callContext)
|
||||
} yield {
|
||||
(JSONFactory500.createUserAuthContextJson(userAuthContext), HttpCode.`201`(callContext))
|
||||
}
|
||||
@ -90,7 +113,7 @@ trait APIMethods500 {
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|""",
|
||||
emptyObjectJson,
|
||||
EmptyBody,
|
||||
userAuthContextJsonV500,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
@ -132,6 +155,7 @@ trait APIMethods500 {
|
||||
userAuthContextUpdateJsonV500,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
$BankNotFound,
|
||||
InvalidJsonFormat,
|
||||
CreateUserAuthContextError,
|
||||
UnknownError
|
||||
@ -148,7 +172,6 @@ trait APIMethods500 {
|
||||
_ <- Helper.booleanToFuture(failMsg = ConsumerHasMissingRoles + CanCreateUserAuthContextUpdate, cc=callContext) {
|
||||
checkScope(bankId.value, getConsumerPrimaryKey(callContext), ApiRole.canCreateUserAuthContextUpdate)
|
||||
}
|
||||
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
|
||||
_ <- Helper.booleanToFuture(ConsentAllowedScaMethods, cc=callContext){
|
||||
List(StrongCustomerAuthentication.SMS.toString(), StrongCustomerAuthentication.EMAIL.toString()).exists(_ == scaMethod)
|
||||
}
|
||||
@ -156,7 +179,7 @@ trait APIMethods500 {
|
||||
postedData <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
json.extract[PostUserAuthContextJson]
|
||||
}
|
||||
(userAuthContextUpdate, callContext) <- NewStyle.function.validateUserAuthContextUpdateRequest(bankId.value, user.userId, postedData.key, postedData.value, scaMethod, callContext)
|
||||
(userAuthContextUpdate, callContext) <- NewStyle.function.validateUserAuthContextUpdateRequest(bankId.value, user.userId, postedData.key.trim, postedData.value.trim, scaMethod, callContext)
|
||||
} yield {
|
||||
|
||||
(JSONFactory500.createUserAuthContextUpdateJson(userAuthContextUpdate), HttpCode.`201`(callContext))
|
||||
@ -170,15 +193,15 @@ trait APIMethods500 {
|
||||
nameOf(answerUserAuthContextUpdateChallenge),
|
||||
"POST",
|
||||
"/banks/BANK_ID/users/current/auth-context-updates/AUTH_CONTEXT_UPDATE_ID/challenge",
|
||||
"Answer Auth Context Update Challenge",
|
||||
"Answer User Auth Context Update Challenge",
|
||||
s"""
|
||||
|Answer Auth Context Update Challenge.
|
||||
|Answer User Auth Context Update Challenge.
|
||||
|""",
|
||||
postUserAuthContextUpdateJsonV310,
|
||||
userAuthContextUpdateJsonV500,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
BankNotFound,
|
||||
$BankNotFound,
|
||||
InvalidJsonFormat,
|
||||
InvalidConnectorResponse,
|
||||
UnknownError
|
||||
@ -201,8 +224,8 @@ trait APIMethods500 {
|
||||
case status if status == UserAuthContextUpdateStatus.ACCEPTED.toString =>
|
||||
NewStyle.function.createUserAuthContext(
|
||||
user,
|
||||
userAuthContextUpdate.key,
|
||||
userAuthContextUpdate.value,
|
||||
userAuthContextUpdate.key.trim,
|
||||
userAuthContextUpdate.value.trim,
|
||||
callContext).map(x => (Some(x._1), x._2))
|
||||
case _ =>
|
||||
Future((None, callContext))
|
||||
@ -224,7 +247,373 @@ trait APIMethods500 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
createConsentRequest,
|
||||
implementedInApiVersion,
|
||||
nameOf(createConsentRequest),
|
||||
"POST",
|
||||
"/consumer/consent-requests",
|
||||
"Create Consent Request",
|
||||
s"""""",
|
||||
postConsentRequestJsonV500,
|
||||
consentRequestResponseJson,
|
||||
List(
|
||||
$BankNotFound,
|
||||
InvalidJsonFormat,
|
||||
ConsentMaxTTL,
|
||||
UnknownError
|
||||
),
|
||||
apiTagConsent :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil
|
||||
)
|
||||
|
||||
lazy val createConsentRequest : OBPEndpoint = {
|
||||
case "consumer" :: "consent-requests" :: Nil JsonPost json -> _ => {
|
||||
cc =>
|
||||
for {
|
||||
(_, callContext) <- applicationAccess(cc)
|
||||
_ <- passesPsd2Aisp(callContext)
|
||||
failMsg = s"$InvalidJsonFormat The Json body should be the $PostConsentBodyCommonJson "
|
||||
consentJson: PostConsentRequestJsonV500 <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
json.extract[PostConsentRequestJsonV500]
|
||||
}
|
||||
maxTimeToLive = APIUtil.getPropsAsIntValue(nameOfProperty="consents.max_time_to_live", defaultValue=3600)
|
||||
_ <- Helper.booleanToFuture(s"$ConsentMaxTTL ($maxTimeToLive)", cc=callContext){
|
||||
consentJson.time_to_live match {
|
||||
case Some(ttl) => ttl <= maxTimeToLive
|
||||
case _ => true
|
||||
}
|
||||
}
|
||||
createdConsentRequest <- Future(ConsentRequests.consentRequestProvider.vend.createConsentRequest(
|
||||
callContext.flatMap(_.consumer),
|
||||
Some(compactRender(json))
|
||||
)) map {
|
||||
i => connectorEmptyResponse(i, callContext)
|
||||
}
|
||||
} yield {
|
||||
(
|
||||
ConsentRequestResponseJson(
|
||||
createdConsentRequest.consentRequestId,
|
||||
net.liftweb.json.parse(createdConsentRequest.payload),
|
||||
createdConsentRequest.consumerId,
|
||||
),
|
||||
HttpCode.`201`(callContext)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
getConsentRequest,
|
||||
implementedInApiVersion,
|
||||
nameOf(getConsentRequest),
|
||||
"GET",
|
||||
"/consumer/consent-requests/CONSENT_REQUEST_ID",
|
||||
"Get Consent Request",
|
||||
s"""""",
|
||||
EmptyBody,
|
||||
consentRequestResponseJson,
|
||||
List(
|
||||
$BankNotFound,
|
||||
ConsentRequestNotFound,
|
||||
UnknownError
|
||||
),
|
||||
apiTagConsent :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil
|
||||
)
|
||||
|
||||
lazy val getConsentRequest : OBPEndpoint = {
|
||||
case "consumer" :: "consent-requests" :: consentRequestId :: Nil JsonGet _ => {
|
||||
cc =>
|
||||
for {
|
||||
(_, callContext) <- applicationAccess(cc)
|
||||
_ <- passesPsd2Aisp(callContext)
|
||||
createdConsentRequest <- Future(ConsentRequests.consentRequestProvider.vend.getConsentRequestById(
|
||||
consentRequestId
|
||||
)) map {
|
||||
i => unboxFullOrFail(i,callContext, ConsentRequestNotFound)
|
||||
}
|
||||
} yield {
|
||||
(ConsentRequestResponseJson(
|
||||
consent_request_id = createdConsentRequest.consentRequestId,
|
||||
payload = json.parse(createdConsentRequest.payload),
|
||||
consumer_id = createdConsentRequest.consumerId
|
||||
),
|
||||
HttpCode.`200`(callContext)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
getConsentByConsentRequestId,
|
||||
implementedInApiVersion,
|
||||
nameOf(getConsentByConsentRequestId),
|
||||
"GET",
|
||||
"/consumer/consent-requests/CONSENT_REQUEST_ID/consents",
|
||||
"Get Consent By Consent Request Id",
|
||||
s"""
|
||||
|
|
||||
|This endpoint gets the Consent By consent request id.
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
""".stripMargin,
|
||||
EmptyBody,
|
||||
consentJsonV500,
|
||||
List(
|
||||
$UserNotLoggedIn,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagConsent, apiTagPSD2AIS, apiTagPsd2, apiTagNewStyle))
|
||||
lazy val getConsentByConsentRequestId: OBPEndpoint = {
|
||||
case "consumer" :: "consent-requests" :: consentRequestId :: "consents" :: Nil JsonGet _ => {
|
||||
cc =>
|
||||
for {
|
||||
(_, callContext) <- applicationAccess(cc)
|
||||
consent<- Future { Consents.consentProvider.vend.getConsentByConsentRequestId(consentRequestId)} map {
|
||||
unboxFullOrFail(_, callContext, ConsentRequestNotFound)
|
||||
}
|
||||
} yield {
|
||||
(
|
||||
ConsentJsonV500(
|
||||
consent.consentId,
|
||||
consent.jsonWebToken,
|
||||
consent.status,
|
||||
Some(consent.consentRequestId)
|
||||
),
|
||||
HttpCode.`200`(cc)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
createConsentByConsentRequestIdEmail,
|
||||
implementedInApiVersion,
|
||||
nameOf(createConsentByConsentRequestIdEmail),
|
||||
"POST",
|
||||
"/consumer/consent-requests/CONSENT_REQUEST_ID/EMAIL/consents",
|
||||
"Create Consent By Request Id(EMAIL)",
|
||||
s"""
|
||||
|
|
||||
|This endpoint starts the process of creating a Consent by consent request id.
|
||||
|
|
||||
|""",
|
||||
EmptyBody,
|
||||
consentJsonV500,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
BankNotFound,
|
||||
InvalidJsonFormat,
|
||||
ConsentAllowedScaMethods,
|
||||
RolesAllowedInConsent,
|
||||
ViewsAllowedInConsent,
|
||||
ConsumerNotFoundByConsumerId,
|
||||
ConsumerIsDisabled,
|
||||
InvalidConnectorResponse,
|
||||
UnknownError
|
||||
),
|
||||
apiTagConsent :: apiTagPSD2AIS :: apiTagPsd2 :: apiTagNewStyle :: Nil)
|
||||
staticResourceDocs += ResourceDoc(
|
||||
createConsentByConsentRequestIdSms,
|
||||
implementedInApiVersion,
|
||||
nameOf(createConsentByConsentRequestIdSms),
|
||||
"POST",
|
||||
"/consumer/consent-requests/CONSENT_REQUEST_ID/SMS/consents",
|
||||
"Create Consent By Request Id (SMS)",
|
||||
s"""
|
||||
|
|
||||
|This endpoint starts the process of creating a Consent.
|
||||
|
|
||||
|""",
|
||||
EmptyBody,
|
||||
consentJsonV500,
|
||||
List(
|
||||
UserNotLoggedIn,
|
||||
$BankNotFound,
|
||||
InvalidJsonFormat,
|
||||
ConsentAllowedScaMethods,
|
||||
RolesAllowedInConsent,
|
||||
ViewsAllowedInConsent,
|
||||
ConsumerNotFoundByConsumerId,
|
||||
ConsumerIsDisabled,
|
||||
MissingPropsValueAtThisInstance,
|
||||
SmsServerNotResponding,
|
||||
InvalidConnectorResponse,
|
||||
UnknownError
|
||||
),
|
||||
apiTagConsent :: apiTagPSD2AIS :: apiTagPsd2 ::apiTagNewStyle :: Nil)
|
||||
|
||||
lazy val createConsentByConsentRequestIdEmail = createConsentByConsentRequestId
|
||||
lazy val createConsentByConsentRequestIdSms = createConsentByConsentRequestId
|
||||
|
||||
lazy val createConsentByConsentRequestId : OBPEndpoint = {
|
||||
case "consumer" :: "consent-requests":: consentRequestId :: scaMethod :: "consents" :: Nil JsonPost _ -> _ => {
|
||||
cc =>
|
||||
for {
|
||||
(Full(user), callContext) <- authenticatedAccess(cc)
|
||||
createdConsentRequest <- Future(ConsentRequests.consentRequestProvider.vend.getConsentRequestById(
|
||||
consentRequestId
|
||||
)) map {
|
||||
i => unboxFullOrFail(i,callContext, ConsentRequestNotFound)
|
||||
}
|
||||
_ <- Helper.booleanToFuture(ConsentRequestAlreadyUsed, cc=callContext){
|
||||
Consents.consentProvider.vend.getConsentByConsentRequestId(consentRequestId).isEmpty
|
||||
}
|
||||
_ <- Helper.booleanToFuture(ConsentAllowedScaMethods, cc=callContext){
|
||||
List(StrongCustomerAuthentication.SMS.toString(), StrongCustomerAuthentication.EMAIL.toString()).exists(_ == scaMethod)
|
||||
}
|
||||
failMsg = s"$InvalidJsonFormat The Json body should be the $PostConsentBodyCommonJson "
|
||||
consentRequestJson <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
json.parse(createdConsentRequest.payload).extract[PostConsentRequestJsonV500]
|
||||
}
|
||||
maxTimeToLive = APIUtil.getPropsAsIntValue(nameOfProperty="consents.max_time_to_live", defaultValue=3600)
|
||||
_ <- Helper.booleanToFuture(s"$ConsentMaxTTL ($maxTimeToLive)", cc=callContext){
|
||||
consentRequestJson.time_to_live match {
|
||||
case Some(ttl) => ttl <= maxTimeToLive
|
||||
case _ => true
|
||||
}
|
||||
}
|
||||
requestedEntitlements = consentRequestJson.entitlements.getOrElse(Nil)
|
||||
myEntitlements <- Entitlement.entitlement.vend.getEntitlementsByUserIdFuture(user.userId)
|
||||
_ <- Helper.booleanToFuture(RolesAllowedInConsent, cc=callContext){
|
||||
requestedEntitlements.forall(
|
||||
re => myEntitlements.getOrElse(Nil).exists(
|
||||
e => e.roleName == re.role_name && e.bankId == re.bank_id
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
postConsentViewJsons <- Future.sequence(
|
||||
consentRequestJson.account_access.map(
|
||||
access =>
|
||||
NewStyle.function.getBankAccountByRouting(None,access.account_routing.scheme, access.account_routing.address, cc.callContext)
|
||||
.map(result =>PostConsentViewJsonV310(
|
||||
result._1.bankId.value,
|
||||
result._1.accountId.value,
|
||||
access.view_id
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
(_, assignedViews) <- Future(Views.views.vend.privateViewsUserCanAccess(user))
|
||||
_ <- Helper.booleanToFuture(ViewsAllowedInConsent, cc=callContext){
|
||||
postConsentViewJsons.forall(
|
||||
rv => assignedViews.exists{
|
||||
e =>
|
||||
e.view_id == rv.view_id &&
|
||||
e.bank_id == rv.bank_id &&
|
||||
e.account_id == rv.account_id
|
||||
}
|
||||
)
|
||||
}
|
||||
(consumerId, applicationText) <- consentRequestJson.consumer_id match {
|
||||
case Some(id) => NewStyle.function.checkConsumerByConsumerId(id, callContext) map {
|
||||
c => (Some(c.consumerId.get), c.description)
|
||||
}
|
||||
case None => Future(None, "Any application")
|
||||
}
|
||||
|
||||
challengeAnswer = Props.mode match {
|
||||
case Props.RunModes.Test => Consent.challengeAnswerAtTestEnvironment
|
||||
case _ => Random.nextInt(99999999).toString()
|
||||
}
|
||||
createdConsent <- Future(Consents.consentProvider.vend.createObpConsent(user, challengeAnswer, Some(consentRequestId))) map {
|
||||
i => connectorEmptyResponse(i, callContext)
|
||||
}
|
||||
|
||||
postConsentBodyCommonJson = PostConsentBodyCommonJson(
|
||||
everything = consentRequestJson.everything,
|
||||
views = postConsentViewJsons,
|
||||
entitlements = consentRequestJson.entitlements.getOrElse(Nil),
|
||||
consumer_id = consentRequestJson.consumer_id,
|
||||
consent_request_id = Some(consentRequestId),
|
||||
valid_from = consentRequestJson.valid_from,
|
||||
time_to_live = consentRequestJson.time_to_live,
|
||||
)
|
||||
|
||||
consentJWT = Consent.createConsentJWT(
|
||||
user,
|
||||
postConsentBodyCommonJson,
|
||||
createdConsent.secret,
|
||||
createdConsent.consentId,
|
||||
consumerId,
|
||||
postConsentBodyCommonJson.valid_from,
|
||||
postConsentBodyCommonJson.time_to_live.getOrElse(3600)
|
||||
)
|
||||
_ <- Future(Consents.consentProvider.vend.setJsonWebToken(createdConsent.consentId, consentJWT)) map {
|
||||
i => connectorEmptyResponse(i, callContext)
|
||||
}
|
||||
challengeText = s"Your consent challenge : ${challengeAnswer}, Application: $applicationText"
|
||||
_ <- scaMethod match {
|
||||
case v if v == StrongCustomerAuthentication.EMAIL.toString => // Send the email
|
||||
for{
|
||||
failMsg <- Future {s"$InvalidJsonFormat The Json body should be the $PostConsentEmailJsonV310"}
|
||||
consentScaEmail <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
consentRequestJson.email.head
|
||||
}
|
||||
(Full(status), callContext) <- Connector.connector.vend.sendCustomerNotification(
|
||||
StrongCustomerAuthentication.EMAIL,
|
||||
consentScaEmail,
|
||||
Some("OBP Consent Challenge"),
|
||||
challengeText,
|
||||
callContext
|
||||
)
|
||||
} yield Future{status}
|
||||
case v if v == StrongCustomerAuthentication.SMS.toString => // Not implemented
|
||||
for {
|
||||
failMsg <- Future {
|
||||
s"$InvalidJsonFormat The Json body should be the $PostConsentPhoneJsonV310"
|
||||
}
|
||||
consentScaPhoneNumber <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
consentRequestJson.phone_number.head
|
||||
}
|
||||
(Full(status), callContext) <- Connector.connector.vend.sendCustomerNotification(
|
||||
StrongCustomerAuthentication.SMS,
|
||||
consentScaPhoneNumber,
|
||||
None,
|
||||
challengeText,
|
||||
callContext
|
||||
)
|
||||
} yield Future{status}
|
||||
case _ =>Future{"Success"}
|
||||
}
|
||||
} yield {
|
||||
(ConsentJsonV500(createdConsent.consentId, consentJWT, createdConsent.status, Some(createdConsent.consentRequestId)), HttpCode.`201`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
headAtms,
|
||||
implementedInApiVersion,
|
||||
nameOf(headAtms),
|
||||
"HEAD",
|
||||
"/banks/BANK_ID/atms",
|
||||
"Head Bank ATMS",
|
||||
s"""Head Bank ATMS.""",
|
||||
EmptyBody,
|
||||
atmsJsonV400,
|
||||
List(
|
||||
$BankNotFound,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagATM, apiTagNewStyle)
|
||||
)
|
||||
lazy val headAtms : OBPEndpoint = {
|
||||
case "banks" :: BankId(bankId) :: "atms" :: Nil JsonHead _ => {
|
||||
cc =>
|
||||
for {
|
||||
(_, callContext) <- getAtmsIsPublic match {
|
||||
case false => authenticatedAccess(cc)
|
||||
case true => anonymousAccess(cc)
|
||||
}
|
||||
} yield {
|
||||
("", HttpCode.`200`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,9 +26,12 @@
|
||||
*/
|
||||
package code.api.v5_0_0
|
||||
|
||||
import com.openbankproject.commons.model.{UserAuthContext, UserAuthContextUpdate}
|
||||
import code.api.v3_1_0.{PostConsentEntitlementJsonV310}
|
||||
import com.openbankproject.commons.model.{AccountRoutingJsonV121, UserAuthContext, UserAuthContextUpdate}
|
||||
import net.liftweb.json.JsonAST.JValue
|
||||
|
||||
import java.util.Date
|
||||
import scala.collection.immutable.List
|
||||
|
||||
case class UserAuthContextJsonV500(
|
||||
user_auth_context_id: String,
|
||||
@ -52,6 +55,33 @@ case class UserAuthContextUpdateJsonV500(
|
||||
consumer_id: String,
|
||||
)
|
||||
|
||||
|
||||
case class PostConsentRequestResponseJson(consentRequestId: String)
|
||||
|
||||
case class ConsentRequestResponseJson(
|
||||
consent_request_id: String,
|
||||
payload : JValue,
|
||||
consumer_id : String
|
||||
)
|
||||
case class AccountAccessV500(
|
||||
// bank_routing: Option[BankRoutingJsonV121],
|
||||
// branch_routing: Option[BranchRoutingJsonV141],
|
||||
account_routing: AccountRoutingJsonV121,
|
||||
view_id: String
|
||||
)
|
||||
|
||||
case class PostConsentRequestJsonV500(
|
||||
everything: Boolean,
|
||||
account_access: List[AccountAccessV500],
|
||||
entitlements: Option[List[PostConsentEntitlementJsonV310]],
|
||||
consumer_id: Option[String],
|
||||
email: Option[String],
|
||||
phone_number: Option[String],
|
||||
valid_from: Option[Date],
|
||||
time_to_live: Option[Long]
|
||||
)
|
||||
|
||||
case class ConsentJsonV500(consent_id: String, jwt: String, status: String, consent_request_id: Option[String])
|
||||
object JSONFactory500 {
|
||||
|
||||
def createUserAuthContextJson(userAuthContext: UserAuthContext): UserAuthContextJsonV500 = {
|
||||
|
||||
@ -81,14 +81,13 @@ object OBPAPI5_0_0 extends OBPRestHelper
|
||||
private val endpoints: List[OBPEndpoint] = OBPAPI4_0_0.routes ++ endpointsOf5_0_0
|
||||
|
||||
// Filter the possible endpoints by the disabled / enabled Props settings and add them together
|
||||
val routes : List[OBPEndpoint] = Implementations4_0_0.root :: // For now we make this mandatory
|
||||
getAllowedEndpoints(endpoints, allResourceDocs)
|
||||
val routes : List[OBPEndpoint] = getAllowedEndpoints(endpoints, allResourceDocs)
|
||||
|
||||
// register v5.0.0 apis first, Make them available for use!
|
||||
registerRoutes(routes, allResourceDocs, apiPrefix, true)
|
||||
|
||||
|
||||
logger.info(s"version $version has been run! There are ${routes.length} routes.")
|
||||
logger.info(s"version $version has been run! There are ${routes.length} routes, ${allResourceDocs.length} allResourceDocs.")
|
||||
|
||||
// specified response for OPTIONS request.
|
||||
private val corsResponse: Box[LiftResponse] = Full{
|
||||
|
||||
@ -37,7 +37,7 @@ object BankAttributeProvider extends BankAttributeProviderTrait {
|
||||
attribute.BankId_(bankId.value)
|
||||
.Name(name)
|
||||
.Type(attributType.toString)
|
||||
.Value(value)
|
||||
.`Value`(value)
|
||||
.IsActive(isActive.getOrElse(true))
|
||||
.saveMe()
|
||||
}
|
||||
@ -50,7 +50,7 @@ object BankAttributeProvider extends BankAttributeProviderTrait {
|
||||
.BankId_(bankId.value)
|
||||
.Name(name)
|
||||
.Type(attributType.toString())
|
||||
.Value(value)
|
||||
.`Value`(value)
|
||||
.IsActive(isActive.getOrElse(true))
|
||||
.saveMe()
|
||||
}
|
||||
@ -73,7 +73,7 @@ class BankAttribute extends BankAttributeTrait with LongKeyedMapper[BankAttribut
|
||||
object BankAttributeId extends MappedUUID(this)
|
||||
object Name extends MappedString(this, 50)
|
||||
object Type extends MappedString(this, 50)
|
||||
object Value extends MappedString(this, 255)
|
||||
object `Value` extends MappedString(this, 255)
|
||||
object IsActive extends MappedBoolean(this) {
|
||||
override def defaultValue = true
|
||||
}
|
||||
@ -83,7 +83,7 @@ class BankAttribute extends BankAttributeTrait with LongKeyedMapper[BankAttribut
|
||||
override def bankAttributeId: String = BankAttributeId.get
|
||||
override def name: String = Name.get
|
||||
override def attributeType: BankAttributeType.Value = BankAttributeType.withName(Type.get)
|
||||
override def value: String = Value.get
|
||||
override def value: String = `Value`.get
|
||||
override def isActive: Option[Boolean] = if (IsActive.jdbcFriendly(IsActive.calcFieldName) == null) { None } else Some(IsActive.get)
|
||||
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import code.accountapplication.AccountApplicationX
|
||||
import code.accountattribute.AccountAttributeX
|
||||
import code.accountholders.{AccountHolders, MapperAccountHolders}
|
||||
import code.api.BerlinGroup.{AuthenticationType, ScaStatus}
|
||||
import code.api.Constant
|
||||
import code.api.Constant.{INCOMING_SETTLEMENT_ACCOUNT_ID, OUTGOING_SETTLEMENT_ACCOUNT_ID}
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.attributedefinition.{AttributeDefinition, AttributeDefinitionDI}
|
||||
@ -840,7 +841,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
}
|
||||
|
||||
private lazy val getDbConnectionParameters: (String, String, String) = {
|
||||
val dbUrl = APIUtil.getPropsValue("db.url") openOr "jdbc:h2:mem:OBPTest;DB_CLOSE_DELAY=-1"
|
||||
val dbUrl = APIUtil.getPropsValue("db.url") openOr Constant.h2DatabaseDefaultUrlValue
|
||||
val username = dbUrl.split(";").filter(_.contains("user")).toList.headOption.map(_.split("=")(1))
|
||||
val password = dbUrl.split(";").filter(_.contains("password")).toList.headOption.map(_.split("=")(1))
|
||||
val dbUser = APIUtil.getPropsValue("db.user").orElse(username)
|
||||
|
||||
@ -17,10 +17,11 @@ object Consents extends SimpleInjector {
|
||||
|
||||
trait ConsentProvider {
|
||||
def getConsentByConsentId(consentId: String): Box[MappedConsent]
|
||||
def getConsentByConsentRequestId(consentRequestId: String): Box[MappedConsent]
|
||||
def updateConsentStatus(consentId: String, status: ConsentStatus): Box[MappedConsent]
|
||||
def updateConsentUser(consentId: String, user: User): Box[MappedConsent]
|
||||
def getConsentsByUser(userId: String): List[MappedConsent]
|
||||
def createConsent(user: User, challenge: String): Box[MappedConsent]
|
||||
def createObpConsent(user: User, challengeAnswer: String, consentRequestId:Option[String]): Box[MappedConsent]
|
||||
def setJsonWebToken(consentId: String, jwt: String): Box[MappedConsent]
|
||||
def revoke(consentId: String): Box[MappedConsent]
|
||||
def checkAnswer(consentId: String, challenge: String): Box[MappedConsent]
|
||||
@ -86,6 +87,8 @@ trait Consent {
|
||||
* @return Consumer ID
|
||||
*/
|
||||
def consumerId: String
|
||||
|
||||
def consentRequestId: String
|
||||
|
||||
/**
|
||||
* This field identifies the standard of API of a related consent
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package code.consent
|
||||
|
||||
import code.model.Consumer
|
||||
import com.openbankproject.commons.model.User
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.util.SimpleInjector
|
||||
|
||||
object ConsentRequests extends SimpleInjector {
|
||||
val consentRequestProvider = new Inject(buildOne _) {}
|
||||
def buildOne: ConsentRequestProvider = MappedConsentRequestProvider
|
||||
}
|
||||
|
||||
trait ConsentRequestProvider {
|
||||
def getConsentRequestById(consentRequestId: String): Box[ConsentRequest]
|
||||
def createConsentRequest(consumer: Option[Consumer], payload: Option[String]): Box[ConsentRequest]
|
||||
}
|
||||
|
||||
trait ConsentRequestTrait {
|
||||
def consentRequestId: String
|
||||
def payload: String
|
||||
def consumerId: String
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
45
obp-api/src/main/scala/code/consent/ConsentRequest.scala
Normal file
45
obp-api/src/main/scala/code/consent/ConsentRequest.scala
Normal file
@ -0,0 +1,45 @@
|
||||
package code.consent
|
||||
|
||||
import code.model.Consumer
|
||||
import code.util.MappedUUID
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.mapper._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
object MappedConsentRequestProvider extends ConsentRequestProvider {
|
||||
override def getConsentRequestById(consentRequestId: String): Box[ConsentRequest] = {
|
||||
ConsentRequest.find(
|
||||
By(ConsentRequest.ConsentRequestId, consentRequestId)
|
||||
)
|
||||
}
|
||||
override def createConsentRequest(consumer: Option[Consumer], payload: Option[String]): Box[ConsentRequest] ={
|
||||
tryo {
|
||||
ConsentRequest
|
||||
.create
|
||||
.ConsumerId(consumer.map(_.consumerId.get).getOrElse(null))
|
||||
.Payload(payload.getOrElse(""))
|
||||
.saveMe()
|
||||
}}
|
||||
}
|
||||
|
||||
class ConsentRequest extends ConsentRequestTrait with LongKeyedMapper[ConsentRequest] with IdPK with CreatedUpdated {
|
||||
|
||||
def getSingleton = ConsentRequest
|
||||
|
||||
//the following are the obp consent.
|
||||
object ConsentRequestId extends MappedUUID(this)
|
||||
object Payload extends MappedText(this)
|
||||
object ConsumerId extends MappedUUID(this) {
|
||||
override def defaultValue = null
|
||||
}
|
||||
|
||||
|
||||
override def consentRequestId: String = ConsentRequestId.get
|
||||
override def payload: String = Payload.get
|
||||
override def consumerId: String = ConsumerId.get
|
||||
|
||||
}
|
||||
|
||||
object ConsentRequest extends ConsentRequest with LongKeyedMetaMapper[ConsentRequest] {
|
||||
override def dbIndexes: List[BaseIndex[ConsentRequest]] = UniqueIndex(ConsentRequestId) :: super.dbIndexes
|
||||
}
|
||||
@ -20,6 +20,13 @@ object MappedConsentProvider extends ConsentProvider {
|
||||
By(MappedConsent.mConsentId, consentId)
|
||||
)
|
||||
}
|
||||
|
||||
override def getConsentByConsentRequestId(consentRequestId: String): Box[MappedConsent] ={
|
||||
MappedConsent.find(
|
||||
By(MappedConsent.mConsentRequestId, consentRequestId)
|
||||
)
|
||||
}
|
||||
|
||||
override def updateConsentStatus(consentId: String, status: ConsentStatus): Box[MappedConsent] = {
|
||||
MappedConsent.find(By(MappedConsent.mConsentId, consentId)) match {
|
||||
case Full(consent) =>
|
||||
@ -55,13 +62,14 @@ object MappedConsentProvider extends ConsentProvider {
|
||||
override def getConsentsByUser(userId: String): List[MappedConsent] = {
|
||||
MappedConsent.findAll(By(MappedConsent.mUserId, userId))
|
||||
}
|
||||
override def createConsent(user: User, challengeAnswer: String): Box[MappedConsent] = {
|
||||
override def createObpConsent(user: User, challengeAnswer: String, consentRequestId:Option[String]): Box[MappedConsent] = {
|
||||
tryo {
|
||||
val salt = BCrypt.gensalt()
|
||||
val challengeAnswerHashed = BCrypt.hashpw(challengeAnswer, salt).substring(0, 44)
|
||||
MappedConsent
|
||||
.create
|
||||
.mUserId(user.userId)
|
||||
.mConsentRequestId(consentRequestId.getOrElse(null))
|
||||
.mChallenge(challengeAnswerHashed)
|
||||
.mSalt(salt)
|
||||
.mStatus(ConsentStatus.INITIATED.toString)
|
||||
@ -234,6 +242,9 @@ class MappedConsent extends Consent with LongKeyedMapper[MappedConsent] with IdP
|
||||
object mConsumerId extends MappedUUID(this) {
|
||||
override def defaultValue = null
|
||||
}
|
||||
object mConsentRequestId extends MappedUUID(this) {
|
||||
override def defaultValue = null
|
||||
}
|
||||
|
||||
object mApiStandard extends MappedString(this, 50)
|
||||
object mApiVersion extends MappedString(this, 50)
|
||||
@ -262,6 +273,7 @@ class MappedConsent extends Consent with LongKeyedMapper[MappedConsent] with IdP
|
||||
override def challenge: String = mChallenge.get
|
||||
override def jsonWebToken: String = mJsonWebToken.get
|
||||
override def consumerId: String = mConsumerId.get
|
||||
override def consentRequestId: String = mConsentRequestId.get
|
||||
|
||||
override def apiStandard: String = mApiStandard.get
|
||||
override def apiVersion: String = mApiVersion.get
|
||||
|
||||
@ -11,11 +11,11 @@ class MappedConsentAuthContext extends ConsentAuthContext with LongKeyedMapper[M
|
||||
object ConsentAuthContextId extends MappedUUID(this)
|
||||
object ConsentId extends UUIDString(this)
|
||||
object Key extends MappedString(this, 255)
|
||||
object Value extends MappedString(this, 255)
|
||||
object `Value` extends MappedString(this, 255)
|
||||
|
||||
override def consentId = ConsentId.get
|
||||
override def key = Key.get
|
||||
override def value = Value.get
|
||||
override def value = `Value`.get
|
||||
override def consentAuthContextId = ConsentAuthContextId.get
|
||||
override def timeStamp = createdAt.get
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ object MappedConsentAuthContextProvider extends ConsentAuthContextProvider with
|
||||
}
|
||||
def createConsentAuthContextAkka(consentId: String, key: String, value: String): Box[MappedConsentAuthContext] =
|
||||
tryo {
|
||||
MappedConsentAuthContext.create.ConsentId(consentId).Key(key).Value(value).saveMe()
|
||||
MappedConsentAuthContext.create.ConsentId(consentId).Key(key).`Value`(value).saveMe()
|
||||
}
|
||||
|
||||
override def getConsentAuthContexts(consentId: String): Future[Box[List[MappedConsentAuthContext]]] = Future {
|
||||
@ -50,11 +50,11 @@ object MappedConsentAuthContextProvider extends ConsentAuthContextProvider with
|
||||
By(MappedConsentAuthContext.ConsentId, consentId),
|
||||
By(MappedConsentAuthContext.Key, authContext.key)
|
||||
).map( authContext =>
|
||||
authContext.Key(authContext.key).Value(authContext.value).saveMe()
|
||||
authContext.Key(authContext.key).`Value`(authContext.value).saveMe()
|
||||
)
|
||||
)
|
||||
val created = create.map( authContext =>
|
||||
MappedConsentAuthContext.create.ConsentId(consentId).Key(authContext.key).Value(authContext.value).saveMe()
|
||||
MappedConsentAuthContext.create.ConsentId(consentId).Key(authContext.key).`Value`(authContext.value).saveMe()
|
||||
)
|
||||
tryo {
|
||||
updated ::: created
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
package code.context
|
||||
|
||||
import code.api.util.ErrorMessages
|
||||
import code.api.util.APIUtil.transactionRequestChallengeTtl
|
||||
import code.api.util.{APIUtil, ErrorMessages}
|
||||
import code.util.Helper.MdcLoggable
|
||||
import com.openbankproject.commons.model.UserAuthContextUpdateStatus
|
||||
import net.liftweb.common.{Box, Empty, Failure, Full}
|
||||
import net.liftweb.mapper.By
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
import com.openbankproject.commons.ExecutionContext.Implicits.global
|
||||
import net.liftweb.util.Helpers
|
||||
|
||||
import scala.compat.Platform
|
||||
import scala.concurrent.Future
|
||||
|
||||
object MappedUserAuthContextUpdateProvider extends UserAuthContextUpdateProvider with MdcLoggable {
|
||||
@ -49,12 +52,21 @@ object MappedUserAuthContextUpdateProvider extends UserAuthContextUpdateProvider
|
||||
override def checkAnswer(consentId: String, challenge: String): Future[Box[MappedUserAuthContextUpdate]] = Future {
|
||||
MappedUserAuthContextUpdate.find(By(MappedUserAuthContextUpdate.mUserAuthContextUpdateId, consentId)) match {
|
||||
case Full(consent) =>
|
||||
consent.status match {
|
||||
case value if value == UserAuthContextUpdateStatus.INITIATED.toString =>
|
||||
val status = if (consent.challenge == challenge) UserAuthContextUpdateStatus.ACCEPTED.toString else UserAuthContextUpdateStatus.REJECTED.toString
|
||||
tryo(consent.mStatus(status).saveMe())
|
||||
case _ =>
|
||||
Full(consent)
|
||||
val createDateTime = consent.createdAt.get
|
||||
val challengeTTL : Long = Helpers.seconds(APIUtil.userAuthContextUpdateRequestChallengeTtl)
|
||||
val expiredDateTime: Long = createDateTime.getTime+challengeTTL
|
||||
val currentTime: Long = Platform.currentTime
|
||||
|
||||
if(expiredDateTime > currentTime)
|
||||
consent.status match {
|
||||
case value if value == UserAuthContextUpdateStatus.INITIATED.toString =>
|
||||
val status = if (consent.challenge == challenge) UserAuthContextUpdateStatus.ACCEPTED.toString else UserAuthContextUpdateStatus.REJECTED.toString
|
||||
tryo(consent.mStatus(status).saveMe())
|
||||
case _ =>
|
||||
Full(consent)
|
||||
}
|
||||
else{
|
||||
Failure(s"${ErrorMessages.OneTimePasswordExpired} Current expiration time is ${APIUtil.userAuthContextUpdateRequestChallengeTtl} seconds")
|
||||
}
|
||||
case Empty =>
|
||||
Empty ?~! ErrorMessages.UserAuthContextUpdateNotFound
|
||||
|
||||
@ -4,6 +4,7 @@ import java.sql.{PreparedStatement, Timestamp}
|
||||
import java.util.Date
|
||||
import java.util.UUID.randomUUID
|
||||
|
||||
import code.api.Constant
|
||||
import code.api.cache.Caching
|
||||
import code.api.util._
|
||||
import code.model.MappedConsumersProvider
|
||||
@ -65,7 +66,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
|
||||
}
|
||||
|
||||
private lazy val getDbConnectionParameters: (String, String, String) = {
|
||||
val dbUrl = APIUtil.getPropsValue("db.url") openOr "jdbc:h2:mem:OBPTest;DB_CLOSE_DELAY=-1"
|
||||
val dbUrl = APIUtil.getPropsValue("db.url") openOr Constant.h2DatabaseDefaultUrlValue
|
||||
val username = dbUrl.split(";").filter(_.contains("user")).toList.headOption.map(_.split("=")(1))
|
||||
val password = dbUrl.split(";").filter(_.contains("password")).toList.headOption.map(_.split("=")(1))
|
||||
val dbUser = APIUtil.getPropsValue("db.user").orElse(username)
|
||||
|
||||
@ -716,7 +716,7 @@ object MappedNonceProvider extends NoncesProvider {
|
||||
case None =>
|
||||
}
|
||||
value match {
|
||||
case Some(v) => n.value(v)
|
||||
case Some(v) => n.`value`(v)
|
||||
case None =>
|
||||
}
|
||||
val nonce = n.saveMe()
|
||||
@ -733,7 +733,7 @@ object MappedNonceProvider extends NoncesProvider {
|
||||
timestamp: Date,
|
||||
value: String): Long = {
|
||||
Nonce.count(
|
||||
By(Nonce.value, value),
|
||||
By(Nonce.`value`, value),
|
||||
By(Nonce.tokenKey, tokenKey),
|
||||
By(Nonce.consumerkey, consumerKey),
|
||||
By(Nonce.timestamp, timestamp)
|
||||
@ -763,7 +763,7 @@ class Nonce extends LongKeyedMapper[Nonce] {
|
||||
timestamp.get.getTime().toString()
|
||||
}
|
||||
}
|
||||
object value extends MappedString(this,250)
|
||||
object `value` extends MappedString(this,250)
|
||||
|
||||
}
|
||||
object Nonce extends Nonce with LongKeyedMetaMapper[Nonce]{}
|
||||
|
||||
@ -30,7 +30,7 @@ import code.api.util.CommonFunctions.validUri
|
||||
import code.UserRefreshes.UserRefreshes
|
||||
import code.accountholders.AccountHolders
|
||||
import code.api.dynamic.endpoint.helper.DynamicEndpointHelper
|
||||
import code.api.util.APIUtil.{hasAnOAuthHeader, logger, validatePasswordOnCreation, _}
|
||||
import code.api.util.APIUtil._
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.util._
|
||||
import code.api.{APIFailure, Constant, DirectLogin, GatewayLogin, OAuthHandshake}
|
||||
@ -43,7 +43,7 @@ import code.users.Users
|
||||
import code.util.Helper
|
||||
import code.util.Helper.MdcLoggable
|
||||
import code.views.Views
|
||||
import com.openbankproject.commons.model.{User, _}
|
||||
import com.openbankproject.commons.model._
|
||||
import net.liftweb.common._
|
||||
import net.liftweb.http._
|
||||
import net.liftweb.mapper._
|
||||
@ -274,7 +274,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with CreatedUpdated with MdcLogga
|
||||
invalidMsg = Helper.i18n("please.enter.your.password")
|
||||
S.error("authuser_password_repeat", Text(Helper.i18n("please.re-enter.your.password")))
|
||||
case false =>
|
||||
if (validatePasswordOnCreation(passwordValue))
|
||||
if (fullPasswordValidation(passwordValue))
|
||||
invalidPw = false
|
||||
else {
|
||||
invalidPw = true
|
||||
@ -947,7 +947,7 @@ def restoreSomeSessions(): Unit = {
|
||||
*/
|
||||
override def login: NodeSeq = {
|
||||
// This query parameter is specific to Hydra ORA login request
|
||||
val loginChallenge = S.param("login_challenge").getOrElse("")
|
||||
val loginChallenge: Box[String] = S.param("login_challenge").or(S.getSessionAttribute("login_challenge"))
|
||||
def redirectUri(): String = {
|
||||
loginRedirect.get match {
|
||||
case Full(url) =>
|
||||
@ -980,12 +980,16 @@ def restoreSomeSessions(): Unit = {
|
||||
// If there is the query parameter login_challenge in a url we know it is tha Hydra request
|
||||
// TODO Write standalone application for Login and Consent Request of Hydra as Identity Provider
|
||||
integrateWithHydra match {
|
||||
case true if !loginChallenge.isEmpty =>
|
||||
val acceptLoginRequest = new AcceptLoginRequest
|
||||
val adminApi: AdminApi = new AdminApi
|
||||
acceptLoginRequest.setSubject(user.username.get)
|
||||
val result = adminApi.acceptLoginRequest(loginChallenge, acceptLoginRequest)
|
||||
S.redirectTo(result.getRedirectTo)
|
||||
case true =>
|
||||
if (loginChallenge.isEmpty == false) {
|
||||
val acceptLoginRequest = new AcceptLoginRequest
|
||||
val adminApi: AdminApi = new AdminApi
|
||||
acceptLoginRequest.setSubject(user.username.get)
|
||||
val result = adminApi.acceptLoginRequest(loginChallenge.getOrElse(""), acceptLoginRequest)
|
||||
S.redirectTo(result.getRedirectTo)
|
||||
} else {
|
||||
S.redirectTo(redirect)
|
||||
}
|
||||
case false =>
|
||||
S.redirectTo(redirect)
|
||||
}
|
||||
|
||||
@ -1,47 +1,47 @@
|
||||
package code.opentok
|
||||
|
||||
import code.api.util.APIUtil
|
||||
import com.opentok._
|
||||
import com.opentok.exception.OpenTokException
|
||||
|
||||
object OpenTokUtil {
|
||||
private var session: Session = null
|
||||
|
||||
def createOpenTok: OpenTok = {
|
||||
// Set the following constants with the API key and API secret
|
||||
// that you receive when you sign up to use the OpenTok API:
|
||||
val apiKey: Int = APIUtil.getPropsValue("meeting.tokbox_api_key", "0000").toInt
|
||||
val apiSecret: String = APIUtil.getPropsValue("meeting.tokbox_api_secret", "YOUR API SECRET")
|
||||
val opentok: OpenTok = new OpenTok(apiKey, apiSecret)
|
||||
return opentok
|
||||
}
|
||||
|
||||
@throws[OpenTokException]
|
||||
def getSession: Session = {
|
||||
if (session == null) {
|
||||
// A session that uses the OpenTok Media Router:
|
||||
session = createOpenTok.createSession(new SessionProperties.Builder().mediaMode(MediaMode.ROUTED).build)
|
||||
}
|
||||
return session
|
||||
}
|
||||
|
||||
@throws[OpenTokException]
|
||||
def generateTokenForModerator(expireTimeInMinutes: Int): String = {
|
||||
// Generate a token. Use the Role MODERATOR. Expire time is defined by parameter expireTimeInMinutes.
|
||||
val token: String = session.generateToken(new TokenOptions.Builder().role(Role.MODERATOR).expireTime((System.currentTimeMillis / 1000L) + (expireTimeInMinutes * 60)).data // in expireTimeInMinutes
|
||||
("name=Simon").build)
|
||||
return token
|
||||
}
|
||||
|
||||
@throws[OpenTokException]
|
||||
def generateTokenForPublisher(expireTimeInMinutes: Int): String = {
|
||||
// Generate a token. Use the Role PUBLISHER. Expire time is defined by parameter expireTimeInMinutes.
|
||||
val token: String = session.generateToken(new TokenOptions.Builder().role(Role.PUBLISHER).expireTime((System.currentTimeMillis / 1000L) + (expireTimeInMinutes * 60)).data // in expireTimeInMinutes
|
||||
("name=Simon").build)
|
||||
return token
|
||||
}
|
||||
}
|
||||
|
||||
class OpenTokUtil() // Empty constructor
|
||||
extends Exception {
|
||||
}
|
||||
//package code.opentok
|
||||
//
|
||||
//import code.api.util.APIUtil
|
||||
//import com.opentok._
|
||||
//import com.opentok.exception.OpenTokException
|
||||
//
|
||||
//object OpenTokUtil {
|
||||
// private var session: Session = null
|
||||
//
|
||||
// def createOpenTok: OpenTok = {
|
||||
// // Set the following constants with the API key and API secret
|
||||
// // that you receive when you sign up to use the OpenTok API:
|
||||
// val apiKey: Int = APIUtil.getPropsValue("meeting.tokbox_api_key", "0000").toInt
|
||||
// val apiSecret: String = APIUtil.getPropsValue("meeting.tokbox_api_secret", "YOUR API SECRET")
|
||||
// val opentok: OpenTok = new OpenTok(apiKey, apiSecret)
|
||||
// return opentok
|
||||
// }
|
||||
//
|
||||
// @throws[OpenTokException]
|
||||
// def getSession: Session = {
|
||||
// if (session == null) {
|
||||
// // A session that uses the OpenTok Media Router:
|
||||
// session = createOpenTok.createSession(new SessionProperties.Builder().mediaMode(MediaMode.ROUTED).build)
|
||||
// }
|
||||
// return session
|
||||
// }
|
||||
//
|
||||
// @throws[OpenTokException]
|
||||
// def generateTokenForModerator(expireTimeInMinutes: Int): String = {
|
||||
// // Generate a token. Use the Role MODERATOR. Expire time is defined by parameter expireTimeInMinutes.
|
||||
// val token: String = session.generateToken(new TokenOptions.Builder().role(Role.MODERATOR).expireTime((System.currentTimeMillis / 1000L) + (expireTimeInMinutes * 60)).data // in expireTimeInMinutes
|
||||
// ("name=Simon").build)
|
||||
// return token
|
||||
// }
|
||||
//
|
||||
// @throws[OpenTokException]
|
||||
// def generateTokenForPublisher(expireTimeInMinutes: Int): String = {
|
||||
// // Generate a token. Use the Role PUBLISHER. Expire time is defined by parameter expireTimeInMinutes.
|
||||
// val token: String = session.generateToken(new TokenOptions.Builder().role(Role.PUBLISHER).expireTime((System.currentTimeMillis / 1000L) + (expireTimeInMinutes * 60)).data // in expireTimeInMinutes
|
||||
// ("name=Simon").build)
|
||||
// return token
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//class OpenTokUtil() // Empty constructor
|
||||
// extends Exception {
|
||||
//}
|
||||
@ -34,7 +34,11 @@ class RemotedataAccountHoldersActor extends Actor with ObpActorHelper with MdcLo
|
||||
|
||||
case cc.bulkDeleteAllAccountHolders() =>
|
||||
logger.debug(s"bulkDeleteAllAccountHolders()")
|
||||
sender ! (mapper.bulkDeleteAllAccountHolders())
|
||||
sender ! (mapper.bulkDeleteAllAccountHolders())
|
||||
|
||||
case cc.deleteAccountHolder(user: User, bankAccountUID :BankIdAccountId) =>
|
||||
logger.debug(s"deleteAccountHolder($user,$bankAccountUID)")
|
||||
sender ! (mapper.deleteAccountHolder(user, bankAccountUID))
|
||||
|
||||
case message => logger.warn("[AKKA ACTOR ERROR - REQUEST NOT RECOGNIZED] " + message)
|
||||
}
|
||||
|
||||
@ -92,6 +92,17 @@ class RemotedataCounterpartiesActor extends Actor with ObpActorHelper with MdcLo
|
||||
case cc.getCounterparties(thisBankId: BankId, thisAccountId: AccountId, viewId: ViewId) =>
|
||||
logger.debug(s"getCounterparties($thisBankId)")
|
||||
sender ! (mapper.getCounterparties(thisBankId, thisAccountId, viewId))
|
||||
|
||||
case cc.getCounterpartyByRoutings(otherBankRoutingScheme: String,
|
||||
otherBankRoutingAddress: String,
|
||||
otherBranchRoutingScheme: String,
|
||||
otherBranchRoutingAddress: String,
|
||||
otherAccountRoutingScheme: String,
|
||||
otherAccountRoutingAddress: String) =>
|
||||
logger.debug(s"getCounterpartyByRoutings($otherBankRoutingScheme,$otherBankRoutingAddress,$otherBranchRoutingScheme,$otherBranchRoutingAddress,$otherAccountRoutingScheme,$otherAccountRoutingAddress)")
|
||||
sender ! (mapper.getCounterpartyByRoutings(otherBankRoutingScheme,
|
||||
otherBankRoutingAddress, otherBranchRoutingScheme,
|
||||
otherBranchRoutingAddress, otherAccountRoutingScheme, otherAccountRoutingAddress))
|
||||
|
||||
case cc.getCounterpartyByIban(iban: String) =>
|
||||
logger.debug(s"getOrCreateMetadata($iban)")
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package code.sandbox
|
||||
|
||||
import code.api.util.APIUtil.validatePasswordOnCreation
|
||||
import code.api.util.APIUtil.fullPasswordValidation
|
||||
import code.api.util.ErrorMessages
|
||||
import code.model.dataAccess.{AuthUser, ResourceUser}
|
||||
import code.users.Users
|
||||
@ -38,7 +38,7 @@ trait CreateAuthUsers {
|
||||
.validated(true)
|
||||
|
||||
val validationErrors = authUser.validate
|
||||
if (!validatePasswordOnCreation(u.password)) Failure(ErrorMessages.InvalidStrongPasswordFormat)
|
||||
if (!fullPasswordValidation(u.password)) Failure(ErrorMessages.InvalidStrongPasswordFormat)
|
||||
else if(!validationErrors.isEmpty) Failure(s"Errors: ${validationErrors.map(_.msg)}")
|
||||
else Full(asSaveable(authUser))
|
||||
}
|
||||
|
||||
@ -1,33 +1,26 @@
|
||||
package code.search
|
||||
|
||||
import java.nio.charset.Charset
|
||||
|
||||
import dispatch.{Http, url}
|
||||
import code.util.Helper.MdcLoggable
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration.Duration
|
||||
import net.liftweb.http.{InMemoryResponse, JsonResponse, LiftResponse}
|
||||
import net.liftweb.json.JsonAST._
|
||||
import net.liftweb.util.Helpers
|
||||
import net.liftweb.util.Props
|
||||
import dispatch._
|
||||
import Defaults._
|
||||
import net.liftweb.json
|
||||
import java.util.Date
|
||||
|
||||
import code.api.util.APIUtil
|
||||
import code.api.util.ErrorMessages._
|
||||
import com.sksamuel.elastic4s.ElasticsearchClientUri
|
||||
import org.elasticsearch.common.settings.Settings
|
||||
import com.sksamuel.elastic4s.http.HttpClient
|
||||
import com.sksamuel.elastic4s.mappings.FieldType._
|
||||
import com.sksamuel.elastic4s.http.ElasticDsl._
|
||||
import dispatch.as.String.charset
|
||||
import code.util.Helper.MdcLoggable
|
||||
import com.sksamuel.elastic4s.http.JavaClient
|
||||
import com.sksamuel.elastic4s.{ElasticClient, ElasticProperties}
|
||||
import dispatch.Defaults._
|
||||
import dispatch.{Http, url, _}
|
||||
import net.liftweb.common.{Box, Empty, Failure, Full}
|
||||
import net.liftweb.http.provider.HTTPCookie
|
||||
import net.liftweb.http.{InMemoryResponse, JsonResponse, LiftResponse}
|
||||
import net.liftweb.json
|
||||
import net.liftweb.json.JsonAST
|
||||
import net.liftweb.json.JsonAST._
|
||||
import net.liftweb.util.Helpers
|
||||
import org.elasticsearch.common.settings.Settings
|
||||
|
||||
import scala.concurrent.Await
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.util.control.NoStackTrace
|
||||
|
||||
|
||||
@ -250,22 +243,23 @@ class elasticsearchMetrics extends elasticsearch {
|
||||
|
||||
if (esIndex.contains(",")) throw new RuntimeException("Props error: es.metrics.index can not be a list")
|
||||
|
||||
var client:HttpClient = null
|
||||
|
||||
val props = ElasticProperties(s"http://$esHost:${esPortTCP.toInt}")
|
||||
val client = ElasticClient(JavaClient(props))
|
||||
// we must import the dsl
|
||||
import com.sksamuel.elastic4s.ElasticDsl._
|
||||
|
||||
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) && APIUtil.getPropsAsBoolValue("allow_elasticsearch_metrics", false) ) {
|
||||
val settings = Settings.builder().put("cluster.name", APIUtil.getPropsValue("es.cluster.name", "elasticsearch")).build()
|
||||
client = HttpClient(ElasticsearchClientUri(esHost, esPortTCP.toInt))
|
||||
try {
|
||||
client.execute {
|
||||
createIndex(esIndex).mappings(
|
||||
mapping("request") as (
|
||||
textField("userId"),
|
||||
textField("url"),
|
||||
dateField("date"),
|
||||
textField("userName"),
|
||||
textField("appName"),
|
||||
textField("developerEmail"),
|
||||
textField("correlationId")
|
||||
createIndex(s"$esIndex/request").mapping(
|
||||
properties (
|
||||
textField("userId"),
|
||||
textField("url"),
|
||||
dateField("date"),
|
||||
textField("userName"),
|
||||
textField("appName"),
|
||||
textField("developerEmail"),
|
||||
textField("correlationId")
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -278,8 +272,10 @@ class elasticsearchMetrics extends elasticsearch {
|
||||
def indexMetric(userId: String, url: String, date: Date, duration: Long, userName: String, appName: String, developerEmail: String, correlationId: String) {
|
||||
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) && APIUtil.getPropsAsBoolValue("allow_elasticsearch_metrics", false) ) {
|
||||
try {
|
||||
// we must import the dsl
|
||||
import com.sksamuel.elastic4s.ElasticDsl._
|
||||
client.execute {
|
||||
indexInto(esIndex / "request") fields (
|
||||
indexInto(s"$esIndex/request") fields (
|
||||
"userId" -> userId,
|
||||
"url" -> url,
|
||||
"date" -> date,
|
||||
@ -304,77 +300,12 @@ class elasticsearchWarehouse extends elasticsearch {
|
||||
override val esPortTCP = APIUtil.getPropsValue("es.warehouse.port.tcp","9300")
|
||||
override val esPortHTTP = APIUtil.getPropsValue("es.warehouse.port.http","9200")
|
||||
override val esIndex = APIUtil.getPropsValue("es.warehouse.index", "warehouse")
|
||||
var client:HttpClient = null
|
||||
val props = ElasticProperties(s"http://$esHost:${esPortTCP.toInt}")
|
||||
var client: ElasticClient = null
|
||||
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) && APIUtil.getPropsAsBoolValue("allow_elasticsearch_warehouse", false) ) {
|
||||
val settings = Settings.builder().put("cluster.name", APIUtil.getPropsValue("es.cluster.name", "elasticsearch")).build()
|
||||
client = HttpClient(ElasticsearchClientUri(esHost, esPortTCP.toInt))
|
||||
client = ElasticClient(JavaClient(props))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
class elasticsearchOBP extends elasticsearch {
|
||||
override val esHost = APIUtil.getPropsValue("es.obp.host","localhost")
|
||||
override val esPortTCP = APIUtil.getPropsValue("es.obp.port.tcp","9300")
|
||||
override val esPortHTTP = APIUtil.getPropsValue("es.obp.port.tcp","9200")
|
||||
override val esIndex = APIUtil.getPropsValue("es.obp.index", "obp")
|
||||
val accountIndex = "account_v1.2.1"
|
||||
val transactionIndex = "transaction_v1.2.1"
|
||||
|
||||
var client:TcpClient = null
|
||||
|
||||
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) ) {
|
||||
client = TcpClient.transport("elasticsearch://" + esHost + ":" + esPortTCP + ",")
|
||||
|
||||
client.execute {
|
||||
create index accountIndex mappings (
|
||||
"account" as (
|
||||
"viewId" typed StringType,
|
||||
"account" typed ObjectType
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
client.execute {
|
||||
create index transactionIndex mappings (
|
||||
"transaction" as (
|
||||
"viewId" typed StringType,
|
||||
"transaction" typed ObjectType
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
/*
|
||||
Index objects in Elastic Search.
|
||||
Use **the same** representations that we return in the REST API.
|
||||
Use the name singular_object_name-version e.g. transaction-v1.2.1 for the index name / type
|
||||
*/
|
||||
|
||||
// Index a Transaction
|
||||
// Put into a index that has the viewId and version in the name.
|
||||
def indexTransaction(viewId: String, transaction: TransactionJSON) {
|
||||
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) ) {
|
||||
client.execute {
|
||||
index into transactionIndex / "transaction" fields (
|
||||
"viewId" -> viewId,
|
||||
"transaction" -> transaction
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Index an Account
|
||||
// Put into a index that has the viewId and version in the name.
|
||||
def indexAccount(viewId: String, account: AccountJSON) {
|
||||
if (APIUtil.getPropsAsBoolValue("allow_elasticsearch", false) ) {
|
||||
client.execute {
|
||||
index into accountIndex / "account" fields (
|
||||
"viewId" -> viewId,
|
||||
"account" -> account
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@ class ConsumerRegistration extends MdcLoggable {
|
||||
private object appType extends RequestVar("Unknown")
|
||||
private object clientCertificateVar extends RequestVar("")
|
||||
private object signingAlgVar extends RequestVar("")
|
||||
private object oidcCheckboxVar extends RequestVar(false)
|
||||
private object jwksUriVar extends RequestVar("")
|
||||
private object jwksVar extends RequestVar("")
|
||||
private object submitButtonDefenseFlag extends RequestVar("")
|
||||
@ -113,6 +114,7 @@ class ConsumerRegistration extends MdcLoggable {
|
||||
if(HydraUtil.integrateWithHydra) {
|
||||
"#app-client_certificate" #> SHtml.textarea(clientCertificateVar, clientCertificateVar (_))&
|
||||
"#app-request_uri" #> SHtml.text(requestUriVar, requestUriVar(_)) &
|
||||
"#oidc_checkbox" #> SHtml.checkbox(oidcCheckboxVar, oidcCheckboxVar(_)) &
|
||||
"#app-signing_alg" #> SHtml.select(signingAlgs, Box!! signingAlgVar.is, signingAlgVar(_)) &
|
||||
"#app-jwks_uri" #> SHtml.text(jwksUriVar, jwksUriVar(_)) &
|
||||
"#app-jwks" #> SHtml.textarea(jwksVar, jwksVar(_))
|
||||
@ -135,12 +137,17 @@ class ConsumerRegistration extends MdcLoggable {
|
||||
if(HydraUtil.integrateWithHydra) {
|
||||
HydraUtil.createHydraClient(consumer, oAuth2Client => {
|
||||
val signingAlg = signingAlgVar.is
|
||||
|
||||
if(oidcCheckboxVar.is == false) {
|
||||
// TODO Set token_endpoint_auth_method in accordance to the Consumer.AppType value
|
||||
// Consumer.AppType = Confidential => client_secret_post
|
||||
// Consumer.AppType = Public => private_key_jwt
|
||||
// Consumer.AppType = Unknown => private_key_jwt
|
||||
oAuth2Client.setTokenEndpointAuthMethod(HydraUtil.hydraTokenEndpointAuthMethod)
|
||||
} else {
|
||||
oAuth2Client.setTokenEndpointAuthMethod(HydraUtil.clientSecretPost)
|
||||
}
|
||||
|
||||
// TODO Set token_endpoint_auth_method in accordance to the Consumer.AppType value
|
||||
// Consumer.AppType = Confidential => client_secret_post
|
||||
// Consumer.AppType = Public => private_key_jwt
|
||||
// Consumer.AppType = Unknown => private_key_jwt
|
||||
oAuth2Client.setTokenEndpointAuthMethod(HydraUtil.hydraTokenEndpointAuthMethod)
|
||||
|
||||
oAuth2Client.setTokenEndpointAuthSigningAlg(signingAlg)
|
||||
oAuth2Client.setRequestObjectSigningAlg(signingAlg)
|
||||
|
||||
@ -44,6 +44,7 @@ import net.liftweb.util.PassThru
|
||||
import scala.xml.{NodeSeq, XML}
|
||||
import scala.io.Source
|
||||
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
|
||||
import net.liftweb.common.{Box, Full}
|
||||
|
||||
|
||||
class WebUI extends MdcLoggable{
|
||||
@ -64,6 +65,27 @@ class WebUI extends MdcLoggable{
|
||||
}
|
||||
}
|
||||
|
||||
def currentPage = {
|
||||
def removeLocale(s: Box[String]) = {
|
||||
s.map(_.replaceAll("&locale=es_ES", "")
|
||||
.replaceAll("&locale=en_EN", "")
|
||||
.replaceAll("\\?locale=es_ES", "")
|
||||
.replaceAll("\\?locale=en_EN", ""))
|
||||
}
|
||||
val page = Constant.HostName + removeLocale(S.uriAndQueryString).getOrElse("")
|
||||
S.queryString.map(_.replaceAll("locale=es_ES", "").replaceAll("locale=en_EN", "")) match {
|
||||
case Full(queryString) if queryString.isEmpty =>
|
||||
"#es a [href]" #> scala.xml.Unparsed(s"${page}?locale=es_ES") &
|
||||
"#en a [href]" #> scala.xml.Unparsed(s"${page}?locale=en_EN")
|
||||
case Full(queryString) =>
|
||||
"#es a [href]" #> scala.xml.Unparsed(s"${page}&locale=es_ES") &
|
||||
"#en a [href]" #> scala.xml.Unparsed(s"${page}&locale=en_EN")
|
||||
case _ =>
|
||||
"#es a [href]" #> scala.xml.Unparsed(s"${page}?locale=es_ES") &
|
||||
"#en a [href]" #> scala.xml.Unparsed(s"${page}?locale=en_EN")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Cookie Consent button.
|
||||
|
||||
@ -68,7 +68,7 @@ object MappedChallengeProvider extends ChallengeProvider {
|
||||
|
||||
expiredDateTime: Long = createDateTime.getTime+challengeTTL
|
||||
currentTime: Long = Platform.currentTime
|
||||
challenge <- if(currentAttemptCounterValue <3){
|
||||
challenge <- if(currentAttemptCounterValue < APIUtil.allowedAnswerTransactionRequestChallengeAttempts){
|
||||
if(expiredDateTime > currentTime) {
|
||||
val currentHashedAnswer = BCrypt.hashpw(challengeAnswer, challenge.salt).substring(0, 44)
|
||||
val expectedHashedAnswer = challenge.expectedAnswer
|
||||
|
||||
@ -99,7 +99,7 @@ object MappedTransactionRequestAttributeProvider extends TransactionRequestAttri
|
||||
.TransactionRequestId(transactionRequestId.value)
|
||||
.Name(name)
|
||||
.Type(attributeType.toString)
|
||||
.Value(value)
|
||||
.`Value`(value)
|
||||
.saveMe()
|
||||
}
|
||||
case _ => Empty
|
||||
@ -112,7 +112,7 @@ object MappedTransactionRequestAttributeProvider extends TransactionRequestAttri
|
||||
.TransactionRequestId(transactionRequestId.value)
|
||||
.Name(name)
|
||||
.Type(attributeType.toString())
|
||||
.Value(value)
|
||||
.`Value`(value)
|
||||
.saveMe()
|
||||
}
|
||||
}
|
||||
@ -131,7 +131,7 @@ object MappedTransactionRequestAttributeProvider extends TransactionRequestAttri
|
||||
.BankId(bankId.value)
|
||||
.Name(transactionRequestAttribute.name)
|
||||
.Type(transactionRequestAttribute.attributeType.toString())
|
||||
.Value(transactionRequestAttribute.value)
|
||||
.`Value`(transactionRequestAttribute.value)
|
||||
.saveMe()
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ class TransactionRequestAttribute extends TransactionRequestAttributeTrait with
|
||||
|
||||
override def attributeType: TransactionRequestAttributeType.Value = TransactionRequestAttributeType.withName(Type.get)
|
||||
|
||||
override def value: String = Value.get
|
||||
override def value: String = `Value`.get
|
||||
|
||||
object BankId extends UUIDString(this) // combination of this
|
||||
|
||||
@ -33,7 +33,7 @@ class TransactionRequestAttribute extends TransactionRequestAttributeTrait with
|
||||
|
||||
object Type extends MappedString(this, 50)
|
||||
|
||||
object Value extends MappedString(this, 255)
|
||||
object `Value` extends MappedString(this, 255)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ object MappedUserAttributeProvider extends UserAttributeProvider {
|
||||
.UserId(userId)
|
||||
.Name(name)
|
||||
.Type(attributeType.toString)
|
||||
.Value(value)
|
||||
.`Value`(value)
|
||||
.saveMe()
|
||||
}
|
||||
case _ => Empty
|
||||
@ -51,7 +51,7 @@ object MappedUserAttributeProvider extends UserAttributeProvider {
|
||||
.UserId(userId)
|
||||
.Name(name)
|
||||
.Type(attributeType.toString())
|
||||
.Value(value)
|
||||
.`Value`(value)
|
||||
.saveMe()
|
||||
}
|
||||
}
|
||||
@ -67,13 +67,13 @@ class UserAttribute extends UserAttributeTrait with LongKeyedMapper[UserAttribut
|
||||
object UserId extends MappedUUID(this)
|
||||
object Name extends MappedString(this, 50)
|
||||
object Type extends MappedString(this, 50)
|
||||
object Value extends MappedString(this, 255)
|
||||
object `Value` extends MappedString(this, 255)
|
||||
|
||||
override def userAttributeId: String = UserAttributeId.get
|
||||
override def userId: String = UserId.get
|
||||
override def name: String = Name.get
|
||||
override def attributeType: UserAttributeType.Value = UserAttributeType.withName(Type.get)
|
||||
override def value: String = Value.get
|
||||
override def value: String = `Value`.get
|
||||
override def insertDate: Date = createdAt.get
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package code.users
|
||||
|
||||
import cats.Now
|
||||
import code.util.Helper.MdcLoggable
|
||||
import net.liftweb.common.{Box, Full}
|
||||
import net.liftweb.mapper.By
|
||||
|
||||
@ -25,6 +25,8 @@ object HydraUtil extends MdcLoggable{
|
||||
|
||||
val mirrorConsumerInHydra = APIUtil.getPropsAsBoolValue("mirror_consumer_in_hydra", false)
|
||||
|
||||
val clientSecretPost = "client_secret_post"
|
||||
|
||||
val hydraTokenEndpointAuthMethod =
|
||||
APIUtil.getPropsValue("hydra_token_endpoint_auth_method", "private_key_jwt")
|
||||
|
||||
@ -40,7 +42,7 @@ object HydraUtil extends MdcLoggable{
|
||||
.openOrThrowException(s"If props $INTEGRATE_WITH_HYDRA is true, hydra_client_scope value should not be blank")
|
||||
.trim.split("""\s*,\s*""").toList
|
||||
|
||||
private lazy val allConsents = hydraConsents.mkString("openid offline ", " ","")
|
||||
private lazy val allConsents = hydraConsents.mkString("openid offline email profile ", " ","")
|
||||
|
||||
|
||||
val grantTypes = ("authorization_code" :: "client_credentials" :: "refresh_token" :: "implicit" :: Nil).asJava
|
||||
|
||||
@ -14,12 +14,12 @@ trait NewAttributeQueryTrait {
|
||||
// TODO Should we rename this column to attributeName
|
||||
private lazy val nameColumn = Name.dbColumnName
|
||||
// TODO Should we rename this column to attributeValue
|
||||
private lazy val valueColumn = Value.dbColumnName
|
||||
private lazy val valueColumn = `Value`.dbColumnName
|
||||
private lazy val parentIdColumn = ParentId.dbColumnName
|
||||
private lazy val bankIdColumn = BankId.dbColumnName
|
||||
val BankId: BaseMappedField
|
||||
val Name: BaseMappedField
|
||||
val Value: BaseMappedField
|
||||
val `Value`: BaseMappedField
|
||||
/**
|
||||
* Attribute entity's parent id, for example: CustomerAttribute.customerId,
|
||||
* need implemented in companion object
|
||||
|
||||
@ -153,6 +153,10 @@ Berlin 13359, Germany
|
||||
<span data-lift="Msg?id=consumer-registration-app-client_certificate-error"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" class="form-check-input" id="oidc_checkbox">
|
||||
<label class="marketing-info-label" for="oidc_checkbox">OpenID Connect Client</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" value="Submit" class="btn btn-danger" aria-describedby="register-consumer-errors"/>
|
||||
|
||||
@ -31,10 +31,12 @@ Berlin 13359, Germany
|
||||
<div id="main-about" data-lift="WebUI.aboutBackground">
|
||||
<div id="main-about-row" class="row">
|
||||
<div id="main-about-box">
|
||||
<h1 id="main-about-text" data-lift="WebUI.aboutText">Welcome to the Open Bank Project API Sandbox test instance!</h1>
|
||||
<h1 id="main-about-text" data-lift="WebUI.aboutText"><lift:loc locid="welcome.to">Welcome to the Open Bank Project API Sandbox test instance!</lift:loc></h1>
|
||||
<div id="main-about-buttons">
|
||||
<a class="api-explorer-link btn btn-danger" data-lift="WebUI.apiExplorerLink" href="">View API Explorer</a>
|
||||
<a id="sandbox-introduction-link" class="btn btn-default" data-lift="WebUI.sandboxIntroductionLink" href="">Introduction</a>
|
||||
<a class="api-explorer-link btn btn-danger" data-lift="WebUI.apiExplorerLink" href="">
|
||||
<lift:loc locid="view_api_explorer">View API Explorer</lift:loc></a>
|
||||
<a id="sandbox-introduction-link" class="btn btn-default" data-lift="WebUI.sandboxIntroductionLink" href="">
|
||||
<lift:loc locid="introduction">Introduction</lift:loc></a>
|
||||
<!-- <a href="/consumer-registration" class="btn btn-default">Get API key</a>-->
|
||||
<!-- <a class="sofi-link btn btn-default" data-lift="WebUI.sofiLink" href="">SOFIT</a>-->
|
||||
<!-- <a id="sandbox-introduction-link" class="btn btn-default" data-lift="WebUI.sandboxIntroductionLink" href="">INTRODUCTION</a>-->
|
||||
@ -46,7 +48,7 @@ Berlin 13359, Germany
|
||||
|
||||
|
||||
<div id="main-get-started">
|
||||
<h2 id="get-started-part">Get started</h2>
|
||||
<h2 id="get-started-part"><lift:loc locid="get_started_title">Get started</lift:loc></h2>
|
||||
<div class="row">
|
||||
<div class="col-md-5 main-get-started-icon">
|
||||
<img class="create-account" src="/media/images/create_account.png" width="237" height="237" alt="create account"/>
|
||||
@ -55,10 +57,9 @@ Berlin 13359, Germany
|
||||
<img class="item-1" src="/media/images/icons/item-1.png" alt="item-1"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-5 main-get-started-text">
|
||||
<h3>Create an account</h3>
|
||||
<p>First, create a free developer account on this sandbox and request a developer key. You will be asked
|
||||
to submit basic information about your app at this stage. <a href="/user_mgt/sign_up">Register for
|
||||
an account</a>.</p>
|
||||
<h3><lift:loc locid="get_started_create_account_title">Create an account</lift:loc></h3>
|
||||
<p><lift:loc locid="get_started_create_account">First, create a free developer account on this sandbox and request a developer key. You will be asked to submit basic information about your app at this stage.</lift:loc><a href="/user_mgt/sign_up"><lift:loc locid="register_for_an_account">Register for an account</lift:loc>
|
||||
</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@ -69,10 +70,10 @@ Berlin 13359, Germany
|
||||
<img class="item-2" src="/media/images/icons/item-2.png" alt="item-2"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-5 main-get-started-text">
|
||||
<h3>Connect your app</h3>
|
||||
<p>Use our SDKs to connect your app to the Open Bank Project APIs. You’ll need your developer key, which
|
||||
<h3><lift:loc locid="get_started_connect_your_app_title">Connect your app</lift:loc></h3>
|
||||
<p><lift:loc locid="get_started_connect_your_app">Use our SDKs to connect your app to the Open Bank Project APIs. You’ll need your developer key, which
|
||||
you should have from when you created your account. Check out all the available APIs on the API
|
||||
Explorer, but make sure that you’re using the correct base URL.</p>
|
||||
Explorer, but make sure that you’re using the correct base URL.</lift:loc></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@ -83,16 +84,17 @@ Berlin 13359, Germany
|
||||
<img class="item-3" src="/media/images/icons/item-3.png" alt="item-3"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-5 main-get-started-text">
|
||||
<h3>Test your app using customer data</h3>
|
||||
<h3><lift:loc locid="get_started_test_your_app_title">Test your app using customer data</lift:loc></h3>
|
||||
<p>
|
||||
Once your app is connected, you can test it using test customer credentials.
|
||||
<lift:loc locid="Test_your_app_description">Once your app is connected, you can test it using test customer credentials.</lift:loc>
|
||||
|
||||
<a class="example_sandbox_credentials_link" data-lift="WebUI.exampleSandboxCredentialsLink"
|
||||
href="https://github.com/OpenBankProject/OBP-API/wiki/">View sandbox customer log ons.</a>
|
||||
href="https://github.com/OpenBankProject/OBP-API/wiki/"><lift:loc locid="get_started_test_your_app_sandbox_date">View sandbox customer log ons.</lift:loc></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn btn-primary">
|
||||
<a href="/consumer-registration">Get API key</a>
|
||||
<a href="/consumer-registration"><lift:loc locid="get_api_key">Get API key</lift:loc></a>
|
||||
</div>
|
||||
|
||||
<hr style="color: #D7D8D6; margin-top: 56px;margin-bottom: 72px;">
|
||||
@ -110,15 +112,15 @@ Berlin 13359, Germany
|
||||
|
||||
|
||||
<div id="main-apis">
|
||||
<h2 id="explorer-apis">Explore APIs</h2>
|
||||
<h2 id="explorer-apis"><lift:loc locid="explore_api_title">Explore APIs</lift:loc></h2>
|
||||
<div class="row">
|
||||
<a class="api-explorer-link" data-lift="WebUI.apiExplorerLink?tags=Account,Card" href="">
|
||||
<div class="col-xs-12 col-sm-1 col-lg-1 main-apis-icon">
|
||||
<img class="icon-accounts" src="/media/images/icons/apis/icon-accounts.png" alt="accounts"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Accounts<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="accounts chevron"/></h3>
|
||||
<p>Access to accounts (XS21) and cards. Provide fine-grained access to guests (auditor, accountant or public).</p>
|
||||
<h3><lift:loc locid="explore_api_accounts_title">Accounts</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="accounts chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_accounts">Access to accounts (XS21) and cards. Provide fine-grained access to guests (auditor, accountant or public).</lift:loc></p>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
@ -130,8 +132,8 @@ Berlin 13359, Germany
|
||||
src="/media/images/icons/apis/icon-branches.png" alt="branches"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Branches, ATMs and Products<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Branches chevron"/></h3>
|
||||
<p>Access open data related to banks including branches and ATMs including geolocation and opening hours.</p>
|
||||
<h3><lift:loc locid="explore_api_branches_title">Branches, ATMs and Products</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Branches chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_branches">Access open data related to banks including branches and ATMs including geolocation and opening hours.</lift:loc></p>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
@ -146,8 +148,8 @@ Berlin 13359, Germany
|
||||
height="100" alt="transactions icon"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Transactions<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Transactions chevron"/></h3>
|
||||
<p>Access the transaction history and transaction metadata.</p>
|
||||
<h3><lift:loc locid="explore_api_transactions_title">Transactions</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Transactions chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_transactions">Access the transaction history and transaction metadata.</lift:loc></p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@ -159,9 +161,9 @@ Berlin 13359, Germany
|
||||
height="100" alt="metadata"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Metadata<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Metadata chevron"/></h3>
|
||||
<p>Enrich transactions and counterparties with metadata including geolocations, comments, pictures
|
||||
and tags (e.g. category of spending).</p>
|
||||
<h3><lift:loc locid="explore_api_metadata_title">Metadata</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Metadata chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_metadata">Enrich transactions and counterparties with metadata including geolocations, comments, pictures
|
||||
and tags (e.g. category of spending).</lift:loc></p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@ -178,9 +180,9 @@ Berlin 13359, Germany
|
||||
alt="counterparties"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Counterparties<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Counterparties chevron"/></h3>
|
||||
<p>Access the payers and payees of an account including metadata such as their aliases, labels,
|
||||
logos and home pages.</p>
|
||||
<h3><lift:loc locid="explore_api_counterparties_title">Metadata</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Counterparties chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_counterparties">Access the payers and payees of an account including metadata such as their aliases, labels,
|
||||
logos and home pages.</lift:loc></p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@ -190,8 +192,8 @@ Berlin 13359, Germany
|
||||
src="/media/images/icons/apis/icon-entitlements.png" alt="entitlements"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Webhooks<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Webhooks chevron"/></h3>
|
||||
<p>Call external web services based on Account events.</p>
|
||||
<h3><lift:loc locid="explore_api_webhooks_title">Webhooks</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Webhooks chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_webhooks">Call external web services based on Account events.</lift:loc></p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@ -203,8 +205,8 @@ Berlin 13359, Germany
|
||||
src="/media/images/icons/apis/icon-messages.png" alt="messages"/>
|
||||
</div>
|
||||
<div id ="customer-onboarding-and-kyc-div" class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Customer onboarding and KYC<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Customer onboarding and KYC chevron"/></h3>
|
||||
<p>Perform user, customer and account creation. Manage Know Your Customer (KYC) documents, media and status. Create customer meetings and messages.</p>
|
||||
<h3><lift:loc locid="explore_api_customer_title">Customer onboarding and KYC</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Customer onboarding and KYC chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_customer">Perform user, customer and account creation. Manage Know Your Customer (KYC) documents, media and status. Create customer meetings and messages.</lift:loc></p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@ -215,8 +217,8 @@ Berlin 13359, Germany
|
||||
src="/media/images/icons/apis/icon-security.png" alt="security"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text" id="api-roles-metrics-documentation">
|
||||
<h3>API Roles, Metrics and Documentation<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="API Roles, Metrics and Documentation chevron"/></h3>
|
||||
<p>Control access to endpoints, get API metrics and documentation.</p>
|
||||
<h3><lift:loc locid="explore_api_roles_title">API Roles, Metrics and Documentation</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="API Roles, Metrics and Documentation chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_roles">Control access to endpoints, get API metrics and documentation.</lift:loc></p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@ -229,8 +231,8 @@ Berlin 13359, Germany
|
||||
src="/media/images/icons/apis/icon-requests.png" alt="requests"/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Payments & Transfers<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Payments & Transfers chevron"/></h3>
|
||||
<p>Initiate Transaction Requests (transfers and payments). View and confirm charges (as per PSD2). Answer strong customer authentication (SCA) challenges.</p>
|
||||
<h3><lift:loc locid="explore_api_payments_title">Payments & Transfers</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="Payments & Transfers chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_payments">Initiate Transaction Requests (transfers and payments). View and confirm charges (as per PSD2). Answer strong customer authentication (SCA) challenges.</lift:loc></p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@ -239,8 +241,8 @@ Berlin 13359, Germany
|
||||
<img class="icon-kyc" src="/media/images/icons/apis/icon-kyc.png" alt="kyc" />
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-lg-5 main-apis-text">
|
||||
<h3>Search warehouse<img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="kyc chevron"/></h3>
|
||||
<p>Perform advanced searches and statistics queries on the data warehouse.</p>
|
||||
<h3><lift:loc locid="explore_api_warehouse_title">Search warehouse</lift:loc><img src="media/images/icons/chevron_right_thick_DB0011.svg" height="14" width="9.21" alt="kyc chevron"/></h3>
|
||||
<p><lift:loc locid="explore_api_warehouse">Perform advanced searches and statistics queries on the data warehouse.</lift:loc></p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@ -268,13 +270,13 @@ Berlin 13359, Germany
|
||||
|
||||
|
||||
<div id="main-support">
|
||||
<h2 id="technical-support">Support</h2>
|
||||
<h2 id="technical-support"><lift:loc locid="support">Support</lift:loc></h2>
|
||||
<div class="row">
|
||||
<div class="col-xs-1" type="hidden"></div>
|
||||
<div class="col-xs-2" type="hidden" id ="main-support_place_holder"></div>
|
||||
<div class="main-support-item col-xs-3">
|
||||
<img class="support-mail" src="/media/images/icons/support/email.svg" width="48" height="48" alt="mail"/>
|
||||
<h3>Email</h3>
|
||||
<h3><lift:loc locid="email.address">Email</lift:loc></h3>
|
||||
<a id="webui-support-email" data-lift="WebUI.supportEmail" href="mailto:contact@openbankproject.com">contact@openbankproject.com</a>
|
||||
</div>
|
||||
|
||||
@ -311,20 +313,23 @@ Berlin 13359, Germany
|
||||
<div id="main-start">
|
||||
<div id="main-start-row" class="row">
|
||||
<div id="main-start_building" class="col-xs-12 col-sm-6">
|
||||
<h2 name="get-started" data-lift="WebUI.getStartedText">Get started building your application</h2>
|
||||
<h2 name="get-started" data-lift="WebUI.getStartedText"><lift:loc locid="get_started_building_your_application">Get started building your application</lift:loc></h2>
|
||||
<div class="btn btn-default pull-left">
|
||||
<a href="/consumer-registration">Get API key</a>
|
||||
<a href="/consumer-registration">
|
||||
<lift:loc locid="get_api_key">Get API key</lift:loc></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="for-banks" name="for-banks" data-lift="WebUI.forBanks" class="col-xs-12 col-sm-6">
|
||||
<h2>For banks</h2>
|
||||
<h2><lift:loc locid="for_banks">For Banks</lift:loc></h2></h2>
|
||||
<a class="api-manager-link btn btn-default pull-left"
|
||||
data-lift="WebUI.apiManagerLink" href="">API Manager</a>
|
||||
data-lift="WebUI.apiManagerLink" href="">
|
||||
<lift:loc locid="api_manager">API Manager</lift:loc></a>
|
||||
<a class="obp-cli-link btn btn-default pull-left" data-lift="WebUI.obpCliLink"
|
||||
href="">OBP CLI</a>
|
||||
<a class="api-tester-link btn btn-default pull-left"
|
||||
data-lift="WebUI.apiTesterLink" href="">API Tester</a>
|
||||
data-lift="WebUI.apiTesterLink" href="">
|
||||
<lift:loc locid="api_tester">API Tester</lift:loc></a>
|
||||
<a class="api-hola-link btn btn-default pull-left"
|
||||
data-lift="WebUI.apiHolaLink" href="">Hola</a>
|
||||
</div>
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
<div id="authorise" tabindex="-1">
|
||||
<div class="login-error"><span data-lift="Msg?id=login&errorClass=error"/></div>
|
||||
<div data-lift="Login.customiseLogin">
|
||||
<h1 id="login-instruction-title">Log on to the Open Bank Project API</h1>
|
||||
<h1 id="login-instruction-title"><lift:loc locid="logontext">Log on to the Open Bank Project API</lift:loc></h1>
|
||||
<div id="login-special-instructions">Special Instructions</div>
|
||||
|
||||
<form class="login" action="/user_mgt/login" method="post">
|
||||
<div class="form-group">
|
||||
<p id="login-form-username">Username </p>
|
||||
<p id="login-form-username"><lift:loc locid="username">Username</lift:loc></p>
|
||||
<input class="form-control" id="username" type="text" name="username" tabindex="0" autofocus autocomplete="off" aria-label="Username" aria-describedby="login-form-username-error"/>
|
||||
<div id = "login-username-error" class="hide">
|
||||
<span data-lift="Msg?id=login-form-username-error"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<p id="login-form-password">Password</p>
|
||||
<p id="login-form-password"><lift:loc locid="passwordlog">Password</lift:loc></p>
|
||||
<input class="form-control" id="password" type="password" name="password" tabindex="0" autocomplete="off" aria-label="Password" aria-describedby="login-form-password-error"/>
|
||||
<div id = "login-password-error" class="hide">
|
||||
<span data-lift="Msg?id=login-form-password-error"/>
|
||||
@ -28,7 +28,7 @@
|
||||
<!-- </div>-->
|
||||
|
||||
<div id="authorise-recover-password">
|
||||
<a href="/user_mgt/lost_password" tabindex="0">Forgotten password?</a>
|
||||
<a href="/user_mgt/lost_password" tabindex="0"><lift:loc locid="Forgotten_password">Forgotten password?</lift:loc></a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
@ -38,14 +38,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class ="login-or"> or </div>
|
||||
<div class ="login-or"> <lift:loc locid="or">or</lift:loc></div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<span id="login-Register-text">Don't have an account? </span>
|
||||
<a href="/user_mgt/sign_up" id="authorise-signup" class="btn btn-default pull-right authorise-button" tabindex="0">Register</a>
|
||||
<span id="login-Register-text"><lift:loc locid="don't_have_account">Don't have an account?</lift:loc> </span>
|
||||
<a href="/user_mgt/sign_up" id="authorise-signup" class="btn btn-default pull-right authorise-button" tabindex="0"><lift:loc locid="register">Register</lift:loc></a>
|
||||
</div>
|
||||
|
||||
<div class ="login-or"> or Login with OpenID : </div>
|
||||
<div class ="login-or">><lift:loc locid="or_login_with_openid">or Login with OpenID :</lift:loc> </div>
|
||||
<hr>
|
||||
<div data-lift="OpenIDConnectSnippet.showFirstButton">
|
||||
<div data-lift="OpenidConnectInvoke.linkButtonFirstProvider">
|
||||
|
||||
@ -139,6 +139,7 @@ Berlin 13359, Germany
|
||||
<a href="/user_mgt/sign_up" class="navbar-btn" id ="register-link"><lift:loc locid="register">Register</lift:loc></a><a data-lift="Login.loggedOut" href="#" class="btn btn-danger login"><lift:loc locid="logon">Log on</lift:loc></a>
|
||||
</p>
|
||||
</li>
|
||||
|
||||
<li class="navitem" data-lift="Login.loggedIn" >
|
||||
<!-- LOGGED IN -->
|
||||
<p class="navbar-btn"><a href="/user-information"><span id="loggedIn-username">username</span></a><a href="#" class="btn btn-default logout">Log off</a></p>
|
||||
@ -184,7 +185,8 @@ Berlin 13359, Germany
|
||||
</li>
|
||||
<li>
|
||||
<div class="navitem" id="technical-faqs-anchor-nav">
|
||||
<a class="navlink" id="technical-faqs-anchor" data-lift="WebUI.technicalFaqsAnchor" href="">Support</a>
|
||||
<a class="navlink" id="technical-faqs-anchor" data-lift="WebUI.technicalFaqsAnchor" href="">
|
||||
<lift:loc locid="support">Support</lift:loc></a>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
@ -205,11 +207,12 @@ Berlin 13359, Germany
|
||||
<div id="footer-div">
|
||||
<ul>
|
||||
<li>
|
||||
<a class="termsAndConditions-link" data-lift="WebUI.termsAndConditions" href="">Terms and
|
||||
Conditions</a>
|
||||
<a class="termsAndConditions-link" data-lift="WebUI.termsAndConditions" href="">
|
||||
<lift:loc locid="terms_conditions">Terms and Conditions</lift:loc></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="privacy-policy-link" data-lift="WebUI.privacyPolicyLink" href="https://openbankproject.com/privacy-policy">Privacy Policy</a>
|
||||
<a class="privacy-policy-link" data-lift="WebUI.privacyPolicyLink" href="https://openbankproject.com/privacy-policy">
|
||||
<lift:loc locid="privacy_policy">Privacy Policy</lift:loc></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://twitter.com/#!/OpenBankProject">Twitter</a>
|
||||
@ -218,21 +221,30 @@ Berlin 13359, Germany
|
||||
<a href="https://github.com/OpenBankProject/OBP-API/">Github</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="api-documentation-link" data-lift="WebUI.apiDocumentationLink" href="">API
|
||||
Documentation</a>
|
||||
<a class="api-documentation-link" data-lift="WebUI.apiDocumentationLink" href="">
|
||||
<lift:loc locid="api_documentation">API Documentation</lift:loc></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="sofi-link" data-lift="WebUI.sofiLink" href="">Sofit</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/user_mgt/sign_up?after-signup=link-to-customer" class="navbar-btn" id ="register-link">On Board</a>
|
||||
<a href="/user_mgt/sign_up?after-signup=link-to-customer" class="navbar-btn" id ="register-link">
|
||||
<lift:loc locid="register">On Board</lift:loc></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="api-link" data-lift="WebUI.apiLinkHuman" href="">This API Host</a>
|
||||
<a class="api-link" data-lift="WebUI.apiLinkHuman" href="">
|
||||
<lift:loc locid="api_host">This API Host</lift:loc></a>
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
<div class="language-tag" data-lift="WebUI.currentPage">
|
||||
<span><a href="#" >Language</a></span>
|
||||
<span><a id="es" href="/" >ES</a></span>
|
||||
<span><a href="/" >|</a></span>
|
||||
<span><a id="en" href="/" >EN</a></span>
|
||||
</div>
|
||||
<div id="copyright">
|
||||
<a href="http://openbankproject.com">Open Bank Project is ©2011 - <span id="copyright-year" data-lift="WebUI.currentYearText">2018</span> </a> <a href="http://tesobe.com">TESOBE and distributed under the AGPL and commercial licenses.</a>
|
||||
<a href="http://openbankproject.com"><lift:loc locid="open_bank_project_is">Open Bank Project is ©2011 - </lift:loc> <span id="copyright-year" data-lift="WebUI.currentYearText">2018</span> </a> <a href="http://tesobe.com"><lift:loc locid="and_commercial_licenses">TESOBE and distributed under the AGPL and commercial licenses. </lift:loc></a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
Binary file not shown.
@ -4,6 +4,7 @@ import code.api.BerlinGroup.ScaStatus
|
||||
import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{CancellationJsonV13, InitiatePaymentResponseJson, StartPaymentAuthorisationJson}
|
||||
import code.api.builder.PaymentInitiationServicePISApi.APIMethods_PaymentInitiationServicePISApi
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.APIUtil.extractErrorMessageCode
|
||||
import code.api.util.ErrorMessages.{AuthorisationNotFound, InvalidJsonFormat, NotPositiveAmount, _}
|
||||
import code.model.dataAccess.{BankAccountRouting, MappedBankAccount}
|
||||
import code.setup.{APIResponse, DefaultUsers}
|
||||
@ -80,7 +81,7 @@ class PaymentInitiationServicePISApiTest extends BerlinGroupServerSetupV1_3 with
|
||||
response.code should equal(400)
|
||||
val error = s"${NotPositiveAmount} Current input is: '-1234'"
|
||||
And("error should be " + error)
|
||||
response.body.extract[ErrorMessage].message should equal (error)
|
||||
response.body.extract[ErrorMessage].message contains extractErrorMessageCode(NotPositiveAmount) should be (true)
|
||||
}
|
||||
scenario("Successful case - small amount -- change the balance", BerlinGroupV1_3, PIS, initiatePayment) {
|
||||
val accountsRoutingIban = BankAccountRouting.findAll(By(BankAccountRouting.AccountRoutingScheme, AccountRoutingScheme.IBAN.toString))
|
||||
|
||||
@ -362,8 +362,9 @@ class OAuthTest extends ServerSetup {
|
||||
|
||||
Then("we set the valid username, valid password and try to login")
|
||||
val verifier = getVerifier(requestToken.value, user2.username.get, user2Password)
|
||||
|
||||
org.scalameta.logger.elem(verifier)
|
||||
Then("we should get a message: " + accountValidationError)
|
||||
println(verifier)
|
||||
verifier.contains(accountValidationError) should equal (true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,12 +79,12 @@ class JSONFactory1_4_0Test extends V140ServerSetup with DefaultUsers {
|
||||
|
||||
scenario("createResourceDocJson should work well, no exception is good enough") {
|
||||
val resourceDoc: ResourceDoc = OBPAPI3_0_0.allResourceDocs(5)
|
||||
val result: ResourceDocJson = JSONFactory1_4_0.createResourceDocJson(resourceDoc,false)
|
||||
val result: ResourceDocJson = JSONFactory1_4_0.createResourceDocJson(resourceDoc,false, None)
|
||||
}
|
||||
|
||||
scenario("createResourceDocsJson should work well, no exception is good enough") {
|
||||
val resourceDoc: mutable.Seq[ResourceDoc] = OBPAPI3_0_0.allResourceDocs
|
||||
val result = JSONFactory1_4_0.createResourceDocsJson(resourceDoc.toList, false)
|
||||
val result = JSONFactory1_4_0.createResourceDocsJson(resourceDoc.toList, false, None)
|
||||
}
|
||||
|
||||
scenario("createTypedBody should work well, no exception is good enough") {
|
||||
@ -97,7 +97,7 @@ class JSONFactory1_4_0Test extends V140ServerSetup with DefaultUsers {
|
||||
|
||||
scenario("validate all the resouceDocs json schema, no exception is good enough") {
|
||||
val resourceDocsRaw= OBPAPI3_0_0.allResourceDocs
|
||||
val resourceDocs = JSONFactory1_4_0.createResourceDocsJson(resourceDocsRaw.toList,false)
|
||||
val resourceDocs = JSONFactory1_4_0.createResourceDocsJson(resourceDocsRaw.toList,false, None)
|
||||
|
||||
for{
|
||||
resouceDoc <- resourceDocs.resource_docs
|
||||
|
||||
@ -3,6 +3,7 @@ package code.api.v2_0_0
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import com.openbankproject.commons.model.ErrorMessage
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.APIUtil.extractErrorMessageCode
|
||||
import code.api.util.ApiRole.CanGetEntitlementsForAnyUserAtAnyBank
|
||||
import code.api.util.ErrorMessages.{UserHasMissingRoles, _}
|
||||
import code.api.util.{ApiRole, ErrorMessages}
|
||||
@ -74,7 +75,7 @@ class EntitlementTests extends V200ServerSetup with DefaultUsers {
|
||||
|
||||
Then("We should get a 403")
|
||||
responsePost.code should equal(403)
|
||||
responsePost.body.toString contains (UserHasMissingRoles) should be (true)
|
||||
responsePost.body.toString contains (extractErrorMessageCode(UserHasMissingRoles)) should be (true)
|
||||
|
||||
Then("We grant the canCreateEntitlementAtOneBank role")
|
||||
Entitlement.entitlement.vend.addEntitlement(testBankId1.value, resourceUser1.userId, ApiRole.canCreateEntitlementAtOneBank.toString)
|
||||
@ -101,7 +102,7 @@ class EntitlementTests extends V200ServerSetup with DefaultUsers {
|
||||
|
||||
Then("We should get a 403")
|
||||
responsePost.code should equal(403)
|
||||
responsePost.body.toString contains (UserHasMissingRoles) should be (true)
|
||||
responsePost.body.toString contains (extractErrorMessageCode(UserHasMissingRoles)) should be (true)
|
||||
|
||||
Then("We grant the canCreateEntitlementAtOneBank role")
|
||||
Entitlement.entitlement.vend.addEntitlement("wrongbankId", resourceUser1.userId, ApiRole.canCreateEntitlementAtOneBank.toString)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package code.api.v2_2_0
|
||||
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.APIUtil.extractErrorMessageCode
|
||||
import code.api.util.{ApiRole, ErrorMessages}
|
||||
import code.api.util.ErrorMessages.UserHasMissingRoles
|
||||
import code.entitlement.Entitlement
|
||||
@ -129,7 +130,7 @@ class AccountTest extends V220ServerSetup with DefaultUsers {
|
||||
val responseWithNoRole = makePutRequest(requestPutNewAccountId, write(accountPutJSON2))
|
||||
|
||||
responseWithNoRole.code should equal(403)
|
||||
responseWithNoRole.body.toString contains(s"$UserHasMissingRoles") should be (true)
|
||||
responseWithNoRole.body.toString contains(extractErrorMessageCode(UserHasMissingRoles)) should be (true)
|
||||
|
||||
|
||||
Then("We grant the roles and test it again")
|
||||
|
||||
@ -5,6 +5,7 @@ import com.openbankproject.commons.model.{AccountRouting, AccountRoutingJsonV121
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.updateAccountRequestJsonV310
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.APIUtil.extractErrorMessageCode
|
||||
import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn}
|
||||
import code.api.util.ApiRole
|
||||
import code.api.v2_0_0.BasicAccountJSON
|
||||
@ -251,7 +252,7 @@ class AccountTest extends V310ServerSetup with DefaultUsers {
|
||||
val responseWithNoRole = makePutRequest(request310WithNewAccountId, write(putCreateAccountOtherUserJsonV310))
|
||||
Then("We should get a 403 and some error message")
|
||||
responseWithNoRole.code should equal(403)
|
||||
responseWithNoRole.body.toString contains(s"$UserHasMissingRoles") should be (true)
|
||||
responseWithNoRole.body.toString contains(extractErrorMessageCode(UserHasMissingRoles)) should be (true)
|
||||
|
||||
|
||||
Then("We grant the roles and test it again")
|
||||
|
||||
@ -464,7 +464,7 @@ class AuthenticationTypeValidationTest extends V400ServerSetup {
|
||||
| "to_currency_code": "USD",
|
||||
| "conversion_value": 1.136305,
|
||||
| "inverse_conversion_value": 0.8800454103431737,
|
||||
| "effective_date": "2017-09-19T00:00:00Z"
|
||||
| "effective_date": "1100-01-01T00:00:00Z"
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package code.api.v4_0_0
|
||||
import com.openbankproject.commons.model.ErrorMessage
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.APIUtil.extractErrorMessageCode
|
||||
import code.api.util.ApiRole.CanCreateDirectDebitAtOneBank
|
||||
import com.openbankproject.commons.util.ApiVersion
|
||||
import code.api.util.ErrorMessages.{NoViewPermission, UserHasMissingRoles, UserNotLoggedIn}
|
||||
@ -45,7 +46,7 @@ class DirectDebitTest extends V400ServerSetup {
|
||||
val response400 = makePostRequest(request400, write(postDirectDebitJsonV400))
|
||||
Then("We should get a 400")
|
||||
response400.code should equal(400)
|
||||
response400.body.extract[ErrorMessage].message should startWith(NoViewPermission)
|
||||
response400.body.extract[ErrorMessage].message contains extractErrorMessageCode(NoViewPermission) should be (true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -683,7 +683,7 @@ class ForceErrorValidationTest extends V400ServerSetup with PropsReset {
|
||||
| "to_currency_code": "USD",
|
||||
| "conversion_value": 1.136305,
|
||||
| "inverse_conversion_value": 0.8800454103431737,
|
||||
| "effective_date": "2017-09-19T00:00:00Z"
|
||||
| "effective_date": "1100-01-01T00:00:00Z"
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
|
||||
@ -502,7 +502,7 @@ class JsonSchemaValidationTest extends V400ServerSetup {
|
||||
| "to_currency_code":"USD",
|
||||
| "conversion_value":1.136305,
|
||||
| "inverse_conversion_value":0.8800454103431737,
|
||||
| "effective_date":"2017-09-19T00:00:00Z"
|
||||
| "effective_date":"1100-01-01T00:00:00Z"
|
||||
| }],
|
||||
| "required":["bank_id","from_currency_code","to_currency_code"],
|
||||
| "properties":{
|
||||
@ -530,7 +530,7 @@ class JsonSchemaValidationTest extends V400ServerSetup {
|
||||
| "to_currency_code": "DEF",
|
||||
| "conversion_value": 1.136305,
|
||||
| "inverse_conversion_value": 0.8800454103431737,
|
||||
| "effective_date": "2017-09-19T00:00:00Z"
|
||||
| "effective_date": "1100-01-01T00:00:00Z"
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
@ -542,7 +542,7 @@ class JsonSchemaValidationTest extends V400ServerSetup {
|
||||
| "to_currency_code": "USD",
|
||||
| "conversion_value": 1.136305,
|
||||
| "inverse_conversion_value": 0.8800454103431737,
|
||||
| "effective_date": "2017-09-19T00:00:00Z"
|
||||
| "effective_date": "1100-01-01T00:00:00Z"
|
||||
|}
|
||||
|""".stripMargin
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package code.api.v4_0_0
|
||||
import com.openbankproject.commons.model.ErrorMessage
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.util.APIUtil.extractErrorMessageCode
|
||||
import code.api.util.ApiRole.CanCreateStandingOrderAtOneBank
|
||||
import com.openbankproject.commons.util.ApiVersion
|
||||
import code.api.util.ErrorMessages.{NoViewPermission, UserHasMissingRoles, UserNotLoggedIn}
|
||||
@ -45,7 +46,7 @@ class StandingOrderTest extends V400ServerSetup {
|
||||
val response400 = makePostRequest(request400, write(postStandingOrderJsonV400))
|
||||
Then("We should get a 400")
|
||||
response400.code should equal(400)
|
||||
response400.body.extract[ErrorMessage].message should startWith(NoViewPermission)
|
||||
response400.body.extract[ErrorMessage].message contains extractErrorMessageCode(NoViewPermission) should be (true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import code.api.ChargePolicy
|
||||
import code.api.Constant._
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.APIUtil.extractErrorMessageCode
|
||||
import code.api.util.ApiRole.CanCreateAnyTransactionRequest
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.util.{APIUtil, ErrorMessages}
|
||||
@ -36,10 +37,15 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers {
|
||||
* This is made possible by the scalatest maven plugin
|
||||
*/
|
||||
object VersionOfApi extends Tag(ApiVersion.v4_0_0.toString)
|
||||
object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createTransactionRequest))
|
||||
object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.answerTransactionRequestChallenge))
|
||||
object ApiEndpoint1 extends Tag(nameOf(Implementations4_0_0.createTransactionRequestAccount))
|
||||
object ApiEndpoint2 extends Tag(nameOf(Implementations4_0_0.createTransactionRequestAccountOtp))
|
||||
object ApiEndpoint3 extends Tag(nameOf(Implementations4_0_0.getTransactionRequest))
|
||||
|
||||
object ApiEndpoint4 extends Tag(nameOf(Implementations4_0_0.createTransactionRequestSepa))
|
||||
object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.createTransactionRequestCounterparty))
|
||||
object ApiEndpoint6 extends Tag(nameOf(Implementations4_0_0.createTransactionRequestRefund))
|
||||
object ApiEndpoint7 extends Tag(nameOf(Implementations4_0_0.createTransactionRequestFreeForm))
|
||||
object ApiEndpoint8 extends Tag(nameOf(Implementations4_0_0.answerTransactionRequestChallenge))
|
||||
object ApiEndpoint9 extends Tag(nameOf(Implementations4_0_0.createTransactionRequestSimple))
|
||||
|
||||
def transactionCount(accounts: BankAccount*): Int = {
|
||||
accounts.foldLeft(0)((accumulator, account) => {
|
||||
@ -606,13 +612,14 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers {
|
||||
feature("we can create transaction requests -- FREE_FORM") {
|
||||
|
||||
if (APIUtil.getPropsAsBoolValue("transactionRequests_enabled", false) == false) {
|
||||
ignore("No challenge, No FX ", ApiEndpoint1) {}
|
||||
ignore("No challenge, No FX ", ApiEndpoint7) {}
|
||||
} else {
|
||||
scenario("No challenge, No FX ", ApiEndpoint1) {
|
||||
scenario("No challenge, No FX ", ApiEndpoint7) {
|
||||
|
||||
When("we prepare all the conditions for a normal success -- V400 Create Transaction Request")
|
||||
val helper = defaultSetup(FREE_FORM.toString)
|
||||
|
||||
addEntitlement(helper.bankId.value, resourceUser1.userId, CanCreateAnyTransactionRequest.toString)
|
||||
|
||||
Then("we call the 'V400 Create Transaction Request' endpoint")
|
||||
val createTransactionRequestResponse = helper.makeCreateTransReqRequest
|
||||
|
||||
@ -636,12 +643,13 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers {
|
||||
}
|
||||
|
||||
if (APIUtil.getPropsAsBoolValue("transactionRequests_enabled", false) == false) {
|
||||
ignore("No challenge, With FX ", ApiEndpoint1) {}
|
||||
ignore("No challenge, With FX ", ApiEndpoint7) {}
|
||||
} else {
|
||||
scenario("No challenge, With FX ", ApiEndpoint1) {
|
||||
scenario("No challenge, With FX ", ApiEndpoint7) {
|
||||
|
||||
When("we prepare all the conditions for a normal success -- V400 Create Transaction Request")
|
||||
val helper = defaultSetup(FREE_FORM.toString)
|
||||
addEntitlement(helper.bankId.value, resourceUser1.userId, CanCreateAnyTransactionRequest.toString)
|
||||
|
||||
And("We set the special conditions for different currencies")
|
||||
val fromCurrency = "AED"
|
||||
@ -676,11 +684,12 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers {
|
||||
}
|
||||
|
||||
if (APIUtil.getPropsAsBoolValue("transactionRequests_enabled", false) == false) {
|
||||
ignore("With challenge, No FX", ApiEndpoint1, ApiEndpoint2) {}
|
||||
ignore("With challenge, No FX", ApiEndpoint7, ApiEndpoint2) {}
|
||||
} else {
|
||||
scenario("With challenge, No FX ", ApiEndpoint1, ApiEndpoint2) {
|
||||
scenario("With challenge, No FX ", ApiEndpoint7, ApiEndpoint2) {
|
||||
When("we prepare all the conditions for a normal success -- V400 Create Transaction Request")
|
||||
val helper = defaultSetup(FREE_FORM.toString)
|
||||
addEntitlement(helper.bankId.value, resourceUser1.userId, CanCreateAnyTransactionRequest.toString)
|
||||
And("We set the special conditions for different currencies")
|
||||
val fromCurrency = "AED"
|
||||
val toCurrency = "AED"
|
||||
@ -722,11 +731,12 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers {
|
||||
}
|
||||
|
||||
if (APIUtil.getPropsAsBoolValue("transactionRequests_enabled", false) == false) {
|
||||
ignore("With challenge, With FX ", ApiEndpoint1, ApiEndpoint2) {}
|
||||
ignore("With challenge, With FX ", ApiEndpoint7, ApiEndpoint2) {}
|
||||
} else {
|
||||
scenario("With challenge, With FX ", ApiEndpoint1, ApiEndpoint2) {
|
||||
scenario("With challenge, With FX ", ApiEndpoint7, ApiEndpoint2) {
|
||||
When("we prepare all the conditions for a normal success -- V400 Create Transaction Request")
|
||||
val helper = defaultSetup(FREE_FORM.toString)
|
||||
addEntitlement(helper.bankId.value, resourceUser1.userId, CanCreateAnyTransactionRequest.toString)
|
||||
|
||||
And("We set the special conditions for different currencies")
|
||||
val fromCurrency = "AED"
|
||||
@ -1172,7 +1182,7 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers {
|
||||
helper.setAnswerTransactionRequest(challengeId = challengeOfUser1.map(_.id).getOrElse(""))
|
||||
And("we call the endpoint")
|
||||
val ansReqResponseUser1 = helper.makeAnswerRequest
|
||||
ansReqResponseUser1.body.extract[ErrorMessage].message should equal(NextChallengePending)
|
||||
ansReqResponseUser1.body.extract[ErrorMessage].message contains extractErrorMessageCode(NextChallengePending) should be (true)
|
||||
|
||||
Then("We call 'Answer Transaction Request Challenge - V400' to finish the request")
|
||||
And("we prepare the parameters for it")
|
||||
@ -1420,7 +1430,7 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers {
|
||||
helper.setAnswerTransactionRequest(challengeId = challengeOfUser1.map(_.id).getOrElse(""))
|
||||
And("we call the endpoint")
|
||||
val ansReqResponseUser1 = helper.makeAnswerRequest
|
||||
ansReqResponseUser1.body.extract[ErrorMessage].message should equal(NextChallengePending)
|
||||
ansReqResponseUser1.body.extract[ErrorMessage].message contains extractErrorMessageCode(NextChallengePending) should be (true)
|
||||
|
||||
Then("We call 'Answer Transaction Request Challenge - V400' to finish the request")
|
||||
And("we prepare the parameters for it")
|
||||
|
||||
75
obp-api/src/test/scala/code/api/v5_0_0/ATMTest.scala
Normal file
75
obp-api/src/test/scala/code/api/v5_0_0/ATMTest.scala
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
Open Bank Project - API
|
||||
Copyright (C) 2011-2019, TESOBE GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Email: contact@tesobe.com
|
||||
TESOBE GmbH
|
||||
Osloerstrasse 16/17
|
||||
Berlin 13359, Germany
|
||||
|
||||
This product includes software developed at
|
||||
TESOBE (http://www.tesobe.com/)
|
||||
*/
|
||||
package code.api.v5_0_0
|
||||
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{postUserAuthContextJson, postUserAuthContextUpdateJsonV310}
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.ApiRole._
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.v3_1_0.CustomerJsonV310
|
||||
import code.api.v5_0_0.OBPAPI5_0_0.Implementations5_0_0
|
||||
import code.entitlement.Entitlement
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
import com.openbankproject.commons.model.ErrorMessage
|
||||
import com.openbankproject.commons.util.ApiVersion
|
||||
import net.liftweb.json.Serialization.write
|
||||
import org.scalatest.Tag
|
||||
|
||||
import scala.language.postfixOps
|
||||
|
||||
class ATMTest extends V500ServerSetupAsync {
|
||||
|
||||
/**
|
||||
* Test tags
|
||||
* Example: To run tests with tag "getPermissions":
|
||||
* mvn test -D tagsToInclude
|
||||
*
|
||||
* This is made possible by the scalatest maven plugin
|
||||
*/
|
||||
object VersionOfApi extends Tag(ApiVersion.v5_0_0.toString)
|
||||
object ApiEndpoint1 extends Tag(nameOf(Implementations5_0_0.headAtms))
|
||||
|
||||
|
||||
feature("Head Bank ATMS v5.0.0") {
|
||||
scenario("We will call the Add endpoint properly", ApiEndpoint1, VersionOfApi) {
|
||||
When("We make a request v5.0.0")
|
||||
lazy val bankId = randomBankId
|
||||
val request500 = (v5_0_0_Request / "banks" / bankId / "atms").HEAD
|
||||
val response500 = makeHeadRequest(request500)
|
||||
Then("We should get a 200")
|
||||
response500.code should equal(200)
|
||||
}
|
||||
scenario("We will call the Add endpoint with wrong BankId", ApiEndpoint1, VersionOfApi) {
|
||||
When("We make a request v5.0.0")
|
||||
val request500 = (v5_0_0_Request / "banks" / "xx_non_existing_bank_id" / "atms").HEAD
|
||||
val response500 = makeHeadRequest(request500)
|
||||
Then("We should get a 404")
|
||||
response500.code should equal(404)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
128
obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala
Normal file
128
obp-api/src/test/scala/code/api/v5_0_0/ConsentRequestTest.scala
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
Open Bank Project - API
|
||||
Copyright (C) 2011-2019, TESOBE GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Email: contact@tesobe.com
|
||||
TESOBE GmbH
|
||||
Osloerstrasse 16/17
|
||||
Berlin 13359, Germany
|
||||
|
||||
This product includes software developed at
|
||||
TESOBE (http://www.tesobe.com/)
|
||||
*/
|
||||
package code.api.v5_0_0
|
||||
|
||||
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.ApiRole._
|
||||
import code.api.util.Consent
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.api.v3_1_0.{PostConsentChallengeJsonV310, PostConsentEntitlementJsonV310, PostConsentViewJsonV310}
|
||||
import code.api.v5_0_0.OBPAPI5_0_0.Implementations5_0_0
|
||||
import code.consent.ConsentStatus
|
||||
import code.entitlement.Entitlement
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
import com.openbankproject.commons.model.{AccountRoutingJsonV121, ErrorMessage}
|
||||
import com.openbankproject.commons.util.ApiVersion
|
||||
import net.liftweb.json.Serialization.write
|
||||
import org.scalatest.Tag
|
||||
|
||||
import scala.language.postfixOps
|
||||
|
||||
class ConsentRequestTest extends V500ServerSetupAsync {
|
||||
|
||||
/**
|
||||
* Test tags
|
||||
* Example: To run tests with tag "getPermissions":
|
||||
* mvn test -D tagsToInclude
|
||||
*
|
||||
* This is made possible by the scalatest maven plugin
|
||||
*/
|
||||
object VersionOfApi extends Tag(ApiVersion.v5_0_0.toString)
|
||||
object ApiEndpoint1 extends Tag(nameOf(Implementations5_0_0.createConsentRequest))
|
||||
object ApiEndpoint2 extends Tag(nameOf(Implementations5_0_0.getConsentByConsentRequestId))
|
||||
object ApiEndpoint3 extends Tag(nameOf(Implementations5_0_0.createConsentByConsentRequestId))
|
||||
object ApiEndpoint4 extends Tag(nameOf(Implementations5_0_0.getConsentByConsentRequestId))
|
||||
|
||||
lazy val entitlements = List(PostConsentEntitlementJsonV310("", CanGetAnyUser.toString()))
|
||||
lazy val accountAccess = List(AccountAccessV500(
|
||||
account_routing = AccountRoutingJsonV121(
|
||||
scheme = "AccountId",
|
||||
address = testAccountId1.value), "owner"))
|
||||
lazy val postConsentRequestJsonV310 = SwaggerDefinitionsJSON.postConsentRequestJsonV500
|
||||
.copy(entitlements=Some(entitlements))
|
||||
.copy(consumer_id=None)
|
||||
.copy(account_access=accountAccess)
|
||||
|
||||
val createConsentRequestWithoutLoginUrl = (v5_0_0_Request / "consumer" / "consent-requests")
|
||||
val createConsentRequestUrl = (v5_0_0_Request / "consumer"/ "consent-requests").POST<@(user1)
|
||||
def getConsentRequestUrl(requestId:String) = (v5_0_0_Request / "consumer"/ "consent-requests"/requestId).GET<@(user1)
|
||||
def createConsentByRequestIdUrl(requestId:String) = (v5_0_0_Request / "consumer"/ "consent-requests"/requestId/"EMAIL"/"consents").POST<@(user1)
|
||||
def getConsentByRequestIdUrl(requestId:String) = (v5_0_0_Request / "consumer"/ "consent-requests"/requestId/"consents").GET<@(user1)
|
||||
|
||||
feature("Create/Get Consent Request v5.0.0") {
|
||||
scenario("We will call the Create endpoint without a user credentials", ApiEndpoint1, VersionOfApi) {
|
||||
When("We make a request v5.0.0")
|
||||
val response500 = makePostRequest(createConsentRequestWithoutLoginUrl, write(postConsentRequestJsonV310))
|
||||
Then("We should get a 401")
|
||||
response500.code should equal(401)
|
||||
response500.body.extract[ErrorMessage].message should equal (ApplicationNotIdentified)
|
||||
}
|
||||
|
||||
scenario("We will call the Create, Get and Delete endpoints with user credentials ", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) {
|
||||
When(s"We try $ApiEndpoint1 v5.0.0")
|
||||
val createConsentResponse = makePostRequest(createConsentRequestUrl, write(postConsentRequestJsonV310))
|
||||
Then("We should get a 201")
|
||||
createConsentResponse.code should equal(201)
|
||||
val createConsentRequestResponseJson = createConsentResponse.body.extract[ConsentRequestResponseJson]
|
||||
val consentRequestId = createConsentRequestResponseJson.consent_request_id
|
||||
|
||||
When("We try to make the GET request v5.0.0")
|
||||
val successGetRes = makeGetRequest(getConsentRequestUrl(consentRequestId))
|
||||
Then("We should get a 200")
|
||||
successGetRes.code should equal(200)
|
||||
val getConsentRequestResponseJson = successGetRes.body.extract[ConsentRequestResponseJson]
|
||||
getConsentRequestResponseJson.payload should not be("")
|
||||
|
||||
When("We try to make the GET request v5.0.0")
|
||||
Then("We grant the role and test it again")
|
||||
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAnyUser.toString)
|
||||
val createConsentByRequestResponse = makePostRequest(createConsentByRequestIdUrl(consentRequestId), write(""))
|
||||
Then("We should get a 200")
|
||||
createConsentByRequestResponse.code should equal(201)
|
||||
val consentId = createConsentByRequestResponse.body.extract[ConsentJsonV500].consent_id
|
||||
|
||||
val answerConsentChallengeRequest = (v5_0_0_Request / "banks" / testBankId1.value / "consents" / consentId / "challenge").POST <@ (user1)
|
||||
val challenge = Consent.challengeAnswerAtTestEnvironment
|
||||
val post = PostConsentChallengeJsonV310(answer = challenge)
|
||||
val answerConsentChallengeResponse = makePostRequest(answerConsentChallengeRequest, write(post))
|
||||
Then("We should get a 201")
|
||||
answerConsentChallengeResponse.code should equal(201)
|
||||
|
||||
When("We try to make the GET request v5.0.0")
|
||||
val getConsentByRequestResponse = makeGetRequest(getConsentByRequestIdUrl(consentRequestId))
|
||||
Then("We should get a 200")
|
||||
getConsentByRequestResponse.code should equal(200)
|
||||
val getConsentByRequestResponseJson = getConsentByRequestResponse.body.extract[ConsentJsonV500]
|
||||
getConsentByRequestResponseJson.consent_request_id.head should be(consentRequestId)
|
||||
getConsentByRequestResponseJson.status should be(ConsentStatus.ACCEPTED.toString)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -154,6 +154,7 @@ class UserAuthContextTest extends V500ServerSetupAsync {
|
||||
|
||||
When("We need to prepare the bankId first.")
|
||||
val requestCreateCustomer = (v5_0_0_Request / "banks" / testBankId1.value / "customers").POST <@(user1)
|
||||
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateCustomerAtAnyBank.toString)
|
||||
val responseCustomer = makePostRequest(requestCreateCustomer, write(SwaggerDefinitionsJSON.postCustomerJsonV310))
|
||||
Then("We should get a 201")
|
||||
responseCustomer.code should equal(201)
|
||||
|
||||
@ -1,10 +1,23 @@
|
||||
package code.api.v5_0_0
|
||||
|
||||
import code.api.v4_0_0.BanksJson400
|
||||
import code.setup._
|
||||
import dispatch.Req
|
||||
|
||||
import scala.util.Random.nextInt
|
||||
|
||||
trait V500ServerSetupAsync extends ServerSetupWithTestDataAsync with DefaultUsers {
|
||||
|
||||
def v5_0_0_Request: Req = baseRequest / "obp" / "v5.0.0"
|
||||
|
||||
|
||||
def randomBankId : String = {
|
||||
def getBanksInfo : APIResponse = {
|
||||
val request = v5_0_0_Request / "banks"
|
||||
makeGetRequest(request)
|
||||
}
|
||||
val banksJson = getBanksInfo.body.extract[BanksJson400]
|
||||
val randomPosition = nextInt(banksJson.banks.size)
|
||||
val bank = banksJson.banks(randomPosition)
|
||||
bank.id
|
||||
}
|
||||
}
|
||||
@ -105,7 +105,7 @@ class MappedAtmsProviderTest extends ServerSetup {
|
||||
atms.size should equal(3)
|
||||
|
||||
And("they should be the licensed ones")
|
||||
atms should equal (expectedAtms)
|
||||
atms.sortBy(_.atmId.value) should equal (expectedAtms.sortBy(_.atmId.value))
|
||||
}
|
||||
|
||||
scenario("We try to get atms for a bank that doesn't have any") {
|
||||
|
||||
@ -104,7 +104,7 @@ class MappedBranchesProviderTest extends ServerSetup {
|
||||
branches.size should equal(3)
|
||||
|
||||
And("they should be the licensed ones")
|
||||
branches should equal (expectedBranches)
|
||||
branches.sortBy(_.branchId.value) should equal (expectedBranches.sortBy(_.branchId.value))
|
||||
}
|
||||
|
||||
scenario("We try to get branches for a bank that doesn't have any") {
|
||||
|
||||
@ -93,7 +93,7 @@ class MappedProductsProviderTest extends ServerSetup {
|
||||
products.size should equal(3)
|
||||
|
||||
And("they should be the licensed ones")
|
||||
products should equal (expectedProducts)
|
||||
products.sortBy(_.code.value) should equal (expectedProducts.sortBy(_.code.value))
|
||||
}
|
||||
|
||||
scenario("We try to get Products for a bank that doesn't have any") {
|
||||
|
||||
@ -71,8 +71,8 @@ trait LocalMappedConnectorTestSetup extends TestConnectorSetupWithStandardPermis
|
||||
BankAccountRouting.create
|
||||
.BankId(bankId.value)
|
||||
.AccountId(accountId.value)
|
||||
.AccountRoutingScheme(randomString(4))
|
||||
.AccountRoutingAddress(randomString(4))
|
||||
.AccountRoutingScheme("AccountId")
|
||||
.AccountRoutingAddress(accountId.value)
|
||||
.saveMe
|
||||
MappedBankAccount.create
|
||||
.bank(bankId.value)
|
||||
|
||||
@ -258,6 +258,16 @@ trait SendServerRequests {
|
||||
val jsonReq = createRequest(reqData)
|
||||
getAPIResponse(jsonReq)
|
||||
}
|
||||
|
||||
/**
|
||||
* this method does a HEAD request given a URL
|
||||
*/
|
||||
def makeHeadRequest(req: Req, params: List[(String, String)] = Nil) : APIResponse = {
|
||||
val extra_headers = Map.empty ++ params
|
||||
val reqData = extractParamsAndHeaders(req.HEAD, "", "UTF-8", extra_headers)
|
||||
val jsonReq = createRequest(reqData)
|
||||
getAPIResponse(jsonReq)
|
||||
}
|
||||
/**
|
||||
* this method does a GET request given a URL
|
||||
*/
|
||||
|
||||
@ -192,6 +192,7 @@ object DynamicEntityOperation extends OBPEnumeration[DynamicEntityOperation] {
|
||||
sealed trait LanguageParam extends EnumValue
|
||||
object LanguageParam extends OBPEnumeration[LanguageParam] {
|
||||
object EN extends Value
|
||||
object ES extends Value
|
||||
object ZH extends Value
|
||||
}
|
||||
|
||||
|
||||
@ -71,10 +71,10 @@ class JsonUtilsTest extends FlatSpec with Matchers {
|
||||
val DateWithMsFormat = new SimpleDateFormat(DateWithMs)
|
||||
val DateWithMsRollbackFormat = new SimpleDateFormat(DateWithMsRollback)
|
||||
|
||||
val DateWithDayExampleString: String = "2017-09-19"
|
||||
val DateWithSecondsExampleString: String = "2017-09-19T02:31:05Z"
|
||||
val DateWithMsExampleString: String = "2017-09-19T02:31:05.000Z"
|
||||
val DateWithMsRollbackExampleString: String = "2017-09-19T02:31:05.000+0000"
|
||||
val DateWithDayExampleString: String = "1100-01-01"
|
||||
val DateWithSecondsExampleString: String = "1100-01-01T01:01:01Z"
|
||||
val DateWithMsExampleString: String = "1100-01-01T01:01:01.000Z"
|
||||
val DateWithMsRollbackExampleString: String = "1100-01-01T01:01:01.000+0000"
|
||||
|
||||
|
||||
val DateWithDayExampleObject = DateWithDayFormat.parse(DateWithDayExampleString)
|
||||
|
||||
6
pom.xml
6
pom.xml
@ -12,13 +12,13 @@
|
||||
<properties>
|
||||
<scala.version>2.12</scala.version>
|
||||
<scala.compiler>2.12.10</scala.compiler>
|
||||
<akka.version>2.5.19</akka.version>
|
||||
<akka-streams-kafka.version>0.22</akka-streams-kafka.version>
|
||||
<akka.version>2.5.31</akka.version>
|
||||
<akka-streams-kafka.version>2.0.5</akka-streams-kafka.version>
|
||||
<kafka.version>1.1.0</kafka.version>
|
||||
<avro.version>1.8.2</avro.version>
|
||||
<lift.version>3.4.1</lift.version>
|
||||
<jetty.version>9.4.12.v20180830</jetty.version>
|
||||
<log4j.version>2.15.0</log4j.version>
|
||||
<log4j.version>2.17.1</log4j.version>
|
||||
<obp-ri.version>2016.11-RC6-SNAPSHOT</obp-ri.version>
|
||||
<!-- Common plugin settings -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
@ -3,6 +3,11 @@
|
||||
### Most recent changes at top of file
|
||||
```
|
||||
Date Commit Action
|
||||
08/08/2022 1ff7bf0a removed props `meeting.tokbox_enabled`, `meeting.tokbox_api_key` and `meeting.tokbox_api_secret`.
|
||||
removed three endpoints: getMeetings, getMeeting and createMeeting in V200.
|
||||
05/08/2022 ba690c1f renamed props `transaction_request_challenge_ttl` to `transactionRequest.challenge.ttl.seconds`.
|
||||
02/08/2022 7b06563f added new props `userAuthContextUpdateRequest.challenge.ttl.seconds`, default is 600 seconds.
|
||||
01/08/2022 d94687d6 added new props `answer_transactionRequest_challenge_allowed_attempts`, default is 3 .
|
||||
03/05/2022 5fe70270 added new props `transaction_request_challenge_ttl`, default is 600 seconds.
|
||||
31/03/2022 a0262c3f added new value SIMPLE to props `transactionRequests_supported_types`
|
||||
added new props `SIMPLE_OTP_INSTRUCTION_TRANSPORT`, default value is `DUMMY`
|
||||
|
||||
Loading…
Reference in New Issue
Block a user