diff --git a/src/main/java/com/commafeed/backend/model/UserRole.java b/src/main/java/com/commafeed/backend/model/UserRole.java
index 152fcc10..e8b342b1 100644
--- a/src/main/java/com/commafeed/backend/model/UserRole.java
+++ b/src/main/java/com/commafeed/backend/model/UserRole.java
@@ -14,7 +14,7 @@ import javax.persistence.Table;
public class UserRole extends AbstractModel {
public static enum Role {
- USER, ADMIN
+ USER, ADMIN, NONE
}
@OneToOne
diff --git a/src/main/java/com/commafeed/frontend/pages/WelcomePage.html b/src/main/java/com/commafeed/frontend/pages/WelcomePage.html
index 7930af51..f5dd0f33 100644
--- a/src/main/java/com/commafeed/frontend/pages/WelcomePage.html
+++ b/src/main/java/com/commafeed/frontend/pages/WelcomePage.html
@@ -30,7 +30,9 @@
diff --git a/src/main/java/com/commafeed/frontend/rest/RESTApplication.java b/src/main/java/com/commafeed/frontend/rest/RESTApplication.java
index 94c0ed4e..fd5db21e 100644
--- a/src/main/java/com/commafeed/frontend/rest/RESTApplication.java
+++ b/src/main/java/com/commafeed/frontend/rest/RESTApplication.java
@@ -5,9 +5,8 @@ import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
-import com.commafeed.frontend.rest.resources.AdminMetricsREST;
-import com.commafeed.frontend.rest.resources.AdminSettingsREST;
-import com.commafeed.frontend.rest.resources.AdminUsersREST;
+import com.commafeed.frontend.rest.resources.AdminREST;
+import com.commafeed.frontend.rest.resources.ApiDocumentationREST;
import com.commafeed.frontend.rest.resources.EntriesREST;
import com.commafeed.frontend.rest.resources.SessionREST;
import com.commafeed.frontend.rest.resources.SettingsREST;
@@ -18,7 +17,7 @@ import com.wordnik.swagger.jaxrs.JaxrsApiReader;
@ApplicationPath("/rest")
public class RESTApplication extends Application {
-
+
static {
JaxrsApiReader.setFormatString("");
}
@@ -26,16 +25,16 @@ public class RESTApplication extends Application {
@Override
public Set> getClasses() {
Set> set = Sets.newHashSet();
- set.add(ApiListingResource.class);
set.add(JacksonJsonProvider.class);
- set.add(SubscriptionsREST.class);
set.add(EntriesREST.class);
+ set.add(SubscriptionsREST.class);
set.add(SettingsREST.class);
- set.add(AdminUsersREST.class);
- set.add(AdminSettingsREST.class);
- set.add(AdminMetricsREST.class);
set.add(SessionREST.class);
+ set.add(AdminREST.class);
+
+ set.add(ApiDocumentationREST.class);
+
return set;
}
}
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java b/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java
index 17b496ff..dc0d8fc7 100644
--- a/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java
+++ b/src/main/java/com/commafeed/frontend/rest/resources/AbstractREST.java
@@ -9,18 +9,13 @@ import javax.interceptor.InvocationContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.UriInfo;
-import org.apache.commons.lang.StringUtils;
import org.apache.wicket.ThreadContext;
import org.apache.wicket.authentication.IAuthenticationStrategy;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
@@ -28,6 +23,7 @@ import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.apache.wicket.protocol.http.servlet.ServletWebResponse;
import org.apache.wicket.request.cycle.RequestCycle;
+import com.commafeed.backend.MetricsBean;
import com.commafeed.backend.dao.FeedCategoryDAO;
import com.commafeed.backend.dao.FeedDAO;
import com.commafeed.backend.dao.FeedEntryDAO;
@@ -47,21 +43,10 @@ import com.commafeed.backend.services.UserService;
import com.commafeed.frontend.CommaFeedApplication;
import com.commafeed.frontend.CommaFeedSession;
import com.commafeed.frontend.SecurityCheck;
-import com.commafeed.frontend.model.Entries;
-import com.commafeed.frontend.rest.ApiListingResource;
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.core.Documentation;
-import com.wordnik.swagger.core.SwaggerSpec;
-import com.wordnik.swagger.core.util.TypeUtil;
-import com.wordnik.swagger.jaxrs.HelpApi;
-import com.wordnik.swagger.jaxrs.JaxrsApiReader;
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
-@SecurityCheck(Role.USER)
-public abstract class AbstractREST {
-
+public class AbstractREST {
@Context
HttpServletRequest request;
@@ -110,6 +95,9 @@ public abstract class AbstractREST {
@Inject
FeedFetcher feedFetcher;
+ @Inject
+ MetricsBean metricsBean;
+
@PostConstruct
public void init() {
CommaFeedApplication app = CommaFeedApplication.get();
@@ -138,11 +126,6 @@ public abstract class AbstractREST {
@AroundInvoke
public Object checkSecurity(InvocationContext context) throws Exception {
User user = getUser();
- if (user == null) {
- throw new WebApplicationException(Response
- .status(Status.UNAUTHORIZED)
- .entity("You need to be authenticated to do this.").build());
- }
boolean allowed = true;
Method method = context.getMethod();
@@ -165,58 +148,13 @@ public abstract class AbstractREST {
}
private boolean checkRole(User user, SecurityCheck annotation) {
+ Role requiredRole = annotation.value();
+ if (requiredRole == Role.NONE) {
+ return true;
+ }
+
Roles roles = CommaFeedSession.get().getRoles();
- boolean authorized = roles.hasAnyRole(new Roles(annotation.value()
- .name()));
+ boolean authorized = roles.hasAnyRole(new Roles(requiredRole.name()));
return authorized;
}
-
- @GET
- @ApiOperation(value = "Returns information about API parameters", responseClass = "com.wordnik.swagger.core.Documentation")
- public Response getHelp(@Context Application app,
- @Context HttpHeaders headers, @Context UriInfo uriInfo) {
-
- TypeUtil.addAllowablePackage(Entries.class.getPackage().getName());
- String apiVersion = ApiListingResource.API_VERSION;
- String swaggerVersion = SwaggerSpec.version();
- String basePath = ApiListingResource
- .getBasePath(applicationSettingsService.get().getPublicUrl());
-
- Class> resource = null;
- String path = prependSlash(uriInfo.getPath());
- for (Class> klass : app.getClasses()) {
- Api api = klass.getAnnotation(Api.class);
- if (api != null && api.value() != null
- && StringUtils.equals(prependSlash(api.value()), path)) {
- resource = klass;
- break;
- }
- }
-
- if (resource == null) {
- return Response
- .status(Status.NOT_FOUND)
- .entity("Api annotation not found on class "
- + getClass().getName()).build();
- }
- Api api = resource.getAnnotation(Api.class);
- String apiPath = api.value();
- String apiListingPath = api.value();
-
- Documentation doc = new HelpApi(null).filterDocs(JaxrsApiReader.read(
- resource, apiVersion, swaggerVersion, basePath, apiPath),
- headers, uriInfo, apiListingPath, apiPath);
-
- doc.setSwaggerVersion(swaggerVersion);
- doc.setBasePath(basePath);
- doc.setApiVersion(apiVersion);
- return Response.ok().entity(doc).build();
- }
-
- private String prependSlash(String path) {
- if (!path.startsWith("/")) {
- path = "/" + path;
- }
- return path;
- }
}
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/AbstractResourceREST.java b/src/main/java/com/commafeed/frontend/rest/resources/AbstractResourceREST.java
new file mode 100644
index 00000000..52334879
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/rest/resources/AbstractResourceREST.java
@@ -0,0 +1,76 @@
+package com.commafeed.frontend.rest.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.commafeed.backend.model.UserRole.Role;
+import com.commafeed.frontend.SecurityCheck;
+import com.commafeed.frontend.model.Entries;
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.core.Documentation;
+import com.wordnik.swagger.core.SwaggerSpec;
+import com.wordnik.swagger.core.util.TypeUtil;
+import com.wordnik.swagger.jaxrs.HelpApi;
+import com.wordnik.swagger.jaxrs.JaxrsApiReader;
+
+@SecurityCheck(Role.USER)
+public abstract class AbstractResourceREST extends AbstractREST {
+
+ @GET
+ @SecurityCheck(value = Role.NONE)
+ @ApiOperation(value = "Returns information about API parameters", responseClass = "com.wordnik.swagger.core.Documentation")
+ public Response getHelp(@Context Application app,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+ TypeUtil.addAllowablePackage(Entries.class.getPackage().getName());
+ String apiVersion = ApiDocumentationREST.API_VERSION;
+ String swaggerVersion = SwaggerSpec.version();
+ String basePath = ApiDocumentationREST
+ .getBasePath(applicationSettingsService.get().getPublicUrl());
+
+ Class> resource = null;
+ String path = prependSlash(uriInfo.getPath());
+ for (Class> klass : app.getClasses()) {
+ Api api = klass.getAnnotation(Api.class);
+ if (api != null && api.value() != null
+ && StringUtils.equals(prependSlash(api.value()), path)) {
+ resource = klass;
+ break;
+ }
+ }
+
+ if (resource == null) {
+ return Response
+ .status(Status.NOT_FOUND)
+ .entity("Api annotation not found on class "
+ + getClass().getName()).build();
+ }
+ Api api = resource.getAnnotation(Api.class);
+ String apiPath = api.value();
+ String apiListingPath = api.value();
+
+ Documentation doc = new HelpApi(null).filterDocs(JaxrsApiReader.read(
+ resource, apiVersion, swaggerVersion, basePath, apiPath),
+ headers, uriInfo, apiListingPath, apiPath);
+
+ doc.setSwaggerVersion(swaggerVersion);
+ doc.setBasePath(basePath);
+ doc.setApiVersion(apiVersion);
+ return Response.ok().entity(doc).build();
+ }
+
+ private String prependSlash(String path) {
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ return path;
+ }
+}
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/AdminMetricsREST.java b/src/main/java/com/commafeed/frontend/rest/resources/AdminMetricsREST.java
deleted file mode 100644
index cd10d4d9..00000000
--- a/src/main/java/com/commafeed/frontend/rest/resources/AdminMetricsREST.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.commafeed.frontend.rest.resources;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-
-import com.commafeed.backend.MetricsBean;
-import com.commafeed.backend.model.UserRole.Role;
-import com.commafeed.frontend.SecurityCheck;
-
-@SecurityCheck(Role.ADMIN)
-@Path("/admin/metrics")
-public class AdminMetricsREST extends AbstractREST {
-
- @Inject
- MetricsBean metricsBean;
-
- @Path("/get")
- @GET
- public int[] get() {
- return new int[] { metricsBean.getFeedsRefreshedLastMinute(),
- metricsBean.getFeedsRefreshedLastHour() };
- }
-
-}
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/AdminUsersREST.java b/src/main/java/com/commafeed/frontend/rest/resources/AdminREST.java
similarity index 80%
rename from src/main/java/com/commafeed/frontend/rest/resources/AdminUsersREST.java
rename to src/main/java/com/commafeed/frontend/rest/resources/AdminREST.java
index f41f26f3..b3c34385 100644
--- a/src/main/java/com/commafeed/frontend/rest/resources/AdminUsersREST.java
+++ b/src/main/java/com/commafeed/frontend/rest/resources/AdminREST.java
@@ -14,6 +14,7 @@ import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang.StringUtils;
import com.commafeed.backend.StartupBean;
+import com.commafeed.backend.model.ApplicationSettings;
import com.commafeed.backend.model.User;
import com.commafeed.backend.model.UserRole;
import com.commafeed.backend.model.UserRole.Role;
@@ -28,11 +29,11 @@ import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
@SecurityCheck(Role.ADMIN)
-@Path("/admin/users")
-@Api(value = "/admin/users", description = "Operations about application users administration")
-public class AdminUsersREST extends AbstractREST {
+@Path("/admin")
+@Api(value = "/admin", description = "Operations about application administration")
+public class AdminREST extends AbstractResourceREST {
- @Path("/save")
+ @Path("/users/save")
@POST
@ApiOperation(value = "Manually save or update a user", notes = "Manually save or update a user. If the id is not specified, a new user will be created")
public Response save(@ApiParam(required = true) UserModel userModel) {
@@ -91,7 +92,7 @@ public class AdminUsersREST extends AbstractREST {
}
- @Path("/get")
+ @Path("/users/get")
@GET
@ApiOperation(value = "Get user information", notes = "Get user information", responseClass = "com.commafeed.frontend.model.UserModel")
public UserModel getUser(
@@ -110,7 +111,7 @@ public class AdminUsersREST extends AbstractREST {
return userModel;
}
- @Path("/getAll")
+ @Path("/users/getAll")
@GET
@ApiOperation(value = "Get all users", notes = "Get all users", responseClass = "List[com.commafeed.frontend.model.UserModel]")
public Collection getUsers() {
@@ -133,7 +134,7 @@ public class AdminUsersREST extends AbstractREST {
return users.values();
}
- @Path("/delete")
+ @Path("/users/delete")
@GET
@ApiOperation(value = "Delete a user", notes = "Delete a user, and all his subscriptions")
public Response delete(
@@ -158,4 +159,27 @@ public class AdminUsersREST extends AbstractREST {
return Response.ok().build();
}
+
+ @Path("/settings/get")
+ @GET
+ @ApiOperation(value = "Retrieve application settings", notes = "Retrieve application settings", responseClass = "com.commafeed.backend.model.ApplicationSettings")
+ public ApplicationSettings getSettings() {
+ return applicationSettingsService.get();
+ }
+
+ @Path("/settings/save")
+ @POST
+ @ApiOperation(value = "Save application settings", notes = "Save application settings")
+ public void saveSettings(@ApiParam(required = true) ApplicationSettings settings) {
+ Preconditions.checkNotNull(settings);
+ applicationSettingsService.save(settings);
+ }
+
+
+ @Path("/metrics/get")
+ @GET
+ public int[] getMetrics() {
+ return new int[] { metricsBean.getFeedsRefreshedLastMinute(),
+ metricsBean.getFeedsRefreshedLastHour() };
+ }
}
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/AdminSettingsREST.java b/src/main/java/com/commafeed/frontend/rest/resources/AdminSettingsREST.java
deleted file mode 100644
index 48dfc82a..00000000
--- a/src/main/java/com/commafeed/frontend/rest/resources/AdminSettingsREST.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.commafeed.frontend.rest.resources;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import com.commafeed.backend.model.ApplicationSettings;
-import com.commafeed.backend.model.UserRole.Role;
-import com.commafeed.backend.services.ApplicationSettingsService;
-import com.commafeed.frontend.SecurityCheck;
-import com.google.common.base.Preconditions;
-import com.wordnik.swagger.annotations.Api;
-import com.wordnik.swagger.annotations.ApiOperation;
-import com.wordnik.swagger.annotations.ApiParam;
-
-@SecurityCheck(Role.ADMIN)
-@Path("/admin/settings")
-@Api(value = "/admin/settings", description = "Operations about application settings administration")
-public class AdminSettingsREST {
-
- @Inject
- ApplicationSettingsService applicationSettingsService;
-
- @Path("/get")
- @GET
- @ApiOperation(value = "Retrieve application settings", notes = "Retrieve application settings", responseClass = "com.commafeed.backend.model.ApplicationSettings")
- public ApplicationSettings get() {
- return applicationSettingsService.get();
- }
-
- @Path("/save")
- @POST
- @ApiOperation(value = "Save application settings", notes = "Save application settings")
- public void save(@ApiParam(required = true) ApplicationSettings settings) {
- Preconditions.checkNotNull(settings);
- applicationSettingsService.save(settings);
- }
-}
diff --git a/src/main/java/com/commafeed/frontend/rest/ApiListingResource.java b/src/main/java/com/commafeed/frontend/rest/resources/ApiDocumentationREST.java
similarity index 72%
rename from src/main/java/com/commafeed/frontend/rest/ApiListingResource.java
rename to src/main/java/com/commafeed/frontend/rest/resources/ApiDocumentationREST.java
index 596c76c2..017339d4 100644
--- a/src/main/java/com/commafeed/frontend/rest/ApiListingResource.java
+++ b/src/main/java/com/commafeed/frontend/rest/resources/ApiDocumentationREST.java
@@ -1,14 +1,11 @@
-package com.commafeed.frontend.rest;
+package com.commafeed.frontend.rest.resources;
-import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
-import com.commafeed.backend.services.ApplicationSettingsService;
import com.commafeed.frontend.model.Entries;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
@@ -19,14 +16,10 @@ import com.wordnik.swagger.core.util.TypeUtil;
@Path("/resources")
@Api("/resources")
-@Produces({ "application/json" })
-public class ApiListingResource {
+public class ApiDocumentationREST extends AbstractREST {
public static final String API_VERSION = "1.0";
- @Inject
- ApplicationSettingsService applicationSettingsService;
-
@GET
@ApiOperation(value = "Returns list of all available api endpoints", responseClass = "List[DocumentationEndPoint]")
public Response getAllApis(@Context Application app) {
@@ -35,7 +28,7 @@ public class ApiListingResource {
Documentation doc = new Documentation();
for (Class> resource : app.getClasses()) {
- if (ApiListingResource.class.equals(resource)) {
+ if (ApiDocumentationREST.class.equals(resource)) {
continue;
}
Api api = resource.getAnnotation(Api.class);
@@ -54,10 +47,12 @@ public class ApiListingResource {
}
public static String getBasePath(String publicUrl) {
- if (publicUrl.endsWith("/")) {
- publicUrl = publicUrl.substring(0, publicUrl.length() - 1);
+ if (!publicUrl.endsWith("/")) {
+ publicUrl = publicUrl + "/";
}
- return publicUrl + "/rest";
+ publicUrl += "rest";
+
+ return publicUrl;
}
}
\ No newline at end of file
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java b/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java
index 2f7c4d78..a521d1b7 100644
--- a/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java
+++ b/src/main/java/com/commafeed/frontend/rest/resources/EntriesREST.java
@@ -28,7 +28,7 @@ import com.wordnik.swagger.annotations.ApiParam;
@Path("/entries/")
@Api(value = "/entries", description = "Operations about feed entries")
-public class EntriesREST extends AbstractREST {
+public class EntriesREST extends AbstractResourceREST {
public static final String ALL = "all";
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/SessionREST.java b/src/main/java/com/commafeed/frontend/rest/resources/SessionREST.java
index 2e9825f9..5bcecece 100644
--- a/src/main/java/com/commafeed/frontend/rest/resources/SessionREST.java
+++ b/src/main/java/com/commafeed/frontend/rest/resources/SessionREST.java
@@ -18,7 +18,7 @@ import com.wordnik.swagger.annotations.ApiParam;
@Path("/session")
@Api(value = "/session", description = "Operations about user profile")
-public class SessionREST extends AbstractREST {
+public class SessionREST extends AbstractResourceREST {
@Path("/get")
@GET
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/SettingsREST.java b/src/main/java/com/commafeed/frontend/rest/resources/SettingsREST.java
index a57c932b..a786155a 100644
--- a/src/main/java/com/commafeed/frontend/rest/resources/SettingsREST.java
+++ b/src/main/java/com/commafeed/frontend/rest/resources/SettingsREST.java
@@ -17,7 +17,7 @@ import com.wordnik.swagger.annotations.ApiParam;
@Path("/settings")
@Api(value = "/settings", description = "Operations about user settings")
-public class SettingsREST extends AbstractREST {
+public class SettingsREST extends AbstractResourceREST {
@Path("/get")
@GET
diff --git a/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java b/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java
index 0a23b726..e8ac59cc 100644
--- a/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java
+++ b/src/main/java/com/commafeed/frontend/rest/resources/SubscriptionsREST.java
@@ -36,7 +36,7 @@ import com.wordnik.swagger.annotations.ApiParam;
@Path("/subscriptions")
@Api(value = "/subscriptions", description = "Operations about user feed subscriptions")
-public class SubscriptionsREST extends AbstractREST {
+public class SubscriptionsREST extends AbstractResourceREST {
@GET
@Path("/feed/fetch")