Skip to content

Commit 424a385

Browse files
committed
Add support for pluggable Authorizer, default to NoopAuthorizer.
Different authorizers can act upon headers to return userToken or throw AuthException if auth fails. If hosting providers, want to support alternative auths or add additional checks in auth, they can just implement this interface.
1 parent b6ca47d commit 424a385

18 files changed

+194
-87
lines changed

app/src/main/java/org/vss/KVStore.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ public interface KVStore {
44

55
String GLOBAL_VERSION_KEY = "vss_global_version";
66

7-
GetObjectResponse get(GetObjectRequest request);
7+
GetObjectResponse get(String userToken, GetObjectRequest request);
88

9-
PutObjectResponse put(PutObjectRequest request);
9+
PutObjectResponse put(String userToken, PutObjectRequest request);
1010

11-
DeleteObjectResponse delete(DeleteObjectRequest request);
11+
DeleteObjectResponse delete(String userToken, DeleteObjectRequest request);
1212

13-
ListKeyVersionsResponse listKeyVersions(ListKeyVersionsRequest request);
13+
ListKeyVersionsResponse listKeyVersions(String userToken, ListKeyVersionsRequest request);
1414
}

app/src/main/java/org/vss/api/AbstractVssApi.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@
77
import org.vss.ErrorCode;
88
import org.vss.ErrorResponse;
99
import org.vss.KVStore;
10+
import org.vss.auth.Authorizer;
1011
import org.vss.exception.AuthException;
1112
import org.vss.exception.ConflictException;
1213
import org.vss.exception.NoSuchKeyException;
1314

1415
public abstract class AbstractVssApi {
1516
final KVStore kvStore;
17+
final Authorizer authorizer;
1618

1719
@Inject
18-
public AbstractVssApi(KVStore kvStore) {
20+
public AbstractVssApi(KVStore kvStore, Authorizer authorizer) {
1921
this.kvStore = kvStore;
22+
this.authorizer = authorizer;
2023
}
2124

2225
Response toResponse(GeneratedMessageV3 protoResponse) {

app/src/main/java/org/vss/api/DeleteObjectApi.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,32 @@
44
import jakarta.ws.rs.POST;
55
import jakarta.ws.rs.Path;
66
import jakarta.ws.rs.Produces;
7+
import jakarta.ws.rs.core.Context;
8+
import jakarta.ws.rs.core.HttpHeaders;
79
import jakarta.ws.rs.core.MediaType;
810
import jakarta.ws.rs.core.Response;
911
import lombok.extern.slf4j.Slf4j;
1012
import org.vss.DeleteObjectRequest;
1113
import org.vss.DeleteObjectResponse;
1214
import org.vss.KVStore;
15+
import org.vss.auth.AuthResponse;
16+
import org.vss.auth.Authorizer;
1317

1418
@Path(VssApiEndpoint.DELETE_OBJECT)
1519
@Slf4j
1620
public class DeleteObjectApi extends AbstractVssApi {
1721
@Inject
18-
public DeleteObjectApi(KVStore kvstore) {
19-
super(kvstore);
22+
public DeleteObjectApi(KVStore kvstore, Authorizer authorizer) {
23+
super(kvstore, authorizer);
2024
}
2125

2226
@POST
2327
@Produces(MediaType.APPLICATION_OCTET_STREAM)
24-
public Response execute(byte[] payload) {
28+
public Response execute(byte[] payload, @Context HttpHeaders headers) {
2529
try {
30+
AuthResponse authResponse = authorizer.verify(headers);
2631
DeleteObjectRequest request = DeleteObjectRequest.parseFrom(payload);
27-
DeleteObjectResponse response = kvStore.delete(request);
32+
DeleteObjectResponse response = kvStore.delete(authResponse.getUserToken(), request);
2833
return toResponse(response);
2934
} catch (Exception e) {
3035
log.error("Exception in DeleteObjectApi: ", e);

app/src/main/java/org/vss/api/GetObjectApi.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,33 @@
44
import jakarta.ws.rs.POST;
55
import jakarta.ws.rs.Path;
66
import jakarta.ws.rs.Produces;
7+
import jakarta.ws.rs.core.Context;
8+
import jakarta.ws.rs.core.HttpHeaders;
79
import jakarta.ws.rs.core.MediaType;
810
import jakarta.ws.rs.core.Response;
911
import lombok.extern.slf4j.Slf4j;
1012
import org.vss.GetObjectRequest;
1113
import org.vss.GetObjectResponse;
1214
import org.vss.KVStore;
15+
import org.vss.auth.AuthResponse;
16+
import org.vss.auth.Authorizer;
1317

1418
@Path(VssApiEndpoint.GET_OBJECT)
1519
@Slf4j
1620
public class GetObjectApi extends AbstractVssApi {
1721

1822
@Inject
19-
public GetObjectApi(KVStore kvstore) {
20-
super(kvstore);
23+
public GetObjectApi(KVStore kvstore, Authorizer authorizer) {
24+
super(kvstore, authorizer);
2125
}
2226

2327
@POST
2428
@Produces(MediaType.APPLICATION_OCTET_STREAM)
25-
public Response execute(byte[] payload) {
29+
public Response execute(byte[] payload, @Context HttpHeaders headers) {
2630
try {
31+
AuthResponse authResponse = authorizer.verify(headers);
2732
GetObjectRequest request = GetObjectRequest.parseFrom(payload);
28-
GetObjectResponse response = kvStore.get(request);
33+
GetObjectResponse response = kvStore.get(authResponse.getUserToken(), request);
2934
return toResponse(response);
3035
} catch (Exception e) {
3136
log.error("Exception in GetObjectApi: ", e);

app/src/main/java/org/vss/api/ListKeyVersionsApi.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,33 @@
44
import jakarta.ws.rs.POST;
55
import jakarta.ws.rs.Path;
66
import jakarta.ws.rs.Produces;
7+
import jakarta.ws.rs.core.Context;
8+
import jakarta.ws.rs.core.HttpHeaders;
79
import jakarta.ws.rs.core.MediaType;
810
import jakarta.ws.rs.core.Response;
911
import lombok.extern.slf4j.Slf4j;
1012
import org.vss.KVStore;
1113
import org.vss.ListKeyVersionsRequest;
1214
import org.vss.ListKeyVersionsResponse;
15+
import org.vss.auth.AuthResponse;
16+
import org.vss.auth.Authorizer;
1317

1418
@Path(VssApiEndpoint.LIST_KEY_VERSIONS)
1519
@Slf4j
1620
public class ListKeyVersionsApi extends AbstractVssApi {
1721

1822
@Inject
19-
public ListKeyVersionsApi(KVStore kvStore) {
20-
super(kvStore);
23+
public ListKeyVersionsApi(KVStore kvStore, Authorizer authorizer) {
24+
super(kvStore, authorizer);
2125
}
2226

2327
@POST
2428
@Produces(MediaType.APPLICATION_OCTET_STREAM)
25-
public Response execute(byte[] payload) {
29+
public Response execute(byte[] payload, @Context HttpHeaders headers) {
2630
try {
31+
AuthResponse authResponse = authorizer.verify(headers);
2732
ListKeyVersionsRequest request = ListKeyVersionsRequest.parseFrom(payload);
28-
ListKeyVersionsResponse response = kvStore.listKeyVersions(request);
33+
ListKeyVersionsResponse response = kvStore.listKeyVersions(authResponse.getUserToken(), request);
2934
return toResponse(response);
3035
} catch (Exception e) {
3136
log.error("Exception in ListKeyVersionsApi: ", e);

app/src/main/java/org/vss/api/PutObjectsApi.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,33 @@
44
import jakarta.ws.rs.POST;
55
import jakarta.ws.rs.Path;
66
import jakarta.ws.rs.Produces;
7+
import jakarta.ws.rs.core.Context;
8+
import jakarta.ws.rs.core.HttpHeaders;
79
import jakarta.ws.rs.core.MediaType;
810
import jakarta.ws.rs.core.Response;
911
import lombok.extern.slf4j.Slf4j;
1012
import org.vss.KVStore;
1113
import org.vss.PutObjectRequest;
1214
import org.vss.PutObjectResponse;
15+
import org.vss.auth.AuthResponse;
16+
import org.vss.auth.Authorizer;
1317

1418
@Path(VssApiEndpoint.PUT_OBJECTS)
1519
@Slf4j
1620
public class PutObjectsApi extends AbstractVssApi {
1721

1822
@Inject
19-
public PutObjectsApi(KVStore kvStore) {
20-
super(kvStore);
23+
public PutObjectsApi(KVStore kvStore, Authorizer authorizer) {
24+
super(kvStore, authorizer);
2125
}
2226

2327
@POST
2428
@Produces(MediaType.APPLICATION_OCTET_STREAM)
25-
public Response execute(byte[] payload) {
29+
public Response execute(byte[] payload, @Context HttpHeaders headers) {
2630
try {
31+
AuthResponse authResponse = authorizer.verify(headers);
2732
PutObjectRequest putObjectRequest = PutObjectRequest.parseFrom(payload);
28-
PutObjectResponse response = kvStore.put(putObjectRequest);
33+
PutObjectResponse response = kvStore.put(authResponse.getUserToken(), putObjectRequest);
2934
return toResponse(response);
3035
} catch (Exception e) {
3136
log.error("Exception in PutObjectsApi: ", e);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.vss.auth;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
6+
@Data
7+
@AllArgsConstructor
8+
public class AuthResponse {
9+
private String userToken;
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.vss.auth;
2+
3+
import jakarta.ws.rs.core.HttpHeaders;
4+
import org.vss.exception.AuthException;
5+
6+
// Interface for authorizer that is run before every request.
7+
public interface Authorizer {
8+
AuthResponse verify(HttpHeaders headers) throws AuthException;
9+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.vss.auth;
2+
3+
import jakarta.ws.rs.core.HttpHeaders;
4+
import org.vss.exception.AuthException;
5+
6+
// A no-operation authorizer, that lets any user-request go through.
7+
public class NoopAuthorizer implements Authorizer {
8+
private static String UNAUTHENTICATED_USER = "unauth-user";
9+
10+
@Override
11+
public AuthResponse verify(HttpHeaders headers) throws AuthException {
12+
return new AuthResponse(UNAUTHENTICATED_USER);
13+
}
14+
}

app/src/main/java/org/vss/guice/BaseModule.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
import org.jooq.DSLContext;
1212
import org.jooq.SQLDialect;
1313
import org.jooq.impl.DSL;
14+
import org.jooq.tools.StringUtils;
1415
import org.vss.KVStore;
16+
import org.vss.auth.Authorizer;
17+
import org.vss.auth.NoopAuthorizer;
1518
import org.vss.impl.postgres.PostgresBackendImpl;
1619

1720
public class BaseModule extends AbstractModule {
@@ -20,6 +23,9 @@ public class BaseModule extends AbstractModule {
2023
protected void configure() {
2124
// Provide PostgresBackend as default implementation for KVStore.
2225
bind(KVStore.class).to(PostgresBackendImpl.class).in(Singleton.class);
26+
27+
// Default to Noop Authorizer.
28+
bind(Authorizer.class).to(NoopAuthorizer.class).in(Singleton.class);
2329
}
2430

2531
@Provides

0 commit comments

Comments
 (0)