Skip to content
This repository was archived by the owner on Jun 23, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 23 additions & 76 deletions auth/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<version>3.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>


<properties>
<java.version>17</java.version>
<spring.native.version>0.12.1</spring.native.version>
<native.buildtools.version>0.9.13</native.buildtools.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -70,7 +68,7 @@
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
Expand All @@ -85,15 +83,29 @@
<artifactId>jedis</artifactId>
<version>4.4.2</version>
</dependency>

<!-- PostgreSQL Driver -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>

<!-- Flyway for db migration -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>10.20.1</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency>

<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.8.0</version>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
Expand All @@ -108,27 +120,27 @@
<dependency>
<groupId>io.envoyproxy.controlplane</groupId>
<artifactId>api</artifactId>
<version>1.0.37</version>
<version>1.0.49</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.55.1</version>
<version>1.72.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.55.1</version>
<version>1.72.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.55.1</version>
<version>1.72.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-services</artifactId>
<version>1.55.1</version>
<version>1.72.0</version>
</dependency>

<dependency>
Expand Down Expand Up @@ -186,7 +198,7 @@
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230227</version>
<version>20231013</version>
</dependency>
</dependencies>

Expand Down Expand Up @@ -237,71 +249,6 @@
</plugins>
</build>
</profile>
<profile>
<id>native</id>
<dependencies>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
<version>${spring.native.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<version>0.12.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>21.2.0</version>
<configuration>
<mainClass>org.example.authserver.Application</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<env>
<BP_BOOT_NATIVE_IMAGE>true</BP_BOOT_NATIVE_IMAGE>
</env>
</image>
</configuration>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.2.1</version>
<dependencies>
<dependency>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-native-image-extension-maven</artifactId>
<version>0.1.0</version>
</dependency>
</dependencies>
<configuration>
<pluginExtensions>
<pluginExtension>
<implementation>com.google.cloud.tools.jib.maven.extension.nativeimage.JibNativeImageExtension</implementation>
</pluginExtension>
</pluginExtensions>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.example.authserver.controller;

import authserver.acl.Acl;
import authserver.common.AclOperation;
import authserver.common.AclOperationDto;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.example.authserver.config.AppProperties;
import org.example.authserver.entity.ResourceDto;
import org.example.authserver.entity.ResourcePermissionsDto;
import org.example.authserver.repo.SubscriptionRepository;
import org.example.authserver.service.AclService;
import org.example.authserver.service.CacheService;
import org.example.authserver.service.ResourceService;
import org.example.authserver.service.SplitTestService;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("/acl/resources")
public class ResourceController {

private final ResourceService resourceService;
private final AclService aclService;
private final SubscriptionRepository subscriptionRepository;
private final SplitTestService splitTestService;
private final CacheService cacheService;
private final AppProperties appProperties;

public ResourceController(ResourceService resourceService, AclService aclService, SubscriptionRepository subscriptionRepository, SplitTestService splitTestService, CacheService cacheService, AppProperties appProperties) {
this.resourceService = resourceService;
this.aclService = aclService;
this.subscriptionRepository = subscriptionRepository;
this.splitTestService = splitTestService;
this.cacheService = cacheService;
this.appProperties = appProperties;
}

@GetMapping
public List<ResourceDto> listResources(@RequestParam String namespace) {
return resourceService.findAllByNamespace(namespace);
}

@PostMapping
public void createResource(@Valid @RequestBody ResourcePermissionsDto resourcePermissions) {
log.info("Creating resource with permissions: {}", resourcePermissions);

ResourceDto resource = new ResourceDto(
resourcePermissions.getNamespace(),
resourcePermissions.getResourceId());

resourceService.createResourceIfMissing(resource);

// Process each user's permissions for this resource
resourcePermissions.getPermissions().forEach((userId, permissions) -> {
for (String permission : permissions) {

Acl acl = new Acl();
acl.setId(UUID.randomUUID());
acl.setNamespace(resourcePermissions.getNamespace());
acl.setObject(resourcePermissions.getResourceId());
acl.setRelation(permission);
acl.setUser(userId);

aclService.save(acl);

subscriptionRepository.publish(acl);
if (appProperties.isCopyModeEnabled()) {
splitTestService.submitAsync(
AclOperationDto.builder().op(AclOperation.CREATE).acl(acl).build());
}
}
});
}

@DeleteMapping("/{namespace}/{resourceId}")
public void deleteResource(@PathVariable String namespace, @PathVariable String resourceId) {
log.info("Delete resource: {}/{}", namespace, resourceId);

List<ResourceDto> resources = resourceService.findAllByNamespaceAndResourceId(namespace, resourceId);
Set<Acl> acls = aclService.findAllByNsObjectIn(List.of(String.format("%s:%s", namespace, resourceId)));
Set<String> users = acls.stream().map(Acl::getUser).collect(java.util.stream.Collectors.toSet());

for (Acl acl : acls) {
aclService.delete(acl);
if (appProperties.isCopyModeEnabled()) {
splitTestService.submitAsync(
AclOperationDto.builder().op(AclOperation.DEL).acl(acl).build());
}
}

for (String userId : users) {
if ("*".equalsIgnoreCase(userId)) continue;
cacheService.purgeCache(userId, System.currentTimeMillis());
}
resourceService.deleteAll(resources);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.example.authserver.controller;

import authserver.acl.Acl;
import authserver.common.AclOperation;
import authserver.common.AclOperationDto;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.example.authserver.config.AppProperties;
import org.example.authserver.entity.RoleDto;
import org.example.authserver.service.CacheService;
import org.example.authserver.service.RoleService;
import org.example.authserver.service.SplitTestService;
import org.springframework.web.bind.annotation.*;

import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/acl/roles")
public class RoleController {

private final RoleService roleService;
private final SplitTestService splitTestService;
private final CacheService cacheService;
private final AppProperties appProperties;

public RoleController(RoleService roleService, SplitTestService splitTestService, CacheService cacheService, AppProperties appProperties) {
this.roleService = roleService;
this.splitTestService = splitTestService;
this.cacheService = cacheService;
this.appProperties = appProperties;
}

@GetMapping
public Set<RoleDto> listRoles() {
return roleService.findAll();
}

@PostMapping
public void createRole(@Valid @RequestBody RoleDto role) {
log.info("Creating RoleDto: {}", role);
roleService.save(role);
}

@DeleteMapping("/{roleId}")
public void deleteRole(@PathVariable String roleId) {
log.info("Delete role: {}", roleId);
Set<Acl> deletedAcls = roleService.deleteById(roleId);
Set<String> users = deletedAcls.stream()
.map(Acl::getUser)
.collect(Collectors.toSet());

for (Acl acl : deletedAcls) {
if (appProperties.isCopyModeEnabled()) {
splitTestService.submitAsync(
AclOperationDto.builder().op(AclOperation.DEL).acl(acl).build());
}
}

for (String userId : users){
if ("*".equalsIgnoreCase(userId)) continue;
cacheService.purgeCache(userId, System.currentTimeMillis());
}
}
}
Loading