Skip to content

Commit

Permalink
Merge pull request #16 from permitio/asaf/per-7182-java-sdk-add-checkurl
Browse files Browse the repository at this point in the history
Add support in check url and sharding key
  • Loading branch information
asafc committed Jul 26, 2023
2 parents 0b8b9b8 + f094ca5 commit fe3ce2c
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 4 deletions.
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,29 @@ This guide will walk you through the steps of installing the Permit.io Java SDK
## Installation

For [Maven](https://maven.apache.org/) projects, use:

```xml
<dependency>
<groupId>io.permit</groupId>
<artifactId>permit-sdk-java</artifactId>
<version>1.3.0</version>
<version>1.4.0</version>
</dependency>
```

For [Gradle](https://gradle.org/) projects, configure `permit-sdk-java` as a dependency in your `build.gradle` file:

```groovy
dependencies {
// ...
implementation 'io.permit:permit-sdk-java:1.3.0'
implementation 'io.permit:permit-sdk-java:1.4.0'
}
```

## Usage

### Initializing the SDK

To init the SDK, you need to create a new Permit client with the API key you got from the Permit.io dashboard.

First we will create a new `PermitConfig` object so we can pass it to the Permit client.
Expand All @@ -52,6 +55,7 @@ Permit permit = new Permit(
```

### Checking permissions

To check permissions using our `permit.check()` method, you will have to create User and Resource models as input to the permission check.
The models are located in ``

Expand Down Expand Up @@ -80,6 +84,7 @@ if (permitted) {
```

A more complicated example (passing attributes on the user object, using an explicit tenant in the resource):

```java
import io.permit.sdk.enforcement.Resource;
import io.permit.sdk.enforcement.User;
Expand Down Expand Up @@ -107,12 +112,14 @@ if (permitted) {
```

### Syncing users

When the user first logins, and after you check if he authenticated successfully (i.e: **by checking the JWT access token**) -
you need to declare the user in the permission system so you can run `permit.check()` on that user.

To declare (or "sync") a user in the Permit.io API, use the `permit.api.users.sync()` method.

Follow the example below:

```java
import io.permit.sdk.api.models.CreateOrUpdateResult;
import io.permit.sdk.enforcement.User;
Expand Down Expand Up @@ -140,6 +147,7 @@ CreateOrUpdateResult<UserRead> result = permit.api.users.sync(new UserCreate("[U
```

## Javadoc reference
To view the javadoc reference, [click here](https://javadoc.io/doc/io.permit/permit-sdk-java/1.3.0/index.html).

It's easiest to start with the root [Permit](https://javadoc.io/static/io.permit/permit-sdk-java/1.3.0/io/permit/sdk/Permit.html) class.
To view the javadoc reference, [click here](https://javadoc.io/doc/io.permit/permit-sdk-java/1.4.0/index.html).

It's easiest to start with the root [Permit](https://javadoc.io/static/io.permit/permit-sdk-java/1.4.0/io/permit/sdk/Permit.html) class.
10 changes: 10 additions & 0 deletions src/main/java/io/permit/sdk/Permit.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,14 @@ public boolean check(User user, String action, Resource resource, Context contex
public boolean check(User user, String action, Resource resource) throws IOException {
return this.enforcer.check(user, action, resource);
}

@Override
public boolean checkUrl(User user, String httpMethod, String url, String tenant, Context context) throws IOException {
return this.enforcer.checkUrl(user, httpMethod, url, tenant, context);
}

@Override
public boolean checkUrl(User user, String httpMethod, String url, String tenant) throws IOException {
return this.enforcer.checkUrl(user, httpMethod, url, tenant);
}
}
89 changes: 89 additions & 0 deletions src/main/java/io/permit/sdk/enforcement/Enforcer.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ class EnforcerInput {
}
}

class CheckUrlInput {
public final User user;
public final String http_method;
public final String url;
public final String tenant;
public final HashMap<String, Object> context;

CheckUrlInput(User user, String http_method, String url, String tenant, HashMap<String, Object> context) {
this.user = user;
this.http_method = http_method;
this.url = url;
this.tenant = tenant;
this.context = context;
}
}

/**
* The {@code OpaResult} class represents the result of a Permit enforcement check returned by the policy agent.
*/
Expand Down Expand Up @@ -118,6 +134,7 @@ public boolean check(User user, String action, Resource resource, Context contex
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", String.format("Bearer %s", this.config.getToken()))
.addHeader("X-Permit-SDK-Version", String.format("java:%s", this.config.version))
.addHeader("X-Tenant-ID", normalizedResource.getTenant()) // sharding key
.build();

try (Response response = client.newCall(request).execute()) {
Expand Down Expand Up @@ -172,4 +189,76 @@ public boolean check(User user, String action, Resource resource, Context contex
public boolean check(User user, String action, Resource resource) throws IOException {
return this.check(user, action, resource, new Context());
}

@Override
public boolean checkUrl(User user, String httpMethod, String url, String tenant, Context context) throws IOException {
CheckUrlInput input = new CheckUrlInput(
user,
httpMethod,
url,
tenant,
context
);

// request body
Gson gson = new Gson();
String requestBody = gson.toJson(input);
RequestBody body = RequestBody.create(requestBody, MediaType.parse("application/json"));

// create the request
String apiUrl = String.format("%s/allowed_url", this.config.getPdpAddress());
Request request = new Request.Builder()
.url(apiUrl)
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", String.format("Bearer %s", this.config.getToken()))
.addHeader("X-Permit-SDK-Version", String.format("java:%s", this.config.version))
.addHeader("X-Tenant-ID", tenant) // sharding key
.build();

try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
String errorMessage = String.format(
"Error in permit.checkUrl(%s, %s, %s, %s): got unexpected status code %d",
user.toString(),
httpMethod,
url,
tenant,
response.code()
);
logger.error(errorMessage);
throw new IOException(errorMessage);
}
ResponseBody responseBody = response.body();
if (responseBody == null) {
String errorMessage = String.format(
"Error in permit.check(%s, %s, %s, %s): got empty response",
user,
httpMethod,
url,
tenant
);
logger.error(errorMessage);
throw new IOException(errorMessage);
}
String responseString = responseBody.string();
OpaResult result = gson.fromJson(responseString, OpaResult.class);
if (this.config.isDebugMode()) {
logger.info(String.format(
"permit.check(%s, %s, %s, %s) = %s",
user,
httpMethod,
url,
tenant,
result.allow.toString()
));
}
return result.allow;
}
}

@Override
public boolean checkUrl(User user, String httpMethod, String url, String tenant) throws IOException {
return this.checkUrl(user, httpMethod, url, tenant, new Context());
}
}
2 changes: 2 additions & 0 deletions src/main/java/io/permit/sdk/enforcement/IEnforcerApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
public interface IEnforcerApi {
boolean check(User user, String action, Resource resource, Context context) throws IOException;
boolean check(User user, String action, Resource resource) throws IOException;
boolean checkUrl(User user, String httpMethod, String url, String tenant) throws IOException;
boolean checkUrl(User user, String httpMethod, String url, String tenant, Context context) throws IOException;
}

0 comments on commit fe3ce2c

Please sign in to comment.