diff --git a/src/main/java/io/permit/sdk/Permit.java b/src/main/java/io/permit/sdk/Permit.java index ca5fd30..6ba1745 100644 --- a/src/main/java/io/permit/sdk/Permit.java +++ b/src/main/java/io/permit/sdk/Permit.java @@ -3,6 +3,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.permit.sdk.api.ApiClient; +import io.permit.sdk.api.ElementsClient; import io.permit.sdk.enforcement.Enforcer; import io.permit.sdk.enforcement.IEnforcerApi; import io.permit.sdk.enforcement.Resource; @@ -19,10 +20,12 @@ public class Permit implements IEnforcerApi { private final Enforcer enforcer; public final PermitConfig config; public final ApiClient api; + public final ElementsClient elements; public Permit(PermitConfig config) { this.config = config; this.api = new ApiClient(this.config); + this.elements = new ElementsClient(this.config); this.enforcer = new Enforcer(this.config); if (this.config.isDebugMode()) { diff --git a/src/main/java/io/permit/sdk/PermitConfig.java b/src/main/java/io/permit/sdk/PermitConfig.java index 066e5ca..dd61f32 100644 --- a/src/main/java/io/permit/sdk/PermitConfig.java +++ b/src/main/java/io/permit/sdk/PermitConfig.java @@ -6,6 +6,7 @@ public class PermitConfig { // main config vars private final String token; private final String pdp; + private final String apiUrl; private final Boolean debugMode; // logger config @@ -25,6 +26,7 @@ public class PermitConfig { private PermitConfig(Builder builder) { this.token = builder.token; this.pdp = builder.pdp; + this.apiUrl = builder.apiUrl; this.debugMode = builder.debugMode; this.logLevel = builder.logLevel; this.logLabel = builder.logLabel; @@ -40,6 +42,7 @@ private PermitConfig(Builder builder) { public String getToken() { return token; } + public String getApiUrl() { return apiUrl; } public String getPdpAddress() { return pdp; } @@ -74,7 +77,8 @@ public Boolean shouldUseDefaultTenantIfEmpty() { public static class Builder { // main config vars private String token; - private String pdp = "http://localhost:7000"; + private String pdp = "http://localhost:7766"; + private String apiUrl = "https://api.permit.io"; private Boolean debugMode = false; // logger config diff --git a/src/main/java/io/permit/sdk/api/ElementsClient.java b/src/main/java/io/permit/sdk/api/ElementsClient.java new file mode 100644 index 0000000..0b6b2b3 --- /dev/null +++ b/src/main/java/io/permit/sdk/api/ElementsClient.java @@ -0,0 +1,101 @@ +package io.permit.sdk.api; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import io.permit.sdk.PermitConfig; +import io.permit.sdk.api.models.*; +import okhttp3.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; + +interface IElementsApi { + UserLoginResponse loginAs(String userId, String tenantId) throws IOException, PermitApiException; +} + +public class ElementsClient implements IElementsApi { + final static Logger logger = LoggerFactory.getLogger(ApiClient.class); + private final OkHttpClient client = new OkHttpClient(); + private final PermitConfig config; + private final Headers headers; + private final String apiUrl; + + public ElementsClient(PermitConfig config) { + this.config = config; + this.headers = new Headers.Builder() + .add("Content-Type", "application/json") + .add("Authorization", String.format("Bearer %s", this.config.getToken())) + .build(); + this.apiUrl = this.config.getApiUrl(); + } + + private void throwIfErrorResponseCode(String requestRepr, Response response, String responseContent, List expectedErrorCodes) throws PermitApiException { + String log = String.format("Received response: %s : status code %d : %s", requestRepr, response.code(), responseContent); + if (!response.isSuccessful() && this.config.isDebugMode()) { + this.logger.error(log); + } else { + this.logger.debug(log); + } + if (!response.isSuccessful() && !expectedErrorCodes.contains(response.code())) { + throw new PermitApiException( + String.format( + "unexpected status code: %d for request: %s", + response.code(), + requestRepr + ) + ); + } + } + + private void throwIfErrorResponseCode(String requestRepr, Response response, String responseContent) throws PermitApiException { + throwIfErrorResponseCode(requestRepr, response, responseContent, List.of()); + } + + @Override + public UserLoginResponse loginAs(String userId, String tenantId) throws IOException, PermitApiException { + UserLoginRequest element = new UserLoginRequest(); + element.tenantId = tenantId; + element.userId = userId; + + // request body + Gson gson = new GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create(); + String requestBody = gson.toJson(element); + RequestBody body = RequestBody.create(requestBody, MediaType.parse("application/json")); + + // create the request + String url = String.format("%s/v2/auth/elements_login_as", this.config.getApiUrl()); + Request request = new Request.Builder() + .url(url) + .headers(this.headers) + .post(body) + .build(); + + String requestRepr = String.format("permit.elements.login_as(%s)", requestBody); + this.logger.debug(String.format("Sending request: %s", requestRepr)); + + // send the request + try (Response response = client.newCall(request).execute()) { + ResponseBody responseBody = response.body(); + if (responseBody == null) { + throw new IOException("got empty response"); + } + String responseString = responseBody.string(); + throwIfErrorResponseCode(requestRepr, response, responseString); + UserLoginResponse userLoginResponse = gson.fromJson(responseString, UserLoginResponse.class); + userLoginResponse.content = new HashMap<>(); + userLoginResponse.content.put("url", userLoginResponse.redirectUrl); + return userLoginResponse; + } + } + + public String getApiUrl() { + return apiUrl; + } +} + diff --git a/src/main/java/io/permit/sdk/api/models/UserLoginRequest.java b/src/main/java/io/permit/sdk/api/models/UserLoginRequest.java new file mode 100644 index 0000000..ddd1cd5 --- /dev/null +++ b/src/main/java/io/permit/sdk/api/models/UserLoginRequest.java @@ -0,0 +1,6 @@ +package io.permit.sdk.api.models; + +public class UserLoginRequest { + public String userId = null; + public String tenantId = null; +} diff --git a/src/main/java/io/permit/sdk/api/models/UserLoginResponse.java b/src/main/java/io/permit/sdk/api/models/UserLoginResponse.java new file mode 100644 index 0000000..0ed1ff5 --- /dev/null +++ b/src/main/java/io/permit/sdk/api/models/UserLoginResponse.java @@ -0,0 +1,11 @@ +package io.permit.sdk.api.models; + +import java.util.Map; + +public class UserLoginResponse { + public String error = null; + public String token = null; + public String extra = null; + public String redirectUrl = null; + public Map content = null; +} diff --git a/src/test/java/io/permit/sdk/PermitIntegrationTests.java b/src/test/java/io/permit/sdk/PermitIntegrationTests.java index cb1685b..f6f9834 100644 --- a/src/test/java/io/permit/sdk/PermitIntegrationTests.java +++ b/src/test/java/io/permit/sdk/PermitIntegrationTests.java @@ -3,8 +3,8 @@ import com.google.common.base.Strings; import com.google.gson.Gson; import io.permit.sdk.api.PermitApiException; +import io.permit.sdk.api.models.UserLoginResponse; import io.permit.sdk.api.models.UserModel; -import io.permit.sdk.enforcement.AssignedRole; import io.permit.sdk.enforcement.Resource; import io.permit.sdk.enforcement.User; import okhttp3.HttpUrl; @@ -15,7 +15,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; -import java.util.ArrayList; +import java.util.Random; import static org.junit.jupiter.api.Assertions.*; @@ -32,9 +32,12 @@ class PermitIntegrationTests { private final static int loggerSeparatorLength = 80; private boolean skipTests = false; + static Random rand = new Random(); + static String suffixedUserKey = "test|" + rand.nextInt(); + private final static String roleKey = "captain"; private final static String tenantKey = "tortuga"; - private final static String userKey = "test|13d4dd3ff127"; + private final static String userKey = suffixedUserKey; private final static String userEmail = "jack@pirates.com"; private final static String userFirstName = "Jack"; private final static String userLastName = "Sparrow"; @@ -90,7 +93,7 @@ private static void logTestIsStarting(String testName) { Boolean allowed = null; try { allowed = permit.check( - User.fromString("55de594980944d48944dc10b9c70483c"), + User.fromString(userKey), "create", Resource.fromString("document") ); @@ -101,6 +104,25 @@ private static void logTestIsStarting(String testName) { assertTrue(allowed, "permit.check() should be true"); } + @Test void testPermitElementsLoginAs() { + if (skipTests) { + return; + } + logTestIsStarting("permitCheckSucceeds"); + Permit permit = new Permit(this.config); + UserLoginResponse loginAs = null; + try { + loginAs = permit.elements.loginAs("raz@permit.io", "fafb66f9c98647ad954f129b9f2b1c84"); + } catch (IOException e) { + fail(e); + } catch (PermitApiException e) { + e.printStackTrace(); + } + + assertNotNull(loginAs.redirectUrl); + assertNotNull(loginAs.content); + } + @Test void testPermitApiUserLifecycle() { if (skipTests) { return;