mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 15:27:01 +00:00
commit
80cf296387
276
obp-api/src/main/resources/docs/glossary/Keycloak_Onboarding.md
Normal file
276
obp-api/src/main/resources/docs/glossary/Keycloak_Onboarding.md
Normal file
@ -0,0 +1,276 @@
|
||||
# Keycloak Onboarding Guide
|
||||
|
||||
## Overview
|
||||
Keycloak is an open-source identity and access management solution that provides production-grade OpenID Connect (OIDC) and OAuth 2.0 authentication services for the OBP-API. It serves as a centralized authentication provider that enables secure user authentication, authorization, and user management for banking applications.
|
||||
|
||||
## What is Keycloak?
|
||||
Keycloak is a comprehensive identity provider that offers:
|
||||
- **Single Sign-On (SSO)** capabilities across multiple applications
|
||||
- **Identity Federation** with external identity providers (Google, Facebook, LDAP, etc.)
|
||||
- **User Management** with role-based access control
|
||||
- **Multi-factor Authentication (MFA)** support
|
||||
- **Standards Compliance** with OAuth 2.0, OpenID Connect, and SAML 2.0
|
||||
|
||||
## Prerequisites for Onboarding
|
||||
|
||||
### System Requirements
|
||||
- Docker or Java 11+ for running Keycloak
|
||||
- Network access to Keycloak instance (default: `localhost:7787`)
|
||||
- Administrative access to configure realms and clients
|
||||
|
||||
### OBP-API Configuration
|
||||
Before integrating with Keycloak, ensure your OBP-API instance has the following properties configured:
|
||||
|
||||
# Enable OAuth2 login
|
||||
`allow_oauth2_login=true`
|
||||
|
||||
# Keycloak-specific configuration
|
||||
`oauth2.oidc_provider=keycloak`
|
||||
`oauth2.keycloak.host=http://localhost:7787`
|
||||
`oauth2.keycloak.realm=master`
|
||||
`oauth2.keycloak.issuer=http://localhost:7787/realms/master`
|
||||
`oauth2.jwk_set.url=http://localhost:7787/realms/master/protocol/openid-connect/certs`
|
||||
|
||||
## Step-by-Step Onboarding Process
|
||||
|
||||
### 1. Setting Up Keycloak Instance
|
||||
|
||||
#### Option A: Using Docker (Recommended for Development)
|
||||
|
||||
The OBP project provides a pre-configured Keycloak Docker image available at:
|
||||
**Docker Hub**: https://hub.docker.com/r/openbankproject/obp-keycloak/tags
|
||||
|
||||
##### Inspect Available Tags
|
||||
First, check available image tags:
|
||||
`docker search openbankproject/obp-keycloak`
|
||||
|
||||
Common available tags:
|
||||
- `main-themed`: Latest themed version with OBP branding
|
||||
- `latest`: Standard latest version
|
||||
- `dev`: Development version
|
||||
- Version-specific tags (e.g., `21.1.2-themed`)
|
||||
|
||||
##### Pull and Inspect the Image
|
||||
# Pull the OBP-themed Keycloak image
|
||||
`docker pull openbankproject/obp-keycloak:main-themed`
|
||||
|
||||
# Inspect image details
|
||||
`docker inspect openbankproject/obp-keycloak:main-themed`
|
||||
|
||||
# View image layers and size
|
||||
`docker images | grep openbankproject/obp-keycloak`
|
||||
|
||||
# Check image history
|
||||
`docker history openbankproject/obp-keycloak:main-themed`
|
||||
|
||||
##### Basic Container Setup
|
||||
# Run Keycloak container with basic configuration
|
||||
`docker run -p 7787:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \`
|
||||
` openbankproject/obp-keycloak:main-themed start-dev`
|
||||
|
||||
##### Advanced Container Setup with Persistent Data
|
||||
# Create a volume for persistent data
|
||||
`docker volume create keycloak_data`
|
||||
|
||||
# Run with persistent data and custom configuration
|
||||
`docker run -d --name obp-keycloak \`
|
||||
` -p 7787:8080 \`
|
||||
` -e KEYCLOAK_ADMIN=admin \`
|
||||
` -e KEYCLOAK_ADMIN_PASSWORD=admin \`
|
||||
` -e KC_DB=h2-file \`
|
||||
` -e KC_DB_URL_PATH=/opt/keycloak/data/keycloak \`
|
||||
` -v keycloak_data:/opt/keycloak/data \`
|
||||
` openbankproject/obp-keycloak:main-themed start-dev`
|
||||
|
||||
##### Container Management Commands
|
||||
# Check container status
|
||||
`docker ps | grep obp-keycloak`
|
||||
|
||||
# View container logs
|
||||
`docker logs obp-keycloak`
|
||||
|
||||
# Follow logs in real-time
|
||||
`docker logs -f obp-keycloak`
|
||||
|
||||
# Stop the container
|
||||
`docker stop obp-keycloak`
|
||||
|
||||
# Start existing container
|
||||
`docker start obp-keycloak`
|
||||
|
||||
# Remove container (data will be preserved in volume)
|
||||
`docker rm obp-keycloak`
|
||||
|
||||
##### Troubleshooting Container Issues
|
||||
# Execute commands inside running container
|
||||
`docker exec -it obp-keycloak bash`
|
||||
|
||||
# Check container resource usage
|
||||
`docker stats obp-keycloak`
|
||||
|
||||
# Inspect container configuration
|
||||
`docker inspect obp-keycloak`
|
||||
|
||||
##### Environment Variables and Configuration
|
||||
The OBP Keycloak image supports these key environment variables:
|
||||
|
||||
**Admin Configuration:**
|
||||
- `KEYCLOAK_ADMIN`: Admin username (default: admin)
|
||||
- `KEYCLOAK_ADMIN_PASSWORD`: Admin password
|
||||
- `KC_PROXY`: Proxy mode (edge, reencrypt, passthrough)
|
||||
|
||||
**Database Configuration:**
|
||||
- `KC_DB`: Database type (h2-file, postgres, mysql, mariadb)
|
||||
- `KC_DB_URL`: Database connection URL
|
||||
- `KC_DB_USERNAME`: Database username
|
||||
- `KC_DB_PASSWORD`: Database password
|
||||
|
||||
**Network Configuration:**
|
||||
- `KC_HOSTNAME`: External hostname for Keycloak
|
||||
- `KC_HTTP_PORT`: HTTP port (default: 8080)
|
||||
- `KC_HTTPS_PORT`: HTTPS port (default: 8443)
|
||||
|
||||
**Example with External Database:**
|
||||
`docker run -d --name obp-keycloak \`
|
||||
` -p 7787:8080 \`
|
||||
` -e KEYCLOAK_ADMIN=admin \`
|
||||
` -e KEYCLOAK_ADMIN_PASSWORD=securepassword \`
|
||||
` -e KC_DB=postgres \`
|
||||
` -e KC_DB_URL=jdbc:postgresql://localhost:5432/keycloak \`
|
||||
` -e KC_DB_USERNAME=keycloak \`
|
||||
` -e KC_DB_PASSWORD=keycloak_password \`
|
||||
` openbankproject/obp-keycloak:main-themed start-dev`
|
||||
|
||||
#### Option B: Manual Installation
|
||||
1. Download Keycloak from [keycloak.org](https://www.keycloak.org/)
|
||||
2. Extract and navigate to the Keycloak directory
|
||||
3. Start Keycloak in development mode:
|
||||
`./bin/kc.sh start-dev --http-port=7787`
|
||||
|
||||
### 2. Initial Keycloak Configuration
|
||||
|
||||
#### Access Keycloak Admin Console
|
||||
- Navigate to <a href="http://localhost:7787/admin" target="_blank">http://localhost:7787/admin</a>
|
||||
- Login with admin credentials (admin/admin for Docker setup)
|
||||
|
||||
#### Create or Configure Realm
|
||||
1. Select or create a realm (e.g., "obp" or use "master")
|
||||
2. Configure realm settings:
|
||||
- **SSL required**: None (for development) or External requests (for production)
|
||||
- **User registration**: Enable if needed
|
||||
- **Login with email**: Enable for email-based authentication
|
||||
|
||||
### 3. Configure OBP Client Application
|
||||
|
||||
#### Create Client
|
||||
1. Navigate to **Clients** → **Create Client**
|
||||
2. Set **Client ID**: `obp-client` (or your preferred identifier)
|
||||
3. Set **Client Type**: `OpenID Connect`
|
||||
4. Enable **Client authentication**
|
||||
|
||||
#### Configure Client Settings
|
||||
- **Root URL**: <a href="getServerUrl" target="_blank">your OBP-API URL</a>
|
||||
- **Valid redirect URIs**: <a href="getServerUrl/auth/openid-connect/callback" target="_blank">callback URL</a>
|
||||
- **Web origins**: <a href="getServerUrl" target="_blank">OBP-API URL</a>
|
||||
- **Access Type**: `confidential`
|
||||
|
||||
#### Retrieve Client Credentials
|
||||
1. Go to **Clients** → **obp-client** → **Credentials**
|
||||
2. Copy the **Client Secret** for OBP-API configuration
|
||||
|
||||
### 4. Update OBP-API Configuration
|
||||
|
||||
Add the following to your OBP-API properties file:
|
||||
|
||||
# OpenID Connect Client Configuration
|
||||
`openid_connect_1.button_text=Keycloak Login`
|
||||
`openid_connect_1.client_id=obp-client`
|
||||
`openid_connect_1.client_secret=YOUR_CLIENT_SECRET_HERE`
|
||||
`openid_connect_1.callback_url=getServerUrl/auth/openid-connect/callback`
|
||||
`openid_connect_1.endpoint.discovery=http://localhost:7787/realms/master/.well-known/openid-configuration`
|
||||
`openid_connect_1.endpoint.authorization=http://localhost:7787/realms/master/protocol/openid-connect/auth`
|
||||
`openid_connect_1.endpoint.userinfo=http://localhost:7787/realms/master/protocol/openid-connect/userinfo`
|
||||
`openid_connect_1.endpoint.token=http://localhost:7787/realms/master/protocol/openid-connect/token`
|
||||
`openid_connect_1.endpoint.jwks_uri=http://localhost:7787/realms/master/protocol/openid-connect/certs`
|
||||
`openid_connect_1.access_type_offline=true`
|
||||
|
||||
### 5. User Management Setup
|
||||
|
||||
#### Create Test Users
|
||||
1. Navigate to **Users** → **Add User**
|
||||
2. Fill in user details:
|
||||
- **Username**: `testuser`
|
||||
- **Email**: `testuser@example.com`
|
||||
- **First Name** and **Last Name**
|
||||
3. Set temporary password in **Credentials** tab
|
||||
4. Assign appropriate roles if using role-based access control
|
||||
|
||||
#### Configure User Attributes (Optional)
|
||||
Map additional user attributes that OBP-API might need:
|
||||
- `email` (standard)
|
||||
- `name` (standard)
|
||||
- `preferred_username` (standard)
|
||||
- Custom attributes as required by your banking application
|
||||
|
||||
### 6. Testing the Integration
|
||||
|
||||
#### Verify Configuration
|
||||
1. Restart OBP-API after configuration changes
|
||||
2. Navigate to <a href="getServerUrl" target="_blank">OBP-API login page</a>
|
||||
3. Look for "Keycloak Login" button (or your configured button text)
|
||||
|
||||
#### Test Authentication Flow
|
||||
1. Click the Keycloak login button
|
||||
2. Should redirect to Keycloak login page
|
||||
3. Login with test user credentials
|
||||
4. Should redirect back to OBP-API with successful authentication
|
||||
5. Verify user session and JWT token validity
|
||||
|
||||
## Production Considerations
|
||||
|
||||
### Security Best Practices
|
||||
- **Use HTTPS** for all Keycloak and OBP-API communications
|
||||
- **Strong passwords** for admin accounts
|
||||
- **Regular updates** of Keycloak version
|
||||
- **Backup** realm configurations and user data
|
||||
- **Monitor** authentication logs for suspicious activity
|
||||
|
||||
### Scalability
|
||||
- **Database**: Configure external database (PostgreSQL, MySQL) instead of H2
|
||||
- **Clustering**: Set up Keycloak cluster for high availability
|
||||
- **Load Balancing**: Use load balancer for multiple Keycloak instances
|
||||
|
||||
### Integration with Banking Systems
|
||||
- **LDAP/Active Directory**: Integrate with existing user directories
|
||||
- **Multi-factor Authentication**: Enable MFA for enhanced security
|
||||
- **Compliance**: Ensure configuration meets banking regulatory requirements
|
||||
|
||||
## Troubleshooting Common Issues
|
||||
|
||||
### Authentication Failures
|
||||
- **Check redirect URIs**: Ensure they match exactly in both Keycloak and OBP-API
|
||||
- **Verify client credentials**: Confirm client ID and secret are correct
|
||||
- **Check realm configuration**: Ensure realm name matches in all configurations
|
||||
|
||||
### JWT Token Issues
|
||||
- **Issuer mismatch**: Verify `oauth2.keycloak.issuer` matches JWT `iss` claim
|
||||
- **JWKS endpoint**: Confirm `oauth2.jwk_set.url` is accessible and returns valid keys
|
||||
- **Token expiration**: Check token validity periods in Keycloak settings
|
||||
|
||||
### Network Connectivity
|
||||
- **Firewall rules**: Ensure ports 7787 (Keycloak) and 8080 (OBP-API) are accessible
|
||||
- **DNS resolution**: Verify hostnames resolve correctly
|
||||
- **SSL certificates**: For HTTPS setups, ensure valid certificates
|
||||
|
||||
## Additional Resources
|
||||
- <a href="https://www.keycloak.org/documentation" target="_blank">Keycloak Official Documentation</a>
|
||||
- <a href="https://openid.net/connect/" target="_blank">OpenID Connect Specification</a>
|
||||
- [OBP OAuth 2.0 Client Credentials Flow Manual](OAuth_2.0_Client_Credentials_Flow_Manual.md)
|
||||
- [OBP OIDC Configuration Guide](../../../OBP_OIDC_Configuration_Guide.md)
|
||||
|
||||
## Support
|
||||
For issues related to Keycloak integration with OBP-API:
|
||||
1. Check the OBP-API logs for detailed error messages
|
||||
2. Verify Keycloak server logs for authentication issues
|
||||
3. Consult the OBP community forums or GitHub issues
|
||||
4. Review the comprehensive troubleshooting section in the OBP documentation
|
||||
@ -2105,7 +2105,7 @@ trait APIMethods600 {
|
||||
NewStyle.function.hasEntitlement("", u.userId, canCreateGroupsAtAllBanks, callContext)
|
||||
}
|
||||
group <- Future {
|
||||
code.group.Group.group.vend.createGroup(
|
||||
code.group.GroupTrait.group.vend.createGroup(
|
||||
postJson.bank_id.filter(_.nonEmpty),
|
||||
postJson.group_name,
|
||||
postJson.group_description,
|
||||
@ -2169,7 +2169,7 @@ trait APIMethods600 {
|
||||
for {
|
||||
(Full(u), callContext) <- authenticatedAccess(cc)
|
||||
group <- Future {
|
||||
code.group.Group.group.vend.getGroup(groupId)
|
||||
code.group.GroupTrait.group.vend.getGroup(groupId)
|
||||
} map {
|
||||
x => unboxFullOrFail(x, callContext, s"$UnknownError Group not found", 404)
|
||||
}
|
||||
@ -2254,15 +2254,15 @@ trait APIMethods600 {
|
||||
}
|
||||
groups <- bankIdFilter match {
|
||||
case Some(bankId) =>
|
||||
code.group.Group.group.vend.getGroupsByBankId(Some(bankId)) map {
|
||||
code.group.GroupTrait.group.vend.getGroupsByBankId(Some(bankId)) map {
|
||||
x => unboxFullOrFail(x, callContext, s"$UnknownError Cannot get groups", 400)
|
||||
}
|
||||
case None if bankIdParam.isDefined =>
|
||||
code.group.Group.group.vend.getGroupsByBankId(None) map {
|
||||
code.group.GroupTrait.group.vend.getGroupsByBankId(None) map {
|
||||
x => unboxFullOrFail(x, callContext, s"$UnknownError Cannot get groups", 400)
|
||||
}
|
||||
case None =>
|
||||
code.group.Group.group.vend.getAllGroups() map {
|
||||
code.group.GroupTrait.group.vend.getAllGroups() map {
|
||||
x => unboxFullOrFail(x, callContext, s"$UnknownError Cannot get groups", 400)
|
||||
}
|
||||
}
|
||||
@ -2333,7 +2333,7 @@ trait APIMethods600 {
|
||||
json.extract[PutGroupJsonV600]
|
||||
}
|
||||
existingGroup <- Future {
|
||||
code.group.Group.group.vend.getGroup(groupId)
|
||||
code.group.GroupTrait.group.vend.getGroup(groupId)
|
||||
} map {
|
||||
x => unboxFullOrFail(x, callContext, s"$UnknownError Group not found", 404)
|
||||
}
|
||||
@ -2344,7 +2344,7 @@ trait APIMethods600 {
|
||||
NewStyle.function.hasEntitlement("", u.userId, canUpdateGroupsAtAllBanks, callContext)
|
||||
}
|
||||
updatedGroup <- Future {
|
||||
code.group.Group.group.vend.updateGroup(
|
||||
code.group.GroupTrait.group.vend.updateGroup(
|
||||
groupId,
|
||||
putJson.group_name,
|
||||
putJson.group_description,
|
||||
@ -2401,7 +2401,7 @@ trait APIMethods600 {
|
||||
for {
|
||||
(Full(u), callContext) <- authenticatedAccess(cc)
|
||||
existingGroup <- Future {
|
||||
code.group.Group.group.vend.getGroup(groupId)
|
||||
code.group.GroupTrait.group.vend.getGroup(groupId)
|
||||
} map {
|
||||
x => unboxFullOrFail(x, callContext, s"$UnknownError Group not found", 404)
|
||||
}
|
||||
@ -2412,7 +2412,7 @@ trait APIMethods600 {
|
||||
NewStyle.function.hasEntitlement("", u.userId, canDeleteGroupsAtAllBanks, callContext)
|
||||
}
|
||||
deleted <- Future {
|
||||
code.group.Group.group.vend.deleteGroup(groupId)
|
||||
code.group.GroupTrait.group.vend.deleteGroup(groupId)
|
||||
} map {
|
||||
x => unboxFullOrFail(x, callContext, s"$UnknownError Cannot delete group", 400)
|
||||
}
|
||||
|
||||
@ -1,45 +1,112 @@
|
||||
package code.group
|
||||
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.util.SimpleInjector
|
||||
import code.util.MappedUUID
|
||||
import net.liftweb.common.{Box, Empty, Full}
|
||||
import net.liftweb.mapper._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
import scala.concurrent.Future
|
||||
import com.openbankproject.commons.ExecutionContext.Implicits.global
|
||||
|
||||
object Group extends SimpleInjector {
|
||||
val group = new Inject(buildOne _) {}
|
||||
object MappedGroupProvider extends GroupProvider {
|
||||
|
||||
def buildOne: GroupProvider = MappedGroupProvider
|
||||
}
|
||||
|
||||
trait GroupProvider {
|
||||
def createGroup(
|
||||
override def createGroup(
|
||||
bankId: Option[String],
|
||||
groupName: String,
|
||||
groupDescription: String,
|
||||
listOfRoles: List[String],
|
||||
isEnabled: Boolean
|
||||
): Box[Group]
|
||||
): Box[GroupTrait] = {
|
||||
tryo {
|
||||
Group.create
|
||||
.BankId(bankId.getOrElse(""))
|
||||
.GroupName(groupName)
|
||||
.GroupDescription(groupDescription)
|
||||
.ListOfRoles(listOfRoles.mkString(","))
|
||||
.IsEnabled(isEnabled)
|
||||
.saveMe()
|
||||
}
|
||||
}
|
||||
|
||||
def getGroup(groupId: String): Box[Group]
|
||||
def getGroupsByBankId(bankId: Option[String]): Future[Box[List[Group]]]
|
||||
def getAllGroups(): Future[Box[List[Group]]]
|
||||
override def getGroup(groupId: String): Box[GroupTrait] = {
|
||||
Group.find(By(Group.GroupId, groupId))
|
||||
}
|
||||
|
||||
def updateGroup(
|
||||
override def getGroupsByBankId(bankId: Option[String]): Future[Box[List[GroupTrait]]] = {
|
||||
Future {
|
||||
tryo {
|
||||
bankId match {
|
||||
case Some(id) =>
|
||||
Group.findAll(By(Group.BankId, id))
|
||||
case None =>
|
||||
Group.findAll(By(Group.BankId, ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def getAllGroups(): Future[Box[List[GroupTrait]]] = {
|
||||
Future {
|
||||
tryo {
|
||||
Group.findAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def updateGroup(
|
||||
groupId: String,
|
||||
groupName: Option[String],
|
||||
groupDescription: Option[String],
|
||||
listOfRoles: Option[List[String]],
|
||||
isEnabled: Option[Boolean]
|
||||
): Box[Group]
|
||||
): Box[GroupTrait] = {
|
||||
Group.find(By(Group.GroupId, groupId)).flatMap { group =>
|
||||
tryo {
|
||||
groupName.foreach(name => group.GroupName(name))
|
||||
groupDescription.foreach(desc => group.GroupDescription(desc))
|
||||
listOfRoles.foreach(roles => group.ListOfRoles(roles.mkString(",")))
|
||||
isEnabled.foreach(enabled => group.IsEnabled(enabled))
|
||||
group.saveMe()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def deleteGroup(groupId: String): Box[Boolean]
|
||||
override def deleteGroup(groupId: String): Box[Boolean] = {
|
||||
Group.find(By(Group.GroupId, groupId)).flatMap { group =>
|
||||
tryo {
|
||||
group.delete_!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait Group {
|
||||
def groupId: String
|
||||
def bankId: Option[String]
|
||||
def groupName: String
|
||||
def groupDescription: String
|
||||
def listOfRoles: List[String]
|
||||
def isEnabled: Boolean
|
||||
class Group extends GroupTrait with LongKeyedMapper[Group] with IdPK with CreatedUpdated {
|
||||
|
||||
def getSingleton = Group
|
||||
|
||||
object GroupId extends MappedUUID(this)
|
||||
object BankId extends MappedString(this, 255) // Empty string for system-level groups
|
||||
object GroupName extends MappedString(this, 255)
|
||||
object GroupDescription extends MappedText(this)
|
||||
object ListOfRoles extends MappedText(this) // Comma-separated list of roles
|
||||
object IsEnabled extends MappedBoolean(this)
|
||||
|
||||
override def groupId: String = GroupId.get.toString
|
||||
override def bankId: Option[String] = {
|
||||
val id = BankId.get
|
||||
if (id == null || id.isEmpty) None else Some(id)
|
||||
}
|
||||
override def groupName: String = GroupName.get
|
||||
override def groupDescription: String = GroupDescription.get
|
||||
override def listOfRoles: List[String] = {
|
||||
val rolesStr = ListOfRoles.get
|
||||
if (rolesStr == null || rolesStr.isEmpty) List.empty
|
||||
else rolesStr.split(",").map(_.trim).filter(_.nonEmpty).toList
|
||||
}
|
||||
override def isEnabled: Boolean = IsEnabled.get
|
||||
}
|
||||
|
||||
object Group extends Group with LongKeyedMetaMapper[Group] {
|
||||
override def dbTableName = "Group" // define the DB table name
|
||||
override def dbIndexes = Index(GroupId) :: Index(BankId) :: super.dbIndexes
|
||||
}
|
||||
45
obp-api/src/main/scala/code/group/GroupTrait.scala
Normal file
45
obp-api/src/main/scala/code/group/GroupTrait.scala
Normal file
@ -0,0 +1,45 @@
|
||||
package code.group
|
||||
|
||||
import net.liftweb.common.Box
|
||||
import net.liftweb.util.SimpleInjector
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
object GroupTrait extends SimpleInjector {
|
||||
val group = new Inject(buildOne _) {}
|
||||
|
||||
def buildOne: GroupProvider = MappedGroupProvider
|
||||
}
|
||||
|
||||
trait GroupProvider {
|
||||
def createGroup(
|
||||
bankId: Option[String],
|
||||
groupName: String,
|
||||
groupDescription: String,
|
||||
listOfRoles: List[String],
|
||||
isEnabled: Boolean
|
||||
): Box[GroupTrait]
|
||||
|
||||
def getGroup(groupId: String): Box[GroupTrait]
|
||||
def getGroupsByBankId(bankId: Option[String]): Future[Box[List[GroupTrait]]]
|
||||
def getAllGroups(): Future[Box[List[GroupTrait]]]
|
||||
|
||||
def updateGroup(
|
||||
groupId: String,
|
||||
groupName: Option[String],
|
||||
groupDescription: Option[String],
|
||||
listOfRoles: Option[List[String]],
|
||||
isEnabled: Option[Boolean]
|
||||
): Box[GroupTrait]
|
||||
|
||||
def deleteGroup(groupId: String): Box[Boolean]
|
||||
}
|
||||
|
||||
trait GroupTrait {
|
||||
def groupId: String
|
||||
def bankId: Option[String]
|
||||
def groupName: String
|
||||
def groupDescription: String
|
||||
def listOfRoles: List[String]
|
||||
def isEnabled: Boolean
|
||||
}
|
||||
@ -1,112 +0,0 @@
|
||||
package code.group
|
||||
|
||||
import code.util.MappedUUID
|
||||
import net.liftweb.common.{Box, Empty, Full}
|
||||
import net.liftweb.mapper._
|
||||
import net.liftweb.util.Helpers.tryo
|
||||
|
||||
import scala.concurrent.Future
|
||||
import com.openbankproject.commons.ExecutionContext.Implicits.global
|
||||
|
||||
object MappedGroupProvider extends GroupProvider {
|
||||
|
||||
override def createGroup(
|
||||
bankId: Option[String],
|
||||
groupName: String,
|
||||
groupDescription: String,
|
||||
listOfRoles: List[String],
|
||||
isEnabled: Boolean
|
||||
): Box[Group] = {
|
||||
tryo {
|
||||
MappedGroup.create
|
||||
.BankId(bankId.getOrElse(""))
|
||||
.GroupName(groupName)
|
||||
.GroupDescription(groupDescription)
|
||||
.ListOfRoles(listOfRoles.mkString(","))
|
||||
.IsEnabled(isEnabled)
|
||||
.saveMe()
|
||||
}
|
||||
}
|
||||
|
||||
override def getGroup(groupId: String): Box[Group] = {
|
||||
MappedGroup.find(By(MappedGroup.GroupId, groupId))
|
||||
}
|
||||
|
||||
override def getGroupsByBankId(bankId: Option[String]): Future[Box[List[Group]]] = {
|
||||
Future {
|
||||
tryo {
|
||||
bankId match {
|
||||
case Some(id) =>
|
||||
MappedGroup.findAll(By(MappedGroup.BankId, id))
|
||||
case None =>
|
||||
MappedGroup.findAll(By(MappedGroup.BankId, ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def getAllGroups(): Future[Box[List[Group]]] = {
|
||||
Future {
|
||||
tryo {
|
||||
MappedGroup.findAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def updateGroup(
|
||||
groupId: String,
|
||||
groupName: Option[String],
|
||||
groupDescription: Option[String],
|
||||
listOfRoles: Option[List[String]],
|
||||
isEnabled: Option[Boolean]
|
||||
): Box[Group] = {
|
||||
MappedGroup.find(By(MappedGroup.GroupId, groupId)).flatMap { group =>
|
||||
tryo {
|
||||
groupName.foreach(name => group.GroupName(name))
|
||||
groupDescription.foreach(desc => group.GroupDescription(desc))
|
||||
listOfRoles.foreach(roles => group.ListOfRoles(roles.mkString(",")))
|
||||
isEnabled.foreach(enabled => group.IsEnabled(enabled))
|
||||
group.saveMe()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def deleteGroup(groupId: String): Box[Boolean] = {
|
||||
MappedGroup.find(By(MappedGroup.GroupId, groupId)).flatMap { group =>
|
||||
tryo {
|
||||
group.delete_!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MappedGroup extends Group with LongKeyedMapper[MappedGroup] with IdPK with CreatedUpdated {
|
||||
|
||||
def getSingleton = MappedGroup
|
||||
|
||||
object GroupId extends MappedUUID(this)
|
||||
object BankId extends MappedString(this, 255) // Empty string for system-level groups
|
||||
object GroupName extends MappedString(this, 255)
|
||||
object GroupDescription extends MappedText(this)
|
||||
object ListOfRoles extends MappedText(this) // Comma-separated list of roles
|
||||
object IsEnabled extends MappedBoolean(this)
|
||||
|
||||
override def groupId: String = GroupId.get.toString
|
||||
override def bankId: Option[String] = {
|
||||
val id = BankId.get
|
||||
if (id == null || id.isEmpty) None else Some(id)
|
||||
}
|
||||
override def groupName: String = GroupName.get
|
||||
override def groupDescription: String = GroupDescription.get
|
||||
override def listOfRoles: List[String] = {
|
||||
val rolesStr = ListOfRoles.get
|
||||
if (rolesStr == null || rolesStr.isEmpty) List.empty
|
||||
else rolesStr.split(",").map(_.trim).filter(_.nonEmpty).toList
|
||||
}
|
||||
override def isEnabled: Boolean = IsEnabled.get
|
||||
}
|
||||
|
||||
object MappedGroup extends MappedGroup with LongKeyedMetaMapper[MappedGroup] {
|
||||
override def dbTableName = "Group" // define the DB table name
|
||||
override def dbIndexes = Index(GroupId) :: Index(BankId) :: super.dbIndexes
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user