Skip to content

Commit 74173c9

Browse files
authored
Merge pull request #231 from ARGOeu/devel
Version 1.7.0
2 parents f3aed4d + bfc903e commit 74173c9

File tree

63 files changed

+2861
-422
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+2861
-422
lines changed

CHANGELOG.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,32 @@ According to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) , the
2626

2727
---
2828

29-
### Unreleased - Added
29+
## 1.7.0 - 2025-07-25
30+
31+
---
32+
33+
## 1.7.0 - Added
34+
35+
- [#219](https://github.com/ARGOeu/argo-accounting/pull/219) - ACC-345 Sys Admin
36+
should be able to manage all projects.
37+
- [#221](https://github.com/ARGOeu/argo-accounting/pull/221) - ACC-355 Implement multitenancy
38+
via supporting different OIDC providers.
39+
- [#223](https://github.com/ARGOeu/argo-accounting/pull/223) - ACC-360 Installation
40+
Report.
41+
- [#224](https://github.com/ARGOeu/argo-accounting/pull/224) - ACC-361 Provider
42+
Report.
43+
- [#225](https://github.com/ARGOeu/argo-accounting/pull/225) - ACC-362 Project
44+
Report.
45+
- [#226](https://github.com/ARGOeu/argo-accounting/pull/226) - ACC-369 Aggregated
46+
Provider report.
47+
- [#227](https://github.com/ARGOeu/argo-accounting/pull/227) - ACC-366 Add issuer
48+
in the client's id.
49+
50+
## 1.6.1 - 2025-03-21
51+
52+
---
53+
54+
### 1.6.1 - Added
3055

3156
- [#211](https://github.com/ARGOeu/argo-accounting/pull/211) - ACC-319 Create
3257
an admin-only endpoint to update user information.

pom.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>org.grnet</groupId>
66
<artifactId>accounting-system</artifactId>
7-
<version>1.6.0</version>
7+
<version>1.7.0</version>
88
<properties>
99
<apache.common3.version>3.12.0</apache.common3.version>
1010
<compiler-plugin.version>3.8.1</compiler-plugin.version>
@@ -197,6 +197,11 @@
197197
<groupId>io.quarkus</groupId>
198198
<artifactId>quarkus-smallrye-metrics</artifactId>
199199
</dependency>
200+
<dependency>
201+
<groupId>commons-codec</groupId>
202+
<artifactId>commons-codec</artifactId>
203+
<version>1.18.0</version>
204+
</dependency>
200205
</dependencies>
201206
<build>
202207
<resources>

src/main/java/org/accounting/system/beans/RequestUserContext.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,59 @@
77
import lombok.Getter;
88
import lombok.Setter;
99
import org.accounting.system.enums.AccessType;
10+
import org.accounting.system.repositories.OidcTenantConfigRepository;
11+
import org.apache.commons.codec.digest.DigestUtils;
1012
import org.eclipse.microprofile.config.inject.ConfigProperty;
1113

1214
import java.util.Optional;
1315

1416
@RequestScoped
1517
public class RequestUserContext {
1618

19+
1720
@ConfigProperty(name = "person.key.to.retrieve.id.from.access.token")
21+
@Getter
1822
String personKey;
1923

2024
@ConfigProperty(name = "service.key.to.retrieve.id.from.access.token")
25+
@Getter
2126
String serviceKey;
2227

2328
@Inject
24-
private final TokenIntrospection tokenIntrospection;
29+
TokenIntrospection tokenIntrospection;
30+
31+
@Inject
32+
OidcTenantConfigRepository oidcTenantConfigRepository;
2533

2634
@Getter
2735
@Setter
2836
private AccessType accessType;
2937

30-
public RequestUserContext(TokenIntrospection tokenIntrospection) {
38+
public String getId() {
3139

32-
this.tokenIntrospection = tokenIntrospection;
33-
}
40+
var optional = oidcTenantConfigRepository.fetchOidcTenantConfigByIssuer(getIssuer());
41+
42+
if(optional.isPresent()){
3443

35-
public String getId(){
44+
var config = optional.get();
45+
46+
personKey = config.getUserIdTokenClaim();
47+
serviceKey = config.getServiceIdTokenClaim();
48+
}
3649

3750
try {
3851

39-
return tokenIntrospection.getJsonObject().getString(personKey);
52+
var input = tokenIntrospection.getJsonObject().getString(personKey)+ "|" + getIssuer();
53+
54+
return DigestUtils.sha256Hex(input);
4055

4156
} catch (Exception e) {
4257

4358
try{
4459

45-
return tokenIntrospection.getJsonObject().getString(serviceKey);
60+
var input = tokenIntrospection.getJsonObject().getString(serviceKey)+ "|" + getIssuer();
61+
62+
return DigestUtils.sha256Hex(input);
4663

4764
} catch (Exception ex){
4865

@@ -74,4 +91,9 @@ public Optional<String> getEmail(){
7491
return Optional.empty();
7592
}
7693
}
94+
95+
public String getIssuer(){
96+
97+
return tokenIntrospection.getJsonObject().getString("iss");
98+
}
7799
}

src/main/java/org/accounting/system/dtos/client/ClientResponseDto.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,18 @@ public class ClientResponseDto {
4848
@Schema(
4949
type = SchemaType.BOOLEAN,
5050
implementation = Boolean.class,
51-
description = "Whether a client is system admin or not",
51+
description = "Whether a client is system admin or not.",
5252
example = "false"
5353
)
5454
@JsonProperty("system_admin")
5555
public boolean systemAdmin;
56+
57+
@Schema(
58+
type = SchemaType.STRING,
59+
implementation = String.class,
60+
description = "The issuer URI that issued the access token the client receives.",
61+
example = "http://localhost:58080/realms/quarkus"
62+
)
63+
@JsonProperty("issuer")
64+
public String issuer;
5665
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package org.accounting.system.dtos.tenant;
2+
3+
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import jakarta.validation.constraints.NotEmpty;
6+
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
7+
import org.eclipse.microprofile.openapi.annotations.media.Schema;
8+
9+
@Schema(name="OidcTenantConfig", description="An object represents a request for creating an Oidc Tenant Configuration.")
10+
public class OidcTenantConfigRequest {
11+
12+
@Schema(
13+
type = SchemaType.STRING,
14+
implementation = String.class,
15+
description = "Issuer URI for the tokens (often the same as `authServerUrl`).",
16+
required = true,
17+
example = "http://localhost:58080/realms/quarkus"
18+
)
19+
@JsonProperty("issuer")
20+
@NotEmpty(message = "issuer may not be empty.")
21+
public String issuer;
22+
23+
@Schema(
24+
type = SchemaType.STRING,
25+
implementation = String.class,
26+
description = "Unique identifier for the tenant.",
27+
required = true,
28+
example = "default"
29+
)
30+
@JsonProperty("tenant_id")
31+
@NotEmpty(message = "tenant_id may not be empty.")
32+
public String tenantId;
33+
34+
@Schema(
35+
type = SchemaType.STRING,
36+
implementation = String.class,
37+
description = "Client ID registered with the identity provider.",
38+
required = true,
39+
example = "backend-service"
40+
)
41+
@JsonProperty("client_id")
42+
@NotEmpty(message = "client_id may not be empty.")
43+
public String clientId;
44+
45+
@Schema(
46+
type = SchemaType.STRING,
47+
implementation = String.class,
48+
description = "Client secret for authenticating the client.",
49+
required = true,
50+
example = "secret"
51+
)
52+
@JsonProperty("secret")
53+
@NotEmpty(message = "secret may not be empty.")
54+
public String secret;
55+
56+
@Schema(
57+
type = SchemaType.STRING,
58+
implementation = String.class,
59+
description = "Path to the authorization endpoint.",
60+
required = true,
61+
example = "/protocol/openid-connect/auth"
62+
)
63+
@JsonProperty("authorization_path")
64+
@NotEmpty(message = "authorization_path may not be empty.")
65+
public String authorizationPath;
66+
67+
@Schema(
68+
type = SchemaType.STRING,
69+
implementation = String.class,
70+
description = "Path to the token introspection endpoint.",
71+
required = true,
72+
example = "/protocol/openid-connect/token/introspect"
73+
)
74+
@JsonProperty("introspection_path")
75+
@NotEmpty(message = "introspection_path may not be empty.")
76+
public String introspectionPath;
77+
78+
@Schema(
79+
type = SchemaType.STRING,
80+
implementation = String.class,
81+
description = "Path to the user info endpoint.",
82+
required = true,
83+
example = "/protocol/openid-connect/userinfo"
84+
)
85+
@JsonProperty("user_info_path")
86+
@NotEmpty(message = "user_info_path may not be empty.")
87+
public String userInfoPath;
88+
89+
@Schema(
90+
type = SchemaType.STRING,
91+
implementation = String.class,
92+
description = "Path to the token endpoint.",
93+
required = true,
94+
example = "/protocol/openid-connect/token"
95+
)
96+
@JsonProperty("token_path")
97+
@NotEmpty(message = "token_path may not be empty.")
98+
public String tokenPath;
99+
100+
@Schema(
101+
type = SchemaType.STRING,
102+
implementation = String.class,
103+
description = "URL of the OIDC server (e.g., Keycloak realm URL).",
104+
required = true,
105+
example = "http://localhost:58080/realms/quarkus"
106+
)
107+
@JsonProperty("auth_server_url")
108+
@NotEmpty(message = "auth_server_url may not be empty.")
109+
public String authServerUrl;
110+
111+
@Schema(
112+
type = SchemaType.STRING,
113+
implementation = String.class,
114+
description = "The name of the claim in the access token that uniquely identifies the user (e.g., 'sub', 'voperson_id').",
115+
required = true,
116+
example = "voperson_id"
117+
)
118+
@JsonProperty("user_id_token_claim")
119+
@NotEmpty(message = "user_id_token_claim may not be empty.")
120+
public String userIdTokenClaim;
121+
122+
@Schema(
123+
type = SchemaType.STRING,
124+
implementation = String.class,
125+
description = "The name of the claim in the access token that uniquely identifies the service (e.g., 'client_id').",
126+
required = true,
127+
example = "client_id"
128+
)
129+
@JsonProperty("service_id_token_claim")
130+
@NotEmpty(message = "service_id_token_claim may not be empty.")
131+
public String serviceIdTokenClaim;
132+
}

0 commit comments

Comments
 (0)