forked from Archives/Athou_commafeed
security revamp
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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]'])];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
5
pom.xml
5
pom.xml
@@ -137,11 +137,6 @@
|
||||
<artifactId>dropwizard-core</artifactId>
|
||||
<version>${dropwizard.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.dropwizard</groupId>
|
||||
<artifactId>dropwizard-auth</artifactId>
|
||||
<version>${dropwizard.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.dropwizard</groupId>
|
||||
<artifactId>dropwizard-hibernate</artifactId>
|
||||
|
||||
@@ -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<CommaFeedConfiguration> {
|
||||
FeedRefreshWorker feedWorker = new FeedRefreshWorker(feedUpdater, feedFetcher, queues, config, metrics);
|
||||
FeedRefreshTaskGiver taskGiver = new FeedRefreshTaskGiver(sessionFactory, queues, feedDAO, feedWorker, config, metrics);
|
||||
|
||||
CachingAuthenticator<BasicCredentials, User> cachingAuthenticator = new CachingAuthenticator<BasicCredentials, User>(
|
||||
environment.metrics(), new CommaFeedAuthenticator(userService), config.getAuthenticationCachePolicy());
|
||||
environment.jersey().register(new BasicAuthProvider<User>(cachingAuthenticator, "CommaFeed"));
|
||||
// TODO add caching of credentials somehow
|
||||
environment.jersey().register(new SecurityCheckProvider(userService));
|
||||
|
||||
environment.jersey().setUrlPattern("/rest/*");
|
||||
environment.jersey()
|
||||
|
||||
@@ -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<BasicCredentials, User> {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
@Override
|
||||
public Optional<User> authenticate(final BasicCredentials credentials) throws AuthenticationException {
|
||||
return Optional.fromNullable(userService.login(credentials.getUsername(), credentials.getPassword()));
|
||||
}
|
||||
}
|
||||
@@ -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<User> {
|
||||
@@ -14,14 +15,17 @@ public class UserDAO extends GenericDAO<User> {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<Role> roles) {
|
||||
return register(name, password, email, roles, false);
|
||||
}
|
||||
|
||||
22
src/main/java/com/commafeed/frontend/auth/SecurityCheck.java
Normal file
22
src/main/java/com/commafeed/frontend/auth/SecurityCheck.java
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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<SecurityCheck, Parameter> {
|
||||
|
||||
private static class SecurityCheckInjectable<T> extends AbstractHttpContextInjectable<User> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -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<Long, UserModel> 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<String, Long> 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<String, Long> 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<String, Long> map = Maps.newHashMap();
|
||||
map.put("contents_without_entries", cleaner.cleanContentsWithoutEntries());
|
||||
return Response.ok(map).build();
|
||||
|
||||
@@ -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<Long, UnreadCount> 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());
|
||||
|
||||
@@ -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<String> 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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user