Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ This project is dual licensed under the AGPL V3 (see NOTICE) and commercial lice
## Setup

### Installing JDK

#### With sdkman

A good way to manage JDK versions and install the correct version for OBP is [sdkman](https://sdkman.io/). If you have this installed then you can install the correct JDK easily using:

```
sdk env install
```
Expand Down Expand Up @@ -368,11 +370,13 @@ OBP-API now operates exclusively as a backend API server. There is no configurat
If your props file contains `server_mode`, you can safely remove it. The property is ignored.

**Before:**

```properties
server_mode=apis
```

**After:**

```properties
# server_mode property removed - no configuration needed
# OBP-API automatically runs in API-only mode
Expand Down Expand Up @@ -540,6 +544,7 @@ hostname=https://your-api-server.com
If not configured, the application will fail to start with error "OBP-00001: Hostname not specified".

The OpenAPI documentation will show a single server entry using the configured hostname:

```json
"servers": [
{"url": "https://your-api-server.com", "description": "Back-end server"}
Expand Down Expand Up @@ -683,17 +688,17 @@ If the email cannot be sent, returns 500 with the most specific OBP error code
for the underlying cause. The exception chain (class name + message) is always
appended after `Detail:` so the operator can diagnose without server logs:

| Failure | Status | Code |
|---|---|---|
| Caller has no email address | 400 | `OBP-30339 UserEmailAddressMissing` |
| `portal_external_url` unset | 500 | `OBP-10056 IncompleteServerConfiguration` |
| `mail.users.userinfo.sender.address` is default | 500 | `OBP-10056 IncompleteServerConfiguration` |
| SMTP rejected credentials | 500 | `OBP-30341 SmtpAuthenticationFailed` |
| TCP connect / host unreachable / timeout / DNS fail | 500 | `OBP-30342 SmtpConnectionFailed` |
| TLS / SSL handshake fail | 500 | `OBP-30343 SmtpTlsHandshakeFailed` |
| Recipient / From / message rejected by server | 500 | `OBP-30344 SmtpRecipientRejected` |
| Other Jakarta Mail protocol error | 500 | `OBP-30345 SmtpProtocolError` |
| Truly unknown | 500 | `OBP-30340 EmailSendingFailed` (fallback) |
| Failure | Status | Code |
| --------------------------------------------------- | ------ | ----------------------------------------- |
| Caller has no email address | 400 | `OBP-30339 UserEmailAddressMissing` |
| `portal_external_url` unset | 500 | `OBP-10056 IncompleteServerConfiguration` |
| `mail.users.userinfo.sender.address` is default | 500 | `OBP-10056 IncompleteServerConfiguration` |
| SMTP rejected credentials | 500 | `OBP-30341 SmtpAuthenticationFailed` |
| TCP connect / host unreachable / timeout / DNS fail | 500 | `OBP-30342 SmtpConnectionFailed` |
| TLS / SSL handshake fail | 500 | `OBP-30343 SmtpTlsHandshakeFailed` |
| Recipient / From / message rejected by server | 500 | `OBP-30344 SmtpRecipientRejected` |
| Other Jakarta Mail protocol error | 500 | `OBP-30345 SmtpProtocolError` |
| Truly unknown | 500 | `OBP-30340 EmailSendingFailed` (fallback) |

Use this from APIManager (or a `curl` with appropriate auth headers) to confirm
that signup / password-reset emails will be deliverable on this instance,
Expand All @@ -718,7 +723,9 @@ Body: { "username": "alice", "email": "alice@example.com" }
of whether the user exists, is already validated, the rate limit was hit, or
the SMTP send failed:
```json
{ "message": "If an unvalidated account exists for this username and email, a validation email has been sent." }
{
"message": "If an unvalidated account exists for this username and email, a validation email has been sent."
}
```
- **Rate-limited**: 3 attempts per email per hour, Redis-backed. Over-limit
requests still get the same 201.
Expand Down Expand Up @@ -980,3 +987,7 @@ Steps to add Spanish language:
- add file `lift-core_es_ES.properties` at the folder `/resources/i18n`

Please note that default translation file is `lift-core.properties`

## Funding Note

This repository has recived funding via The OGCR Project which has received funding from the European Union's Horizon Europe programme under grant agreement 101218854.
15 changes: 12 additions & 3 deletions obp-api/src/main/scala/code/api/util/NotificationUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,19 @@ import net.liftweb.common.Box


import scala.collection.immutable.List
import scala.concurrent.Future
import com.openbankproject.commons.ExecutionContext.Implicits.global

object NotificationUtil extends MdcLoggable {
def sendEmailRegardingAssignedRole(userId : String, entitlement: Entitlement): Unit = {
val user = Users.users.vend.getUserByUserId(userId)
sendEmailRegardingAssignedRole(user, entitlement)
// Fire-and-forget: the user lookup and the SMTP send both block, and the
// grant-entitlement response must not wait on them.
Future {
val user = Users.users.vend.getUserByUserId(userId)
sendEmailRegardingAssignedRole(user, entitlement)
}.failed.foreach(e =>
logger.error(s"sendEmailRegardingAssignedRole says: failed for userId=$userId role=${entitlement.roleName}", e)
)
}
def sendEmailRegardingAssignedRole(user: Box[User], entitlement: Entitlement): Unit = {
val mailSent = for {
Expand All @@ -32,7 +40,8 @@ object NotificationUtil extends MdcLoggable {
subject = s"You have been granted the role: ${entitlement.roleName}",
textContent = Some(bodyOfMessage)
)
//this is an async call
// Blocking SMTP send (Transport.send) — only call this off the request
// thread; the userId overload above wraps it in a Future.
CommonsEmailWrapper.sendTextEmail(emailContent)
}
if(mailSent.isEmpty) {
Expand Down
6 changes: 4 additions & 2 deletions obp-api/src/main/scala/code/api/v6_0_0/Http4s600.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13208,6 +13208,8 @@ object Http4s600 {
None,
http4sPartialFunction = Some(getConfigProps)
)
// Intentional drift from Lift's APIMethods600.scala source-of-truth:
// description reworded to mention "config" explicitly (searchability), post-migration.
resourceDocs += ResourceDoc(
implementedInApiVersion,
nameOf(getAppDirectory),
Expand All @@ -13216,11 +13218,11 @@ object Http4s600 {
"Get App Directory",
s"""Get connectivity information for apps in the OBP ecosystem.
|
|Returns configuration properties that apps (Portal, API Explorer, API Manager,
|Returns config (configuration) properties that apps (Portal, API Explorer, API Manager,
|Sandbox Populator, OIDC, Keycloak, Hola, MCP, Opey) and agents can use to discover
|endpoints in the OBP ecosystem.
|
|Any props starting with public_ and ending with _url are included automatically.
|Any config props starting with public_ and ending with _url are included automatically.
|
|Known public app URL props:
|${APIUtil.publicAppUrlPropNames.mkString(", ")}
Expand Down
Loading