mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
removed wicket and tomee, use dropwizard instead. remove wro4j, use gulp instead
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
package com.commafeed.frontend;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.annotation.processing.SupportedOptions;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.wicket.util.io.IOUtils;
|
||||
|
||||
import com.commafeed.frontend.model.Entries;
|
||||
import com.commafeed.frontend.model.request.MarkRequest;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.wordnik.swagger.annotations.Api;
|
||||
import com.wordnik.swagger.core.Documentation;
|
||||
import com.wordnik.swagger.core.DocumentationEndPoint;
|
||||
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;
|
||||
|
||||
@SupportedAnnotationTypes("com.wordnik.swagger.annotations.Api")
|
||||
@SupportedOptions("outputDirectory")
|
||||
public class APIGenerator extends AbstractProcessor {
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
try {
|
||||
return processInternal(annotations, roundEnv);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean processInternal(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws Exception {
|
||||
JaxrsApiReader.setFormatString("");
|
||||
TypeUtil.addAllowablePackage(Entries.class.getPackage().getName());
|
||||
TypeUtil.addAllowablePackage(MarkRequest.class.getPackage().getName());
|
||||
|
||||
String apiVersion = "1.0";
|
||||
String swaggerVersion = SwaggerSpec.version();
|
||||
String basePath = "../rest";
|
||||
|
||||
Documentation doc = new Documentation();
|
||||
for (Element element : roundEnv.getElementsAnnotatedWith(Api.class)) {
|
||||
TypeElement type = (TypeElement) element;
|
||||
String fqn = type.getQualifiedName().toString();
|
||||
Class<?> resource = Class.forName(fqn);
|
||||
|
||||
Api api = resource.getAnnotation(Api.class);
|
||||
String apiPath = api.value();
|
||||
|
||||
Documentation apiDoc = JaxrsApiReader.read(resource, apiVersion, swaggerVersion, basePath, apiPath);
|
||||
apiDoc = new HelpApi(null).filterDocs(apiDoc, null, null, null, null);
|
||||
|
||||
apiDoc.setSwaggerVersion(swaggerVersion);
|
||||
apiDoc.setApiVersion(apiVersion);
|
||||
write(apiDoc.getResourcePath(), apiDoc, element);
|
||||
|
||||
doc.addApi(new DocumentationEndPoint(api.value(), api.description()));
|
||||
|
||||
}
|
||||
doc.setSwaggerVersion(swaggerVersion);
|
||||
doc.setApiVersion(apiVersion);
|
||||
|
||||
write(doc.getResourcePath(), doc, null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void write(String resourcePath, Object doc, Element element) throws Exception {
|
||||
String fileName = StringUtils.defaultString(resourcePath, "resources");
|
||||
fileName = StringUtils.removeStart(fileName, "/");
|
||||
|
||||
FileObject resource = null;
|
||||
try {
|
||||
resource = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", fileName, element);
|
||||
} catch (Exception e) {
|
||||
// already processed
|
||||
}
|
||||
if (resource != null) {
|
||||
OutputStream os = resource.openOutputStream();
|
||||
try {
|
||||
IOUtils.write(new ObjectMapper().writeValueAsString(doc), os, "UTF-8");
|
||||
} finally {
|
||||
IOUtils.closeQuietly(os);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
package com.commafeed.frontend;
|
||||
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.wicket.Application;
|
||||
import org.apache.wicket.Component;
|
||||
import org.apache.wicket.IRequestCycleProvider;
|
||||
import org.apache.wicket.Page;
|
||||
import org.apache.wicket.RuntimeConfigurationType;
|
||||
import org.apache.wicket.Session;
|
||||
import org.apache.wicket.ajax.AjaxRequestTarget;
|
||||
import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy;
|
||||
import org.apache.wicket.authorization.Action;
|
||||
import org.apache.wicket.authorization.IAuthorizationStrategy;
|
||||
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
|
||||
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
|
||||
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
|
||||
import org.apache.wicket.cdi.CdiConfiguration;
|
||||
import org.apache.wicket.cdi.CdiContainer;
|
||||
import org.apache.wicket.cdi.ConversationPropagation;
|
||||
import org.apache.wicket.core.request.handler.PageProvider;
|
||||
import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
|
||||
import org.apache.wicket.core.request.handler.RenderPageRequestHandler.RedirectPolicy;
|
||||
import org.apache.wicket.markup.head.IHeaderResponse;
|
||||
import org.apache.wicket.markup.head.filter.JavaScriptFilteredIntoFooterHeaderResponse;
|
||||
import org.apache.wicket.markup.html.IHeaderResponseDecorator;
|
||||
import org.apache.wicket.markup.html.WebPage;
|
||||
import org.apache.wicket.request.IRequestHandler;
|
||||
import org.apache.wicket.request.Request;
|
||||
import org.apache.wicket.request.Response;
|
||||
import org.apache.wicket.request.Url;
|
||||
import org.apache.wicket.request.UrlRenderer;
|
||||
import org.apache.wicket.request.component.IRequestableComponent;
|
||||
import org.apache.wicket.request.cycle.AbstractRequestCycleListener;
|
||||
import org.apache.wicket.request.cycle.RequestCycle;
|
||||
import org.apache.wicket.request.cycle.RequestCycleContext;
|
||||
import org.apache.wicket.util.cookies.CookieUtils;
|
||||
|
||||
import com.commafeed.backend.services.ApplicationPropertiesService;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.frontend.pages.DemoLoginPage;
|
||||
import com.commafeed.frontend.pages.HomePage;
|
||||
import com.commafeed.frontend.pages.LogoutPage;
|
||||
import com.commafeed.frontend.pages.NextUnreadRedirectPage;
|
||||
import com.commafeed.frontend.pages.PasswordRecoveryCallbackPage;
|
||||
import com.commafeed.frontend.pages.PasswordRecoveryPage;
|
||||
import com.commafeed.frontend.pages.WelcomePage;
|
||||
import com.commafeed.frontend.utils.WicketUtils;
|
||||
import com.commafeed.frontend.utils.exception.DisplayExceptionPage;
|
||||
|
||||
@Slf4j
|
||||
public class CommaFeedApplication extends AuthenticatedWebApplication {
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
public CommaFeedApplication() {
|
||||
super();
|
||||
boolean prod = ApplicationPropertiesService.get().isProduction();
|
||||
setConfigurationType(prod ? RuntimeConfigurationType.DEPLOYMENT : RuntimeConfigurationType.DEVELOPMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
setupInjection();
|
||||
setupSecurity();
|
||||
|
||||
mountPage("welcome", WelcomePage.class);
|
||||
mountPage("demo", DemoLoginPage.class);
|
||||
|
||||
mountPage("recover", PasswordRecoveryPage.class);
|
||||
mountPage("recover2", PasswordRecoveryCallbackPage.class);
|
||||
|
||||
mountPage("logout", LogoutPage.class);
|
||||
mountPage("error", DisplayExceptionPage.class);
|
||||
|
||||
mountPage("next", NextUnreadRedirectPage.class);
|
||||
|
||||
getMarkupSettings().setStripWicketTags(true);
|
||||
getMarkupSettings().setCompressWhitespace(true);
|
||||
getMarkupSettings().setDefaultMarkupEncoding("UTF-8");
|
||||
|
||||
setHeaderResponseDecorator(new IHeaderResponseDecorator() {
|
||||
@Override
|
||||
public IHeaderResponse decorate(IHeaderResponse response) {
|
||||
return new JavaScriptFilteredIntoFooterHeaderResponse(response, "footer-container");
|
||||
}
|
||||
});
|
||||
|
||||
getRequestCycleListeners().add(new AbstractRequestCycleListener() {
|
||||
@Override
|
||||
public IRequestHandler onException(RequestCycle cycle, Exception ex) {
|
||||
AjaxRequestTarget target = cycle.find(AjaxRequestTarget.class);
|
||||
// redirect to the error page if ajax request, render error on current page otherwise
|
||||
RedirectPolicy policy = target == null ? RedirectPolicy.NEVER_REDIRECT : RedirectPolicy.AUTO_REDIRECT;
|
||||
return new RenderPageRequestHandler(new PageProvider(new DisplayExceptionPage(ex)), policy);
|
||||
}
|
||||
});
|
||||
|
||||
setRequestCycleProvider(new IRequestCycleProvider() {
|
||||
@Override
|
||||
public RequestCycle get(RequestCycleContext context) {
|
||||
return new RequestCycle(context) {
|
||||
@Override
|
||||
protected UrlRenderer newUrlRenderer() {
|
||||
return new UrlRenderer(getRequest()) {
|
||||
@Override
|
||||
public String renderUrl(Url url) {
|
||||
// override wicket's relative-to-absolute url conversion with what we know is the correct protocol
|
||||
String publicUrl = applicationSettingsService.get().getPublicUrl();
|
||||
if (StringUtils.isNotBlank(publicUrl)) {
|
||||
Url parsed = Url.parse(publicUrl);
|
||||
url.setProtocol(parsed.getProtocol());
|
||||
url.setPort(parsed.getPort());
|
||||
}
|
||||
return super.renderUrl(url);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupSecurity() {
|
||||
getSecuritySettings().setAuthenticationStrategy(new DefaultAuthenticationStrategy("LoggedIn") {
|
||||
|
||||
private CookieUtils cookieUtils = null;
|
||||
|
||||
@Override
|
||||
protected CookieUtils getCookieUtils() {
|
||||
|
||||
if (cookieUtils == null) {
|
||||
cookieUtils = new CookieUtils() {
|
||||
@Override
|
||||
protected void initializeCookie(Cookie cookie) {
|
||||
super.initializeCookie(cookie);
|
||||
cookie.setHttpOnly(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
return cookieUtils;
|
||||
}
|
||||
});
|
||||
getSecuritySettings().setAuthorizationStrategy(new IAuthorizationStrategy() {
|
||||
|
||||
@Override
|
||||
public <T extends IRequestableComponent> boolean isInstantiationAuthorized(Class<T> componentClass) {
|
||||
boolean authorized = true;
|
||||
|
||||
boolean restricted = componentClass.isAnnotationPresent(SecurityCheck.class);
|
||||
if (restricted) {
|
||||
SecurityCheck annotation = componentClass.getAnnotation(SecurityCheck.class);
|
||||
Roles roles = CommaFeedSession.get().getRoles();
|
||||
authorized = roles.hasAnyRole(new Roles(annotation.value().name()));
|
||||
}
|
||||
return authorized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActionAuthorized(Component component, Action action) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Page> getHomePage() {
|
||||
return HomePage.class;
|
||||
}
|
||||
|
||||
protected void setupInjection() {
|
||||
try {
|
||||
BeanManager beanManager = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
|
||||
CdiContainer container = new CdiConfiguration(beanManager).setPropagation(ConversationPropagation.NONE).configure(this);
|
||||
container.getNonContextualManager().inject(this);
|
||||
} catch (NamingException e) {
|
||||
log.warn("Could not locate bean manager. CDI is disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restartResponseAtSignInPage() {
|
||||
// preserve https if it was set
|
||||
RequestCycle.get().getUrlRenderer().setBaseUrl(Url.parse(WicketUtils.getClientFullUrl()));
|
||||
super.restartResponseAtSignInPage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session newSession(Request request, Response response) {
|
||||
return new CommaFeedSession(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends WebPage> getSignInPageClass() {
|
||||
return WelcomePage.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends AbstractAuthenticatedWebSession> getWebSessionClass() {
|
||||
return CommaFeedSession.class;
|
||||
}
|
||||
|
||||
public static CommaFeedApplication get() {
|
||||
|
||||
return (CommaFeedApplication) Application.get();
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.commafeed.frontend;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import org.apache.wicket.Session;
|
||||
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
|
||||
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
|
||||
import org.apache.wicket.request.Request;
|
||||
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
public class CommaFeedSession extends AuthenticatedWebSession {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private User user;
|
||||
private Roles roles = new Roles();
|
||||
|
||||
@Getter(lazy = true)
|
||||
private final CommaFeedSessionServices services = newServices();
|
||||
|
||||
public CommaFeedSession(Request request) {
|
||||
super(request);
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public static CommaFeedSession get() {
|
||||
return (CommaFeedSession) Session.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Roles getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authenticate(String userName, String password) {
|
||||
User user = getServices().getUserService().login(userName, password);
|
||||
setUser(user);
|
||||
return user != null;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
if (user == null) {
|
||||
this.user = null;
|
||||
this.roles = new Roles();
|
||||
} else {
|
||||
|
||||
Set<String> roleSet = Sets.newHashSet();
|
||||
for (Role role : getServices().getUserRoleDAO().findRoles(user)) {
|
||||
roleSet.add(role.name());
|
||||
}
|
||||
this.user = user;
|
||||
this.roles = new Roles(roleSet.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
||||
private CommaFeedSessionServices newServices() {
|
||||
return new CommaFeedSessionServices();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.commafeed.frontend;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.wicket.Component;
|
||||
|
||||
import com.commafeed.backend.dao.UserRoleDAO;
|
||||
import com.commafeed.backend.services.UserService;
|
||||
|
||||
// extend Component in order to benefit from injection
|
||||
public class CommaFeedSessionServices extends Component {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Inject
|
||||
UserService userService;
|
||||
|
||||
@Inject
|
||||
UserRoleDAO userRoleDAO;
|
||||
|
||||
public CommaFeedSessionServices() {
|
||||
super("services");
|
||||
}
|
||||
|
||||
public UserService getUserService() {
|
||||
return userService;
|
||||
}
|
||||
|
||||
public UserRoleDAO getUserRoleDAO() {
|
||||
return userRoleDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRender() {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.commafeed.frontend;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebFilter(urlPatterns = "/*")
|
||||
public class InterceptingFilter implements Filter {
|
||||
|
||||
private static final String HEADER_CORS = "Access-Control-Allow-Origin";
|
||||
private static final String HEADER_CORS_VALUE = "*";
|
||||
private static final String HEADER_CORS_METHODS = "Access-Control-Allow-Methods";
|
||||
private static final String HEADER_CORS_METHODS_VALUE = "POST, GET, OPTIONS";
|
||||
private static final String HEADER_CORS_MAXAGE = "Access-Control-Max-Age";
|
||||
private static final String HEADER_CORS_MAXAGE_VALUE = "2592000";
|
||||
private static final String HEADER_CORS_ALLOW_HEADERS = "Access-Control-Allow-Headers";
|
||||
private static final String HEADER_CORS_ALLOW_HEADERS_VALUE = "Authorization";
|
||||
private static final String HEADER_CORS_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials";
|
||||
private static final String HEADER_CORS_ALLOW_CREDENTIALS_VALUE = "true";
|
||||
|
||||
private static final String HEADER_X_UA_COMPATIBLE = "X-UA-Compatible";
|
||||
private static final String HEADER_X_UA_COMPATIBLE_VALUE = "IE=Edge,chrome=1";
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletResponse resp = (HttpServletResponse) response;
|
||||
resp.addHeader(HEADER_CORS, HEADER_CORS_VALUE);
|
||||
resp.addHeader(HEADER_CORS_METHODS, HEADER_CORS_METHODS_VALUE);
|
||||
resp.addHeader(HEADER_CORS_MAXAGE, HEADER_CORS_MAXAGE_VALUE);
|
||||
resp.addHeader(HEADER_CORS_ALLOW_HEADERS, HEADER_CORS_ALLOW_HEADERS_VALUE);
|
||||
resp.addHeader(HEADER_CORS_ALLOW_CREDENTIALS, HEADER_CORS_ALLOW_CREDENTIALS_VALUE);
|
||||
|
||||
resp.addHeader(HEADER_X_UA_COMPATIBLE, HEADER_X_UA_COMPATIBLE_VALUE);
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.commafeed.frontend;
|
||||
|
||||
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 javax.enterprise.util.Nonbinding;
|
||||
import javax.interceptor.InterceptorBinding;
|
||||
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
|
||||
@Inherited
|
||||
@InterceptorBinding
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SecurityCheck {
|
||||
|
||||
/**
|
||||
* Roles needed.
|
||||
*/
|
||||
@Nonbinding
|
||||
Role value() default Role.USER;
|
||||
|
||||
@Nonbinding
|
||||
boolean apiKeyAllowed() default false;
|
||||
}
|
||||
@@ -6,32 +6,32 @@ import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Entry details")
|
||||
@ApiModel("Entry details")
|
||||
@Data
|
||||
public class Category implements Serializable {
|
||||
|
||||
@ApiProperty("category id")
|
||||
@ApiModelProperty("category id")
|
||||
private String id;
|
||||
|
||||
@ApiProperty("parent category id")
|
||||
@ApiModelProperty("parent category id")
|
||||
private String parentId;
|
||||
|
||||
@ApiProperty("category id")
|
||||
@ApiModelProperty("category id")
|
||||
private String name;
|
||||
|
||||
@ApiProperty("category children categories")
|
||||
@ApiModelProperty("category children categories")
|
||||
private List<Category> children = Lists.newArrayList();
|
||||
|
||||
@ApiProperty("category feeds")
|
||||
@ApiModelProperty("category feeds")
|
||||
private List<Subscription> feeds = Lists.newArrayList();
|
||||
|
||||
@ApiProperty("wether the category is expanded or collapsed")
|
||||
@ApiModelProperty("wether the category is expanded or collapsed")
|
||||
private boolean expanded;
|
||||
|
||||
@ApiProperty("position of the category in the list")
|
||||
@ApiModelProperty("position of the category in the list")
|
||||
private Integer position;
|
||||
}
|
||||
@@ -6,42 +6,42 @@ import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("List of entries with some metadata")
|
||||
@ApiModel("List of entries with some metadata")
|
||||
@Data
|
||||
public class Entries implements Serializable {
|
||||
|
||||
@ApiProperty("name of the feed or the category requested")
|
||||
@ApiModelProperty("name of the feed or the category requested")
|
||||
private String name;
|
||||
|
||||
@ApiProperty("error or warning message")
|
||||
@ApiModelProperty("error or warning message")
|
||||
private String message;
|
||||
|
||||
@ApiProperty("times the server tried to refresh the feed and failed")
|
||||
@ApiModelProperty("times the server tried to refresh the feed and failed")
|
||||
private int errorCount;
|
||||
|
||||
@ApiProperty("URL of the website, extracted from the feed")
|
||||
@ApiModelProperty("URL of the website, extracted from the feed")
|
||||
private String feedLink;
|
||||
|
||||
@ApiProperty("list generation timestamp")
|
||||
@ApiModelProperty("list generation timestamp")
|
||||
private long timestamp;
|
||||
|
||||
@ApiProperty("if the query has more elements")
|
||||
@ApiModelProperty("if the query has more elements")
|
||||
private boolean hasMore;
|
||||
|
||||
@ApiProperty("the requested offset")
|
||||
@ApiModelProperty("the requested offset")
|
||||
private int offset;
|
||||
|
||||
@ApiProperty("the requested limit")
|
||||
@ApiModelProperty("the requested limit")
|
||||
private int limit;
|
||||
|
||||
@ApiProperty("list of entries")
|
||||
@ApiModelProperty("list of entries")
|
||||
private List<Entry> entries = Lists.newArrayList();
|
||||
|
||||
@ApiProperty("if true, the unread flag was ignored in the request, all entries are returned regardless of their read status")
|
||||
@ApiModelProperty("if true, the unread flag was ignored in the request, all entries are returned regardless of their read status")
|
||||
private boolean ignoredReadStatus;
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.commafeed.backend.feeds.FeedUtils;
|
||||
import com.commafeed.backend.feed.FeedUtils;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryContent;
|
||||
import com.commafeed.backend.model.FeedEntryStatus;
|
||||
@@ -17,11 +17,11 @@ import com.google.common.collect.Lists;
|
||||
import com.sun.syndication.feed.synd.SyndContentImpl;
|
||||
import com.sun.syndication.feed.synd.SyndEntry;
|
||||
import com.sun.syndication.feed.synd.SyndEntryImpl;
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Entry details")
|
||||
@ApiModel("Entry details")
|
||||
@Data
|
||||
public class Entry implements Serializable {
|
||||
|
||||
@@ -78,63 +78,63 @@ public class Entry implements Serializable {
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ApiProperty("entry id")
|
||||
@ApiModelProperty("entry id")
|
||||
private String id;
|
||||
|
||||
@ApiProperty("entry guid")
|
||||
@ApiModelProperty("entry guid")
|
||||
private String guid;
|
||||
|
||||
@ApiProperty("entry title")
|
||||
@ApiModelProperty("entry title")
|
||||
private String title;
|
||||
|
||||
@ApiProperty("entry content")
|
||||
@ApiModelProperty("entry content")
|
||||
private String content;
|
||||
|
||||
@ApiProperty("wether entry content and title are rtl")
|
||||
@ApiModelProperty("wether entry content and title are rtl")
|
||||
private boolean rtl;
|
||||
|
||||
@ApiProperty("entry author")
|
||||
@ApiModelProperty("entry author")
|
||||
private String author;
|
||||
|
||||
@ApiProperty("entry enclosure url, if any")
|
||||
@ApiModelProperty("entry enclosure url, if any")
|
||||
private String enclosureUrl;
|
||||
|
||||
@ApiProperty("entry enclosure mime type, if any")
|
||||
@ApiModelProperty("entry enclosure mime type, if any")
|
||||
private String enclosureType;
|
||||
|
||||
@ApiProperty("entry publication date")
|
||||
@ApiModelProperty("entry publication date")
|
||||
private Date date;
|
||||
|
||||
@ApiProperty("entry insertion date in the database")
|
||||
@ApiModelProperty("entry insertion date in the database")
|
||||
private Date insertedDate;
|
||||
|
||||
@ApiProperty("feed id")
|
||||
@ApiModelProperty("feed id")
|
||||
private String feedId;
|
||||
|
||||
@ApiProperty("feed name")
|
||||
@ApiModelProperty("feed name")
|
||||
private String feedName;
|
||||
|
||||
@ApiProperty("this entry's feed url")
|
||||
@ApiModelProperty("this entry's feed url")
|
||||
private String feedUrl;
|
||||
|
||||
@ApiProperty("this entry's website url")
|
||||
@ApiModelProperty("this entry's website url")
|
||||
private String feedLink;
|
||||
|
||||
@ApiProperty(value = "The favicon url to use for this feed")
|
||||
@ApiModelProperty(value = "The favicon url to use for this feed")
|
||||
private String iconUrl;
|
||||
|
||||
@ApiProperty("entry url")
|
||||
@ApiModelProperty("entry url")
|
||||
private String url;
|
||||
|
||||
@ApiProperty("read sttaus")
|
||||
@ApiModelProperty("read sttaus")
|
||||
private boolean read;
|
||||
|
||||
@ApiProperty("starred status")
|
||||
@ApiModelProperty("starred status")
|
||||
private boolean starred;
|
||||
|
||||
@ApiProperty("wether the entry is still markable (old entry statuses are discarded)")
|
||||
@ApiModelProperty("wether the entry is still markable (old entry statuses are discarded)")
|
||||
private boolean markable;
|
||||
|
||||
@ApiProperty("tags")
|
||||
@ApiModelProperty("tags")
|
||||
private List<String> tags;
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ import lombok.Data;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
|
||||
@ApiClass("Feed count")
|
||||
@ApiModel("Feed count")
|
||||
@Data
|
||||
public class FeedCount implements Serializable {
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Feed details")
|
||||
@ApiModel("Feed details")
|
||||
@Data
|
||||
public class FeedInfo implements Serializable {
|
||||
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
package com.commafeed.frontend.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Server infos")
|
||||
@ApiModel("Server infos")
|
||||
@Data
|
||||
public class ServerInfo implements Serializable {
|
||||
|
||||
private String announcement;
|
||||
private String version;
|
||||
private String gitCommit;
|
||||
private Map<String, String> supportedLanguages = Maps.newHashMap();
|
||||
|
||||
}
|
||||
|
||||
@@ -4,41 +4,41 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("User settings")
|
||||
@ApiModel("User settings")
|
||||
@Data
|
||||
public class Settings implements Serializable {
|
||||
|
||||
@ApiProperty(value = "user's preferred language, english if none")
|
||||
@ApiModelProperty(value = "user's preferred language, english if none")
|
||||
private String language;
|
||||
|
||||
@ApiProperty(value = "user reads all entries or unread entries only", allowableValues = "all,unread", required = true)
|
||||
@ApiModelProperty(value = "user reads all entries or unread entries only", allowableValues = "all,unread", required = true)
|
||||
private String readingMode;
|
||||
|
||||
@ApiProperty(value = "user reads entries in ascending or descending order", allowableValues = "asc,desc", required = true)
|
||||
@ApiModelProperty(value = "user reads entries in ascending or descending order", allowableValues = "asc,desc", required = true)
|
||||
private String readingOrder;
|
||||
|
||||
@ApiProperty(value = "user viewing mode, either title-only or expande view", allowableValues = "title,expanded", required = true)
|
||||
@ApiModelProperty(value = "user viewing mode, either title-only or expande view", allowableValues = "title,expanded", required = true)
|
||||
private String viewMode;
|
||||
|
||||
@ApiProperty(value = "user wants category and feeds with no unread entries shown", required = true)
|
||||
@ApiModelProperty(value = "user wants category and feeds with no unread entries shown", required = true)
|
||||
private boolean showRead;
|
||||
|
||||
@ApiProperty(value = "In expanded view, scroll through entries mark them as read", required = true)
|
||||
@ApiModelProperty(value = "In expanded view, scroll through entries mark them as read", required = true)
|
||||
private boolean scrollMarks;
|
||||
|
||||
@ApiProperty(value = "user's selected theme")
|
||||
@ApiModelProperty(value = "user's selected theme")
|
||||
private String theme;
|
||||
|
||||
@ApiProperty(value = "user's custom css for the website")
|
||||
@ApiModelProperty(value = "user's custom css for the website")
|
||||
private String customCss;
|
||||
|
||||
@ApiProperty(value = "user's preferred scroll speed when navigating between entries")
|
||||
|
||||
@ApiModelProperty(value = "user's preferred scroll speed when navigating between entries")
|
||||
private int scrollSpeed;
|
||||
|
||||
|
||||
private boolean email;
|
||||
private boolean gmail;
|
||||
private boolean facebook;
|
||||
|
||||
@@ -5,15 +5,15 @@ import java.util.Date;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.commafeed.backend.feeds.FeedUtils;
|
||||
import com.commafeed.backend.feed.FeedUtils;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("User information")
|
||||
@ApiModel("User information")
|
||||
@Data
|
||||
public class Subscription implements Serializable {
|
||||
|
||||
@@ -38,43 +38,43 @@ public class Subscription implements Serializable {
|
||||
return sub;
|
||||
}
|
||||
|
||||
@ApiProperty(value = "subscription id", required = true)
|
||||
@ApiModelProperty(value = "subscription id", required = true)
|
||||
private Long id;
|
||||
|
||||
@ApiProperty(value = "subscription name", required = true)
|
||||
@ApiModelProperty(value = "subscription name", required = true)
|
||||
private String name;
|
||||
|
||||
@ApiProperty(value = "error message while fetching the feed", required = true)
|
||||
@ApiModelProperty(value = "error message while fetching the feed", required = true)
|
||||
private String message;
|
||||
|
||||
@ApiProperty(value = "error count", required = true)
|
||||
@ApiModelProperty(value = "error count", required = true)
|
||||
private int errorCount;
|
||||
|
||||
@ApiProperty(value = "last time the feed was refreshed", required = true)
|
||||
@ApiModelProperty(value = "last time the feed was refreshed", required = true)
|
||||
private Date lastRefresh;
|
||||
|
||||
@ApiProperty(value = "next time the feed refresh is planned, null if refresh is already queued", required = true)
|
||||
@ApiModelProperty(value = "next time the feed refresh is planned, null if refresh is already queued", required = true)
|
||||
private Date nextRefresh;
|
||||
|
||||
@ApiProperty(value = "this subscription's feed url", required = true)
|
||||
@ApiModelProperty(value = "this subscription's feed url", required = true)
|
||||
private String feedUrl;
|
||||
|
||||
@ApiProperty(value = "this subscription's website url", required = true)
|
||||
@ApiModelProperty(value = "this subscription's website url", required = true)
|
||||
private String feedLink;
|
||||
|
||||
@ApiProperty(value = "The favicon url to use for this feed")
|
||||
@ApiModelProperty(value = "The favicon url to use for this feed")
|
||||
private String iconUrl;
|
||||
|
||||
@ApiProperty(value = "unread count", required = true)
|
||||
@ApiModelProperty(value = "unread count", required = true)
|
||||
private long unread;
|
||||
|
||||
@ApiProperty(value = "category id")
|
||||
@ApiModelProperty(value = "category id")
|
||||
private String categoryId;
|
||||
|
||||
@ApiProperty("position of the subscription's in the list")
|
||||
@ApiModelProperty("position of the subscription's in the list")
|
||||
private Integer position;
|
||||
|
||||
@ApiProperty("date of the newest item")
|
||||
@ApiModelProperty("date of the newest item")
|
||||
private Date newestItemTime;
|
||||
|
||||
}
|
||||
@@ -5,10 +5,10 @@ import java.util.Date;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Unread count")
|
||||
@ApiModel("Unread count")
|
||||
@Data
|
||||
public class UnreadCount implements Serializable {
|
||||
|
||||
@@ -17,7 +17,6 @@ public class UnreadCount implements Serializable {
|
||||
private Date newestItemTime;
|
||||
|
||||
public UnreadCount() {
|
||||
|
||||
}
|
||||
|
||||
public UnreadCount(long feedId, long unreadCount, Date newestItemTime) {
|
||||
|
||||
@@ -5,39 +5,39 @@ import java.util.Date;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("User information")
|
||||
@ApiModel("User information")
|
||||
@Data
|
||||
public class UserModel implements Serializable {
|
||||
|
||||
@ApiProperty(value = "user id", required = true)
|
||||
@ApiModelProperty(value = "user id", required = true)
|
||||
private Long id;
|
||||
|
||||
@ApiProperty(value = "user name", required = true)
|
||||
@ApiModelProperty(value = "user name", required = true)
|
||||
private String name;
|
||||
|
||||
@ApiProperty("user email, if any")
|
||||
@ApiModelProperty("user email, if any")
|
||||
private String email;
|
||||
|
||||
@ApiProperty("api key")
|
||||
@ApiModelProperty("api key")
|
||||
private String apiKey;
|
||||
|
||||
@ApiProperty(value = "user password, never returned by the api")
|
||||
@ApiModelProperty(value = "user password, never returned by the api")
|
||||
private String password;
|
||||
|
||||
@ApiProperty(value = "account status")
|
||||
@ApiModelProperty(value = "account status")
|
||||
private boolean enabled;
|
||||
|
||||
@ApiProperty(value = "account creation date")
|
||||
@ApiModelProperty(value = "account creation date")
|
||||
private Date created;
|
||||
|
||||
@ApiProperty(value = "last login date")
|
||||
@ApiModelProperty(value = "last login date")
|
||||
private Date lastLogin;
|
||||
|
||||
@ApiProperty(value = "user is admin")
|
||||
@ApiModelProperty(value = "user is admin")
|
||||
private boolean admin;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,18 +4,18 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Add Category Request")
|
||||
@ApiModel("Add Category Request")
|
||||
@Data
|
||||
public class AddCategoryRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "name", required = true)
|
||||
@ApiModelProperty(value = "name", required = true)
|
||||
private String name;
|
||||
|
||||
@ApiProperty(value = "parent category id, if any")
|
||||
@ApiModelProperty(value = "parent category id, if any")
|
||||
private String parentId;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,24 +4,24 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Category modification request")
|
||||
@ApiModel("Category modification request")
|
||||
@Data
|
||||
public class CategoryModificationRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "id", required = true)
|
||||
@ApiModelProperty(value = "id", required = true)
|
||||
private Long id;
|
||||
|
||||
@ApiProperty(value = "new name, null if not changed")
|
||||
@ApiModelProperty(value = "new name, null if not changed")
|
||||
private String name;
|
||||
|
||||
@ApiProperty(value = "new parent category id")
|
||||
@ApiModelProperty(value = "new parent category id")
|
||||
private String parentId;
|
||||
|
||||
@ApiProperty(value = "new display position, null if not changed")
|
||||
@ApiModelProperty(value = "new display position, null if not changed")
|
||||
private Integer position;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,18 +4,18 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Mark Request")
|
||||
@ApiModel("Mark Request")
|
||||
@Data
|
||||
public class CollapseRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "category id", required = true)
|
||||
@ApiModelProperty(value = "category id", required = true)
|
||||
private Long id;
|
||||
|
||||
@ApiProperty(value = "collapse", required = true)
|
||||
@ApiModelProperty(value = "collapse", required = true)
|
||||
private boolean collapse;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Feed information request")
|
||||
@ApiModel("Feed information request")
|
||||
@Data
|
||||
public class FeedInfoRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "feed url", required = true)
|
||||
@ApiModelProperty(value = "feed url", required = true)
|
||||
private String url;
|
||||
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@ import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Feed merge Request")
|
||||
@ApiModel("Feed merge Request")
|
||||
@Data
|
||||
public class FeedMergeRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "merge into this feed", required = true)
|
||||
@ApiModelProperty(value = "merge into this feed", required = true)
|
||||
private Long intoFeedId;
|
||||
|
||||
@ApiProperty(value = "id of the feeds to merge", required = true)
|
||||
@ApiModelProperty(value = "id of the feeds to merge", required = true)
|
||||
private List<Long> feedIds;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,24 +4,24 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Feed modification request")
|
||||
@ApiModel("Feed modification request")
|
||||
@Data
|
||||
public class FeedModificationRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "id", required = true)
|
||||
@ApiModelProperty(value = "id", required = true)
|
||||
private Long id;
|
||||
|
||||
@ApiProperty(value = "new name, null if not changed")
|
||||
@ApiModelProperty(value = "new name, null if not changed")
|
||||
private String name;
|
||||
|
||||
@ApiProperty(value = "new parent category id")
|
||||
@ApiModelProperty(value = "new parent category id")
|
||||
private String categoryId;
|
||||
|
||||
@ApiProperty(value = "new display position, null if not changed")
|
||||
@ApiModelProperty(value = "new display position, null if not changed")
|
||||
private Integer position;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass
|
||||
@ApiModel
|
||||
@Data
|
||||
public class IDRequest implements Serializable {
|
||||
|
||||
@ApiProperty
|
||||
@ApiModelProperty
|
||||
private Long id;
|
||||
|
||||
}
|
||||
|
||||
@@ -5,26 +5,26 @@ import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Mark Request")
|
||||
@ApiModel("Mark Request")
|
||||
@Data
|
||||
public class MarkRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "entry id, category id, 'all' or 'starred'", required = true)
|
||||
@ApiModelProperty(value = "entry id, category id, 'all' or 'starred'", required = true)
|
||||
private String id;
|
||||
|
||||
@ApiProperty(value = "mark as read or unread")
|
||||
@ApiModelProperty(value = "mark as read or unread")
|
||||
private boolean read;
|
||||
|
||||
@ApiProperty(
|
||||
@ApiModelProperty(
|
||||
value = "only entries older than this, pass the timestamp you got from the entry list to prevent marking an entry that was not retrieved",
|
||||
required = false)
|
||||
private Long olderThan;
|
||||
|
||||
@ApiProperty(value = "if marking a category or 'all', exclude those subscriptions from the marking", required = false)
|
||||
@ApiModelProperty(value = "if marking a category or 'all', exclude those subscriptions from the marking", required = false)
|
||||
private List<Long> excludedSubscriptions;
|
||||
|
||||
}
|
||||
|
||||
@@ -5,15 +5,15 @@ import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Multiple Mark Request")
|
||||
@ApiModel("Multiple Mark Request")
|
||||
@Data
|
||||
public class MultipleMarkRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "list of mark requests", required = true)
|
||||
@ApiModelProperty(value = "list of mark requests", required = true)
|
||||
private List<MarkRequest> requests;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,21 +4,21 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Profile modification request")
|
||||
@ApiModel("Profile modification request")
|
||||
@Data
|
||||
public class ProfileModificationRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "changes email of the user, if specified")
|
||||
@ApiModelProperty(value = "changes email of the user, if specified")
|
||||
private String email;
|
||||
|
||||
@ApiProperty(value = "changes password of the user, if specified")
|
||||
@ApiModelProperty(value = "changes password of the user, if specified")
|
||||
private String password;
|
||||
|
||||
@ApiProperty(value = "generate a new api key")
|
||||
@ApiModelProperty(value = "generate a new api key")
|
||||
private boolean newApiKey;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,19 +4,21 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Data
|
||||
@ApiModel
|
||||
public class RegistrationRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "username, between 3 and 32 characters", required = true)
|
||||
@ApiModelProperty(value = "username, between 3 and 32 characters", required = true)
|
||||
private String name;
|
||||
|
||||
@ApiProperty(value = "password, minimum 6 characters", required = true)
|
||||
@ApiModelProperty(value = "password, minimum 6 characters", required = true)
|
||||
private String password;
|
||||
|
||||
@ApiProperty(value = "email address for password recovery", required = true)
|
||||
@ApiModelProperty(value = "email address for password recovery", required = true)
|
||||
private String email;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,21 +4,21 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Star Request")
|
||||
@ApiModel("Star Request")
|
||||
@Data
|
||||
public class StarRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "id", required = true)
|
||||
@ApiModelProperty(value = "id", required = true)
|
||||
private String id;
|
||||
|
||||
@ApiProperty(value = "feed id", required = true)
|
||||
@ApiModelProperty(value = "feed id", required = true)
|
||||
private Long feedId;
|
||||
|
||||
@ApiProperty(value = "starred or not")
|
||||
@ApiModelProperty(value = "starred or not")
|
||||
private boolean starred;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,21 +4,21 @@ import java.io.Serializable;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Subscription request")
|
||||
@ApiModel("Subscription request")
|
||||
@Data
|
||||
public class SubscribeRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "url of the feed", required = true)
|
||||
@ApiModelProperty(value = "url of the feed", required = true)
|
||||
private String url;
|
||||
|
||||
@ApiProperty(value = "name of the feed for the user", required = true)
|
||||
@ApiModelProperty(value = "name of the feed for the user", required = true)
|
||||
private String title;
|
||||
|
||||
@ApiProperty(value = "id of the user category to place the feed in")
|
||||
@ApiModelProperty(value = "id of the user category to place the feed in")
|
||||
private String categoryId;
|
||||
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@ import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.wordnik.swagger.annotations.ApiClass;
|
||||
import com.wordnik.swagger.annotations.ApiProperty;
|
||||
import com.wordnik.swagger.annotations.ApiModel;
|
||||
import com.wordnik.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApiClass("Tag Request")
|
||||
@ApiModel("Tag Request")
|
||||
@Data
|
||||
public class TagRequest implements Serializable {
|
||||
|
||||
@ApiProperty(value = "entry id", required = true)
|
||||
@ApiModelProperty(value = "entry id", required = true)
|
||||
private Long entryId;
|
||||
|
||||
@ApiProperty(value = "tags")
|
||||
@ApiModelProperty(value = "tags")
|
||||
private List<String> tags;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:wicket="http://wicket.apache.org" wicket:id="html">
|
||||
<head>
|
||||
<title>CommaFeed</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="app-icon-57.png" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="app-icon-72.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="app-icon-114.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="app-icon-144.png" />
|
||||
<link rel="icon" sizes="32x32" href="app-icon-32.png" />
|
||||
<link rel="icon" sizes="64x64" href="app-icon-64.png" />
|
||||
<link rel="icon" sizes="128x128" href="app-icon-128.png" />
|
||||
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||
<meta name="application-name" content="CommaFeed" />
|
||||
<meta name="msapplication-navbutton-color" content="#F88A14" />
|
||||
<meta name="msapplication-starturl" content="/" />
|
||||
<meta name="msapplication-square70x70logo" content="metro-icon-70.png" />
|
||||
<meta name="msapplication-square150x150logo" content="metro-icon-150.png" />
|
||||
<link rel="fluid-icon" href="app-icon-512.png" title="CommaFeed" />
|
||||
<link rel="logo" type="image/svg" href="app-icon.svg" />
|
||||
</head>
|
||||
<body>
|
||||
<wicket:child />
|
||||
<wicket:container wicket:id="footer-container" />
|
||||
<wicket:container wicket:id="uservoice">
|
||||
<script>
|
||||
(function() {
|
||||
var uv = document.createElement('script');
|
||||
uv.type = 'text/javascript';
|
||||
uv.async = true;
|
||||
uv.src = '//widget.uservoice.com/XYpTZZteqS4lHvgrTXeA.js';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(uv, s);
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
UserVoice = window.UserVoice || [];
|
||||
UserVoice.push(['showTab', 'classic_widget', {
|
||||
mode : 'full',
|
||||
default_mode : 'feedback',
|
||||
primary_color : '#000',
|
||||
link_color : '#007dbf',
|
||||
forum_id : 204509,
|
||||
support_tab_name : 'Contact',
|
||||
feedback_tab_name : 'Feedback',
|
||||
tab_label : 'Feedback',
|
||||
tab_color : '#7e72db',
|
||||
tab_position : 'bottom-right',
|
||||
tab_inverted : false
|
||||
}]);
|
||||
</script>
|
||||
</wicket:container>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,130 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.wicket.AttributeModifier;
|
||||
import org.apache.wicket.RuntimeConfigurationType;
|
||||
import org.apache.wicket.markup.head.CssHeaderItem;
|
||||
import org.apache.wicket.markup.head.IHeaderResponse;
|
||||
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
|
||||
import org.apache.wicket.markup.head.filter.HeaderResponseContainer;
|
||||
import org.apache.wicket.markup.html.TransparentWebMarkupContainer;
|
||||
import org.apache.wicket.markup.html.WebMarkupContainer;
|
||||
import org.apache.wicket.markup.html.WebPage;
|
||||
|
||||
import com.commafeed.backend.dao.FeedCategoryDAO;
|
||||
import com.commafeed.backend.dao.FeedDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
import com.commafeed.backend.dao.UserDAO;
|
||||
import com.commafeed.backend.dao.UserRoleDAO;
|
||||
import com.commafeed.backend.dao.UserSettingsDAO;
|
||||
import com.commafeed.backend.model.ApplicationSettings;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserSettings;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.MailService;
|
||||
import com.commafeed.backend.startup.StartupBean;
|
||||
import com.commafeed.frontend.CommaFeedSession;
|
||||
import com.commafeed.frontend.utils.WicketUtils;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class BasePage extends WebPage {
|
||||
|
||||
@Inject
|
||||
protected FeedDAO feedDAO;
|
||||
|
||||
@Inject
|
||||
StartupBean startupBean;
|
||||
|
||||
@Inject
|
||||
protected FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
|
||||
@Inject
|
||||
protected FeedCategoryDAO feedCategoryDAO;
|
||||
|
||||
@Inject
|
||||
protected FeedEntryDAO feedEntryDAO;
|
||||
|
||||
@Inject
|
||||
protected FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
|
||||
@Inject
|
||||
protected UserDAO userDAO;
|
||||
|
||||
@Inject
|
||||
protected UserSettingsDAO userSettingsDAO;
|
||||
|
||||
@Inject
|
||||
protected UserRoleDAO userRoleDAO;
|
||||
|
||||
@Inject
|
||||
MailService mailService;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
private ApplicationSettings settings;
|
||||
|
||||
public BasePage() {
|
||||
|
||||
String lang = "en";
|
||||
String theme = "default";
|
||||
User user = CommaFeedSession.get().getUser();
|
||||
if (user != null) {
|
||||
UserSettings settings = userSettingsDAO.findByUser(user);
|
||||
if (settings != null) {
|
||||
lang = settings.getLanguage() == null ? "en" : settings.getLanguage();
|
||||
theme = settings.getTheme() == null ? "default" : settings.getTheme();
|
||||
}
|
||||
}
|
||||
|
||||
add(new TransparentWebMarkupContainer("html").setMarkupId("theme-" + theme).add(new AttributeModifier("lang", lang)));
|
||||
|
||||
settings = applicationSettingsService.get();
|
||||
add(new HeaderResponseContainer("footer-container", "footer-container"));
|
||||
add(new WebMarkupContainer("uservoice") {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
setVisibilityAllowed(settings.isFeedbackButton());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderHead(IHeaderResponse response) {
|
||||
super.renderHead(response);
|
||||
|
||||
if (getApplication().getConfigurationType() == RuntimeConfigurationType.DEPLOYMENT) {
|
||||
long startupTime = startupBean.getStartupTime();
|
||||
String suffix = "?" + startupTime;
|
||||
response.render(JavaScriptHeaderItem.forUrl("static/all.js" + suffix));
|
||||
response.render(CssHeaderItem.forUrl("static/all.css" + suffix));
|
||||
} else {
|
||||
response.render(JavaScriptHeaderItem.forUrl("wro/lib.js"));
|
||||
response.render(CssHeaderItem.forUrl("wro/lib.css"));
|
||||
response.render(CssHeaderItem.forUrl("wro/app.css"));
|
||||
|
||||
response.render(JavaScriptHeaderItem.forUrl("js/welcome.js"));
|
||||
response.render(JavaScriptHeaderItem.forUrl("js/main.js"));
|
||||
response.render(JavaScriptHeaderItem.forUrl("js/controllers.js"));
|
||||
response.render(JavaScriptHeaderItem.forUrl("js/directives.js"));
|
||||
response.render(JavaScriptHeaderItem.forUrl("js/filters.js"));
|
||||
response.render(JavaScriptHeaderItem.forUrl("js/services.js"));
|
||||
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(settings.getGoogleAnalyticsTrackingCode())) {
|
||||
Map<String, Object> vars = Maps.newHashMap();
|
||||
vars.put("trackingCode", settings.getGoogleAnalyticsTrackingCode());
|
||||
WicketUtils.loadJS(response, BasePage.class, "analytics", vars);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.wicket.markup.html.WebPage;
|
||||
|
||||
import com.commafeed.backend.services.UserService;
|
||||
import com.commafeed.backend.startup.StartupBean;
|
||||
import com.commafeed.frontend.CommaFeedSession;
|
||||
|
||||
public class DemoLoginPage extends WebPage {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Inject
|
||||
UserService userService;
|
||||
|
||||
public DemoLoginPage() {
|
||||
CommaFeedSession.get().authenticate(StartupBean.USERNAME_DEMO, StartupBean.USERNAME_DEMO);
|
||||
setResponsePage(getApplication().getHomePage());
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:wicket="http://wicket.apache.org">
|
||||
<body>
|
||||
<wicket:extend>
|
||||
<div ng-app="commafeed" id="main" class="main">
|
||||
<div ui-view>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</wicket:extend>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import org.apache.wicket.markup.head.CssHeaderItem;
|
||||
import org.apache.wicket.markup.head.IHeaderResponse;
|
||||
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
||||
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.model.UserSettings;
|
||||
import com.commafeed.frontend.CommaFeedSession;
|
||||
import com.commafeed.frontend.SecurityCheck;
|
||||
import com.commafeed.frontend.resources.UserCustomCssReference;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@SecurityCheck(Role.USER)
|
||||
public class HomePage extends BasePage {
|
||||
|
||||
@Override
|
||||
public void renderHead(IHeaderResponse response) {
|
||||
super.renderHead(response);
|
||||
|
||||
response.render(CssHeaderItem.forReference(new UserCustomCssReference() {
|
||||
@Override
|
||||
protected String getCss() {
|
||||
User user = CommaFeedSession.get().getUser();
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
UserSettings settings = userSettingsDAO.findByUser(user);
|
||||
return settings == null ? null : settings.getCustomCss();
|
||||
}
|
||||
}, new PageParameters().add("_t", System.currentTimeMillis()), null));
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import org.apache.wicket.markup.html.WebPage;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class LogoutPage extends WebPage {
|
||||
public LogoutPage() {
|
||||
getSession().invalidate();
|
||||
setResponsePage(getApplication().getHomePage());
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.wicket.markup.html.WebPage;
|
||||
import org.apache.wicket.request.flow.RedirectToUrlException;
|
||||
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
||||
|
||||
import com.commafeed.backend.dao.FeedCategoryDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.FeedEntryStatus;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingOrder;
|
||||
import com.commafeed.frontend.CommaFeedSession;
|
||||
import com.commafeed.frontend.SecurityCheck;
|
||||
import com.commafeed.frontend.rest.resources.CategoryREST;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@SecurityCheck(Role.USER)
|
||||
public class NextUnreadRedirectPage extends WebPage {
|
||||
|
||||
public static final String PARAM_CATEGORYID = "category";
|
||||
public static final String PARAM_READINGORDER = "order";
|
||||
|
||||
@Inject
|
||||
FeedCategoryDAO feedCategoryDAO;
|
||||
|
||||
@Inject
|
||||
FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
|
||||
@Inject
|
||||
FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
|
||||
public NextUnreadRedirectPage(PageParameters params) {
|
||||
String categoryId = params.get(PARAM_CATEGORYID).toString();
|
||||
String orderParam = params.get(PARAM_READINGORDER).toString();
|
||||
|
||||
User user = CommaFeedSession.get().getUser();
|
||||
ReadingOrder order = ReadingOrder.desc;
|
||||
|
||||
if (StringUtils.equals(orderParam, "asc")) {
|
||||
order = ReadingOrder.asc;
|
||||
}
|
||||
|
||||
List<FeedEntryStatus> statuses = null;
|
||||
if (StringUtils.isBlank(categoryId) || CategoryREST.ALL.equals(categoryId)) {
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(user);
|
||||
statuses = feedEntryStatusDAO.findBySubscriptions(user, subs, true, null, null, 0, 1, order, true, false, null);
|
||||
} else {
|
||||
FeedCategory category = feedCategoryDAO.findById(user, Long.valueOf(categoryId));
|
||||
if (category != null) {
|
||||
List<FeedCategory> children = feedCategoryDAO.findAllChildrenCategories(user, category);
|
||||
List<FeedSubscription> subscriptions = feedSubscriptionDAO.findByCategories(user, children);
|
||||
statuses = feedEntryStatusDAO.findBySubscriptions(user, subscriptions, true, null, null, 0, 1, order, true, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(statuses)) {
|
||||
setResponsePage(HomePage.class);
|
||||
} else {
|
||||
FeedEntryStatus status = Iterables.getFirst(statuses, null);
|
||||
String url = status.getEntry().getUrl();
|
||||
status.setRead(true);
|
||||
feedEntryStatusDAO.saveOrUpdate(status);
|
||||
throw new RedirectToUrlException(url);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<html xmlns:wicket="http://wicket.apache.org">
|
||||
<body>
|
||||
<wicket:extend>
|
||||
<div class="container">
|
||||
<div class="text-center">
|
||||
<img src="images/logo_2.png" />
|
||||
<div wicket:id="feedback"></div>
|
||||
<form wicket:id="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label>New Password</label>
|
||||
<input type="password" wicket:id="password" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Confirm</label>
|
||||
<input type="password" wicket:id="confirm" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" class="btn btn-primary" value="Submit" />
|
||||
<input type="button" class="btn btn-default" wicket:id="cancel" value="Home page" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</wicket:extend>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,77 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.apache.wicket.markup.html.form.Form;
|
||||
import org.apache.wicket.markup.html.form.PasswordTextField;
|
||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
||||
import org.apache.wicket.model.IModel;
|
||||
import org.apache.wicket.model.Model;
|
||||
import org.apache.wicket.request.mapper.parameter.PageParameters;
|
||||
import org.apache.wicket.validation.validator.StringValidator;
|
||||
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.services.PasswordEncryptionService;
|
||||
import com.commafeed.backend.services.UserService;
|
||||
import com.commafeed.frontend.pages.components.BootstrapFeedbackPanel;
|
||||
import com.commafeed.frontend.utils.exception.DisplayException;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class PasswordRecoveryCallbackPage extends BasePage {
|
||||
|
||||
public static final String PARAM_EMAIL = "email";
|
||||
public static final String PARAM_TOKEN = "token";
|
||||
|
||||
@Inject
|
||||
PasswordEncryptionService encryptionService;
|
||||
|
||||
@Inject
|
||||
UserService userService;
|
||||
|
||||
public PasswordRecoveryCallbackPage(PageParameters params) {
|
||||
String email = params.get(PARAM_EMAIL).toString();
|
||||
String token = params.get(PARAM_TOKEN).toString();
|
||||
|
||||
final User user = userDAO.findByEmail(email);
|
||||
if (user == null) {
|
||||
throw new DisplayException("email not found");
|
||||
}
|
||||
if (user.getRecoverPasswordToken() == null || !user.getRecoverPasswordToken().equals(token)) {
|
||||
throw new DisplayException("invalid token");
|
||||
}
|
||||
if (user.getRecoverPasswordTokenDate().before(DateUtils.addDays(new Date(), -2))) {
|
||||
throw new DisplayException("token expired");
|
||||
}
|
||||
|
||||
final IModel<String> password = new Model<String>();
|
||||
final IModel<String> confirm = new Model<String>();
|
||||
add(new BootstrapFeedbackPanel("feedback"));
|
||||
Form<Void> form = new Form<Void>("form") {
|
||||
@Override
|
||||
protected void onSubmit() {
|
||||
String passwd = password.getObject();
|
||||
if (StringUtils.equals(passwd, confirm.getObject())) {
|
||||
byte[] password = encryptionService.getEncryptedPassword(passwd, user.getSalt());
|
||||
user.setPassword(password);
|
||||
user.setApiKey(userService.generateApiKey(user));
|
||||
user.setRecoverPasswordToken(null);
|
||||
user.setRecoverPasswordTokenDate(null);
|
||||
userDAO.saveOrUpdate(user);
|
||||
info("Password saved.");
|
||||
} else {
|
||||
error("Passwords do not match.");
|
||||
}
|
||||
}
|
||||
};
|
||||
add(form);
|
||||
form.add(new PasswordTextField("password", password).setResetPassword(true).add(StringValidator.minimumLength(6)));
|
||||
form.add(new PasswordTextField("confirm", confirm).setResetPassword(true).add(StringValidator.minimumLength(6)));
|
||||
|
||||
form.add(new BookmarkablePageLink<Void>("cancel", HomePage.class));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<html xmlns:wicket="http://wicket.apache.org">
|
||||
<body>
|
||||
<wicket:extend>
|
||||
<div class="container">
|
||||
<div class="col-xs-6 col-xs-offset-3 text-center">
|
||||
<img src="images/logo_2.png" />
|
||||
<div wicket:id="feedback"></div>
|
||||
<form wicket:id="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label>Email</label>
|
||||
<input type="email" wicket:id="email" class="form-control"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" class="btn btn-primary" value="Submit" />
|
||||
<input type="button" class="btn btn-default" wicket:id="cancel" value="Cancel" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</wicket:extend>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,78 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.wicket.extensions.validation.validator.RfcCompliantEmailAddressValidator;
|
||||
import org.apache.wicket.markup.html.form.Form;
|
||||
import org.apache.wicket.markup.html.form.RequiredTextField;
|
||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
||||
import org.apache.wicket.model.IModel;
|
||||
import org.apache.wicket.model.Model;
|
||||
|
||||
import com.commafeed.backend.feeds.FeedUtils;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.frontend.pages.components.BootstrapFeedbackPanel;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Slf4j
|
||||
public class PasswordRecoveryPage extends BasePage {
|
||||
|
||||
public PasswordRecoveryPage() {
|
||||
|
||||
IModel<String> email = new Model<String>();
|
||||
add(new BootstrapFeedbackPanel("feedback"));
|
||||
Form<String> form = new Form<String>("form", email) {
|
||||
@Override
|
||||
protected void onSubmit() {
|
||||
super.onSubmit();
|
||||
User user = userDAO.findByEmail(getModelObject());
|
||||
if (user == null) {
|
||||
error("Email not found.");
|
||||
} else {
|
||||
try {
|
||||
user.setRecoverPasswordToken(DigestUtils.sha1Hex(UUID.randomUUID().toString()));
|
||||
user.setRecoverPasswordTokenDate(new Date());
|
||||
userDAO.saveOrUpdate(user);
|
||||
mailService.sendMail(user, "Password recovery", buildEmailContent(user));
|
||||
info("Email sent.");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
error("Cannot send email, please contact the staff.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
add(form);
|
||||
|
||||
form.add(new RequiredTextField<String>("email", email) {
|
||||
@Override
|
||||
protected String getInputType() {
|
||||
return "email";
|
||||
}
|
||||
}.add(RfcCompliantEmailAddressValidator.getInstance()));
|
||||
|
||||
form.add(new BookmarkablePageLink<Void>("cancel", HomePage.class));
|
||||
}
|
||||
|
||||
private String buildEmailContent(User user) throws Exception {
|
||||
|
||||
String publicUrl = FeedUtils.removeTrailingSlash(applicationSettingsService.get().getPublicUrl());
|
||||
publicUrl += "/recover2";
|
||||
|
||||
return String
|
||||
.format("You asked for password recovery for account '%s', <a href='%s'>follow this link</a> to change your password. Ignore this if you didn't request a password recovery.",
|
||||
user.getName(), callbackUrl(user, publicUrl));
|
||||
}
|
||||
|
||||
private String callbackUrl(User user, String publicUrl) throws Exception {
|
||||
return new URIBuilder(publicUrl).addParameter(PasswordRecoveryCallbackPage.PARAM_EMAIL, user.getEmail())
|
||||
.addParameter(PasswordRecoveryCallbackPage.PARAM_TOKEN, user.getRecoverPasswordToken()).build().toURL().toString();
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang.math.RandomUtils;
|
||||
import org.apache.wicket.markup.html.WebPage;
|
||||
import org.apache.wicket.request.handler.TextRequestHandler;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sun.syndication.feed.synd.SyndEntry;
|
||||
import com.sun.syndication.feed.synd.SyndEntryImpl;
|
||||
import com.sun.syndication.feed.synd.SyndFeed;
|
||||
import com.sun.syndication.feed.synd.SyndFeedImpl;
|
||||
import com.sun.syndication.io.SyndFeedOutput;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class TestRssPage extends WebPage {
|
||||
|
||||
public TestRssPage() {
|
||||
SyndFeed feed = new SyndFeedImpl();
|
||||
feed.setFeedType("rss_2.0");
|
||||
feed.setTitle("Test RSS");
|
||||
|
||||
feed.setLink("");
|
||||
feed.setDescription("New entries everytime it is accessed");
|
||||
|
||||
List<SyndEntry> entries = Lists.newArrayList();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
SyndEntry entry = new SyndEntryImpl();
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
entry.setUri(uuid);
|
||||
entry.setTitle(uuid);
|
||||
entry.setLink("http://www.example.com/" + uuid);
|
||||
entry.setPublishedDate(new Date());
|
||||
entries.add(entry);
|
||||
}
|
||||
feed.setEntries(entries);
|
||||
SyndFeedOutput output = new SyndFeedOutput();
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
try {
|
||||
output.output(feed, writer);
|
||||
} catch (Exception e) {
|
||||
writer.write("Could not get feed information");
|
||||
}
|
||||
|
||||
try {
|
||||
// simulate internet lag
|
||||
Thread.sleep(Math.abs(RandomUtils.nextLong() % 5000));
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
getRequestCycle().scheduleRequestHandlerAfterCurrent(new TextRequestHandler("text/xml", "UTF-8", writer.toString()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:wicket="http://wicket.apache.org">
|
||||
<body>
|
||||
<wicket:extend>
|
||||
<div class="welcome">
|
||||
<div class="container">
|
||||
<div class="row header">
|
||||
<div class="pull-left">
|
||||
<a wicket:id="logo-link">
|
||||
<img src="images/logo_2.png"></img>
|
||||
</a>
|
||||
</div>
|
||||
<div class="pull-right tagline">Bloat-free feed reader</div>
|
||||
<div class="text-center">
|
||||
<a wicket:id="demo-login">
|
||||
<img src="images/preview.jpg" class="preview" />
|
||||
<br />
|
||||
<span class="demo">
|
||||
Try out the demo
|
||||
<br />
|
||||
<small>(some features are disabled)</small>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="well" id="login-panel">
|
||||
<h3>Login</h3>
|
||||
<span wicket:id="login"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6" wicket:enclosure="register">
|
||||
<div class="well" id="register-panel">
|
||||
<h3>Register</h3>
|
||||
<span wicket:id="register"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<div class="footer">
|
||||
<div class="row">
|
||||
<span>
|
||||
©
|
||||
<a href="http://www.commafeed.com" target="_blank">CommaFeed</a>
|
||||
</span>
|
||||
<span>
|
||||
- Sources on
|
||||
<a href="https://github.com/Athou/commafeed" target="_blank">GitHub</a>
|
||||
</span>
|
||||
<span>
|
||||
- REST API
|
||||
<a href="api" target="_blank">documentation</a>
|
||||
</span>
|
||||
<span class="pull-right">
|
||||
<a href="https://twitter.com/CommaFeed"
|
||||
class="twitter-follow-button" data-show-count="false"
|
||||
data-size="large">Follow @CommaFeed</a>
|
||||
<script>
|
||||
!function(d, s, id) {
|
||||
var js, fjs = d.getElementsByTagName(s)[0], p = /^http:/
|
||||
.test(d.location) ? 'http'
|
||||
: 'https';
|
||||
if (!d.getElementById(id)) {
|
||||
js = d.createElement(s);
|
||||
js.id = id;
|
||||
js.src = p
|
||||
+ '://platform.twitter.com/widgets.js';
|
||||
fjs.parentNode.insertBefore(js, fjs);
|
||||
}
|
||||
}(document, 'script', 'twitter-wjs');
|
||||
</script>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</wicket:extend>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.commafeed.frontend.pages;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
||||
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.frontend.pages.components.LoginPanel;
|
||||
import com.commafeed.frontend.pages.components.RegisterPanel;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class WelcomePage extends BasePage {
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
public WelcomePage() {
|
||||
add(new BookmarkablePageLink<Void>("logo-link", getApplication().getHomePage()));
|
||||
add(new BookmarkablePageLink<Void>("demo-login", DemoLoginPage.class));
|
||||
add(new LoginPanel("login"));
|
||||
add(new RegisterPanel("register") {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
setVisibilityAllowed(applicationSettingsService.get().isAllowRegistrations());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o), m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', '${trackingCode}');
|
||||
ga('send', 'pageview');
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.commafeed.frontend.pages.components;
|
||||
|
||||
import org.apache.wicket.behavior.AttributeAppender;
|
||||
import org.apache.wicket.feedback.IFeedbackMessageFilter;
|
||||
import org.apache.wicket.markup.ComponentTag;
|
||||
import org.apache.wicket.markup.html.panel.FeedbackPanel;
|
||||
import org.apache.wicket.model.AbstractReadOnlyModel;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class BootstrapFeedbackPanel extends FeedbackPanel {
|
||||
|
||||
public BootstrapFeedbackPanel(String id) {
|
||||
super(id);
|
||||
init();
|
||||
}
|
||||
|
||||
public BootstrapFeedbackPanel(String id, IFeedbackMessageFilter filter) {
|
||||
super(id, filter);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setOutputMarkupPlaceholderTag(true);
|
||||
add(new AttributeAppender("class", new AbstractReadOnlyModel<String>() {
|
||||
|
||||
@Override
|
||||
public String getObject() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (anyMessage()) {
|
||||
sb.append(" bs-fb alert");
|
||||
}
|
||||
if (anyErrorMessage()) {
|
||||
sb.append(" alert-error");
|
||||
} else {
|
||||
sb.append(" alert-success");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}));
|
||||
|
||||
get("feedbackul").add(new AttributeAppender("class", " unstyled"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onComponentTag(ComponentTag tag) {
|
||||
tag.setName("div");
|
||||
super.onComponentTag(tag);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:wicket="http://wicket.apache.org">
|
||||
<body>
|
||||
<wicket:panel>
|
||||
<span wicket:id="feedback"></span>
|
||||
<form wicket:id="signInForm">
|
||||
<div class="form-group">
|
||||
<label for="username">User Name</label>
|
||||
<input type="text" id="username" wicket:id="username" class="form-control"></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" wicket:id="password" class="form-control"></input>
|
||||
</div>
|
||||
<div wicket:id="rememberMeRow">
|
||||
<label>
|
||||
<input wicket:id="rememberMe" type="checkbox" />
|
||||
Remember me
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" class="btn btn-primary" value="Log in" />
|
||||
<a wicket:id="recover" class="pull-right">Forgot password?</a>
|
||||
</div>
|
||||
</form>
|
||||
</wicket:panel>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.commafeed.frontend.pages.components;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.wicket.authroles.authentication.panel.SignInPanel;
|
||||
import org.apache.wicket.feedback.ContainerFeedbackMessageFilter;
|
||||
import org.apache.wicket.markup.html.form.Form;
|
||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
||||
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.frontend.pages.PasswordRecoveryPage;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class LoginPanel extends SignInPanel {
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
public LoginPanel(String id) {
|
||||
super(id);
|
||||
replace(new BootstrapFeedbackPanel("feedback", new ContainerFeedbackMessageFilter(this)));
|
||||
Form<?> form = (Form<?>) get("signInForm");
|
||||
form.add(new BookmarkablePageLink<Void>("recover", PasswordRecoveryPage.class) {
|
||||
@Override
|
||||
protected void onConfigure() {
|
||||
super.onConfigure();
|
||||
String smtpHost = applicationSettingsService.get().getSmtpHost();
|
||||
setVisibilityAllowed(StringUtils.isNotBlank(smtpHost));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:wicket="http://wicket.apache.org">
|
||||
<body>
|
||||
<wicket:panel>
|
||||
<div wicket:id="feedback"></div>
|
||||
<form wicket:id="form" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<label>User Name</label>
|
||||
<input type="text" wicket:id="name" class="form-control"></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Password</label>
|
||||
<input type="password" wicket:id="password" class="form-control"></input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Email address (used for password recovery only)</label>
|
||||
<input type="email" wicket:id="email" class="form-control"></input>
|
||||
</div>
|
||||
<div>
|
||||
<input type="submit" class="btn btn-primary" value="Register" />
|
||||
</div>
|
||||
</form>
|
||||
</wicket:panel>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,94 +0,0 @@
|
||||
package com.commafeed.frontend.pages.components;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.wicket.authentication.IAuthenticationStrategy;
|
||||
import org.apache.wicket.extensions.validation.validator.RfcCompliantEmailAddressValidator;
|
||||
import org.apache.wicket.feedback.ContainerFeedbackMessageFilter;
|
||||
import org.apache.wicket.markup.html.form.Form;
|
||||
import org.apache.wicket.markup.html.form.PasswordTextField;
|
||||
import org.apache.wicket.markup.html.form.RequiredTextField;
|
||||
import org.apache.wicket.markup.html.form.StatelessForm;
|
||||
import org.apache.wicket.markup.html.panel.Panel;
|
||||
import org.apache.wicket.model.IModel;
|
||||
import org.apache.wicket.model.Model;
|
||||
import org.apache.wicket.model.PropertyModel;
|
||||
import org.apache.wicket.validation.IValidatable;
|
||||
import org.apache.wicket.validation.IValidator;
|
||||
import org.apache.wicket.validation.ValidationError;
|
||||
import org.apache.wicket.validation.validator.StringValidator;
|
||||
|
||||
import com.commafeed.backend.dao.UserDAO;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.UserService;
|
||||
import com.commafeed.frontend.CommaFeedSession;
|
||||
import com.commafeed.frontend.model.request.RegistrationRequest;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class RegisterPanel extends Panel {
|
||||
|
||||
@Inject
|
||||
UserDAO userDAO;
|
||||
|
||||
@Inject
|
||||
UserService userService;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
public RegisterPanel(String markupId) {
|
||||
super(markupId);
|
||||
|
||||
IModel<RegistrationRequest> model = Model.of(new RegistrationRequest());
|
||||
|
||||
Form<RegistrationRequest> form = new StatelessForm<RegistrationRequest>("form", model) {
|
||||
@Override
|
||||
protected void onSubmit() {
|
||||
if (applicationSettingsService.get().isAllowRegistrations()) {
|
||||
RegistrationRequest req = getModelObject();
|
||||
userService.register(req.getName(), req.getPassword(), req.getEmail(), Arrays.asList(Role.USER));
|
||||
|
||||
IAuthenticationStrategy strategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
|
||||
strategy.save(req.getName(), req.getPassword());
|
||||
CommaFeedSession.get().signIn(req.getName(), req.getPassword());
|
||||
}
|
||||
setResponsePage(getApplication().getHomePage());
|
||||
}
|
||||
};
|
||||
add(form);
|
||||
add(new BootstrapFeedbackPanel("feedback", new ContainerFeedbackMessageFilter(form)));
|
||||
|
||||
form.add(new RequiredTextField<String>("name", new PropertyModel<String>(model, "name")).add(StringValidator.lengthBetween(3, 32))
|
||||
.add(new IValidator<String>() {
|
||||
@Override
|
||||
public void validate(IValidatable<String> validatable) {
|
||||
String name = validatable.getValue();
|
||||
User user = userDAO.findByName(name);
|
||||
if (user != null) {
|
||||
validatable.error(new ValidationError("Name is already taken."));
|
||||
}
|
||||
}
|
||||
}));
|
||||
form.add(new PasswordTextField("password", new PropertyModel<String>(model, "password")).setResetPassword(false).add(
|
||||
StringValidator.minimumLength(6)));
|
||||
form.add(new RequiredTextField<String>("email", new PropertyModel<String>(model, "email")) {
|
||||
@Override
|
||||
protected String getInputType() {
|
||||
return "email";
|
||||
}
|
||||
}.add(RfcCompliantEmailAddressValidator.getInstance()).add(new IValidator<String>() {
|
||||
@Override
|
||||
public void validate(IValidatable<String> validatable) {
|
||||
String email = validatable.getValue();
|
||||
User user = userDAO.findByEmail(email);
|
||||
if (user != null) {
|
||||
validatable.error(new ValidationError("Email is already taken."));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,39 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
package com.commafeed.frontend.resource;
|
||||
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.dropwizard.hibernate.UnitOfWork;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.commafeed.backend.dao.FeedDAO;
|
||||
import com.commafeed.CommaFeedApplication;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.CommaFeedConfiguration.ApplicationSettings;
|
||||
import com.commafeed.backend.dao.UserDAO;
|
||||
import com.commafeed.backend.dao.UserRoleDAO;
|
||||
import com.commafeed.backend.feeds.FeedRefreshTaskGiver;
|
||||
import com.commafeed.backend.feeds.FeedRefreshUpdater;
|
||||
import com.commafeed.backend.feeds.FeedRefreshWorker;
|
||||
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;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.DatabaseCleaningService;
|
||||
import com.commafeed.backend.services.FeedService;
|
||||
import com.commafeed.backend.services.PasswordEncryptionService;
|
||||
import com.commafeed.backend.services.UserService;
|
||||
import com.commafeed.backend.startup.StartupBean;
|
||||
import com.commafeed.frontend.SecurityCheck;
|
||||
import com.commafeed.backend.service.DatabaseCleaningService;
|
||||
import com.commafeed.backend.service.PasswordEncryptionService;
|
||||
import com.commafeed.backend.service.UserService;
|
||||
import com.commafeed.frontend.model.UserModel;
|
||||
import com.commafeed.frontend.model.request.IDRequest;
|
||||
import com.commafeed.frontend.rest.PrettyPrint;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -41,51 +41,28 @@ import com.wordnik.swagger.annotations.Api;
|
||||
import com.wordnik.swagger.annotations.ApiOperation;
|
||||
import com.wordnik.swagger.annotations.ApiParam;
|
||||
|
||||
@SecurityCheck(Role.ADMIN)
|
||||
@Path("/admin")
|
||||
@Api(value = "/admin", description = "Operations about application administration")
|
||||
public class AdminREST extends AbstractREST {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@AllArgsConstructor
|
||||
public class AdminREST {
|
||||
|
||||
@Inject
|
||||
FeedService feedService;
|
||||
// TODO check roles
|
||||
|
||||
@Inject
|
||||
UserService userService;
|
||||
|
||||
@Inject
|
||||
UserDAO userDAO;
|
||||
|
||||
@Inject
|
||||
UserRoleDAO userRoleDAO;
|
||||
|
||||
@Inject
|
||||
FeedDAO feedDAO;
|
||||
|
||||
@Inject
|
||||
MetricRegistry metrics;
|
||||
|
||||
@Inject
|
||||
DatabaseCleaningService cleaner;
|
||||
|
||||
@Inject
|
||||
FeedRefreshWorker feedRefreshWorker;
|
||||
|
||||
@Inject
|
||||
FeedRefreshUpdater feedRefreshUpdater;
|
||||
|
||||
@Inject
|
||||
FeedRefreshTaskGiver taskGiver;
|
||||
|
||||
@Inject
|
||||
PasswordEncryptionService encryptionService;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
private final UserDAO userDAO;
|
||||
private final UserRoleDAO userRoleDAO;
|
||||
private final UserService userService;
|
||||
private final PasswordEncryptionService encryptionService;
|
||||
private final DatabaseCleaningService cleaner;
|
||||
private final CommaFeedConfiguration config;
|
||||
private final MetricRegistry metrics;
|
||||
|
||||
@Path("/user/save")
|
||||
@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(@ApiParam(required = true) UserModel userModel) {
|
||||
public Response save(@Auth User user, @ApiParam(required = true) UserModel userModel) {
|
||||
Preconditions.checkNotNull(userModel);
|
||||
Preconditions.checkNotNull(userModel.getName());
|
||||
|
||||
@@ -103,26 +80,26 @@ public class AdminREST extends AbstractREST {
|
||||
return Response.status(Status.CONFLICT).entity(e.getMessage()).build();
|
||||
}
|
||||
} else {
|
||||
User user = userDAO.findById(id);
|
||||
if (StartupBean.USERNAME_ADMIN.equals(user.getName()) && !userModel.isEnabled()) {
|
||||
User u = userDAO.findById(id);
|
||||
if (CommaFeedApplication.USERNAME_ADMIN.equals(u.getName()) && !userModel.isEnabled()) {
|
||||
return Response.status(Status.FORBIDDEN).entity("You cannot disable the admin user.").build();
|
||||
}
|
||||
user.setName(userModel.getName());
|
||||
u.setName(userModel.getName());
|
||||
if (StringUtils.isNotBlank(userModel.getPassword())) {
|
||||
user.setPassword(encryptionService.getEncryptedPassword(userModel.getPassword(), user.getSalt()));
|
||||
u.setPassword(encryptionService.getEncryptedPassword(userModel.getPassword(), u.getSalt()));
|
||||
}
|
||||
user.setEmail(userModel.getEmail());
|
||||
user.setDisabled(!userModel.isEnabled());
|
||||
userDAO.saveOrUpdate(user);
|
||||
u.setEmail(userModel.getEmail());
|
||||
u.setDisabled(!userModel.isEnabled());
|
||||
userDAO.saveOrUpdate(u);
|
||||
|
||||
Set<Role> roles = userRoleDAO.findRoles(user);
|
||||
Set<Role> roles = userRoleDAO.findRoles(u);
|
||||
if (userModel.isAdmin() && !roles.contains(Role.ADMIN)) {
|
||||
userRoleDAO.saveOrUpdate(new UserRole(user, Role.ADMIN));
|
||||
userRoleDAO.saveOrUpdate(new UserRole(u, Role.ADMIN));
|
||||
} else if (!userModel.isAdmin() && roles.contains(Role.ADMIN)) {
|
||||
if (StartupBean.USERNAME_ADMIN.equals(user.getName())) {
|
||||
if (CommaFeedApplication.USERNAME_ADMIN.equals(u.getName())) {
|
||||
return Response.status(Status.FORBIDDEN).entity("You cannot remove the admin role from the admin user.").build();
|
||||
}
|
||||
for (UserRole userRole : userRoleDAO.findAll(user)) {
|
||||
for (UserRole userRole : userRoleDAO.findAll(u)) {
|
||||
if (userRole.getRole() == Role.ADMIN) {
|
||||
userRoleDAO.delete(userRole);
|
||||
}
|
||||
@@ -136,16 +113,17 @@ public class AdminREST extends AbstractREST {
|
||||
|
||||
@Path("/user/get/{id}")
|
||||
@GET
|
||||
@ApiOperation(value = "Get user information", notes = "Get user information", responseClass = "com.commafeed.frontend.model.UserModel")
|
||||
public Response getUser(@ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
|
||||
@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) {
|
||||
Preconditions.checkNotNull(id);
|
||||
User user = userDAO.findById(id);
|
||||
User u = userDAO.findById(id);
|
||||
UserModel userModel = new UserModel();
|
||||
userModel.setId(user.getId());
|
||||
userModel.setName(user.getName());
|
||||
userModel.setEmail(user.getEmail());
|
||||
userModel.setEnabled(!user.isDisabled());
|
||||
for (UserRole role : userRoleDAO.findAll(user)) {
|
||||
userModel.setId(u.getId());
|
||||
userModel.setName(u.getName());
|
||||
userModel.setEmail(u.getEmail());
|
||||
userModel.setEnabled(!u.isDisabled());
|
||||
for (UserRole role : userRoleDAO.findAll(u)) {
|
||||
if (role.getRole() == Role.ADMIN) {
|
||||
userModel.setAdmin(true);
|
||||
}
|
||||
@@ -155,21 +133,22 @@ public class AdminREST extends AbstractREST {
|
||||
|
||||
@Path("/user/getAll")
|
||||
@GET
|
||||
@ApiOperation(value = "Get all users", notes = "Get all users", responseClass = "List[com.commafeed.frontend.model.UserModel]")
|
||||
public Response getUsers() {
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get all users", notes = "Get all users", response = UserModel.class, responseContainer = "List")
|
||||
public Response getUsers(@Auth User user) {
|
||||
Map<Long, UserModel> users = Maps.newHashMap();
|
||||
for (UserRole role : userRoleDAO.findAll()) {
|
||||
User user = role.getUser();
|
||||
User u = role.getUser();
|
||||
Long key = user.getId();
|
||||
UserModel userModel = users.get(key);
|
||||
if (userModel == null) {
|
||||
userModel = new UserModel();
|
||||
userModel.setId(user.getId());
|
||||
userModel.setName(user.getName());
|
||||
userModel.setEmail(user.getEmail());
|
||||
userModel.setEnabled(!user.isDisabled());
|
||||
userModel.setCreated(user.getCreated());
|
||||
userModel.setLastLogin(user.getLastLogin());
|
||||
userModel.setId(u.getId());
|
||||
userModel.setName(u.getName());
|
||||
userModel.setEmail(u.getEmail());
|
||||
userModel.setEnabled(!u.isDisabled());
|
||||
userModel.setCreated(u.getCreated());
|
||||
userModel.setLastLogin(u.getLastLogin());
|
||||
users.put(key, userModel);
|
||||
}
|
||||
if (role.getRole() == Role.ADMIN) {
|
||||
@@ -181,53 +160,44 @@ public class AdminREST extends AbstractREST {
|
||||
|
||||
@Path("/user/delete")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Delete a user", notes = "Delete a user, and all his subscriptions")
|
||||
public Response delete(@ApiParam(required = true) IDRequest req) {
|
||||
public Response delete(@Auth User user, @ApiParam(required = true) IDRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
User user = userDAO.findById(req.getId());
|
||||
if (user == null) {
|
||||
User u = userDAO.findById(req.getId());
|
||||
if (u == null) {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
if (StartupBean.USERNAME_ADMIN.equals(user.getName())) {
|
||||
if (CommaFeedApplication.USERNAME_ADMIN.equals(u.getName())) {
|
||||
return Response.status(Status.FORBIDDEN).entity("You cannot delete the admin user.").build();
|
||||
}
|
||||
userService.unregister(user);
|
||||
userService.unregister(u);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Path("/settings")
|
||||
@GET
|
||||
@ApiOperation(
|
||||
value = "Retrieve application settings",
|
||||
notes = "Retrieve application settings",
|
||||
responseClass = "com.commafeed.backend.model.ApplicationSettings")
|
||||
public Response getSettings() {
|
||||
return Response.ok(applicationSettingsService.get()).build();
|
||||
}
|
||||
|
||||
@Path("/settings")
|
||||
@POST
|
||||
@ApiOperation(value = "Save application settings", notes = "Save application settings")
|
||||
public Response saveSettings(@ApiParam(required = true) ApplicationSettings settings) {
|
||||
Preconditions.checkNotNull(settings);
|
||||
applicationSettingsService.save(settings);
|
||||
return Response.ok().build();
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Retrieve application settings", notes = "Retrieve application settings", response = ApplicationSettings.class)
|
||||
public Response getSettings(@Auth User user) {
|
||||
return Response.ok(config.getApplicationSettings()).build();
|
||||
}
|
||||
|
||||
@Path("/metrics")
|
||||
@GET
|
||||
@PrettyPrint
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Retrieve server metrics")
|
||||
public Response getMetrics() {
|
||||
public Response getMetrics(@Auth User user) {
|
||||
return Response.ok(metrics).build();
|
||||
}
|
||||
|
||||
@Path("/cleanup/entries")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Entries cleanup", notes = "Delete entries without subscriptions")
|
||||
public Response cleanupEntries() {
|
||||
public Response cleanupEntries(@Auth User user) {
|
||||
Map<String, Long> map = Maps.newHashMap();
|
||||
map.put("entries_without_subscriptions", cleaner.cleanEntriesWithoutSubscriptions());
|
||||
return Response.ok(map).build();
|
||||
@@ -235,8 +205,9 @@ public class AdminREST extends AbstractREST {
|
||||
|
||||
@Path("/cleanup/feeds")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Feeds cleanup", notes = "Delete feeds without subscriptions")
|
||||
public Response cleanupFeeds() {
|
||||
public Response cleanupFeeds(@Auth User user) {
|
||||
Map<String, Long> map = Maps.newHashMap();
|
||||
map.put("feeds_without_subscriptions", cleaner.cleanFeedsWithoutSubscriptions());
|
||||
return Response.ok(map).build();
|
||||
@@ -244,8 +215,9 @@ public class AdminREST extends AbstractREST {
|
||||
|
||||
@Path("/cleanup/content")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Content cleanup", notes = "Delete contents without entries")
|
||||
public Response cleanupContents() {
|
||||
public Response cleanupContents(@Auth User user) {
|
||||
Map<String, Long> map = Maps.newHashMap();
|
||||
map.put("contents_without_entries", cleaner.cleanContentsWithoutEntries());
|
||||
return Response.ok(map).build();
|
||||
@@ -1,4 +1,7 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
package com.commafeed.frontend.resource;
|
||||
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.dropwizard.hibernate.UnitOfWork;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.Collections;
|
||||
@@ -8,7 +11,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
@@ -19,28 +22,27 @@ import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.backend.cache.CacheService;
|
||||
import com.commafeed.backend.dao.FeedCategoryDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
import com.commafeed.backend.feeds.FeedUtils;
|
||||
import com.commafeed.backend.feed.FeedUtils;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.FeedEntryStatus;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingMode;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingOrder;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.FeedEntryService;
|
||||
import com.commafeed.backend.services.FeedSubscriptionService;
|
||||
import com.commafeed.frontend.SecurityCheck;
|
||||
import com.commafeed.backend.service.FeedEntryService;
|
||||
import com.commafeed.backend.service.FeedSubscriptionService;
|
||||
import com.commafeed.frontend.model.Category;
|
||||
import com.commafeed.frontend.model.Entries;
|
||||
import com.commafeed.frontend.model.Entry;
|
||||
@@ -51,6 +53,7 @@ import com.commafeed.frontend.model.request.CategoryModificationRequest;
|
||||
import com.commafeed.frontend.model.request.CollapseRequest;
|
||||
import com.commafeed.frontend.model.request.IDRequest;
|
||||
import com.commafeed.frontend.model.request.MarkRequest;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sun.syndication.feed.synd.SyndEntry;
|
||||
@@ -64,39 +67,28 @@ import com.wordnik.swagger.annotations.ApiParam;
|
||||
@Path("/category")
|
||||
@Api(value = "/category", description = "Operations about user categories")
|
||||
@Slf4j
|
||||
public class CategoryREST extends AbstractREST {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@AllArgsConstructor
|
||||
public class CategoryREST {
|
||||
|
||||
public static final String ALL = "all";
|
||||
public static final String STARRED = "starred";
|
||||
|
||||
@Inject
|
||||
FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
|
||||
@Inject
|
||||
FeedEntryService feedEntryService;
|
||||
|
||||
@Inject
|
||||
FeedCategoryDAO feedCategoryDAO;
|
||||
|
||||
@Inject
|
||||
FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
|
||||
@Inject
|
||||
FeedSubscriptionService feedSubscriptionService;
|
||||
|
||||
@Inject
|
||||
CacheService cache;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
private final FeedCategoryDAO feedCategoryDAO;
|
||||
private final FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
private final FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
private final FeedEntryService feedEntryService;
|
||||
private final FeedSubscriptionService feedSubscriptionService;
|
||||
private final CacheService cache;
|
||||
private final CommaFeedConfiguration config;
|
||||
|
||||
@Path("/entries")
|
||||
@GET
|
||||
@ApiOperation(
|
||||
value = "Get category entries",
|
||||
notes = "Get a list of category entries",
|
||||
responseClass = "com.commafeed.frontend.model.Entries")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get category entries", notes = "Get a list of category entries", response = Entries.class)
|
||||
public Response getCategoryEntries(
|
||||
@Auth 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,
|
||||
@@ -136,38 +128,38 @@ public class CategoryREST extends AbstractREST {
|
||||
}
|
||||
|
||||
if (ALL.equals(id)) {
|
||||
entries.setName(ObjectUtils.defaultIfNull(tag, "All"));
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(getUser());
|
||||
entries.setName(Optional.fromNullable(tag).or("All"));
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(user);
|
||||
removeExcludedSubscriptions(subs, excludedIds);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(getUser(), subs, unreadOnly, keywords, newerThanDate,
|
||||
offset, limit + 1, order, true, onlyIds, tag);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(user, subs, unreadOnly, keywords, newerThanDate, offset,
|
||||
limit + 1, order, true, onlyIds, tag);
|
||||
|
||||
for (FeedEntryStatus status : list) {
|
||||
entries.getEntries().add(
|
||||
Entry.build(status, applicationSettingsService.get().getPublicUrl(), applicationSettingsService.get()
|
||||
Entry.build(status, config.getApplicationSettings().getPublicUrl(), config.getApplicationSettings()
|
||||
.isImageProxyEnabled()));
|
||||
}
|
||||
|
||||
} else if (STARRED.equals(id)) {
|
||||
entries.setName("Starred");
|
||||
List<FeedEntryStatus> starred = feedEntryStatusDAO.findStarred(getUser(), newerThanDate, offset, limit + 1, order, !onlyIds);
|
||||
List<FeedEntryStatus> starred = feedEntryStatusDAO.findStarred(user, newerThanDate, offset, limit + 1, order, !onlyIds);
|
||||
for (FeedEntryStatus status : starred) {
|
||||
entries.getEntries().add(
|
||||
Entry.build(status, applicationSettingsService.get().getPublicUrl(), applicationSettingsService.get()
|
||||
Entry.build(status, config.getApplicationSettings().getPublicUrl(), config.getApplicationSettings()
|
||||
.isImageProxyEnabled()));
|
||||
}
|
||||
} else {
|
||||
FeedCategory parent = feedCategoryDAO.findById(getUser(), Long.valueOf(id));
|
||||
FeedCategory parent = feedCategoryDAO.findById(user, Long.valueOf(id));
|
||||
if (parent != null) {
|
||||
List<FeedCategory> categories = feedCategoryDAO.findAllChildrenCategories(getUser(), parent);
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategories(getUser(), categories);
|
||||
List<FeedCategory> categories = feedCategoryDAO.findAllChildrenCategories(user, parent);
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategories(user, categories);
|
||||
removeExcludedSubscriptions(subs, excludedIds);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(getUser(), subs, unreadOnly, keywords, newerThanDate,
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(user, subs, unreadOnly, keywords, newerThanDate,
|
||||
offset, limit + 1, order, true, onlyIds, tag);
|
||||
|
||||
for (FeedEntryStatus status : list) {
|
||||
entries.getEntries().add(
|
||||
Entry.build(status, applicationSettingsService.get().getPublicUrl(), applicationSettingsService.get()
|
||||
Entry.build(status, config.getApplicationSettings().getPublicUrl(), config.getApplicationSettings()
|
||||
.isImageProxyEnabled()));
|
||||
}
|
||||
entries.setName(parent.getName());
|
||||
@@ -190,10 +182,11 @@ public class CategoryREST extends AbstractREST {
|
||||
|
||||
@Path("/entriesAsFeed")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get category entries as feed", notes = "Get a feed of category entries")
|
||||
@Produces(MediaType.APPLICATION_XML)
|
||||
@SecurityCheck(value = Role.USER, apiKeyAllowed = true)
|
||||
public Response getCategoryEntriesAsFeed(
|
||||
@Auth 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,
|
||||
@@ -206,8 +199,8 @@ public class CategoryREST extends AbstractREST {
|
||||
@ApiParam(value = "comma-separated list of excluded subscription ids") @QueryParam("excludedSubscriptionIds") String excludedSubscriptionIds,
|
||||
@ApiParam(value = "keep only entries tagged with this tag") @QueryParam("tag") String tag) {
|
||||
|
||||
Response response = getCategoryEntries(id, readType, newerThan, offset, limit, order, keywords, onlyIds, excludedSubscriptionIds,
|
||||
tag);
|
||||
Response response = getCategoryEntries(user, id, readType, newerThan, offset, limit, order, keywords, onlyIds,
|
||||
excludedSubscriptionIds, tag);
|
||||
if (response.getStatus() != Status.OK.getStatusCode()) {
|
||||
return response;
|
||||
}
|
||||
@@ -217,7 +210,7 @@ public class CategoryREST extends AbstractREST {
|
||||
feed.setFeedType("rss_2.0");
|
||||
feed.setTitle("CommaFeed - " + entries.getName());
|
||||
feed.setDescription("CommaFeed - " + entries.getName());
|
||||
String publicUrl = applicationSettingsService.get().getPublicUrl();
|
||||
String publicUrl = config.getApplicationSettings().getPublicUrl();
|
||||
feed.setLink(publicUrl);
|
||||
|
||||
List<SyndEntry> children = Lists.newArrayList();
|
||||
@@ -239,25 +232,26 @@ public class CategoryREST extends AbstractREST {
|
||||
|
||||
@Path("/mark")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Mark category entries", notes = "Mark feed entries of this category as read")
|
||||
public Response markCategoryEntries(@ApiParam(value = "category id, or 'all'", required = true) MarkRequest req) {
|
||||
public Response markCategoryEntries(@Auth User user, @ApiParam(value = "category id, or 'all'", required = true) MarkRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
Date olderThan = req.getOlderThan() == null ? null : new Date(req.getOlderThan());
|
||||
|
||||
if (ALL.equals(req.getId())) {
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(getUser());
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findAll(user);
|
||||
removeExcludedSubscriptions(subs, req.getExcludedSubscriptions());
|
||||
feedEntryService.markSubscriptionEntries(getUser(), subs, olderThan);
|
||||
feedEntryService.markSubscriptionEntries(user, subs, olderThan);
|
||||
} else if (STARRED.equals(req.getId())) {
|
||||
feedEntryService.markStarredEntries(getUser(), olderThan);
|
||||
feedEntryService.markStarredEntries(user, olderThan);
|
||||
} else {
|
||||
FeedCategory parent = feedCategoryDAO.findById(getUser(), Long.valueOf(req.getId()));
|
||||
List<FeedCategory> categories = feedCategoryDAO.findAllChildrenCategories(getUser(), parent);
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategories(getUser(), categories);
|
||||
FeedCategory parent = feedCategoryDAO.findById(user, Long.valueOf(req.getId()));
|
||||
List<FeedCategory> categories = feedCategoryDAO.findAllChildrenCategories(user, parent);
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategories(user, categories);
|
||||
removeExcludedSubscriptions(subs, req.getExcludedSubscriptions());
|
||||
feedEntryService.markSubscriptionEntries(getUser(), subs, olderThan);
|
||||
feedEntryService.markSubscriptionEntries(user, subs, olderThan);
|
||||
}
|
||||
return Response.ok().build();
|
||||
}
|
||||
@@ -276,14 +270,15 @@ public class CategoryREST extends AbstractREST {
|
||||
|
||||
@Path("/add")
|
||||
@POST
|
||||
@ApiOperation(value = "Add a category", notes = "Add a new feed category", responseClass = "java.lang.Long")
|
||||
public Response addCategory(@ApiParam(required = true) AddCategoryRequest req) {
|
||||
@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) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getName());
|
||||
|
||||
FeedCategory cat = new FeedCategory();
|
||||
cat.setName(req.getName());
|
||||
cat.setUser(getUser());
|
||||
cat.setUser(user);
|
||||
cat.setPosition(0);
|
||||
String parentId = req.getParentId();
|
||||
if (parentId != null && !ALL.equals(parentId)) {
|
||||
@@ -292,26 +287,27 @@ public class CategoryREST extends AbstractREST {
|
||||
cat.setParent(parent);
|
||||
}
|
||||
feedCategoryDAO.saveOrUpdate(cat);
|
||||
cache.invalidateUserRootCategory(getUser());
|
||||
cache.invalidateUserRootCategory(user);
|
||||
return Response.ok(cat.getId()).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/delete")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Delete a category", notes = "Delete an existing feed category")
|
||||
public Response deleteCategory(@ApiParam(required = true) IDRequest req) {
|
||||
public Response deleteCategory(@Auth User user, @ApiParam(required = true) IDRequest req) {
|
||||
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
FeedCategory cat = feedCategoryDAO.findById(getUser(), req.getId());
|
||||
FeedCategory cat = feedCategoryDAO.findById(user, req.getId());
|
||||
if (cat != null) {
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategory(getUser(), cat);
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategory(user, cat);
|
||||
for (FeedSubscription sub : subs) {
|
||||
sub.setCategory(null);
|
||||
}
|
||||
feedSubscriptionDAO.saveOrUpdate(subs);
|
||||
List<FeedCategory> categories = feedCategoryDAO.findAllChildrenCategories(getUser(), cat);
|
||||
List<FeedCategory> categories = feedCategoryDAO.findAllChildrenCategories(user, cat);
|
||||
for (FeedCategory child : categories) {
|
||||
if (!child.getId().equals(cat.getId()) && child.getParent().getId().equals(cat.getId())) {
|
||||
child.setParent(null);
|
||||
@@ -320,7 +316,7 @@ public class CategoryREST extends AbstractREST {
|
||||
feedCategoryDAO.saveOrUpdate(categories);
|
||||
|
||||
feedCategoryDAO.delete(cat);
|
||||
cache.invalidateUserRootCategory(getUser());
|
||||
cache.invalidateUserRootCategory(user);
|
||||
return Response.ok().build();
|
||||
} else {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
@@ -329,12 +325,13 @@ public class CategoryREST extends AbstractREST {
|
||||
|
||||
@POST
|
||||
@Path("/modify")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Rename a category", notes = "Rename an existing feed category")
|
||||
public Response modifyCategory(@ApiParam(required = true) CategoryModificationRequest req) {
|
||||
public Response modifyCategory(@Auth User user, @ApiParam(required = true) CategoryModificationRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
FeedCategory category = feedCategoryDAO.findById(getUser(), req.getId());
|
||||
FeedCategory category = feedCategoryDAO.findById(user, req.getId());
|
||||
|
||||
if (StringUtils.isNotBlank(req.getName())) {
|
||||
category.setName(req.getName());
|
||||
@@ -343,12 +340,12 @@ public class CategoryREST extends AbstractREST {
|
||||
FeedCategory parent = null;
|
||||
if (req.getParentId() != null && !CategoryREST.ALL.equals(req.getParentId())
|
||||
&& !StringUtils.equals(req.getParentId(), String.valueOf(req.getId()))) {
|
||||
parent = feedCategoryDAO.findById(getUser(), Long.valueOf(req.getParentId()));
|
||||
parent = feedCategoryDAO.findById(user, Long.valueOf(req.getParentId()));
|
||||
}
|
||||
category.setParent(parent);
|
||||
|
||||
if (req.getPosition() != null) {
|
||||
List<FeedCategory> categories = feedCategoryDAO.findByParent(getUser(), parent);
|
||||
List<FeedCategory> categories = feedCategoryDAO.findByParent(user, parent);
|
||||
Collections.sort(categories, new Comparator<FeedCategory>() {
|
||||
@Override
|
||||
public int compare(FeedCategory o1, FeedCategory o2) {
|
||||
@@ -376,44 +373,42 @@ public class CategoryREST extends AbstractREST {
|
||||
}
|
||||
|
||||
feedCategoryDAO.saveOrUpdate(category);
|
||||
cache.invalidateUserRootCategory(getUser());
|
||||
cache.invalidateUserRootCategory(user);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/collapse")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Collapse a category", notes = "Save collapsed or expanded status for a category")
|
||||
public Response collapse(@ApiParam(required = true) CollapseRequest req) {
|
||||
public Response collapse(@Auth User user, @ApiParam(required = true) CollapseRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
FeedCategory category = feedCategoryDAO.findById(getUser(), Long.valueOf(req.getId()));
|
||||
FeedCategory category = feedCategoryDAO.findById(user, Long.valueOf(req.getId()));
|
||||
if (category == null) {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
category.setCollapsed(req.isCollapse());
|
||||
feedCategoryDAO.saveOrUpdate(category);
|
||||
cache.invalidateUserRootCategory(getUser());
|
||||
cache.invalidateUserRootCategory(user);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/unreadCount")
|
||||
@ApiOperation(value = "Get unread count for feed subscriptions", responseClass = "List[com.commafeed.frontend.model.UnreadCount]")
|
||||
public Response getUnreadCount() {
|
||||
Map<Long, UnreadCount> unreadCount = feedSubscriptionService.getUnreadCount(getUser());
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get unread count for feed subscriptions", response = UnreadCount.class, responseContainer = "List")
|
||||
public Response getUnreadCount(@Auth User user) {
|
||||
Map<Long, UnreadCount> unreadCount = feedSubscriptionService.getUnreadCount(user);
|
||||
return Response.ok(Lists.newArrayList(unreadCount.values())).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/get")
|
||||
@ApiOperation(
|
||||
value = "Get feed categories",
|
||||
notes = "Get all categories and subscriptions of the user",
|
||||
responseClass = "com.commafeed.frontend.model.Category")
|
||||
public Response getSubscriptions() {
|
||||
User user = getUser();
|
||||
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get feed categories", notes = "Get all categories and subscriptions of the user", response = Category.class)
|
||||
public Response getSubscriptions(@Auth User user) {
|
||||
Category root = cache.getUserRootCategory(user);
|
||||
if (root == null) {
|
||||
log.debug("tree cache miss for {}", user.getId());
|
||||
@@ -460,7 +455,7 @@ public class CategoryREST extends AbstractREST {
|
||||
if ((id == null && subscription.getCategory() == null)
|
||||
|| (subscription.getCategory() != null && ObjectUtils.equals(subscription.getCategory().getId(), id))) {
|
||||
UnreadCount uc = unreadCount.get(subscription.getId());
|
||||
Subscription sub = Subscription.build(subscription, applicationSettingsService.get().getPublicUrl(), uc);
|
||||
Subscription sub = Subscription.build(subscription, config.getApplicationSettings().getPublicUrl(), uc);
|
||||
category.getFeeds().add(sub);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,24 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
package com.commafeed.frontend.resource;
|
||||
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.dropwizard.hibernate.UnitOfWork;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import com.commafeed.backend.dao.FeedEntryTagDAO;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.FeedEntryService;
|
||||
import com.commafeed.backend.services.FeedEntryTagService;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.service.FeedEntryService;
|
||||
import com.commafeed.backend.service.FeedEntryTagService;
|
||||
import com.commafeed.frontend.model.request.MarkRequest;
|
||||
import com.commafeed.frontend.model.request.MultipleMarkRequest;
|
||||
import com.commafeed.frontend.model.request.StarRequest;
|
||||
@@ -25,46 +30,37 @@ import com.wordnik.swagger.annotations.ApiParam;
|
||||
|
||||
@Path("/entry")
|
||||
@Api(value = "/entry", description = "Operations about feed entries")
|
||||
public class EntryREST extends AbstractREST {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@AllArgsConstructor
|
||||
public class EntryREST {
|
||||
|
||||
@Inject
|
||||
FeedEntryService feedEntryService;
|
||||
|
||||
@Inject
|
||||
FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
|
||||
@Inject
|
||||
FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
|
||||
@Inject
|
||||
FeedEntryTagDAO feedEntryTagDAO;
|
||||
|
||||
@Inject
|
||||
FeedEntryTagService feedEntryTagService;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
private final FeedEntryTagDAO feedEntryTagDAO;
|
||||
private final FeedEntryService feedEntryService;
|
||||
private final FeedEntryTagService feedEntryTagService;
|
||||
|
||||
@Path("/mark")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
||||
public Response markFeedEntry(@ApiParam(value = "Mark Request", required = true) MarkRequest req) {
|
||||
public Response markFeedEntry(@Auth User user, @ApiParam(value = "Mark Request", required = true) MarkRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
feedEntryService.markEntry(getUser(), Long.valueOf(req.getId()), req.isRead());
|
||||
feedEntryService.markEntry(user, Long.valueOf(req.getId()), req.isRead());
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Path("/markMultiple")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Mark multiple feed entries", notes = "Mark feed entries as read/unread")
|
||||
public Response markFeedEntries(@ApiParam(value = "Multiple Mark Request", required = true) MultipleMarkRequest req) {
|
||||
public Response markFeedEntries(@Auth User user, @ApiParam(value = "Multiple Mark Request", required = true) MultipleMarkRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getRequests());
|
||||
|
||||
for (MarkRequest r : req.getRequests()) {
|
||||
markFeedEntry(r);
|
||||
markFeedEntry(user, r);
|
||||
}
|
||||
|
||||
return Response.ok().build();
|
||||
@@ -72,33 +68,36 @@ public class EntryREST extends AbstractREST {
|
||||
|
||||
@Path("/star")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
||||
public Response starFeedEntry(@ApiParam(value = "Star Request", required = true) StarRequest req) {
|
||||
public Response starFeedEntry(@Auth User user, @ApiParam(value = "Star Request", required = true) StarRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
Preconditions.checkNotNull(req.getFeedId());
|
||||
|
||||
feedEntryService.starEntry(getUser(), Long.valueOf(req.getId()), req.getFeedId(), req.isStarred());
|
||||
feedEntryService.starEntry(user, Long.valueOf(req.getId()), req.getFeedId(), req.isStarred());
|
||||
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Path("/tags")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get list of tags for the user", notes = "Get list of tags for the user")
|
||||
public Response getTags() {
|
||||
List<String> tags = feedEntryTagDAO.findByUser(getUser());
|
||||
public Response getTags(@Auth User user) {
|
||||
List<String> tags = feedEntryTagDAO.findByUser(user);
|
||||
return Response.ok(tags).build();
|
||||
}
|
||||
|
||||
@Path("/tag")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Mark a feed entry", notes = "Mark a feed entry as read/unread")
|
||||
public Response tagFeedEntry(@ApiParam(value = "Tag Request", required = true) TagRequest req) {
|
||||
public Response tagFeedEntry(@Auth User user, @ApiParam(value = "Tag Request", required = true) TagRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getEntryId());
|
||||
|
||||
feedEntryTagService.updateTags(getUser(), req.getEntryId(), req.getTags());
|
||||
feedEntryTagService.updateTags(user, req.getEntryId(), req.getTags());
|
||||
|
||||
return Response.ok().build();
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
package com.commafeed.frontend.resource;
|
||||
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.dropwizard.hibernate.UnitOfWork;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
@@ -9,8 +13,6 @@ import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
@@ -21,45 +23,40 @@ import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.CacheControl;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileItemFactory;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.commafeed.CommaFeedApplication;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.backend.cache.CacheService;
|
||||
import com.commafeed.backend.dao.FeedCategoryDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
import com.commafeed.backend.feeds.FaviconFetcher;
|
||||
import com.commafeed.backend.feeds.FeedFetcher;
|
||||
import com.commafeed.backend.feeds.FeedRefreshTaskGiver;
|
||||
import com.commafeed.backend.feeds.FeedUtils;
|
||||
import com.commafeed.backend.feeds.FetchedFeed;
|
||||
import com.commafeed.backend.feed.FaviconFetcher;
|
||||
import com.commafeed.backend.feed.FeedFetcher;
|
||||
import com.commafeed.backend.feed.FeedQueues;
|
||||
import com.commafeed.backend.feed.FeedUtils;
|
||||
import com.commafeed.backend.feed.FetchedFeed;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.FeedEntryStatus;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingMode;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingOrder;
|
||||
import com.commafeed.backend.opml.OPMLExporter;
|
||||
import com.commafeed.backend.opml.OPMLImporter;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.FeedEntryService;
|
||||
import com.commafeed.backend.services.FeedSubscriptionService;
|
||||
import com.commafeed.backend.startup.StartupBean;
|
||||
import com.commafeed.frontend.SecurityCheck;
|
||||
import com.commafeed.backend.service.FeedEntryService;
|
||||
import com.commafeed.backend.service.FeedSubscriptionService;
|
||||
import com.commafeed.frontend.model.Entries;
|
||||
import com.commafeed.frontend.model.Entry;
|
||||
import com.commafeed.frontend.model.FeedInfo;
|
||||
@@ -73,6 +70,7 @@ import com.commafeed.frontend.model.request.SubscribeRequest;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sun.jersey.multipart.FormDataParam;
|
||||
import com.sun.syndication.feed.opml.Opml;
|
||||
import com.sun.syndication.feed.synd.SyndEntry;
|
||||
import com.sun.syndication.feed.synd.SyndFeed;
|
||||
@@ -86,54 +84,30 @@ import com.wordnik.swagger.annotations.ApiParam;
|
||||
@Path("/feed")
|
||||
@Api(value = "/feed", description = "Operations about feeds")
|
||||
@Slf4j
|
||||
public class FeedREST extends AbstractREST {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@AllArgsConstructor
|
||||
public class FeedREST {
|
||||
|
||||
@Inject
|
||||
StartupBean startupBean;
|
||||
|
||||
@Inject
|
||||
FeedCategoryDAO feedCategoryDAO;
|
||||
|
||||
@Inject
|
||||
FaviconFetcher faviconFetcher;
|
||||
|
||||
@Inject
|
||||
FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
|
||||
@Inject
|
||||
FeedEntryService feedEntryService;
|
||||
|
||||
@Inject
|
||||
FeedSubscriptionService feedSubscriptionService;
|
||||
|
||||
@Inject
|
||||
FeedFetcher feedFetcher;
|
||||
|
||||
@Inject
|
||||
FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
|
||||
@Inject
|
||||
FeedRefreshTaskGiver taskGiver;
|
||||
|
||||
@Inject
|
||||
OPMLImporter opmlImporter;
|
||||
|
||||
@Inject
|
||||
OPMLExporter opmlExporter;
|
||||
|
||||
@Inject
|
||||
CacheService cache;
|
||||
|
||||
@Context
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
private final FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
private final FeedCategoryDAO feedCategoryDAO;
|
||||
private final FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
private final FaviconFetcher faviconFetcher;
|
||||
private final FeedFetcher feedFetcher;
|
||||
private final FeedEntryService feedEntryService;
|
||||
private final FeedSubscriptionService feedSubscriptionService;
|
||||
private final FeedQueues queues;
|
||||
private final OPMLImporter opmlImporter;
|
||||
private final OPMLExporter opmlExporter;
|
||||
private final CacheService cache;
|
||||
private final CommaFeedConfiguration config;
|
||||
|
||||
@Path("/entries")
|
||||
@GET
|
||||
@ApiOperation(value = "Get feed entries", notes = "Get a list of feed entries", responseClass = "com.commafeed.frontend.model.Entries")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get feed entries", notes = "Get a list of feed entries", response = Entries.class)
|
||||
public Response getFeedEntries(
|
||||
@Auth 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,
|
||||
@@ -161,19 +135,19 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
Date newerThanDate = newerThan == null ? null : new Date(Long.valueOf(newerThan));
|
||||
|
||||
FeedSubscription subscription = feedSubscriptionDAO.findById(getUser(), Long.valueOf(id));
|
||||
FeedSubscription subscription = feedSubscriptionDAO.findById(user, Long.valueOf(id));
|
||||
if (subscription != null) {
|
||||
entries.setName(subscription.getTitle());
|
||||
entries.setMessage(subscription.getFeed().getMessage());
|
||||
entries.setErrorCount(subscription.getFeed().getErrorCount());
|
||||
entries.setFeedLink(subscription.getFeed().getLink());
|
||||
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(getUser(), Arrays.asList(subscription), unreadOnly,
|
||||
keywords, newerThanDate, offset, limit + 1, order, true, onlyIds, null);
|
||||
List<FeedEntryStatus> list = feedEntryStatusDAO.findBySubscriptions(user, Arrays.asList(subscription), unreadOnly, keywords,
|
||||
newerThanDate, offset, limit + 1, order, true, onlyIds, null);
|
||||
|
||||
for (FeedEntryStatus status : list) {
|
||||
entries.getEntries().add(
|
||||
Entry.build(status, applicationSettingsService.get().getPublicUrl(), applicationSettingsService.get()
|
||||
Entry.build(status, config.getApplicationSettings().getPublicUrl(), config.getApplicationSettings()
|
||||
.isImageProxyEnabled()));
|
||||
}
|
||||
|
||||
@@ -194,10 +168,11 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
@Path("/entriesAsFeed")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get feed entries as a feed", notes = "Get a feed of feed entries")
|
||||
@Produces(MediaType.APPLICATION_XML)
|
||||
@SecurityCheck(value = Role.USER, apiKeyAllowed = true)
|
||||
public Response getFeedEntriesAsFeed(
|
||||
@Auth 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,
|
||||
@@ -208,7 +183,7 @@ public class FeedREST extends AbstractREST {
|
||||
value = "search for keywords in either the title or the content of the entries, separated by spaces, 3 characters minimum") @QueryParam("keywords") String keywords,
|
||||
@ApiParam(value = "return only entry ids") @DefaultValue("false") @QueryParam("onlyIds") boolean onlyIds) {
|
||||
|
||||
Response response = getFeedEntries(id, readType, newerThan, offset, limit, order, keywords, onlyIds);
|
||||
Response response = getFeedEntries(user, id, readType, newerThan, offset, limit, order, keywords, onlyIds);
|
||||
if (response.getStatus() != Status.OK.getStatusCode()) {
|
||||
return response;
|
||||
}
|
||||
@@ -218,7 +193,7 @@ public class FeedREST extends AbstractREST {
|
||||
feed.setFeedType("rss_2.0");
|
||||
feed.setTitle("CommaFeed - " + entries.getName());
|
||||
feed.setDescription("CommaFeed - " + entries.getName());
|
||||
String publicUrl = applicationSettingsService.get().getPublicUrl();
|
||||
String publicUrl = config.getApplicationSettings().getPublicUrl();
|
||||
feed.setLink(publicUrl);
|
||||
|
||||
List<SyndEntry> children = Lists.newArrayList();
|
||||
@@ -257,8 +232,9 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
@POST
|
||||
@Path("/fetch")
|
||||
@ApiOperation(value = "Fetch a feed", notes = "Fetch a feed by its url", responseClass = "com.commafeed.frontend.model.FeedInfo")
|
||||
public Response fetchFeed(@ApiParam(value = "feed url", required = true) FeedInfoRequest req) {
|
||||
@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) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getUrl());
|
||||
|
||||
@@ -274,24 +250,26 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
@Path("/refreshAll")
|
||||
@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() {
|
||||
feedSubscriptionService.refreshAll(getUser());
|
||||
public Response queueAllForRefresh(@Auth User user) {
|
||||
feedSubscriptionService.refreshAll(user);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Path("/refresh")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Queue a feed for refresh", notes = "Manually add a feed to the refresh queue")
|
||||
public Response queueForRefresh(@ApiParam(value = "Feed id") IDRequest req) {
|
||||
public Response queueForRefresh(@Auth User user, @ApiParam(value = "Feed id") IDRequest req) {
|
||||
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(getUser(), req.getId());
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(user, req.getId());
|
||||
if (sub != null) {
|
||||
Feed feed = sub.getFeed();
|
||||
taskGiver.add(feed, true);
|
||||
queues.add(feed, true);
|
||||
return Response.ok().build();
|
||||
}
|
||||
return Response.ok(Status.NOT_FOUND).build();
|
||||
@@ -299,41 +277,44 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
@Path("/mark")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Mark feed entries", notes = "Mark feed entries as read (unread is not supported)")
|
||||
public Response markFeedEntries(@ApiParam(value = "Mark request") MarkRequest req) {
|
||||
public Response markFeedEntries(@Auth User user, @ApiParam(value = "Mark request") MarkRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
Date olderThan = req.getOlderThan() == null ? null : new Date(req.getOlderThan());
|
||||
|
||||
FeedSubscription subscription = feedSubscriptionDAO.findById(getUser(), Long.valueOf(req.getId()));
|
||||
FeedSubscription subscription = feedSubscriptionDAO.findById(user, Long.valueOf(req.getId()));
|
||||
if (subscription != null) {
|
||||
feedEntryService.markSubscriptionEntries(getUser(), Arrays.asList(subscription), olderThan);
|
||||
feedEntryService.markSubscriptionEntries(user, Arrays.asList(subscription), olderThan);
|
||||
}
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/get/{id}")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "", notes = "")
|
||||
public Response get(@ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
|
||||
public Response get(@Auth User user, @ApiParam(value = "user id", required = true) @PathParam("id") Long id) {
|
||||
|
||||
Preconditions.checkNotNull(id);
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(getUser(), id);
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(user, id);
|
||||
if (sub == null) {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
UnreadCount unreadCount = feedSubscriptionService.getUnreadCount(getUser()).get(id);
|
||||
return Response.ok(Subscription.build(sub, applicationSettingsService.get().getPublicUrl(), unreadCount)).build();
|
||||
UnreadCount unreadCount = feedSubscriptionService.getUnreadCount(user).get(id);
|
||||
return Response.ok(Subscription.build(sub, config.getApplicationSettings().getPublicUrl(), unreadCount)).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/favicon/{id}")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Fetch a feed's icon", notes = "Fetch a feed's icon")
|
||||
public Response getFavicon(@ApiParam(value = "subscription id") @PathParam("id") Long id) {
|
||||
public Response getFavicon(@Auth User user, @ApiParam(value = "subscription id") @PathParam("id") Long id) {
|
||||
|
||||
Preconditions.checkNotNull(id);
|
||||
FeedSubscription subscription = feedSubscriptionDAO.findById(getUser(), id);
|
||||
FeedSubscription subscription = feedSubscriptionDAO.findById(user, id);
|
||||
if (subscription == null) {
|
||||
return Response.status(Status.NOT_FOUND).build();
|
||||
}
|
||||
@@ -343,7 +324,7 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
ResponseBuilder builder = null;
|
||||
if (icon == null) {
|
||||
String baseUrl = FeedUtils.removeTrailingSlash(applicationSettingsService.get().getPublicUrl());
|
||||
String baseUrl = FeedUtils.removeTrailingSlash(config.getApplicationSettings().getPublicUrl());
|
||||
builder = Response.status(Status.MOVED_PERMANENTLY).location(URI.create(baseUrl + "/images/default_favicon.gif"));
|
||||
} else {
|
||||
builder = Response.ok(icon, "image/x-icon");
|
||||
@@ -358,15 +339,16 @@ public class FeedREST extends AbstractREST {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.MONTH, 1);
|
||||
builder.expires(calendar.getTime());
|
||||
builder.lastModified(new Date(startupBean.getStartupTime()));
|
||||
builder.lastModified(CommaFeedApplication.STARTUP_TIME);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/subscribe")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
|
||||
public Response subscribe(@ApiParam(value = "subscription request", required = true) SubscribeRequest req) {
|
||||
public Response subscribe(@Auth User user, @ApiParam(value = "subscription request", required = true) SubscribeRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getTitle());
|
||||
Preconditions.checkNotNull(req.getUrl());
|
||||
@@ -380,9 +362,9 @@ public class FeedREST extends AbstractREST {
|
||||
category = feedCategoryDAO.findById(Long.valueOf(req.getCategoryId()));
|
||||
}
|
||||
FeedInfo info = fetchFeedInternal(url);
|
||||
feedSubscriptionService.subscribe(getUser(), info.getUrl(), req.getTitle(), category);
|
||||
feedSubscriptionService.subscribe(user, info.getUrl(), req.getTitle(), category);
|
||||
} catch (Exception e) {
|
||||
log.info("Failed to subscribe to URL {}: {}", url, e.getMessage());
|
||||
log.error("Failed to subscribe to URL {}: {}", url, e.getMessage(), e);
|
||||
return Response.status(Status.SERVICE_UNAVAILABLE).entity("Failed to subscribe to URL " + url + ": " + e.getMessage()).build();
|
||||
}
|
||||
return Response.ok().build();
|
||||
@@ -390,8 +372,9 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
@GET
|
||||
@Path("/subscribe")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Subscribe to a feed", notes = "Subscribe to a feed")
|
||||
public Response subscribe(@ApiParam(value = "feed url", required = true) @QueryParam("url") String url) {
|
||||
public Response subscribe(@Auth User user, @ApiParam(value = "feed url", required = true) @QueryParam("url") String url) {
|
||||
|
||||
try {
|
||||
Preconditions.checkNotNull(url);
|
||||
@@ -400,11 +383,11 @@ public class FeedREST extends AbstractREST {
|
||||
url = fetchFeedInternal(url).getUrl();
|
||||
|
||||
FeedInfo info = fetchFeedInternal(url);
|
||||
feedSubscriptionService.subscribe(getUser(), info.getUrl(), info.getTitle(), null);
|
||||
feedSubscriptionService.subscribe(user, info.getUrl(), info.getTitle(), null);
|
||||
} catch (Exception e) {
|
||||
log.info("Could not subscribe to url {} : {}", url, e.getMessage());
|
||||
}
|
||||
return Response.temporaryRedirect(URI.create(applicationSettingsService.get().getPublicUrl())).build();
|
||||
return Response.temporaryRedirect(URI.create(config.getApplicationSettings().getPublicUrl())).build();
|
||||
}
|
||||
|
||||
private String prependHttp(String url) {
|
||||
@@ -416,12 +399,13 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
@POST
|
||||
@Path("/unsubscribe")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Unsubscribe from a feed", notes = "Unsubscribe from a feed")
|
||||
public Response unsubscribe(@ApiParam(required = true) IDRequest req) {
|
||||
public Response unsubscribe(@Auth User user, @ApiParam(required = true) IDRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
boolean deleted = feedSubscriptionService.unsubscribe(getUser(), req.getId());
|
||||
boolean deleted = feedSubscriptionService.unsubscribe(user, req.getId());
|
||||
if (deleted) {
|
||||
return Response.ok().build();
|
||||
} else {
|
||||
@@ -431,12 +415,13 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
@POST
|
||||
@Path("/modify")
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Modify a subscription", notes = "Modify a feed subscription")
|
||||
public Response modify(@ApiParam(value = "subscription id", required = true) FeedModificationRequest req) {
|
||||
public Response modify(@Auth User user, @ApiParam(value = "subscription id", required = true) FeedModificationRequest req) {
|
||||
Preconditions.checkNotNull(req);
|
||||
Preconditions.checkNotNull(req.getId());
|
||||
|
||||
FeedSubscription subscription = feedSubscriptionDAO.findById(getUser(), req.getId());
|
||||
FeedSubscription subscription = feedSubscriptionDAO.findById(user, req.getId());
|
||||
|
||||
if (StringUtils.isNotBlank(req.getName())) {
|
||||
subscription.setTitle(req.getName());
|
||||
@@ -444,12 +429,12 @@ public class FeedREST extends AbstractREST {
|
||||
|
||||
FeedCategory parent = null;
|
||||
if (req.getCategoryId() != null && !CategoryREST.ALL.equals(req.getCategoryId())) {
|
||||
parent = feedCategoryDAO.findById(getUser(), Long.valueOf(req.getCategoryId()));
|
||||
parent = feedCategoryDAO.findById(user, Long.valueOf(req.getCategoryId()));
|
||||
}
|
||||
subscription.setCategory(parent);
|
||||
|
||||
if (req.getPosition() != null) {
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategory(getUser(), parent);
|
||||
List<FeedSubscription> subs = feedSubscriptionDAO.findByCategory(user, parent);
|
||||
Collections.sort(subs, new Comparator<FeedSubscription>() {
|
||||
@Override
|
||||
public int compare(FeedSubscription o1, FeedSubscription o2) {
|
||||
@@ -475,49 +460,43 @@ public class FeedREST extends AbstractREST {
|
||||
} else {
|
||||
feedSubscriptionDAO.saveOrUpdate(subscription);
|
||||
}
|
||||
cache.invalidateUserRootCategory(getUser());
|
||||
cache.invalidateUserRootCategory(user);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/import")
|
||||
@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() {
|
||||
public Response importOpml(@Auth User user, @FormDataParam("file") InputStream input) {
|
||||
|
||||
String publicUrl = applicationSettingsService.get().getPublicUrl();
|
||||
String publicUrl = config.getApplicationSettings().getPublicUrl();
|
||||
if (StringUtils.isBlank(publicUrl)) {
|
||||
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR)
|
||||
.entity("Set the public URL in the admin section.").build());
|
||||
}
|
||||
|
||||
if (StartupBean.USERNAME_DEMO.equals(getUser().getName())) {
|
||||
if (CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
|
||||
return Response.status(Status.FORBIDDEN).entity("Import is disabled for the demo account").build();
|
||||
}
|
||||
try {
|
||||
FileItemFactory factory = new DiskFileItemFactory(1000000, null);
|
||||
ServletFileUpload upload = new ServletFileUpload(factory);
|
||||
for (FileItem item : upload.parseRequest(request)) {
|
||||
if ("file".equals(item.getFieldName())) {
|
||||
String opml = IOUtils.toString(item.getInputStream(), "UTF-8");
|
||||
if (StringUtils.isNotBlank(opml)) {
|
||||
opmlImporter.importOpml(getUser(), opml);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
String opml = IOUtils.toString(input, "UTF-8");
|
||||
opmlImporter.importOpml(user, opml);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build());
|
||||
}
|
||||
return Response.temporaryRedirect(URI.create(applicationSettingsService.get().getPublicUrl())).build();
|
||||
return Response.seeOther(URI.create(config.getApplicationSettings().getPublicUrl())).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/export")
|
||||
@UnitOfWork
|
||||
@Produces(MediaType.APPLICATION_XML)
|
||||
@ApiOperation(value = "OPML export", notes = "Export an OPML file of the user's subscriptions")
|
||||
public Response exportOpml() {
|
||||
Opml opml = opmlExporter.export(getUser());
|
||||
public Response exportOpml(@Auth User user) {
|
||||
Opml opml = opmlExporter.export(user);
|
||||
WireFeedOutput output = new WireFeedOutput();
|
||||
String opmlString = null;
|
||||
try {
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
package com.commafeed.frontend.resource;
|
||||
|
||||
import io.dropwizard.hibernate.UnitOfWork;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
@@ -17,59 +17,44 @@ import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.codahale.metrics.Meter;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.backend.dao.FeedDAO;
|
||||
import com.commafeed.backend.feeds.FeedParser;
|
||||
import com.commafeed.backend.feeds.FeedRefreshTaskGiver;
|
||||
import com.commafeed.backend.feeds.FetchedFeed;
|
||||
import com.commafeed.backend.feed.FeedParser;
|
||||
import com.commafeed.backend.feed.FeedQueues;
|
||||
import com.commafeed.backend.feed.FetchedFeed;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.frontend.SecurityCheck;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@Path("/push")
|
||||
@Slf4j
|
||||
public class PubSubHubbubCallbackREST extends AbstractREST {
|
||||
@RequiredArgsConstructor
|
||||
public class PubSubHubbubCallbackREST {
|
||||
|
||||
@Context
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Inject
|
||||
FeedDAO feedDAO;
|
||||
|
||||
@Inject
|
||||
FeedParser parser;
|
||||
|
||||
@Inject
|
||||
FeedRefreshTaskGiver taskGiver;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
private Meter pushReceived;
|
||||
|
||||
@PostConstruct
|
||||
public void initMetrics() {
|
||||
pushReceived = metrics.meter(MetricRegistry.name(getClass(), "pushReceived"));
|
||||
|
||||
}
|
||||
private final FeedDAO feedDAO;
|
||||
private final FeedParser parser;
|
||||
private final FeedQueues queues;
|
||||
private final CommaFeedConfiguration config;
|
||||
private final MetricRegistry metricRegistry;
|
||||
|
||||
@Path("/callback")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
@SecurityCheck(Role.NONE)
|
||||
public Response verify(@QueryParam("hub.mode") String mode, @QueryParam("hub.topic") String topic,
|
||||
@QueryParam("hub.challenge") String challenge, @QueryParam("hub.lease_seconds") String leaseSeconds,
|
||||
@QueryParam("hub.verify_token") String verifyToken) {
|
||||
if (!applicationSettingsService.get().isPubsubhubbub()) {
|
||||
if (!config.getApplicationSettings().isPubsubhubbub()) {
|
||||
return Response.status(Status.FORBIDDEN).entity("pubsubhubbub is disabled").build();
|
||||
}
|
||||
|
||||
@@ -95,11 +80,11 @@ public class PubSubHubbubCallbackREST extends AbstractREST {
|
||||
|
||||
@Path("/callback")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@Consumes({ MediaType.APPLICATION_ATOM_XML, "application/rss+xml" })
|
||||
@SecurityCheck(Role.NONE)
|
||||
public Response callback() {
|
||||
|
||||
if (!applicationSettingsService.get().isPubsubhubbub()) {
|
||||
if (!config.getApplicationSettings().isPubsubhubbub()) {
|
||||
return Response.status(Status.FORBIDDEN).entity("pubsubhubbub is disabled").build();
|
||||
}
|
||||
|
||||
@@ -124,9 +109,9 @@ public class PubSubHubbubCallbackREST extends AbstractREST {
|
||||
|
||||
for (Feed feed : feeds) {
|
||||
log.debug("pushing content to queue for {}", feed.getUrl());
|
||||
taskGiver.add(feed, false);
|
||||
queues.add(feed, false);
|
||||
}
|
||||
pushReceived.mark();
|
||||
metricRegistry.meter(MetricRegistry.name(getClass(), "pushReceived")).mark();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Could not parse pubsub callback: " + e.getMessage());
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.commafeed.frontend.resource;
|
||||
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.dropwizard.hibernate.UnitOfWork;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.backend.HttpGetter;
|
||||
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.model.ServerInfo;
|
||||
import com.wordnik.swagger.annotations.Api;
|
||||
import com.wordnik.swagger.annotations.ApiOperation;
|
||||
|
||||
@Path("/server")
|
||||
@Api(value = "/server", description = "Operations about server infos")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@AllArgsConstructor
|
||||
public class ServerREST {
|
||||
|
||||
private final HttpGetter httpGetter;
|
||||
private final CommaFeedConfiguration config;
|
||||
private final ApplicationPropertiesService applicationPropertiesService;
|
||||
|
||||
@Path("/get")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Get server infos", notes = "Get server infos", response = ServerInfo.class)
|
||||
public Response get(@Auth User user) {
|
||||
ServerInfo infos = new ServerInfo();
|
||||
infos.setAnnouncement(config.getApplicationSettings().getAnnouncement());
|
||||
infos.setVersion(applicationPropertiesService.getVersion());
|
||||
infos.setGitCommit(applicationPropertiesService.getGitCommit());
|
||||
return Response.ok(infos).build();
|
||||
}
|
||||
|
||||
@Path("/proxy")
|
||||
@GET
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "proxy image")
|
||||
@Produces("image/png")
|
||||
public Response get(@Auth User user, @QueryParam("u") String url) {
|
||||
if (!config.getApplicationSettings().isImageProxyEnabled()) {
|
||||
return Response.status(Status.FORBIDDEN).build();
|
||||
}
|
||||
|
||||
url = FeedUtils.imageProxyDecoder(url);
|
||||
try {
|
||||
HttpResult result = httpGetter.getBinary(url, 20000);
|
||||
return Response.ok(result.getContent()).build();
|
||||
} catch (Exception e) {
|
||||
return Response.status(Status.SERVICE_UNAVAILABLE).entity(e.getMessage()).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,24 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
package com.commafeed.frontend.resource;
|
||||
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.dropwizard.hibernate.UnitOfWork;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.commafeed.CommaFeedApplication;
|
||||
import com.commafeed.backend.dao.UserDAO;
|
||||
import com.commafeed.backend.dao.UserRoleDAO;
|
||||
import com.commafeed.backend.dao.UserSettingsDAO;
|
||||
@@ -21,11 +29,8 @@ import com.commafeed.backend.model.UserSettings;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingMode;
|
||||
import com.commafeed.backend.model.UserSettings.ReadingOrder;
|
||||
import com.commafeed.backend.model.UserSettings.ViewMode;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.services.PasswordEncryptionService;
|
||||
import com.commafeed.backend.services.UserService;
|
||||
import com.commafeed.backend.startup.StartupBean;
|
||||
import com.commafeed.frontend.SecurityCheck;
|
||||
import com.commafeed.backend.service.PasswordEncryptionService;
|
||||
import com.commafeed.backend.service.UserService;
|
||||
import com.commafeed.frontend.model.Settings;
|
||||
import com.commafeed.frontend.model.UserModel;
|
||||
import com.commafeed.frontend.model.request.ProfileModificationRequest;
|
||||
@@ -37,44 +42,30 @@ import com.wordnik.swagger.annotations.ApiParam;
|
||||
|
||||
@Path("/user")
|
||||
@Api(value = "/user", description = "Operations about the user")
|
||||
public class UserREST extends AbstractREST {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@AllArgsConstructor
|
||||
public class UserREST {
|
||||
|
||||
@Inject
|
||||
UserDAO userDAO;
|
||||
|
||||
@Inject
|
||||
UserSettingsDAO userSettingsDAO;
|
||||
|
||||
@Inject
|
||||
UserRoleDAO userRoleDAO;
|
||||
|
||||
@Inject
|
||||
StartupBean startupBean;
|
||||
|
||||
@Inject
|
||||
UserService userService;
|
||||
|
||||
@Inject
|
||||
PasswordEncryptionService encryptionService;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
private final UserDAO userDAO;
|
||||
private final UserRoleDAO userRoleDAO;
|
||||
private final UserSettingsDAO userSettingsDAO;
|
||||
private final UserService userService;
|
||||
private final PasswordEncryptionService encryptionService;
|
||||
|
||||
@Path("/settings")
|
||||
@GET
|
||||
@ApiOperation(
|
||||
value = "Retrieve user settings",
|
||||
notes = "Retrieve user settings",
|
||||
responseClass = "com.commafeed.frontend.model.Settings")
|
||||
public Response getSettings() {
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Retrieve user settings", notes = "Retrieve user settings", response = Settings.class)
|
||||
public Response getSettings(@Auth User user) {
|
||||
Settings s = new Settings();
|
||||
UserSettings settings = userSettingsDAO.findByUser(getUser());
|
||||
UserSettings settings = userSettingsDAO.findByUser(user);
|
||||
if (settings != null) {
|
||||
s.setReadingMode(settings.getReadingMode().name());
|
||||
s.setReadingOrder(settings.getReadingOrder().name());
|
||||
s.setViewMode(settings.getViewMode().name());
|
||||
s.setShowRead(settings.isShowRead());
|
||||
|
||||
|
||||
s.setEmail(settings.isEmail());
|
||||
s.setGmail(settings.isGmail());
|
||||
s.setFacebook(settings.isFacebook());
|
||||
@@ -85,7 +76,7 @@ public class UserREST extends AbstractREST {
|
||||
s.setInstapaper(settings.isInstapaper());
|
||||
s.setBuffer(settings.isBuffer());
|
||||
s.setReadability(settings.isReadability());
|
||||
|
||||
|
||||
s.setScrollMarks(settings.isScrollMarks());
|
||||
s.setTheme(settings.getTheme());
|
||||
s.setCustomCss(settings.getCustomCss());
|
||||
@@ -97,7 +88,7 @@ public class UserREST extends AbstractREST {
|
||||
s.setViewMode(ViewMode.title.name());
|
||||
s.setShowRead(true);
|
||||
s.setTheme("default");
|
||||
|
||||
|
||||
s.setEmail(true);
|
||||
s.setGmail(true);
|
||||
s.setFacebook(true);
|
||||
@@ -108,7 +99,7 @@ public class UserREST extends AbstractREST {
|
||||
s.setInstapaper(true);
|
||||
s.setBuffer(true);
|
||||
s.setReadability(true);
|
||||
|
||||
|
||||
s.setScrollMarks(true);
|
||||
s.setLanguage("en");
|
||||
s.setScrollSpeed(400);
|
||||
@@ -118,18 +109,15 @@ public class UserREST extends AbstractREST {
|
||||
|
||||
@Path("/settings")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Save user settings", notes = "Save user settings")
|
||||
public Response saveSettings(@ApiParam Settings settings) {
|
||||
public Response saveSettings(@Auth User user, @ApiParam(required = true) Settings settings) {
|
||||
Preconditions.checkNotNull(settings);
|
||||
|
||||
if (startupBean.getSupportedLanguages().get(settings.getLanguage()) == null) {
|
||||
settings.setLanguage("en");
|
||||
}
|
||||
|
||||
UserSettings s = userSettingsDAO.findByUser(getUser());
|
||||
UserSettings s = userSettingsDAO.findByUser(user);
|
||||
if (s == null) {
|
||||
s = new UserSettings();
|
||||
s.setUser(getUser());
|
||||
s.setUser(user);
|
||||
}
|
||||
s.setReadingMode(ReadingMode.valueOf(settings.getReadingMode()));
|
||||
s.setReadingOrder(ReadingOrder.valueOf(settings.getReadingOrder()));
|
||||
@@ -140,7 +128,7 @@ public class UserREST extends AbstractREST {
|
||||
s.setCustomCss(settings.getCustomCss());
|
||||
s.setLanguage(settings.getLanguage());
|
||||
s.setScrollSpeed(settings.getScrollSpeed());
|
||||
|
||||
|
||||
s.setEmail(settings.isEmail());
|
||||
s.setGmail(settings.isGmail());
|
||||
s.setFacebook(settings.isFacebook());
|
||||
@@ -151,7 +139,7 @@ public class UserREST extends AbstractREST {
|
||||
s.setInstapaper(settings.isInstapaper());
|
||||
s.setBuffer(settings.isBuffer());
|
||||
s.setReadability(settings.isReadability());
|
||||
|
||||
|
||||
userSettingsDAO.saveOrUpdate(s);
|
||||
return Response.ok().build();
|
||||
|
||||
@@ -159,9 +147,9 @@ public class UserREST extends AbstractREST {
|
||||
|
||||
@Path("/profile")
|
||||
@GET
|
||||
@ApiOperation(value = "Retrieve user's profile", responseClass = "com.commafeed.frontend.model.UserModel")
|
||||
public Response get() {
|
||||
User user = getUser();
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Retrieve user's profile", response = UserModel.class)
|
||||
public Response get(@Auth User user) {
|
||||
UserModel userModel = new UserModel();
|
||||
userModel.setId(user.getId());
|
||||
userModel.setName(user.getName());
|
||||
@@ -178,17 +166,16 @@ public class UserREST extends AbstractREST {
|
||||
|
||||
@Path("/profile")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Save user's profile")
|
||||
public Response save(@ApiParam(required = true) ProfileModificationRequest request) {
|
||||
User user = getUser();
|
||||
|
||||
public Response save(@Auth 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());
|
||||
Preconditions.checkArgument(u == null || user.getId().equals(u.getId()));
|
||||
}
|
||||
|
||||
if (StartupBean.USERNAME_DEMO.equals(user.getName())) {
|
||||
if (CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
|
||||
return Response.status(Status.FORBIDDEN).build();
|
||||
}
|
||||
|
||||
@@ -201,14 +188,14 @@ public class UserREST extends AbstractREST {
|
||||
if (request.isNewApiKey()) {
|
||||
user.setApiKey(userService.generateApiKey(user));
|
||||
}
|
||||
userDAO.saveOrUpdate(user);
|
||||
userDAO.merge(user);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Path("/register")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Register a new account")
|
||||
@SecurityCheck(Role.NONE)
|
||||
public Response register(@ApiParam(required = true) RegistrationRequest req) {
|
||||
try {
|
||||
userService.register(req.getName(), req.getPassword(), req.getEmail(), Arrays.asList(Role.USER));
|
||||
@@ -221,12 +208,13 @@ public class UserREST extends AbstractREST {
|
||||
|
||||
@Path("/profile/deleteAccount")
|
||||
@POST
|
||||
@UnitOfWork
|
||||
@ApiOperation(value = "Delete the user account")
|
||||
public Response delete() {
|
||||
if (StartupBean.USERNAME_ADMIN.equals(getUser().getName()) || StartupBean.USERNAME_DEMO.equals(getUser().getName())) {
|
||||
public Response delete(@Auth User user) {
|
||||
if (CommaFeedApplication.USERNAME_ADMIN.equals(user.getName()) || CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
|
||||
return Response.status(Status.FORBIDDEN).build();
|
||||
}
|
||||
userService.unregister(getUser());
|
||||
userService.unregister(user);
|
||||
return Response.ok().build();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.commafeed.frontend.resources;
|
||||
|
||||
import ro.isdc.wro.model.resource.processor.impl.css.CssUrlRewritingProcessor;
|
||||
|
||||
public class CustomCssUrlRewritingProcessor extends CssUrlRewritingProcessor {
|
||||
|
||||
/**
|
||||
* ignore webjar image replacements since they won't be available at runtime anyway
|
||||
*/
|
||||
@Override
|
||||
protected String replaceImageUrl(String cssUri, String imageUrl) {
|
||||
if (cssUri.startsWith("webjar:")) {
|
||||
return imageUrl;
|
||||
}
|
||||
return super.replaceImageUrl(cssUri, imageUrl);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.commafeed.frontend.resources;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import ro.isdc.wro.model.resource.Resource;
|
||||
import ro.isdc.wro.model.resource.ResourceType;
|
||||
import ro.isdc.wro.model.resource.SupportedResourceType;
|
||||
import ro.isdc.wro.model.resource.processor.impl.css.CssImportPreProcessor;
|
||||
|
||||
@SupportedResourceType(ResourceType.CSS)
|
||||
public class SassImportProcessor extends CssImportPreProcessor {
|
||||
|
||||
@Override
|
||||
protected String doTransform(String cssContent, List<Resource> foundImports) throws IOException {
|
||||
for (Resource resource : foundImports) {
|
||||
String uri = resource.getUri();
|
||||
int lastSlash = uri.lastIndexOf('/');
|
||||
String prefix = uri.substring(0, lastSlash);
|
||||
String suffix = uri.substring(lastSlash + 1);
|
||||
uri = prefix + "/_" + suffix + ".scss";
|
||||
resource.setUri(uri);
|
||||
}
|
||||
return super.doTransform(cssContent, foundImports);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.commafeed.frontend.resources;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import ro.isdc.wro.extensions.processor.css.RubySassCssProcessor;
|
||||
import ro.isdc.wro.model.resource.Resource;
|
||||
import ro.isdc.wro.model.resource.ResourceType;
|
||||
import ro.isdc.wro.model.resource.SupportedResourceType;
|
||||
|
||||
@SupportedResourceType(ResourceType.CSS)
|
||||
public class SassOnlyProcessor extends RubySassCssProcessor {
|
||||
|
||||
@Override
|
||||
public void process(Resource resource, Reader reader, Writer writer) throws IOException {
|
||||
if (resource.getUri().endsWith(".sass") || resource.getUri().endsWith(".scss")) {
|
||||
super.process(resource, reader, writer);
|
||||
} else {
|
||||
writer.write(IOUtils.toString(reader));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.commafeed.frontend.resources;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import ro.isdc.wro.model.resource.Resource;
|
||||
import ro.isdc.wro.model.resource.ResourceType;
|
||||
import ro.isdc.wro.model.resource.SupportedResourceType;
|
||||
import ro.isdc.wro.model.resource.processor.ResourcePreProcessor;
|
||||
|
||||
@SupportedResourceType(ResourceType.JS)
|
||||
public class TimestampProcessor implements ResourcePreProcessor {
|
||||
|
||||
private static final String NOW = "" + System.currentTimeMillis();
|
||||
|
||||
@Override
|
||||
public void process(Resource resource, Reader reader, Writer writer) throws IOException {
|
||||
String content = IOUtils.toString(reader);
|
||||
content = content.replace("${timestamp}", NOW);
|
||||
writer.write(content);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.commafeed.frontend.resources;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.wicket.request.resource.AbstractResource;
|
||||
import org.apache.wicket.request.resource.IResource;
|
||||
import org.apache.wicket.request.resource.ResourceReference;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class UserCustomCssReference extends ResourceReference {
|
||||
|
||||
public UserCustomCssReference() {
|
||||
super(UserCustomCssReference.class, "custom.css");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IResource getResource() {
|
||||
return new AbstractResource() {
|
||||
@Override
|
||||
protected ResourceResponse newResourceResponse(Attributes attributes) {
|
||||
ResourceResponse resourceResponse = new ResourceResponse();
|
||||
resourceResponse.setContentType("text/css");
|
||||
resourceResponse.setTextEncoding("UTF-8");
|
||||
resourceResponse.setWriteCallback(new WriteCallback() {
|
||||
@Override
|
||||
public void writeData(Attributes attributes) throws IOException {
|
||||
attributes.getResponse().write(StringUtils.trimToEmpty(getCss()));
|
||||
}
|
||||
});
|
||||
return resourceResponse;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract String getCss();
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.commafeed.frontend.resources;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ro.isdc.wro.model.resource.processor.ResourcePostProcessor;
|
||||
import ro.isdc.wro.model.resource.processor.ResourcePreProcessor;
|
||||
import ro.isdc.wro.model.resource.processor.support.ProcessorProvider;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* Build-time solution
|
||||
*
|
||||
*/
|
||||
public class WroAdditionalProvider implements ProcessorProvider {
|
||||
|
||||
@Override
|
||||
public Map<String, ResourcePreProcessor> providePreProcessors() {
|
||||
Map<String, ResourcePreProcessor> map = Maps.newHashMap();
|
||||
map.put("sassOnlyProcessor", new SassOnlyProcessor());
|
||||
map.put("sassImport", new SassImportProcessor());
|
||||
map.put("timestamp", new TimestampProcessor());
|
||||
map.put("cssUrlRewriting", new CustomCssUrlRewritingProcessor());
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ResourcePostProcessor> providePostProcessors() {
|
||||
return Maps.newHashMap();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.commafeed.frontend.resources;
|
||||
|
||||
import ro.isdc.wro.config.jmx.WroConfiguration;
|
||||
import ro.isdc.wro.http.WroServletContextListener;
|
||||
|
||||
import com.commafeed.backend.services.ApplicationPropertiesService;
|
||||
|
||||
public class WroListener extends WroServletContextListener {
|
||||
|
||||
@Override
|
||||
protected WroConfiguration newConfiguration() {
|
||||
WroConfiguration conf = super.newConfiguration();
|
||||
ApplicationPropertiesService properties = ApplicationPropertiesService.get();
|
||||
boolean prod = properties.isProduction();
|
||||
|
||||
conf.setResourceWatcherUpdatePeriod(prod ? 0 : 1);
|
||||
conf.setDisableCache(!prod);
|
||||
conf.setDebug(!prod);
|
||||
return conf;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.commafeed.frontend.resources;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ro.isdc.wro.manager.factory.ConfigurableWroManagerFactory;
|
||||
import ro.isdc.wro.model.resource.processor.ResourcePreProcessor;
|
||||
|
||||
/**
|
||||
* Runtime solution
|
||||
*
|
||||
*/
|
||||
public class WroManagerFactory extends ConfigurableWroManagerFactory {
|
||||
|
||||
@Override
|
||||
protected void contributePreProcessors(Map<String, ResourcePreProcessor> map) {
|
||||
map.put("sassOnlyProcessor", new SassOnlyProcessor());
|
||||
map.put("sassImport", new SassImportProcessor());
|
||||
map.put("timestamp", new TimestampProcessor());
|
||||
map.put("cssUrlRewriting", new CustomCssUrlRewritingProcessor());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package com.commafeed.frontend.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.ext.MessageBodyReader;
|
||||
import javax.ws.rs.ext.MessageBodyWriter;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
import org.apache.http.HttpHeaders;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectWriter;
|
||||
|
||||
@Provider
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class JsonProvider implements MessageBodyReader<Object>, MessageBodyWriter<Object> {
|
||||
|
||||
private static final String CONTENT_TYPE_VALUE_SUFFIX = ";charset=UTF-8";
|
||||
private static final String CACHE_CONTROL_VALUE = "no-cache";
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
@Context
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Override
|
||||
public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
|
||||
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException {
|
||||
|
||||
httpHeaders.putSingle(HttpHeaders.CONTENT_TYPE, mediaType.toString() + CONTENT_TYPE_VALUE_SUFFIX);
|
||||
httpHeaders.putSingle(HttpHeaders.CACHE_CONTROL, CACHE_CONTROL_VALUE);
|
||||
httpHeaders.putSingle(HttpHeaders.PRAGMA, CACHE_CONTROL_VALUE);
|
||||
|
||||
ObjectWriter writer = getMapper().writer();
|
||||
if (hasPrettyPrint(annotations)) {
|
||||
writer = writer.withDefaultPrettyPrinter();
|
||||
}
|
||||
writer.writeValue(entityStream, value);
|
||||
|
||||
}
|
||||
|
||||
private boolean hasPrettyPrint(Annotation[] annotations) {
|
||||
boolean prettyPrint = false;
|
||||
|
||||
for (Annotation annotation : annotations) {
|
||||
if (PrettyPrint.class.equals(annotation.annotationType())) {
|
||||
prettyPrint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!prettyPrint && request != null) {
|
||||
prettyPrint = Boolean.parseBoolean(request.getParameter("pretty"));
|
||||
}
|
||||
return prettyPrint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
|
||||
MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
|
||||
return getMapper().readValue(entityStream, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ObjectMapper getMapper() {
|
||||
return MAPPER;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.commafeed.frontend.rest;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PrettyPrint {
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.commafeed.frontend.rest;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
import com.commafeed.frontend.rest.resources.AdminREST;
|
||||
import com.commafeed.frontend.rest.resources.CategoryREST;
|
||||
import com.commafeed.frontend.rest.resources.EntryREST;
|
||||
import com.commafeed.frontend.rest.resources.FeedREST;
|
||||
import com.commafeed.frontend.rest.resources.PubSubHubbubCallbackREST;
|
||||
import com.commafeed.frontend.rest.resources.ServerREST;
|
||||
import com.commafeed.frontend.rest.resources.UserREST;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
@ApplicationPath("/rest")
|
||||
public class RESTApplication extends Application {
|
||||
|
||||
@Override
|
||||
public Set<Class<?>> getClasses() {
|
||||
Set<Class<?>> set = Sets.newHashSet();
|
||||
set.add(JsonProvider.class);
|
||||
|
||||
set.add(EntryREST.class);
|
||||
set.add(FeedREST.class);
|
||||
set.add(CategoryREST.class);
|
||||
set.add(UserREST.class);
|
||||
set.add(ServerREST.class);
|
||||
set.add(AdminREST.class);
|
||||
|
||||
set.add(PubSubHubbubCallbackREST.class);
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package com.commafeed.frontend.rest.resources;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import javax.interceptor.AroundInvoke;
|
||||
import javax.interceptor.InvocationContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.Produces;
|
||||
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 org.apache.wicket.ThreadContext;
|
||||
import org.apache.wicket.authentication.IAuthenticationStrategy;
|
||||
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
|
||||
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
|
||||
import org.apache.wicket.protocol.http.servlet.ServletWebResponse;
|
||||
import org.apache.wicket.request.cycle.RequestCycle;
|
||||
import org.apache.wicket.util.crypt.Base64;
|
||||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.commafeed.backend.dao.UserDAO;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.model.UserRole.Role;
|
||||
import com.commafeed.frontend.CommaFeedApplication;
|
||||
import com.commafeed.frontend.CommaFeedSession;
|
||||
import com.commafeed.frontend.SecurityCheck;
|
||||
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@SecurityCheck(Role.USER)
|
||||
public abstract class AbstractREST {
|
||||
|
||||
@Context
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Context
|
||||
private HttpServletResponse response;
|
||||
|
||||
@Inject
|
||||
MetricRegistry metrics;
|
||||
|
||||
@Inject
|
||||
private UserDAO userDAO;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
CommaFeedApplication app = CommaFeedApplication.get();
|
||||
ServletWebRequest swreq = new ServletWebRequest(request, "");
|
||||
ServletWebResponse swresp = new ServletWebResponse(swreq, response);
|
||||
RequestCycle cycle = app.createRequestCycle(swreq, swresp);
|
||||
ThreadContext.setRequestCycle(cycle);
|
||||
CommaFeedSession session = (CommaFeedSession) app.fetchCreateAndSetSession(cycle);
|
||||
|
||||
if (session.getUser() == null) {
|
||||
cookieLogin(app, session);
|
||||
}
|
||||
if (session.getUser() == null) {
|
||||
basicHttpLogin(swreq, session);
|
||||
}
|
||||
}
|
||||
|
||||
private void cookieLogin(CommaFeedApplication app, CommaFeedSession session) {
|
||||
IAuthenticationStrategy authenticationStrategy = app.getSecuritySettings().getAuthenticationStrategy();
|
||||
String[] data = authenticationStrategy.load();
|
||||
if (data != null && data.length > 1) {
|
||||
session.signIn(data[0], data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private void basicHttpLogin(ServletWebRequest req, CommaFeedSession session) {
|
||||
String value = req.getHeader(HttpHeaders.AUTHORIZATION);
|
||||
if (value != null && value.startsWith("Basic ")) {
|
||||
value = value.substring(6);
|
||||
String decoded = new String(Base64.decodeBase64(value));
|
||||
String[] data = decoded.split(":");
|
||||
if (data != null && data.length > 1) {
|
||||
session.signIn(data[0], data[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void apiKeyLogin() {
|
||||
String apiKey = request.getParameter("apiKey");
|
||||
User user = userDAO.findByApiKey(apiKey);
|
||||
CommaFeedSession.get().setUser(user);
|
||||
}
|
||||
|
||||
protected User getUser() {
|
||||
return CommaFeedSession.get().getUser();
|
||||
}
|
||||
|
||||
@AroundInvoke
|
||||
public Object intercept(InvocationContext context) throws Exception {
|
||||
Method method = context.getMethod();
|
||||
|
||||
// check security
|
||||
boolean allowed = true;
|
||||
User user = null;
|
||||
|
||||
SecurityCheck check = method.isAnnotationPresent(SecurityCheck.class) ? method.getAnnotation(SecurityCheck.class) : method
|
||||
.getDeclaringClass().getAnnotation(SecurityCheck.class);
|
||||
|
||||
if (check != null) {
|
||||
user = getUser();
|
||||
if (user == null && check.apiKeyAllowed()) {
|
||||
apiKeyLogin();
|
||||
user = getUser();
|
||||
}
|
||||
|
||||
allowed = checkRole(check.value());
|
||||
}
|
||||
if (!allowed) {
|
||||
if (user == null) {
|
||||
return Response.status(Status.UNAUTHORIZED).entity("You are not authorized to do this.").build();
|
||||
} else {
|
||||
return Response.status(Status.FORBIDDEN).entity("You are not authorized to do this.").build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object result = null;
|
||||
com.codahale.metrics.Timer.Context timer = metrics.timer(
|
||||
MetricRegistry.name(method.getDeclaringClass(), method.getName(), "responseTime")).time();
|
||||
try {
|
||||
result = context.proceed();
|
||||
} finally {
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean checkRole(Role requiredRole) {
|
||||
if (requiredRole == Role.NONE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Roles roles = CommaFeedSession.get().getRoles();
|
||||
boolean authorized = roles.hasAnyRole(new Roles(requiredRole.name()));
|
||||
return authorized;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
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.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import com.commafeed.backend.HttpGetter;
|
||||
import com.commafeed.backend.HttpGetter.HttpResult;
|
||||
import com.commafeed.backend.feeds.FeedUtils;
|
||||
import com.commafeed.backend.services.ApplicationPropertiesService;
|
||||
import com.commafeed.backend.services.ApplicationSettingsService;
|
||||
import com.commafeed.backend.startup.StartupBean;
|
||||
import com.commafeed.frontend.model.ServerInfo;
|
||||
import com.wordnik.swagger.annotations.Api;
|
||||
import com.wordnik.swagger.annotations.ApiOperation;
|
||||
|
||||
@Path("/server")
|
||||
@Api(value = "/server", description = "Operations about server infos")
|
||||
public class ServerREST extends AbstractREST {
|
||||
|
||||
@Inject
|
||||
StartupBean startupBean;
|
||||
|
||||
@Inject
|
||||
HttpGetter httpGetter;
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
@Path("/get")
|
||||
@GET
|
||||
@ApiOperation(value = "Get server infos", notes = "Get server infos", responseClass = "com.commafeed.frontend.model.ServerInfo")
|
||||
public Response get() {
|
||||
ApplicationPropertiesService properties = ApplicationPropertiesService.get();
|
||||
|
||||
ServerInfo infos = new ServerInfo();
|
||||
infos.setAnnouncement(applicationSettingsService.get().getAnnouncement());
|
||||
infos.getSupportedLanguages().putAll(startupBean.getSupportedLanguages());
|
||||
infos.setVersion(properties.getVersion());
|
||||
infos.setGitCommit(properties.getGitCommit());
|
||||
return Response.ok(infos).build();
|
||||
}
|
||||
|
||||
@Path("/proxy")
|
||||
@GET
|
||||
@ApiOperation(value = "proxy image")
|
||||
@Produces("image/png")
|
||||
public Response get(@QueryParam("u") String url) {
|
||||
if (!applicationSettingsService.get().isImageProxyEnabled()) {
|
||||
return Response.status(Status.FORBIDDEN).build();
|
||||
}
|
||||
|
||||
url = FeedUtils.imageProxyDecoder(url);
|
||||
try {
|
||||
HttpResult result = httpGetter.getBinary(url, 20000);
|
||||
return Response.ok(result.getContent()).build();
|
||||
} catch (Exception e) {
|
||||
return Response.status(Status.SERVICE_UNAVAILABLE).entity(e.getMessage()).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
package com.commafeed.frontend.utils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.commafeed.backend.dao.UserSettingsDAO;
|
||||
import com.commafeed.backend.model.UserSettings;
|
||||
import com.commafeed.backend.services.ApplicationPropertiesService;
|
||||
import com.commafeed.frontend.CommaFeedSession;
|
||||
|
||||
/**
|
||||
* Replace variables from templates on the fly in dev mode only. In production the substitution is done at build-time.
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
public class InternationalizationDevelopmentFilter implements Filter {
|
||||
|
||||
@Inject
|
||||
UserSettingsDAO userSettingsDAO;
|
||||
|
||||
private boolean production = true;
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
ApplicationPropertiesService properties = ApplicationPropertiesService.get();
|
||||
production = properties.isProduction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
if (production) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
final ServletOutputStream wrapper = new ServletOutputStreamWrapper();
|
||||
ServletResponse interceptor = new HttpServletResponseWrapper((HttpServletResponse) response) {
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
return wrapper;
|
||||
}
|
||||
};
|
||||
chain.doFilter(request, interceptor);
|
||||
|
||||
UserSettings settings = userSettingsDAO.findByUser(CommaFeedSession.get().getUser());
|
||||
String lang = (settings == null || settings.getLanguage() == null) ? "en" : settings.getLanguage();
|
||||
|
||||
byte[] bytes = translate(wrapper.toString(), lang).getBytes("UTF-8");
|
||||
response.setContentLength(bytes.length);
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.getOutputStream().write(bytes);
|
||||
response.getOutputStream().close();
|
||||
|
||||
}
|
||||
|
||||
private String translate(String content, String lang) {
|
||||
Properties props = new Properties();
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = getClass().getResourceAsStream("/i18n/" + lang + ".properties");
|
||||
props.load(new InputStreamReader(is, "UTF-8"));
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
|
||||
return replace(content, props);
|
||||
}
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("\\$\\{(.+?)\\}");
|
||||
|
||||
public String replace(String content, Properties props) {
|
||||
Matcher m = PATTERN.matcher(content);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (m.find()) {
|
||||
String var = m.group(1);
|
||||
Object replacement = props.get(var);
|
||||
String replacementValue = replacement == null ? var : replacement.toString().split("#")[0];
|
||||
m.appendReplacement(sb, replacementValue);
|
||||
}
|
||||
m.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static class ServletOutputStreamWrapper extends ServletOutputStream {
|
||||
|
||||
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
baos.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return baos.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package com.commafeed.frontend.utils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.wicket.markup.head.HeaderItem;
|
||||
import org.apache.wicket.markup.head.IHeaderResponse;
|
||||
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
|
||||
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
|
||||
import org.apache.wicket.request.cycle.RequestCycle;
|
||||
import org.apache.wicket.request.http.WebResponse;
|
||||
import org.apache.wicket.request.resource.JavaScriptResourceReference;
|
||||
import org.apache.wicket.util.io.IOUtils;
|
||||
import org.apache.wicket.util.template.PackageTextTemplate;
|
||||
|
||||
public class WicketUtils {
|
||||
|
||||
public static void loadJS(IHeaderResponse response, Class<?> klass, String fileName) {
|
||||
HeaderItem result = JavaScriptHeaderItem.forReference(new JavaScriptResourceReference(klass, fileName + ".js"));
|
||||
response.render(result);
|
||||
}
|
||||
|
||||
public static void loadJS(IHeaderResponse response, Class<?> klass, String fileName, Map<String, ? extends Object> variables) {
|
||||
HeaderItem result = null;
|
||||
PackageTextTemplate template = null;
|
||||
try {
|
||||
template = new PackageTextTemplate(klass, fileName + ".js");
|
||||
String script = template.asString(variables);
|
||||
result = JavaScriptHeaderItem.forScript(script, null);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(template);
|
||||
}
|
||||
response.render(result);
|
||||
}
|
||||
|
||||
public static HttpServletRequest getHttpServletRequest() {
|
||||
ServletWebRequest servletWebRequest = (ServletWebRequest) RequestCycle.get().getRequest();
|
||||
return servletWebRequest.getContainerRequest();
|
||||
}
|
||||
|
||||
public static HttpServletResponse getHttpServletResponse() {
|
||||
WebResponse webResponse = (WebResponse) RequestCycle.get().getResponse();
|
||||
return (HttpServletResponse) webResponse.getContainerResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* like wicket's Request.getClientUrl() but returns an absolute url instead of a relative one
|
||||
*/
|
||||
public static String getClientFullUrl() {
|
||||
HttpServletRequest request = getHttpServletRequest();
|
||||
StringBuffer requestURL = request.getRequestURL();
|
||||
String queryString = request.getQueryString();
|
||||
|
||||
if (queryString == null) {
|
||||
return requestURL.toString();
|
||||
} else {
|
||||
return requestURL.append('?').append(queryString).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.commafeed.frontend.utils.exception;
|
||||
|
||||
public class DisplayException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private DisplayException() {
|
||||
|
||||
}
|
||||
|
||||
public DisplayException(String message) {
|
||||
super(message, new DisplayException());
|
||||
}
|
||||
|
||||
public DisplayException(Throwable t) {
|
||||
super(t.getMessage(), t);
|
||||
}
|
||||
|
||||
public DisplayException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:wicket="http://wicket.apache.org">
|
||||
<body>
|
||||
<wicket:extend>
|
||||
<div class="container">
|
||||
<div class="page-header">
|
||||
<h1>An unexpected error occured</h1>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-error" style="cursor: pointer"
|
||||
data-toggle="collapse" data-target="#stacktrace">
|
||||
<ul class="feedbackPanel unstyled" style="margin-bottom: 0px;">
|
||||
<li class="feedbackPanelERROR">
|
||||
<span class="feedbackPanelERROR" wicket:id="message"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Go back to the <a href="javascript:window.history.back()">previous page</a> or to the <a wicket:id="homepage">home page.</a>
|
||||
|
||||
<div id="stacktrace" class="collapse">
|
||||
<pre wicket:id="stacktrace"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</wicket:extend>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.commafeed.frontend.utils.exception;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.apache.wicket.markup.html.basic.Label;
|
||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
||||
|
||||
import com.commafeed.frontend.pages.BasePage;
|
||||
|
||||
public class DisplayExceptionPage extends BasePage {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public DisplayExceptionPage(Throwable t) {
|
||||
Throwable de = findDisplayException(t);
|
||||
if (de != null) {
|
||||
t = de;
|
||||
}
|
||||
|
||||
add(new Label("message", t.getMessage()));
|
||||
|
||||
add(new BookmarkablePageLink<Void>("homepage", getApplication().getHomePage()));
|
||||
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
t.printStackTrace(new PrintWriter(stringWriter));
|
||||
t.printStackTrace();
|
||||
add(new Label("stacktrace", stringWriter.toString()));
|
||||
|
||||
}
|
||||
|
||||
private Throwable findDisplayException(Throwable t) {
|
||||
while (t != null && !(t instanceof DisplayException)) {
|
||||
t = t.getCause();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user