diff --git a/obp-api/src/main/resources/docs/glossary/Keycloak_Onboarding.md b/obp-api/src/main/resources/docs/glossary/Keycloak_Onboarding.md
new file mode 100644
index 0000000000..d5c1d1be92
--- /dev/null
+++ b/obp-api/src/main/resources/docs/glossary/Keycloak_Onboarding.md
@@ -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 http://localhost:7787/admin
+- 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**: your OBP-API URL
+- **Valid redirect URIs**: callback URL
+- **Web origins**: OBP-API URL
+- **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 OBP-API login page
+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
+- Keycloak Official Documentation
+- OpenID Connect Specification
+- [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
\ No newline at end of file
diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala
index d84b498c78..eb842588b5 100644
--- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala
+++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala
@@ -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)
}
diff --git a/obp-api/src/main/scala/code/group/Group.scala b/obp-api/src/main/scala/code/group/Group.scala
index de5f16accb..a89d7423c2 100644
--- a/obp-api/src/main/scala/code/group/Group.scala
+++ b/obp-api/src/main/scala/code/group/Group.scala
@@ -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()
+ }
+ }
+
+ override def getGroup(groupId: String): Box[GroupTrait] = {
+ Group.find(By(Group.GroupId, groupId))
+ }
- def getGroup(groupId: String): Box[Group]
- def getGroupsByBankId(bankId: Option[String]): Future[Box[List[Group]]]
- def getAllGroups(): Future[Box[List[Group]]]
+ 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, ""))
+ }
+ }
+ }
+ }
- def updateGroup(
+ 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()
+ }
+ }
+ }
+
+ override def deleteGroup(groupId: String): Box[Boolean] = {
+ Group.find(By(Group.GroupId, groupId)).flatMap { group =>
+ tryo {
+ group.delete_!
+ }
+ }
+ }
+}
+
+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)
- def deleteGroup(groupId: String): Box[Boolean]
+ 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
}
-trait Group {
- def groupId: String
- def bankId: Option[String]
- def groupName: String
- def groupDescription: String
- def listOfRoles: List[String]
- def isEnabled: Boolean
+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
}
\ No newline at end of file
diff --git a/obp-api/src/main/scala/code/group/GroupTrait.scala b/obp-api/src/main/scala/code/group/GroupTrait.scala
new file mode 100644
index 0000000000..939454b724
--- /dev/null
+++ b/obp-api/src/main/scala/code/group/GroupTrait.scala
@@ -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
+}
\ No newline at end of file
diff --git a/obp-api/src/main/scala/code/group/MappedGroup.scala b/obp-api/src/main/scala/code/group/MappedGroup.scala
deleted file mode 100644
index 5579b9c341..0000000000
--- a/obp-api/src/main/scala/code/group/MappedGroup.scala
+++ /dev/null
@@ -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
-}
\ No newline at end of file