Skip to content

Commit 98d03f7

Browse files
author
Adrien
committed
feat(dpd): add database provider plugins
1 parent 6c071ea commit 98d03f7

File tree

14 files changed

+1106
-0
lines changed

14 files changed

+1106
-0
lines changed

dpb/README.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# 📦 DPB - Database Provider Plugin
2+
3+
The Database Provider Plugin (DPB) is responsible for managing relational database access through configurable datasources within the LinID Identity Manager API ecosystem.
4+
5+
---
6+
7+
## 🚀 Overview
8+
9+
This plugin enables dynamic persistence of entities to PostgreSQL databases using **jOOQ** for SQL construction and execution. It supports configuration-driven entity mapping without requiring static entity definitions, allowing flexible database integration through YAML configuration.
10+
11+
⚠️ **Current Scope**: PostgreSQL only (extensible architecture for future)
12+
13+
---
14+
15+
## 📋 Configuration Model
16+
17+
The plugin integrates with the global YAML configuration:
18+
19+
```yaml
20+
providers:
21+
- name: ExampleDatabase
22+
type: database
23+
url: jdbc:postgresql://DATABASE_HOST:DATABASE_PORT/DATABASE_NAME
24+
username: DATABASE_USER
25+
password: DATABASE_PASSWORD
26+
27+
entities:
28+
- name: account
29+
route: accounts
30+
provider: ExampleDatabase
31+
tasks:
32+
# ... task definitions
33+
access:
34+
table: ACCOUNT_TABLE_NAME
35+
attributes:
36+
- name: id
37+
type: String
38+
required: false
39+
input: Text
40+
access:
41+
column: ID_COLUMN_NAME
42+
- name: username
43+
type: String
44+
required: true
45+
input: Text
46+
access:
47+
column: USERNAME_COLUMN_NAME
48+
```
49+
50+
### Configuration Fields
51+
52+
| Key | Required | Description |
53+
| --------------------------------------- | -------- | ------------------------------------------------------------------------- |
54+
| `providers[].name` | ✅ | Unique identifier for the database provider |
55+
| `providers[].type` | ✅ | Must be `database` to activate this plugin |
56+
| `providers[].url` | ✅ | JDBC connection URL (PostgreSQL format: `jdbc:postgresql://host:port/db`) |
57+
| `providers[].username` | ✅ | Database authentication username |
58+
| `providers[].password` | ✅ | Database authentication password |
59+
| `entities[].provider` | ✅ | Reference to the database provider name |
60+
| `entities[].access.table` | ✅ | Target database table name for this entity |
61+
| `entities[].attributes[].access.column` | ✅ | Target database column name for this attribute |
62+
63+
---
64+
65+
## 🏗️ Architecture
66+
67+
### Connection Pooling
68+
69+
- **Pool Provider**: HikariCP
70+
- **Pool Scope**: One pool per configured database provider
71+
- **Configuration**:
72+
- Maximum pool size
73+
- Idle timeout
74+
- Connection timeout
75+
- Validation query (if needed)
76+
77+
### Dynamic Mapping
78+
79+
1. Entity → Table mapping via `entities[].access.table`
80+
2. Attribute → Column mapping via `entities[].attributes[].access.column`
81+
3. Only declared attributes are persisted
82+
4. No static JPA entities required
83+
84+
### jOOQ Integration
85+
86+
- All queries constructed via `DSLContext`
87+
- Dynamic table/field resolution using `DSL.name(...)`
88+
- Bind parameters for all values
89+
- Type-safe SQL construction
90+
91+
---
92+
93+
## 🛠 Building the Project
94+
95+
To compile and build the plugin:
96+
97+
```bash
98+
mvn clean install
99+
```
100+
101+
---
102+
103+
## 🧪 Running Tests
104+
105+
Run tests using:
106+
107+
```bash
108+
mvn test
109+
```
110+
111+
---
112+
113+
## 📝 Usage
114+
115+
1. **Configure Provider**: Add a provider with `type: database` in your YAML configuration
116+
2. **Define Entity Mapping**: Configure `access.table` and column mappings via `attributes[].access.column`
117+
3. **Provider Type**: The plugin responds to provider type `Database`
118+
119+
Example minimal configuration:
120+
121+
```yaml
122+
providers:
123+
- name: MyPostgres
124+
type: database
125+
url: jdbc:postgresql://localhost:5432/mydb
126+
username: dbuser
127+
password: dbpass
128+
129+
entities:
130+
- name: user
131+
route: users
132+
provider: MyPostgres
133+
access:
134+
table: users
135+
attributes:
136+
- name: id
137+
type: String
138+
access:
139+
column: user_id
140+
```
141+
142+
---

dpb/changelog.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Added
11+
12+
- Initial plugin structure for Database Provider Plugin (DPB)
13+
14+
### Technical Details
15+
16+
### Planned
17+

dpb/pom.xml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0"
2+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>io.github.linagora.linid.im</groupId>
9+
<artifactId>linid-im-api-community-plugins</artifactId>
10+
<version>0.1.0</version>
11+
<relativePath>../pom.xml</relativePath>
12+
</parent>
13+
14+
<artifactId>dpb</artifactId>
15+
<version>0.1.0</version>
16+
<name>Database Provider Plugin for linid-im-api</name>
17+
<description>A database provider plugin for handling database operations</description>
18+
<url>https://github.com/linagora/linid-im-api-community-plugins</url>
19+
20+
<licenses>
21+
<license>
22+
<name>GNU Affero General Public License v3.0</name>
23+
<url>https://www.gnu.org/licenses/agpl-3.0.html</url>
24+
<distribution>repo</distribution>
25+
<comments>This project is licensed under the GNU AGPL v3.0</comments>
26+
</license>
27+
</licenses>
28+
29+
<developers>
30+
<developer>
31+
<id>Hamilcar31</id>
32+
<name>Adrien CÉRÉ</name>
33+
<email>adrien.cere@gmail.com</email>
34+
</developer>
35+
</developers>
36+
37+
<scm>
38+
<connection>scm:git:git://github.com/linagora/linid-im-api-community-plugins.git</connection>
39+
<developerConnection>scm:git:ssh://git@github.com:linagora/linid-im-api-community-plugins.git</developerConnection>
40+
<url>https://github.com/linagora/linid-im-api-community-plugins</url>
41+
</scm>
42+
43+
<dependencies>
44+
<dependency>
45+
<groupId>org.jooq</groupId>
46+
<artifactId>jooq</artifactId>
47+
</dependency>
48+
49+
<dependency>
50+
<groupId>com.zaxxer</groupId>
51+
<artifactId>HikariCP</artifactId>
52+
</dependency>
53+
54+
<dependency>
55+
<groupId>org.postgresql</groupId>
56+
<artifactId>postgresql</artifactId>
57+
<scope>runtime</scope>
58+
</dependency>
59+
60+
<!-- Test dependencies -->
61+
<!-- <dependency>
62+
<groupId>org.postgresql</groupId>
63+
<artifactId>postgresql</artifactId>
64+
<scope>test</scope>
65+
</dependency> -->
66+
</dependencies>
67+
68+
</project>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright (C) 2020-2026 Linagora
3+
*
4+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
5+
* Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
6+
* any later version, provided you comply with the Additional Terms applicable for LinID Identity Manager software by
7+
* LINAGORA pursuant to Section 7 of the GNU Affero General Public License, subsections (b), (c), and (e), pursuant to
8+
* which these Appropriate Legal Notices must notably (i) retain the display of the "LinID™" trademark/logo at the top
9+
* of the interface window, the display of the “You are using the Open Source and free version of LinID™, powered by
10+
* Linagora © 2009–2013. Contribute to LinID R&D by subscribing to an Enterprise offer!” infobox and in the e-mails
11+
* sent with the Program, notice appended to any type of outbound messages (e.g. e-mail and meeting requests) as well
12+
* as in the LinID Identity Manager user interface, (ii) retain all hypertext links between LinID Identity Manager
13+
* and https://linid.org/, as well as between LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA
14+
* intellectual property rights over its trademarks and commercial brands. Other Additional Terms apply, see
15+
* <http://www.linagora.com/licenses/> for more details.
16+
*
17+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
18+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19+
* details.
20+
*
21+
* You should have received a copy of the GNU Affero General Public License and its applicable Additional Terms for
22+
* LinID Identity Manager along with this program. If not, see <http://www.gnu.org/licenses/> for the GNU Affero
23+
* General Public License version 3 and <http://www.linagora.com/licenses/> for the Additional Terms applicable to the
24+
* LinID Identity Manager software.
25+
*/
26+
27+
package io.github.linagora.linid.im.dpb;
28+
29+
import io.github.linagora.linid.im.corelib.plugin.config.dto.ProviderConfiguration;
30+
import io.github.linagora.linid.im.corelib.plugin.entity.DynamicEntity;
31+
import io.github.linagora.linid.im.corelib.plugin.provider.ProviderPlugin;
32+
import io.github.linagora.linid.im.corelib.plugin.task.TaskEngine;
33+
import io.github.linagora.linid.im.corelib.plugin.task.TaskExecutionContext;
34+
import io.github.linagora.linid.im.dpb.service.CrudService;
35+
import org.springframework.beans.factory.annotation.Autowired;
36+
import org.springframework.data.domain.Page;
37+
import org.springframework.data.domain.Pageable;
38+
import org.springframework.stereotype.Component;
39+
import org.springframework.util.MultiValueMap;
40+
41+
/**
42+
* Database Provider Plugin implementation.
43+
*/
44+
@Component
45+
public class DatabaseProviderPlugin implements ProviderPlugin {
46+
47+
private final CrudService crudService;
48+
private final TaskEngine taskEngine;
49+
50+
@Autowired
51+
public DatabaseProviderPlugin(final CrudService crudService, final TaskEngine taskEngine) {
52+
this.crudService = crudService;
53+
this.taskEngine = taskEngine;
54+
}
55+
56+
@Override
57+
public DynamicEntity create(TaskExecutionContext context, ProviderConfiguration config,
58+
DynamicEntity dynamicEntity) {
59+
taskEngine.execute(dynamicEntity, context, "beforeCreate");
60+
crudService.insert(config, dynamicEntity);
61+
taskEngine.execute(dynamicEntity, context, "afterCreate");
62+
63+
return dynamicEntity;
64+
}
65+
66+
public boolean delete(TaskExecutionContext context, ProviderConfiguration config, String id,
67+
DynamicEntity dynamicEntity) {
68+
taskEngine.execute(dynamicEntity, context, "beforeDelete");
69+
crudService.delete(config, id, dynamicEntity);
70+
taskEngine.execute(dynamicEntity, context, "afterDelete");
71+
72+
return true;
73+
}
74+
75+
@Override
76+
public boolean supports(String type) {
77+
return "database".equals(type);
78+
}
79+
80+
@Override
81+
public DynamicEntity patch(TaskExecutionContext context, ProviderConfiguration config, String id,
82+
DynamicEntity dynamicEntity) {
83+
return dynamicEntity;
84+
}
85+
86+
@Override
87+
public DynamicEntity findById(TaskExecutionContext context, ProviderConfiguration config, String id,
88+
DynamicEntity dynamicEntity) {
89+
return null;
90+
}
91+
92+
@Override
93+
public Page<DynamicEntity> findAll(TaskExecutionContext context, ProviderConfiguration config,
94+
MultiValueMap<String, String> filters, Pageable pageable, DynamicEntity dynamicEntity) {
95+
96+
taskEngine.execute(dynamicEntity, context, "beforeFindAll");
97+
Page<DynamicEntity> result = crudService.select(config, dynamicEntity);
98+
taskEngine.execute(dynamicEntity, context, "afterFindAll");
99+
100+
return result;
101+
}
102+
103+
@Override
104+
public DynamicEntity update(TaskExecutionContext context, ProviderConfiguration config, String id,
105+
DynamicEntity dynamicEntity) {
106+
taskEngine.execute(dynamicEntity, context, "beforeUpdate");
107+
crudService.update(config, id, dynamicEntity);
108+
taskEngine.execute(dynamicEntity, context, "afterUpdate");
109+
110+
return dynamicEntity;
111+
}
112+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (C) 2020-2026 Linagora
3+
*
4+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
5+
* Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
6+
* any later version, provided you comply with the Additional Terms applicable for LinID Identity Manager software by
7+
* LINAGORA pursuant to Section 7 of the GNU Affero General Public License, subsections (b), (c), and (e), pursuant to
8+
* which these Appropriate Legal Notices must notably (i) retain the display of the "LinID™" trademark/logo at the top
9+
* of the interface window, the display of the “You are using the Open Source and free version of LinID™, powered by
10+
* Linagora © 2009–2013. Contribute to LinID R&D by subscribing to an Enterprise offer!” infobox and in the e-mails
11+
* sent with the Program, notice appended to any type of outbound messages (e.g. e-mail and meeting requests) as well
12+
* as in the LinID Identity Manager user interface, (ii) retain all hypertext links between LinID Identity Manager
13+
* and https://linid.org/, as well as between LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA
14+
* intellectual property rights over its trademarks and commercial brands. Other Additional Terms apply, see
15+
* <http://www.linagora.com/licenses/> for more details.
16+
*
17+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
18+
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19+
* details.
20+
*
21+
* You should have received a copy of the GNU Affero General Public License and its applicable Additional Terms for
22+
* LinID Identity Manager along with this program. If not, see <http://www.gnu.org/licenses/> for the GNU Affero
23+
* General Public License version 3 and <http://www.linagora.com/licenses/> for the Additional Terms applicable to the
24+
* LinID Identity Manager software.
25+
*/
26+
27+
/**
28+
* Database Provider Plugin package dpb.
29+
*/
30+
31+
package io.github.linagora.linid.im.dpb;

0 commit comments

Comments
 (0)