mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 09:26:53 +00:00
Changed from full timestamp to hour-only format to match implementation. OLD: /active-rate-limits/2025-12-31T13:34:46Z (YYYY-MM-DDTHH:MM:SSZ) NEW: /active-rate-limits/2025-12-31-13 (YYYY-MM-DD-HH) Benefits: - API now matches actual implementation (hour-level caching) - Eliminates timezone/minute truncation confusion - Clearer semantics: 'active during this hour' not 'at this second' - Direct cache key mapping improves performance - Simpler date parsing (no timezone handling needed) Files changed: - APIMethods600.scala: Updated endpoint and date parsing - RateLimitsTest.scala: Updated all test cases to new format - Glossary.scala: Updated API documentation - introductory_system_documentation.md: Updated user docs This is a breaking change but necessary to align API with implementation. Rate limits are cached and queried at hour granularity, so the API should reflect that reality.
9.9 KiB
9.9 KiB
OBP API ABAC Rules - Quick Reference Guide
Most Common Patterns
Quick reference for the most frequently used ABAC rule patterns in OBP API v6.0.0.
1. Self-Access Checks
Allow users to access their own data:
// Basic self-access
userOpt.exists(_.userId == authenticatedUser.userId)
// Self-access by email
userOpt.exists(_.emailAddress == authenticatedUser.emailAddress)
// Self-access for accounts
accountOpt.exists(_.accountHolders.exists(_.userId == authenticatedUser.userId))
2. Role-Based Access
Check user roles and permissions:
// Admin access
authenticatedUserAttributes.exists(attr => attr.name == "role" && attr.value == "admin")
// Multiple role check
authenticatedUserAttributes.exists(attr => attr.name == "role" && List("admin", "manager", "supervisor").contains(attr.value))
// Department-based access
authenticatedUserAttributes.exists(ua => ua.name == "department" && accountAttributes.exists(aa => aa.name == "department" && ua.value == aa.value))
3. Balance and Amount Checks
Transaction and balance validations:
// Transaction within account balance
transactionOpt.exists(t => accountOpt.exists(a => t.amount < a.balance))
// Transaction within 50% of balance
transactionOpt.exists(t => accountOpt.exists(a => t.amount <= a.balance * 0.5))
// Account balance threshold
accountOpt.exists(_.balance > 1000)
// No overdraft
transactionOpt.exists(t => accountOpt.exists(a => a.balance - t.amount >= 0))
4. Currency Matching
Ensure currency consistency:
// Transaction currency matches account
transactionOpt.exists(t => accountOpt.exists(a => t.currency == a.currency))
// Specific currency check
accountOpt.exists(acc => acc.currency == "USD" && acc.balance > 5000)
5. Bank and Account Validation
Verify bank and account relationships:
// Specific bank
bankOpt.exists(_.bankId.value == "gh.29.uk")
// Account belongs to bank
accountOpt.exists(a => bankOpt.exists(b => a.bankId == b.bankId.value))
// Transaction request matches account
transactionRequestOpt.exists(tr => accountOpt.exists(a => tr.this_account_id.value == a.accountId.value))
6. Customer Validation
Customer and KYC checks:
// Customer email matches user
customerOpt.exists(_.email == authenticatedUser.emailAddress)
// Active customer relationship
customerOpt.exists(_.relationshipStatus == "ACTIVE")
// KYC verified
userAttributes.exists(attr => attr.name == "kyc_status" && attr.value == "verified")
// VIP customer
customerAttributes.exists(attr => attr.name == "vip_status" && attr.value == "true")
7. Transaction Type Checks
Validate transaction types:
// Specific transaction type
transactionOpt.exists(_.transactionType.contains("TRANSFER"))
// Amount limit by type
transactionOpt.exists(t => t.amount < 10000 && t.transactionType.exists(_.contains("WIRE")))
// Transaction request type
transactionRequestOpt.exists(_.type == "SEPA")
8. Delegation (On Behalf Of)
Handle delegation scenarios:
// No delegation or self-delegation only
onBehalfOfUserOpt.isEmpty || onBehalfOfUserOpt.exists(_.userId == authenticatedUser.userId)
// Authorized delegation
onBehalfOfUserOpt.isEmpty || onBehalfOfUserAttributes.exists(_.name == "authorized")
// Delegation to target user
onBehalfOfUserOpt.exists(obu => userOpt.exists(u => obu.userId == u.userId))
9. Tier and Level Matching
Check tier compatibility:
// User tier matches account tier
userAttributes.exists(ua => ua.name == "tier" && accountAttributes.exists(aa => aa.name == "tier" && ua.value == aa.value))
// Minimum tier requirement
userAttributes.find(_.name == "tier").exists(_.value.toInt >= 2)
// Premium account
accountAttributes.exists(attr => attr.name == "account_tier" && attr.value == "premium")
10. IP and Context Checks
Request context validation:
// Internal network
callContext.exists(_.ipAddress.exists(_.startsWith("192.168")))
// Specific HTTP method
callContext.exists(_.verb.exists(_ == "GET"))
// URL path check
callContext.exists(_.url.exists(_.contains("/accounts/")))
// Authentication method
authenticatedUserAuthContext.exists(_.key == "auth_method" && _.value == "certificate")
11. Combined Conditions
Complex multi-condition rules:
// Admin OR self-access
authenticatedUserAttributes.exists(_.name == "role" && _.value == "admin") || userOpt.exists(_.userId == authenticatedUser.userId)
// Manager accessing team member's data
authenticatedUserAttributes.exists(_.name == "role" && _.value == "manager") && userOpt.exists(_.userId != authenticatedUser.userId)
// Verified user with proper delegation
userAttributes.exists(_.name == "kyc_status" && _.value == "verified") && (onBehalfOfUserOpt.isEmpty || onBehalfOfUserAttributes.exists(_.name == "authorized"))
12. Safe Option Handling
Always use safe patterns:
// ✅ CORRECT: Use exists()
accountOpt.exists(_.balance > 1000)
// ✅ CORRECT: Use pattern matching
userOpt match { case Some(u) => u.userId == authenticatedUser.userId case None => false }
// ✅ CORRECT: Use forall() for negative conditions
userOpt.forall(!_.isDeleted.getOrElse(false))
// ✅ CORRECT: Use map() with getOrElse()
accountOpt.map(_.balance).getOrElse(0) > 100
// ❌ WRONG: Direct .get (can throw exception)
// accountOpt.get.balance > 1000
13. Real-World Business Scenarios
Loan Approval
customerAttributes.exists(ca => ca.name == "credit_score" && ca.value.toInt > 650) &&
accountOpt.exists(_.balance > 5000) &&
!transactionAttributes.exists(_.name == "fraud_flag")
Wire Transfer Authorization
transactionOpt.exists(t => t.amount < 100000 && t.transactionType.exists(_.contains("WIRE"))) &&
authenticatedUserAttributes.exists(_.name == "wire_authorized" && _.value == "true")
Joint Account Access
accountOpt.exists(a => a.accountHolders.exists(h =>
h.userId == authenticatedUser.userId ||
h.emailAddress == authenticatedUser.emailAddress
))
Account Closure (Self-service or Manager)
accountOpt.exists(a =>
(a.balance == 0 && userOpt.exists(_.userId == authenticatedUser.userId)) ||
authenticatedUserAttributes.exists(_.name == "role" && _.value == "manager")
)
VIP Priority Processing
customerAttributes.exists(_.name == "vip_status" && _.value == "true") ||
accountAttributes.exists(_.name == "account_tier" && _.value == "platinum") ||
userAttributes.exists(_.name == "priority_level" && _.value.toInt >= 9)
Cross-Border Transaction Compliance
transactionAttributes.exists(_.name == "compliance_docs_attached") &&
transactionOpt.exists(_.amount <= 50000) &&
customerAttributes.exists(_.name == "international_enabled" && _.value == "true")
14. Common Mistakes to Avoid
❌ Wrong Property Names
// WRONG - Snake case
user.user_id
account.account_id
user.email_address
// CORRECT - Camel case
user.userId
account.accountId
user.emailAddress
❌ Wrong Parameter Names
// WRONG - Missing Opt suffix
user.userId
account.balance
bank.bankId
// CORRECT - Proper naming
authenticatedUser.userId // No Opt (always present)
userOpt.exists(_.userId == ...) // Has Opt (optional)
accountOpt.exists(_.balance > ...) // Has Opt (optional)
bankOpt.exists(_.bankId == ...) // Has Opt (optional)
❌ Unsafe Option Access
// WRONG - Can throw NoSuchElementException
if (accountOpt.isDefined) {
accountOpt.get.balance > 1000
}
// CORRECT - Safe access
accountOpt.exists(_.balance > 1000)
15. Parameter Reference
Always Available (Required)
authenticatedUser- UserauthenticatedUserAttributes- List[UserAttributeTrait]authenticatedUserAuthContext- List[UserAuthContext]
Optional (Check before use)
onBehalfOfUserOpt- Option[User]onBehalfOfUserAttributes- List[UserAttributeTrait]onBehalfOfUserAuthContext- List[UserAuthContext]userOpt- Option[User]userAttributes- List[UserAttributeTrait]bankOpt- Option[Bank]bankAttributes- List[BankAttributeTrait]accountOpt- Option[BankAccount]accountAttributes- List[AccountAttribute]transactionOpt- Option[Transaction]transactionAttributes- List[TransactionAttribute]transactionRequestOpt- Option[TransactionRequest]transactionRequestAttributes- List[TransactionRequestAttributeTrait]customerOpt- Option[Customer]customerAttributes- List[CustomerAttribute]callContext- Option[CallContext]
16. Useful Operators and Methods
Comparison
==,!=,>,<,>=,<=
Logical
&&(AND),||(OR),!(NOT)
String Methods
contains(),startsWith(),endsWith(),split()
Option Methods
isDefined,isEmpty,exists(),forall(),map(),getOrElse()
List Methods
exists(),find(),filter(),forall(),map()
Numeric Conversions
toInt,toDouble,toLong
Quick Tips
- Always use camelCase for property names
- Check Optional parameters with
exists(), not.get - Use pattern matching for complex Option handling
- Attributes are Lists - use collection methods
- Rules return Boolean - true = granted, false = denied
- Combine conditions with
&&and|| - Test thoroughly before deploying to production
Getting Full Schema
To get the complete schema with all 170+ examples:
curl -X GET \
https://your-obp-instance/obp/v6.0.0/management/abac-rules-schema \
-H 'Authorization: DirectLogin token=YOUR_TOKEN'
Related Documentation
- Full Enhancement Spec:
obp-abac-schema-examples-enhancement.md - Before/After Comparison:
obp-abac-examples-before-after.md - Implementation Summary:
obp-abac-schema-examples-implementation-summary.md
Version: OBP API v6.0.0
Last Updated: 2024
Status: Production Ready ✅