Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/acl search #42

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
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
7 changes: 6 additions & 1 deletion acl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@
</properties>

<dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<version>1.18.34</version>
<scope>compile</scope>
</dependency>
</dependencies>
Expand Down
18 changes: 18 additions & 0 deletions acl/src/main/java/authserver/acl/Acl.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.java.Log;
import org.json.JSONObject;

@Log
@Data
Expand Down Expand Up @@ -91,6 +92,23 @@ public int hashCode() {
namespace, object, relation, user, usersetNamespace, usersetObject, usersetRelation);
}

@Override
public String toString() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", id.toString());
jsonObject.put("namespace", namespace);
jsonObject.put("object", object);
jsonObject.put("relation", relation);
jsonObject.put("user", user);
jsonObject.put("usersetNamespace", usersetNamespace);
jsonObject.put("usersetObject", usersetObject);
jsonObject.put("usersetRelation", usersetRelation);
jsonObject.put("created", created);
jsonObject.put("updated", updated);

return jsonObject.toString();
}

private static Acl parseAcl(String aclExpr) {
Matcher m = aclExprPattern.matcher(aclExpr);
if (!m.find()) {
Expand Down
40 changes: 20 additions & 20 deletions auth/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
<version>3.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

Expand Down Expand Up @@ -70,7 +70,7 @@
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
Expand All @@ -93,12 +93,12 @@
<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>
<artifactId>commons-text</artifactId>
<version>1.10.0</version>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
Expand All @@ -108,50 +108,50 @@
<dependency>
<groupId>io.envoyproxy.controlplane</groupId>
<artifactId>api</artifactId>
<version>1.0.37</version>
<version>1.0.46</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.55.1</version>
<version>1.68.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.55.1</version>
<version>1.68.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.55.1</version>
<version>1.68.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-services</artifactId>
<version>1.55.1</version>
<version>1.68.2</version>
</dependency>

<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
<version>1.17.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
<version>2.4.0-b180830.0359</version>
</dependency>

<dependency>
<groupId>com.newrelic.agent.java</groupId>
<artifactId>newrelic-api</artifactId>
<version>8.3.0</version>
<version>8.11.1</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<version>1.18.34</version>
</dependency>

<dependency>
Expand All @@ -169,12 +169,12 @@
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.3</version>
<version>8.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-json-classic</artifactId>
<version>0.1.2</version>
<version>0.1.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
Expand All @@ -183,11 +183,6 @@
<version>0.1.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230227</version>
</dependency>
</dependencies>

<repositories>
Expand All @@ -199,6 +194,11 @@
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>maven_central</id>
<name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

import org.example.authserver.controller.MappingController;
import org.springframework.http.HttpStatus;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ FilterRegistrationBean<ApiKeyFilter> apiKeyFilter() {
final FilterRegistrationBean<ApiKeyFilter> filterFilterRegistrationBean =
new FilterRegistrationBean<>();
filterFilterRegistrationBean.setFilter(new ApiKeyFilter(properties));
filterFilterRegistrationBean.addUrlPatterns(
"/mapping/clear",
"/mapping/delete/**");
filterFilterRegistrationBean.addUrlPatterns("/mapping/clear", "/mapping/delete/**");

return filterFilterRegistrationBean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class UrlFilteringInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
StringBuffer url = request.getRequestURL();
url.delete(0,7); // http://
url.delete(0, 7); // http://
if (url.indexOf("//") != -1) {
log.error("Double slash detected, blocking url {}", request.getRequestURL());
response.sendError(400, "Double slash in URL is prohibited");
Expand Down
10 changes: 5 additions & 5 deletions auth/src/main/java/org/example/authserver/config/WebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UrlFilteringInterceptor());
}
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UrlFilteringInterceptor());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@
import authserver.common.AclOperationDto;
import com.google.common.base.Stopwatch;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.example.authserver.config.AppProperties;
import org.example.authserver.entity.AclsRequestDTO;
import org.example.authserver.entity.PageView;
import org.example.authserver.repo.SubscriptionRepository;
import org.example.authserver.service.AclService;
import org.example.authserver.service.CacheService;
import org.example.authserver.service.SplitTestService;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

@Slf4j
Expand Down Expand Up @@ -42,8 +48,32 @@ public AclController(
}

@GetMapping("/list")
public Set<Acl> listAcl() {
return repository.findAll();
public PageView<Acl> listAcl(
@RequestParam(required = false) String namespace,
@RequestParam(required = false) String object,
@RequestParam(required = false) List<String> relations,
@RequestParam(required = false) String user,
@RequestParam(name = "userset_namespace", required = false) String usersetNamespace,
@RequestParam(name = "userset_object", required = false) String usersetObject,
@RequestParam(name = "userset_relation", required = false) List<String> usersetRelations,
@RequestParam(value = "sort", required = false) String sort,
@RequestParam(value = "direction", required = false) Sort.Direction direction,
@Min(value = 1, message = "min: 1") @RequestParam(value = "page", defaultValue = "1")
Integer page,
@Max(value = 100, message = "max: 100") @RequestParam(value = "pageSize", defaultValue = "50")
Integer pageSize) {
return repository.findAll(
namespace,
object,
relations,
user,
usersetNamespace,
usersetObject,
usersetRelations,
sort,
direction,
page,
pageSize);
}

@PostMapping("/create")
Expand All @@ -67,6 +97,29 @@ public void createMultiAcl(@Valid @RequestBody AclsRequestDTO multiAcl) {
private void createAcl_(Acl acl) {
Stopwatch stopwatch = Stopwatch.createStarted();
log.info("Creating ACL: {}", acl);
List<String> relations = acl.getRelation() != null ? List.of(acl.getRelation()) : null;
List<String> usersetRelations =
acl.getUsersetRelation() != null ? List.of(acl.getUsersetRelation()) : null;
PageView<Acl> existingAcls =
repository.findAll(
acl.getNamespace(),
acl.getObject(),
relations,
acl.getUser(),
acl.getUsersetNamespace(),
acl.getUsersetObject(),
usersetRelations,
null,
Sort.Direction.ASC,
1,
1);
if (existingAcls.getTotal() > 0) {
log.info(
"Skipping acl {}, existing aclId {}",
acl,
new ArrayList<>(existingAcls.getData()).get(0).getId());
return;
}
repository.save(acl);
subscriptionRepository.publish(acl);
if (appProperties.isCopyModeEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ public void clearMappings(@RequestHeader(value = API_KEY) String apiKey) {
}

@DeleteMapping("/delete/{id}")
public void deleteAcl(
@PathVariable String id, @RequestHeader(value = API_KEY) String apiKey) {
public void deleteAcl(@PathVariable String id, @RequestHeader(value = API_KEY) String apiKey) {
log.info("Delete Mapping by id: {}", id);
repository.deleteById(id);
}
Expand Down
20 changes: 20 additions & 0 deletions auth/src/main/java/org/example/authserver/entity/PageView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.example.authserver.entity;

import java.util.Collection;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@SuperBuilder
@Data
@NoArgsConstructor
public class PageView<T> {
private long total;
private long pages;
private long currentPage;
private Collection<T> data;

public static long calculateTotalPages(long totalRecords, long pageSize) {
return (totalRecords + pageSize - 1) / pageSize;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package org.example.authserver.exception;

public class NotSortableFieldException extends RuntimeException {}
21 changes: 21 additions & 0 deletions auth/src/main/java/org/example/authserver/repo/AclRepository.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,36 @@
package org.example.authserver.repo;

import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import java.util.Set;
import org.example.authserver.entity.AclEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AclRepository extends CrudRepository<AclEntity, String> {

Page<AclEntity> findAll(@NotNull Specification<AclEntity> spec, @Nullable Pageable pageable);

Page<AclEntity> findByNamespaceLikeAndObjectLikeAndRelationIn(
String namespace, String object, List<String> relations, @Nullable Pageable pageable);

Page<AclEntity> findByNamespaceLike(String namespace, PageRequest pageRequest);

Page<AclEntity> findByNamespaceLikeAndObjectLike(
String namespace, String object, PageRequest pageRequest);

Page<AclEntity> findByNsobjectLike(String nsobject, PageRequest pageRequest);

long countByNamespaceLikeAndObjectLikeAndRelationIn(
String namespace, String object, List<String> relations);

List<AclEntity> findAll();

Set<AclEntity> findAllByNsobjectAndUser(String nsobject, String user);
Expand Down
Loading