diff --git a/config.yml b/config.yml
index 316e53fa..17d4227a 100644
--- a/config.yml
+++ b/config.yml
@@ -1,5 +1,5 @@
app:
- publicUrl: http://localhost:8083/
+ publicUrl: http://localhost:8082/
allowRegistrations: false
googleAnalyticsTrackingCode:
googleClientId:
@@ -38,8 +38,10 @@ database:
server:
applicationConnectors:
- type: http
- port: 8082
-
+ port: 8083
+ adminConnectors:
+ - type: http
+ port: 8084
logging:
level: WARN
loggers:
diff --git a/gulpfile.js b/gulpfile.js
index 78b93807..6d9c5102 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -63,9 +63,9 @@ gulp.task('watch', function() {
gulp.task('serve', function() {
connect.server({
root : BUILD_DIR,
- port : 8083,
+ port : 8082,
middleware : function() {
- return [modRewrite(['^/rest/(.*)$ http://localhost:8082/rest/$1 [P]'])];
+ return [modRewrite(['^/rest/(.*)$ http://localhost:8083/rest/$1 [P]'])];
}
});
});
diff --git a/pom.xml b/pom.xml
index 45f4b8bc..5a019456 100644
--- a/pom.xml
+++ b/pom.xml
@@ -137,11 +137,6 @@
dropwizard-core
${dropwizard.version}
-
- io.dropwizard
- dropwizard-auth
- ${dropwizard.version}
-
io.dropwizard
dropwizard-hibernate
diff --git a/src/main/java/com/commafeed/CommaFeedApplication.java b/src/main/java/com/commafeed/CommaFeedApplication.java
index b4a965a6..68d40046 100644
--- a/src/main/java/com/commafeed/CommaFeedApplication.java
+++ b/src/main/java/com/commafeed/CommaFeedApplication.java
@@ -2,9 +2,6 @@ package com.commafeed;
import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
-import io.dropwizard.auth.CachingAuthenticator;
-import io.dropwizard.auth.basic.BasicAuthProvider;
-import io.dropwizard.auth.basic.BasicCredentials;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.hibernate.HibernateBundle;
import io.dropwizard.migrations.MigrationsBundle;
@@ -61,6 +58,7 @@ import com.commafeed.backend.service.PasswordEncryptionService;
import com.commafeed.backend.service.PubSubService;
import com.commafeed.backend.service.StartupService;
import com.commafeed.backend.service.UserService;
+import com.commafeed.frontend.auth.SecurityCheckProvider;
import com.commafeed.frontend.resource.AdminREST;
import com.commafeed.frontend.resource.CategoryREST;
import com.commafeed.frontend.resource.EntryREST;
@@ -152,9 +150,8 @@ public class CommaFeedApplication extends Application {
FeedRefreshWorker feedWorker = new FeedRefreshWorker(feedUpdater, feedFetcher, queues, config, metrics);
FeedRefreshTaskGiver taskGiver = new FeedRefreshTaskGiver(sessionFactory, queues, feedDAO, feedWorker, config, metrics);
- CachingAuthenticator cachingAuthenticator = new CachingAuthenticator(
- environment.metrics(), new CommaFeedAuthenticator(userService), config.getAuthenticationCachePolicy());
- environment.jersey().register(new BasicAuthProvider(cachingAuthenticator, "CommaFeed"));
+ // TODO add caching of credentials somehow
+ environment.jersey().register(new SecurityCheckProvider(userService));
environment.jersey().setUrlPattern("/rest/*");
environment.jersey()
diff --git a/src/main/java/com/commafeed/CommaFeedAuthenticator.java b/src/main/java/com/commafeed/CommaFeedAuthenticator.java
deleted file mode 100644
index 4c729e17..00000000
--- a/src/main/java/com/commafeed/CommaFeedAuthenticator.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.commafeed;
-
-import io.dropwizard.auth.AuthenticationException;
-import io.dropwizard.auth.Authenticator;
-import io.dropwizard.auth.basic.BasicCredentials;
-import lombok.RequiredArgsConstructor;
-
-import com.commafeed.backend.model.User;
-import com.commafeed.backend.service.UserService;
-import com.google.common.base.Optional;
-
-@RequiredArgsConstructor
-public class CommaFeedAuthenticator implements Authenticator {
-
- private final UserService userService;
-
- @Override
- public Optional authenticate(final BasicCredentials credentials) throws AuthenticationException {
- return Optional.fromNullable(userService.login(credentials.getUsername(), credentials.getPassword()));
- }
-}
diff --git a/src/main/java/com/commafeed/backend/dao/UserDAO.java b/src/main/java/com/commafeed/backend/dao/UserDAO.java
index a9ab20c5..14bdbf01 100644
--- a/src/main/java/com/commafeed/backend/dao/UserDAO.java
+++ b/src/main/java/com/commafeed/backend/dao/UserDAO.java
@@ -3,6 +3,7 @@ package com.commafeed.backend.dao;
import org.hibernate.SessionFactory;
import com.commafeed.backend.model.QUser;
+import com.commafeed.backend.model.QUserRole;
import com.commafeed.backend.model.User;
public class UserDAO extends GenericDAO {
@@ -14,14 +15,17 @@ public class UserDAO extends GenericDAO {
}
public User findByName(String name) {
- return newQuery().from(user).where(user.name.equalsIgnoreCase(name)).uniqueResult(user);
+ return newQuery().from(user).where(user.name.equalsIgnoreCase(name)).leftJoin(user.roles, QUserRole.userRole).fetch()
+ .uniqueResult(user);
}
public User findByApiKey(String key) {
- return newQuery().from(user).where(user.apiKey.equalsIgnoreCase(key)).uniqueResult(user);
+ return newQuery().from(user).where(user.apiKey.equalsIgnoreCase(key)).leftJoin(user.roles, QUserRole.userRole).fetch()
+ .uniqueResult(user);
}
public User findByEmail(String email) {
- return newQuery().from(user).where(user.email.equalsIgnoreCase(email)).uniqueResult(user);
+ return newQuery().from(user).where(user.email.equalsIgnoreCase(email)).leftJoin(user.roles, QUserRole.userRole).fetch()
+ .uniqueResult(user);
}
}
diff --git a/src/main/java/com/commafeed/backend/model/User.java b/src/main/java/com/commafeed/backend/model/User.java
index 1b69d57e..e1fe1394 100644
--- a/src/main/java/com/commafeed/backend/model/User.java
+++ b/src/main/java/com/commafeed/backend/model/User.java
@@ -17,6 +17,7 @@ import lombok.Setter;
import org.hibernate.annotations.Cascade;
+import com.commafeed.backend.model.UserRole.Role;
import com.google.common.collect.Sets;
@Entity
@@ -68,4 +69,13 @@ public class User extends AbstractModel {
@Temporal(TemporalType.TIMESTAMP)
private Date lastFullRefresh;
+ public boolean hasRole(Role role) {
+ for (UserRole userRole : getRoles()) {
+ if (userRole.getRole() == role) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
diff --git a/src/main/java/com/commafeed/backend/model/UserRole.java b/src/main/java/com/commafeed/backend/model/UserRole.java
index bed925d5..a32d4e63 100644
--- a/src/main/java/com/commafeed/backend/model/UserRole.java
+++ b/src/main/java/com/commafeed/backend/model/UserRole.java
@@ -20,7 +20,7 @@ import lombok.Setter;
public class UserRole extends AbstractModel {
public static enum Role {
- USER, ADMIN, NONE
+ USER, ADMIN
}
@OneToOne(fetch = FetchType.LAZY)
diff --git a/src/main/java/com/commafeed/backend/service/UserService.java b/src/main/java/com/commafeed/backend/service/UserService.java
index 14e2aa6b..e71592a8 100644
--- a/src/main/java/com/commafeed/backend/service/UserService.java
+++ b/src/main/java/com/commafeed/backend/service/UserService.java
@@ -64,6 +64,18 @@ public class UserService {
return null;
}
+ public User login(String apiKey) {
+ if (apiKey == null) {
+ return null;
+ }
+
+ User user = userDAO.findByApiKey(apiKey);
+ if (user != null && !user.isDisabled()) {
+ return user;
+ }
+ return null;
+ }
+
public User register(String name, String password, String email, Collection roles) {
return register(name, password, email, roles, false);
}
diff --git a/src/main/java/com/commafeed/frontend/auth/SecurityCheck.java b/src/main/java/com/commafeed/frontend/auth/SecurityCheck.java
new file mode 100644
index 00000000..0e685686
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/auth/SecurityCheck.java
@@ -0,0 +1,22 @@
+package com.commafeed.frontend.auth;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.commafeed.backend.model.UserRole.Role;
+
+@Inherited
+@Target({ ElementType.PARAMETER })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SecurityCheck {
+
+ /**
+ * Roles needed.
+ */
+ Role value() default Role.USER;
+
+ boolean apiKeyAllowed() default false;
+}
\ No newline at end of file
diff --git a/src/main/java/com/commafeed/frontend/auth/SecurityCheckProvider.java b/src/main/java/com/commafeed/frontend/auth/SecurityCheckProvider.java
new file mode 100644
index 00000000..47402e27
--- /dev/null
+++ b/src/main/java/com/commafeed/frontend/auth/SecurityCheckProvider.java
@@ -0,0 +1,95 @@
+package com.commafeed.frontend.auth;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.eclipse.jetty.util.B64Code;
+import org.eclipse.jetty.util.StringUtil;
+
+import com.commafeed.backend.model.User;
+import com.commafeed.backend.model.UserRole.Role;
+import com.commafeed.backend.service.UserService;
+import com.sun.jersey.api.core.HttpContext;
+import com.sun.jersey.api.model.Parameter;
+import com.sun.jersey.core.spi.component.ComponentContext;
+import com.sun.jersey.core.spi.component.ComponentScope;
+import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable;
+import com.sun.jersey.spi.inject.Injectable;
+import com.sun.jersey.spi.inject.InjectableProvider;
+
+@Slf4j
+public class SecurityCheckProvider implements InjectableProvider {
+
+ private static class SecurityCheckInjectable extends AbstractHttpContextInjectable {
+ private static final String PREFIX = "Basic";
+
+ private final UserService userService;
+ private Role role;
+ private final boolean apiKeyAllowed;
+
+ private SecurityCheckInjectable(UserService userService, Role role, boolean apiKeyAllowed) {
+ this.userService = userService;
+ this.role = role;
+ this.apiKeyAllowed = apiKeyAllowed;
+ }
+
+ @Override
+ public User getValue(HttpContext c) {
+ final String header = c.getRequest().getHeaderValue(HttpHeaders.AUTHORIZATION);
+ try {
+ if (header != null) {
+ final int space = header.indexOf(' ');
+ if (space > 0) {
+ final String method = header.substring(0, space);
+ if (PREFIX.equalsIgnoreCase(method)) {
+ final String decoded = B64Code.decode(header.substring(space + 1), StringUtil.__ISO_8859_1);
+ final int i = decoded.indexOf(':');
+ if (i > 0) {
+ final String username = decoded.substring(0, i);
+ final String password = decoded.substring(i + 1);
+ final User user = userService.login(username, password);
+ if (user != null && user.hasRole(role)) {
+ return user;
+ }
+ }
+ }
+ }
+ } else {
+ String apiKey = c.getUriInfo().getPathParameters().getFirst("apiKey");
+ if (apiKey != null && apiKeyAllowed) {
+ User user = userService.login(apiKey);
+ if (user != null && user.hasRole(role)) {
+ return user;
+ }
+ }
+ }
+ } catch (IllegalArgumentException e) {
+ log.debug("Error decoding credentials", e);
+ }
+
+ throw new WebApplicationException(Response.status(Response.Status.UNAUTHORIZED)
+ .header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"CommaFeed\"")
+ .entity("Credentials are required to access this resource.").type(MediaType.TEXT_PLAIN_TYPE).build());
+ }
+ }
+
+ private UserService userService;
+
+ public SecurityCheckProvider(UserService userService) {
+ this.userService = userService;
+ }
+
+ @Override
+ public ComponentScope getScope() {
+ return ComponentScope.PerRequest;
+ }
+
+ @Override
+ public Injectable> getInjectable(ComponentContext ic, SecurityCheck sc, Parameter c) {
+ return new SecurityCheckInjectable<>(userService, sc.value(), sc.apiKeyAllowed());
+ }
+}
diff --git a/src/main/java/com/commafeed/frontend/resource/AdminREST.java b/src/main/java/com/commafeed/frontend/resource/AdminREST.java
index aaec677d..8711168e 100644
--- a/src/main/java/com/commafeed/frontend/resource/AdminREST.java
+++ b/src/main/java/com/commafeed/frontend/resource/AdminREST.java
@@ -1,6 +1,5 @@
package com.commafeed.frontend.resource;
-import io.dropwizard.auth.Auth;
import io.dropwizard.hibernate.UnitOfWork;
import java.util.Map;
@@ -32,6 +31,7 @@ import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.backend.service.DatabaseCleaningService;
import com.commafeed.backend.service.PasswordEncryptionService;
import com.commafeed.backend.service.UserService;
+import com.commafeed.frontend.auth.SecurityCheck;
import com.commafeed.frontend.model.UserModel;
import com.commafeed.frontend.model.request.IDRequest;
import com.google.common.base.Preconditions;
@@ -62,7 +62,7 @@ public class AdminREST {
@POST
@UnitOfWork
@ApiOperation(value = "Save or update a user", notes = "Save or update a user. If the id is not specified, a new user will be created")
- public Response save(@Auth User user, @ApiParam(required = true) UserModel userModel) {
+ public Response save(@SecurityCheck(Role.ADMIN) User user, @ApiParam(required = true) UserModel userModel) {
Preconditions.checkNotNull(userModel);
Preconditions.checkNotNull(userModel.getName());
@@ -115,7 +115,7 @@ public class AdminREST {
@GET
@UnitOfWork
@ApiOperation(value = "Get user information", notes = "Get user information", response = UserModel.class)
- public Response getUser(@Auth User user, @ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
+ public Response getUser(@SecurityCheck(Role.ADMIN) User user, @ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
Preconditions.checkNotNull(id);
User u = userDAO.findById(id);
UserModel userModel = new UserModel();
@@ -135,7 +135,7 @@ public class AdminREST {
@GET
@UnitOfWork
@ApiOperation(value = "Get all users", notes = "Get all users", response = UserModel.class, responseContainer = "List")
- public Response getUsers(@Auth User user) {
+ public Response getUsers(@SecurityCheck(Role.ADMIN) User user) {
Map users = Maps.newHashMap();
for (UserRole role : userRoleDAO.findAll()) {
User u = role.getUser();
@@ -162,7 +162,7 @@ public class AdminREST {
@POST
@UnitOfWork
@ApiOperation(value = "Delete a user", notes = "Delete a user, and all his subscriptions")
- public Response delete(@Auth User user, @ApiParam(required = true) IDRequest req) {
+ public Response delete(@SecurityCheck(Role.ADMIN) User user, @ApiParam(required = true) IDRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -181,7 +181,7 @@ public class AdminREST {
@GET
@UnitOfWork
@ApiOperation(value = "Retrieve application settings", notes = "Retrieve application settings", response = ApplicationSettings.class)
- public Response getSettings(@Auth User user) {
+ public Response getSettings(@SecurityCheck(Role.ADMIN) User user) {
return Response.ok(config.getApplicationSettings()).build();
}
@@ -189,7 +189,7 @@ public class AdminREST {
@GET
@UnitOfWork
@ApiOperation(value = "Retrieve server metrics")
- public Response getMetrics(@Auth User user) {
+ public Response getMetrics(@SecurityCheck(Role.ADMIN) User user) {
return Response.ok(metrics).build();
}
@@ -197,7 +197,7 @@ public class AdminREST {
@GET
@UnitOfWork
@ApiOperation(value = "Entries cleanup", notes = "Delete entries without subscriptions")
- public Response cleanupEntries(@Auth User user) {
+ public Response cleanupEntries(@SecurityCheck(Role.ADMIN) User user) {
Map map = Maps.newHashMap();
map.put("entries_without_subscriptions", cleaner.cleanEntriesWithoutSubscriptions());
return Response.ok(map).build();
@@ -207,7 +207,7 @@ public class AdminREST {
@GET
@UnitOfWork
@ApiOperation(value = "Feeds cleanup", notes = "Delete feeds without subscriptions")
- public Response cleanupFeeds(@Auth User user) {
+ public Response cleanupFeeds(@SecurityCheck(Role.ADMIN) User user) {
Map map = Maps.newHashMap();
map.put("feeds_without_subscriptions", cleaner.cleanFeedsWithoutSubscriptions());
return Response.ok(map).build();
@@ -217,7 +217,7 @@ public class AdminREST {
@GET
@UnitOfWork
@ApiOperation(value = "Content cleanup", notes = "Delete contents without entries")
- public Response cleanupContents(@Auth User user) {
+ public Response cleanupContents(@SecurityCheck(Role.ADMIN) User user) {
Map map = Maps.newHashMap();
map.put("contents_without_entries", cleaner.cleanContentsWithoutEntries());
return Response.ok(map).build();
diff --git a/src/main/java/com/commafeed/frontend/resource/CategoryREST.java b/src/main/java/com/commafeed/frontend/resource/CategoryREST.java
index ad1f218f..1819bf60 100644
--- a/src/main/java/com/commafeed/frontend/resource/CategoryREST.java
+++ b/src/main/java/com/commafeed/frontend/resource/CategoryREST.java
@@ -1,6 +1,5 @@
package com.commafeed.frontend.resource;
-import io.dropwizard.auth.Auth;
import io.dropwizard.hibernate.UnitOfWork;
import java.io.StringWriter;
@@ -43,6 +42,7 @@ import com.commafeed.backend.model.UserSettings.ReadingMode;
import com.commafeed.backend.model.UserSettings.ReadingOrder;
import com.commafeed.backend.service.FeedEntryService;
import com.commafeed.backend.service.FeedSubscriptionService;
+import com.commafeed.frontend.auth.SecurityCheck;
import com.commafeed.frontend.model.Category;
import com.commafeed.frontend.model.Entries;
import com.commafeed.frontend.model.Entry;
@@ -88,7 +88,7 @@ public class CategoryREST {
@UnitOfWork
@ApiOperation(value = "Get category entries", notes = "Get a list of category entries", response = Entries.class)
public Response getCategoryEntries(
- @Auth User user,
+ @SecurityCheck User user,
@ApiParam(value = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id,
@ApiParam(value = "all entries or only unread ones", allowableValues = "all,unread", required = true) @DefaultValue("unread") @QueryParam("readType") ReadingMode readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@@ -186,7 +186,7 @@ public class CategoryREST {
@ApiOperation(value = "Get category entries as feed", notes = "Get a feed of category entries")
@Produces(MediaType.APPLICATION_XML)
public Response getCategoryEntriesAsFeed(
- @Auth User user,
+ @SecurityCheck(apiKeyAllowed = true) User user,
@ApiParam(value = "id of the category, 'all' or 'starred'", required = true) @QueryParam("id") String id,
@ApiParam(value = "all entries or only unread ones", allowableValues = "all,unread", required = true) @DefaultValue("all") @QueryParam("readType") ReadingMode readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@@ -234,7 +234,8 @@ public class CategoryREST {
@POST
@UnitOfWork
@ApiOperation(value = "Mark category entries", notes = "Mark feed entries of this category as read")
- public Response markCategoryEntries(@Auth User user, @ApiParam(value = "category id, or 'all'", required = true) MarkRequest req) {
+ public Response markCategoryEntries(@SecurityCheck User user,
+ @ApiParam(value = "category id, or 'all'", required = true) MarkRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -272,7 +273,7 @@ public class CategoryREST {
@POST
@UnitOfWork
@ApiOperation(value = "Add a category", notes = "Add a new feed category", response = Long.class)
- public Response addCategory(@Auth User user, @ApiParam(required = true) AddCategoryRequest req) {
+ public Response addCategory(@SecurityCheck User user, @ApiParam(required = true) AddCategoryRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getName());
@@ -295,7 +296,7 @@ public class CategoryREST {
@Path("/delete")
@UnitOfWork
@ApiOperation(value = "Delete a category", notes = "Delete an existing feed category")
- public Response deleteCategory(@Auth User user, @ApiParam(required = true) IDRequest req) {
+ public Response deleteCategory(@SecurityCheck User user, @ApiParam(required = true) IDRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -327,7 +328,7 @@ public class CategoryREST {
@Path("/modify")
@UnitOfWork
@ApiOperation(value = "Rename a category", notes = "Rename an existing feed category")
- public Response modifyCategory(@Auth User user, @ApiParam(required = true) CategoryModificationRequest req) {
+ public Response modifyCategory(@SecurityCheck User user, @ApiParam(required = true) CategoryModificationRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -381,7 +382,7 @@ public class CategoryREST {
@Path("/collapse")
@UnitOfWork
@ApiOperation(value = "Collapse a category", notes = "Save collapsed or expanded status for a category")
- public Response collapse(@Auth User user, @ApiParam(required = true) CollapseRequest req) {
+ public Response collapse(@SecurityCheck User user, @ApiParam(required = true) CollapseRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -399,7 +400,7 @@ public class CategoryREST {
@Path("/unreadCount")
@UnitOfWork
@ApiOperation(value = "Get unread count for feed subscriptions", response = UnreadCount.class, responseContainer = "List")
- public Response getUnreadCount(@Auth User user) {
+ public Response getUnreadCount(@SecurityCheck User user) {
Map unreadCount = feedSubscriptionService.getUnreadCount(user);
return Response.ok(Lists.newArrayList(unreadCount.values())).build();
}
@@ -408,7 +409,7 @@ public class CategoryREST {
@Path("/get")
@UnitOfWork
@ApiOperation(value = "Get feed categories", notes = "Get all categories and subscriptions of the user", response = Category.class)
- public Response getSubscriptions(@Auth User user) {
+ public Response getSubscriptions(@SecurityCheck User user) {
Category root = cache.getUserRootCategory(user);
if (root == null) {
log.debug("tree cache miss for {}", user.getId());
diff --git a/src/main/java/com/commafeed/frontend/resource/EntryREST.java b/src/main/java/com/commafeed/frontend/resource/EntryREST.java
index bef9b51a..d9c4771a 100644
--- a/src/main/java/com/commafeed/frontend/resource/EntryREST.java
+++ b/src/main/java/com/commafeed/frontend/resource/EntryREST.java
@@ -1,6 +1,5 @@
package com.commafeed.frontend.resource;
-import io.dropwizard.auth.Auth;
import io.dropwizard.hibernate.UnitOfWork;
import java.util.List;
@@ -19,6 +18,7 @@ import com.commafeed.backend.dao.FeedEntryTagDAO;
import com.commafeed.backend.model.User;
import com.commafeed.backend.service.FeedEntryService;
import com.commafeed.backend.service.FeedEntryTagService;
+import com.commafeed.frontend.auth.SecurityCheck;
import com.commafeed.frontend.model.request.MarkRequest;
import com.commafeed.frontend.model.request.MultipleMarkRequest;
import com.commafeed.frontend.model.request.StarRequest;
@@ -43,7 +43,7 @@ public class EntryREST {
@POST
@UnitOfWork
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
- public Response markFeedEntry(@Auth User user, @ApiParam(value = "Mark Request", required = true) MarkRequest req) {
+ public Response markFeedEntry(@SecurityCheck User user, @ApiParam(value = "Mark Request", required = true) MarkRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -55,7 +55,8 @@ public class EntryREST {
@POST
@UnitOfWork
@ApiOperation(value = "Mark multiple feed entries", notes = "Mark feed entries as read/unread")
- public Response markFeedEntries(@Auth User user, @ApiParam(value = "Multiple Mark Request", required = true) MultipleMarkRequest req) {
+ public Response markFeedEntries(@SecurityCheck User user,
+ @ApiParam(value = "Multiple Mark Request", required = true) MultipleMarkRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getRequests());
@@ -70,7 +71,7 @@ public class EntryREST {
@POST
@UnitOfWork
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
- public Response starFeedEntry(@Auth User user, @ApiParam(value = "Star Request", required = true) StarRequest req) {
+ public Response starFeedEntry(@SecurityCheck User user, @ApiParam(value = "Star Request", required = true) StarRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
Preconditions.checkNotNull(req.getFeedId());
@@ -84,7 +85,7 @@ public class EntryREST {
@GET
@UnitOfWork
@ApiOperation(value = "Get list of tags for the user", notes = "Get list of tags for the user")
- public Response getTags(@Auth User user) {
+ public Response getTags(@SecurityCheck User user) {
List tags = feedEntryTagDAO.findByUser(user);
return Response.ok(tags).build();
}
@@ -93,7 +94,7 @@ public class EntryREST {
@POST
@UnitOfWork
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
- public Response tagFeedEntry(@Auth User user, @ApiParam(value = "Tag Request", required = true) TagRequest req) {
+ public Response tagFeedEntry(@SecurityCheck User user, @ApiParam(value = "Tag Request", required = true) TagRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getEntryId());
diff --git a/src/main/java/com/commafeed/frontend/resource/FeedREST.java b/src/main/java/com/commafeed/frontend/resource/FeedREST.java
index b36f5f71..ef56bbd5 100644
--- a/src/main/java/com/commafeed/frontend/resource/FeedREST.java
+++ b/src/main/java/com/commafeed/frontend/resource/FeedREST.java
@@ -1,6 +1,5 @@
package com.commafeed.frontend.resource;
-import io.dropwizard.auth.Auth;
import io.dropwizard.hibernate.UnitOfWork;
import java.io.InputStream;
@@ -57,6 +56,7 @@ import com.commafeed.backend.opml.OPMLExporter;
import com.commafeed.backend.opml.OPMLImporter;
import com.commafeed.backend.service.FeedEntryService;
import com.commafeed.backend.service.FeedSubscriptionService;
+import com.commafeed.frontend.auth.SecurityCheck;
import com.commafeed.frontend.model.Entries;
import com.commafeed.frontend.model.Entry;
import com.commafeed.frontend.model.FeedInfo;
@@ -107,7 +107,7 @@ public class FeedREST {
@UnitOfWork
@ApiOperation(value = "Get feed entries", notes = "Get a list of feed entries", response = Entries.class)
public Response getFeedEntries(
- @Auth User user,
+ @SecurityCheck User user,
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
@ApiParam(value = "all entries or only unread ones", allowableValues = "all,unread", required = true) @DefaultValue("unread") @QueryParam("readType") ReadingMode readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@@ -172,7 +172,7 @@ public class FeedREST {
@ApiOperation(value = "Get feed entries as a feed", notes = "Get a feed of feed entries")
@Produces(MediaType.APPLICATION_XML)
public Response getFeedEntriesAsFeed(
- @Auth User user,
+ @SecurityCheck(apiKeyAllowed = true) User user,
@ApiParam(value = "id of the feed", required = true) @QueryParam("id") String id,
@ApiParam(value = "all entries or only unread ones", allowableValues = "all,unread", required = true) @DefaultValue("all") @QueryParam("readType") ReadingMode readType,
@ApiParam(value = "only entries newer than this") @QueryParam("newerThan") Long newerThan,
@@ -234,7 +234,7 @@ public class FeedREST {
@Path("/fetch")
@UnitOfWork
@ApiOperation(value = "Fetch a feed", notes = "Fetch a feed by its url", response = FeedInfo.class)
- public Response fetchFeed(@Auth User user, @ApiParam(value = "feed url", required = true) FeedInfoRequest req) {
+ public Response fetchFeed(@SecurityCheck User user, @ApiParam(value = "feed url", required = true) FeedInfoRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getUrl());
@@ -252,7 +252,7 @@ public class FeedREST {
@GET
@UnitOfWork
@ApiOperation(value = "Queue all feeds of the user for refresh", notes = "Manually add all feeds of the user to the refresh queue")
- public Response queueAllForRefresh(@Auth User user) {
+ public Response queueAllForRefresh(@SecurityCheck User user) {
feedSubscriptionService.refreshAll(user);
return Response.ok().build();
}
@@ -261,7 +261,7 @@ public class FeedREST {
@POST
@UnitOfWork
@ApiOperation(value = "Queue a feed for refresh", notes = "Manually add a feed to the refresh queue")
- public Response queueForRefresh(@Auth User user, @ApiParam(value = "Feed id") IDRequest req) {
+ public Response queueForRefresh(@SecurityCheck User user, @ApiParam(value = "Feed id") IDRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -279,7 +279,7 @@ public class FeedREST {
@POST
@UnitOfWork
@ApiOperation(value = "Mark feed entries", notes = "Mark feed entries as read (unread is not supported)")
- public Response markFeedEntries(@Auth User user, @ApiParam(value = "Mark request") MarkRequest req) {
+ public Response markFeedEntries(@SecurityCheck User user, @ApiParam(value = "Mark request") MarkRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -296,7 +296,7 @@ public class FeedREST {
@Path("/get/{id}")
@UnitOfWork
@ApiOperation(value = "", notes = "")
- public Response get(@Auth User user, @ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
+ public Response get(@SecurityCheck User user, @ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
Preconditions.checkNotNull(id);
FeedSubscription sub = feedSubscriptionDAO.findById(user, id);
@@ -311,7 +311,7 @@ public class FeedREST {
@Path("/favicon/{id}")
@UnitOfWork
@ApiOperation(value = "Fetch a feed's icon", notes = "Fetch a feed's icon")
- public Response getFavicon(@Auth User user, @ApiParam(value = "subscription id") @PathParam("id") Long id) {
+ public Response getFavicon(@SecurityCheck User user, @ApiParam(value = "subscription id") @PathParam("id") Long id) {
Preconditions.checkNotNull(id);
FeedSubscription subscription = feedSubscriptionDAO.findById(user, id);
@@ -348,7 +348,7 @@ public class FeedREST {
@Path("/subscribe")
@UnitOfWork
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
- public Response subscribe(@Auth User user, @ApiParam(value = "subscription request", required = true) SubscribeRequest req) {
+ public Response subscribe(@SecurityCheck User user, @ApiParam(value = "subscription request", required = true) SubscribeRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getTitle());
Preconditions.checkNotNull(req.getUrl());
@@ -374,7 +374,7 @@ public class FeedREST {
@Path("/subscribe")
@UnitOfWork
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
- public Response subscribe(@Auth User user, @ApiParam(value = "feed url", required = true) @QueryParam("url") String url) {
+ public Response subscribe(@SecurityCheck User user, @ApiParam(value = "feed url", required = true) @QueryParam("url") String url) {
try {
Preconditions.checkNotNull(url);
@@ -401,7 +401,7 @@ public class FeedREST {
@Path("/unsubscribe")
@UnitOfWork
@ApiOperation(value = "Unsubscribe from a feed", notes = "Unsubscribe from a feed")
- public Response unsubscribe(@Auth User user, @ApiParam(required = true) IDRequest req) {
+ public Response unsubscribe(@SecurityCheck User user, @ApiParam(required = true) IDRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -417,7 +417,7 @@ public class FeedREST {
@Path("/modify")
@UnitOfWork
@ApiOperation(value = "Modify a subscription", notes = "Modify a feed subscription")
- public Response modify(@Auth User user, @ApiParam(value = "subscription id", required = true) FeedModificationRequest req) {
+ public Response modify(@SecurityCheck User user, @ApiParam(value = "subscription id", required = true) FeedModificationRequest req) {
Preconditions.checkNotNull(req);
Preconditions.checkNotNull(req.getId());
@@ -469,7 +469,7 @@ public class FeedREST {
@UnitOfWork
@Consumes(MediaType.MULTIPART_FORM_DATA)
@ApiOperation(value = "OPML import", notes = "Import an OPML file, posted as a FORM with the 'file' name")
- public Response importOpml(@Auth User user, @FormDataParam("file") InputStream input) {
+ public Response importOpml(@SecurityCheck User user, @FormDataParam("file") InputStream input) {
String publicUrl = config.getApplicationSettings().getPublicUrl();
if (StringUtils.isBlank(publicUrl)) {
@@ -495,7 +495,7 @@ public class FeedREST {
@UnitOfWork
@Produces(MediaType.APPLICATION_XML)
@ApiOperation(value = "OPML export", notes = "Export an OPML file of the user's subscriptions")
- public Response exportOpml(@Auth User user) {
+ public Response exportOpml(@SecurityCheck User user) {
Opml opml = opmlExporter.export(user);
WireFeedOutput output = new WireFeedOutput();
String opmlString = null;
diff --git a/src/main/java/com/commafeed/frontend/resource/ServerREST.java b/src/main/java/com/commafeed/frontend/resource/ServerREST.java
index d16d2dc4..47310049 100644
--- a/src/main/java/com/commafeed/frontend/resource/ServerREST.java
+++ b/src/main/java/com/commafeed/frontend/resource/ServerREST.java
@@ -1,6 +1,5 @@
package com.commafeed.frontend.resource;
-import io.dropwizard.auth.Auth;
import io.dropwizard.hibernate.UnitOfWork;
import javax.ws.rs.Consumes;
@@ -20,6 +19,7 @@ import com.commafeed.backend.HttpGetter.HttpResult;
import com.commafeed.backend.feed.FeedUtils;
import com.commafeed.backend.model.User;
import com.commafeed.backend.service.ApplicationPropertiesService;
+import com.commafeed.frontend.auth.SecurityCheck;
import com.commafeed.frontend.model.ServerInfo;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
@@ -39,7 +39,7 @@ public class ServerREST {
@GET
@UnitOfWork
@ApiOperation(value = "Get server infos", notes = "Get server infos", response = ServerInfo.class)
- public Response get(@Auth User user) {
+ public Response get(@SecurityCheck User user) {
ServerInfo infos = new ServerInfo();
infos.setAnnouncement(config.getApplicationSettings().getAnnouncement());
infos.setVersion(applicationPropertiesService.getVersion());
@@ -52,7 +52,7 @@ public class ServerREST {
@UnitOfWork
@ApiOperation(value = "proxy image")
@Produces("image/png")
- public Response get(@Auth User user, @QueryParam("u") String url) {
+ public Response get(@SecurityCheck User user, @QueryParam("u") String url) {
if (!config.getApplicationSettings().isImageProxyEnabled()) {
return Response.status(Status.FORBIDDEN).build();
}
diff --git a/src/main/java/com/commafeed/frontend/resource/UserREST.java b/src/main/java/com/commafeed/frontend/resource/UserREST.java
index b8ff3bcf..eb22084d 100644
--- a/src/main/java/com/commafeed/frontend/resource/UserREST.java
+++ b/src/main/java/com/commafeed/frontend/resource/UserREST.java
@@ -1,6 +1,5 @@
package com.commafeed.frontend.resource;
-import io.dropwizard.auth.Auth;
import io.dropwizard.hibernate.UnitOfWork;
import java.util.Arrays;
@@ -31,6 +30,7 @@ import com.commafeed.backend.model.UserSettings.ReadingOrder;
import com.commafeed.backend.model.UserSettings.ViewMode;
import com.commafeed.backend.service.PasswordEncryptionService;
import com.commafeed.backend.service.UserService;
+import com.commafeed.frontend.auth.SecurityCheck;
import com.commafeed.frontend.model.Settings;
import com.commafeed.frontend.model.UserModel;
import com.commafeed.frontend.model.request.ProfileModificationRequest;
@@ -57,7 +57,7 @@ public class UserREST {
@GET
@UnitOfWork
@ApiOperation(value = "Retrieve user settings", notes = "Retrieve user settings", response = Settings.class)
- public Response getSettings(@Auth User user) {
+ public Response getSettings(@SecurityCheck User user) {
Settings s = new Settings();
UserSettings settings = userSettingsDAO.findByUser(user);
if (settings != null) {
@@ -111,7 +111,7 @@ public class UserREST {
@POST
@UnitOfWork
@ApiOperation(value = "Save user settings", notes = "Save user settings")
- public Response saveSettings(@Auth User user, @ApiParam(required = true) Settings settings) {
+ public Response saveSettings(@SecurityCheck User user, @ApiParam(required = true) Settings settings) {
Preconditions.checkNotNull(settings);
UserSettings s = userSettingsDAO.findByUser(user);
@@ -149,7 +149,7 @@ public class UserREST {
@GET
@UnitOfWork
@ApiOperation(value = "Retrieve user's profile", response = UserModel.class)
- public Response get(@Auth User user) {
+ public Response get(@SecurityCheck User user) {
UserModel userModel = new UserModel();
userModel.setId(user.getId());
userModel.setName(user.getName());
@@ -168,7 +168,7 @@ public class UserREST {
@POST
@UnitOfWork
@ApiOperation(value = "Save user's profile")
- public Response save(@Auth User user, @ApiParam(required = true) ProfileModificationRequest request) {
+ public Response save(@SecurityCheck User user, @ApiParam(required = true) ProfileModificationRequest request) {
Preconditions.checkArgument(StringUtils.isBlank(request.getPassword()) || request.getPassword().length() >= 6);
if (StringUtils.isNotBlank(request.getEmail())) {
User u = userDAO.findByEmail(request.getEmail());
@@ -210,7 +210,7 @@ public class UserREST {
@POST
@UnitOfWork
@ApiOperation(value = "Delete the user account")
- public Response delete(@Auth User user) {
+ public Response delete(@SecurityCheck User user) {
if (CommaFeedApplication.USERNAME_ADMIN.equals(user.getName()) || CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
return Response.status(Status.FORBIDDEN).build();
}