import from google reader

This commit is contained in:
Athou
2013-04-05 16:31:42 +02:00
parent ad1e64b101
commit a1ab76d176
16 changed files with 388 additions and 1 deletions

View File

@@ -11,10 +11,12 @@ import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.commafeed.backend.dao.ApplicationSettingsService;
import com.commafeed.backend.dao.FeedCategoryService;
import com.commafeed.backend.dao.FeedService;
import com.commafeed.backend.dao.FeedSubscriptionService;
import com.commafeed.backend.dao.UserService;
import com.commafeed.backend.model.ApplicationSettings;
import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedCategory;
import com.commafeed.backend.model.FeedSubscription;
@@ -44,6 +46,9 @@ public class StartupBean {
@Inject
PasswordEncryptionService encryptionService;
@Inject
ApplicationSettingsService applicationSettingsService;
private long startupTime;
@PostConstruct
@@ -52,6 +57,8 @@ public class StartupBean {
if (userService.getCount() == 0) {
log.info("Populating database with default values");
applicationSettingsService.save(new ApplicationSettings());
User user = userService.register(ADMIN_NAME, "admin",
Arrays.asList(Role.ADMIN, Role.USER));
userService.register("test", "test", Arrays.asList(Role.USER));

View File

@@ -0,0 +1,34 @@
package com.commafeed.backend.dao;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.commafeed.backend.model.ApplicationSettings;
import com.google.common.collect.Iterables;
import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
@Stateless
public class ApplicationSettingsService {
@PersistenceContext
protected EntityManager em;
public void save(ApplicationSettings settings) {
if (settings.getId() == null) {
em.persist(settings);
} else {
em.merge(settings);
}
}
public ApplicationSettings get() {
EasyCriteria<ApplicationSettings> criteria = EasyCriteriaFactory
.createQueryCriteria(em, ApplicationSettings.class);
List<ApplicationSettings> list = criteria.getResultList();
return Iterables.getFirst(list, null);
}
}

View File

@@ -0,0 +1,48 @@
package com.commafeed.backend.model;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "APPLICATIONSETTINGS")
@SuppressWarnings("serial")
public class ApplicationSettings extends AbstractModel {
private String publicUrl;
private boolean allowRegistrations = false;
private String googleClientId;
private String googleClientSecret;
public String getPublicUrl() {
return publicUrl;
}
public void setPublicUrl(String publicUrl) {
this.publicUrl = publicUrl;
}
public boolean isAllowRegistrations() {
return allowRegistrations;
}
public void setAllowRegistrations(boolean allowRegistrations) {
this.allowRegistrations = allowRegistrations;
}
public String getGoogleClientId() {
return googleClientId;
}
public void setGoogleClientId(String googleClientId) {
this.googleClientId = googleClientId;
}
public String getGoogleClientSecret() {
return googleClientSecret;
}
public void setGoogleClientSecret(String googleClientSecret) {
this.googleClientSecret = googleClientSecret;
}
}

View File

@@ -21,6 +21,10 @@ public class User extends AbstractModel {
@Index(name = "username_index")
private String name;
@Column(length = 256, unique = true)
@Index(name = "useremail_index")
private String email;
@Column(length = 256, nullable = false)
private byte[] password;

View File

@@ -39,6 +39,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.commafeed.frontend.pages.FaviconPage;
import com.commafeed.frontend.pages.GoogleImportCallbackPage;
import com.commafeed.frontend.pages.GoogleImportRedirectPage;
import com.commafeed.frontend.pages.HomePage;
import com.commafeed.frontend.pages.LoginPage;
import com.commafeed.frontend.pages.LogoutPage;
@@ -59,6 +61,8 @@ public class CommaFeedApplication extends AuthenticatedWebApplication {
mountPage("logout", LogoutPage.class);
mountPage("error", DisplayExceptionPage.class);
mountPage("favicon", FaviconPage.class);
mountPage("google/import/redirect", GoogleImportRedirectPage.class);
mountPage("google/import/callback", GoogleImportCallbackPage.class);
setupInjection();

View File

@@ -0,0 +1,98 @@
package com.commafeed.frontend.pages;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.request.Url;
import org.apache.wicket.request.UrlRenderer;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import com.commafeed.backend.dao.ApplicationSettingsService;
import com.commafeed.backend.dao.UserService;
import com.commafeed.backend.feeds.OPMLImporter;
import com.commafeed.backend.model.ApplicationSettings;
import com.commafeed.frontend.utils.WicketUtils;
import com.commafeed.frontend.utils.exception.DisplayException;
import com.google.api.client.auth.oauth2.AuthorizationCodeResponseUrl;
import com.google.api.client.auth.oauth2.AuthorizationCodeTokenRequest;
import com.google.api.client.auth.oauth2.BearerToken;
import com.google.api.client.auth.oauth2.TokenResponse;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
@SuppressWarnings("serial")
public class GoogleImportCallbackPage extends WebPage {
@Inject
ApplicationSettingsService applicationSettingsService;
@Inject
OPMLImporter importer;
@Inject
UserService userService;
private static final String TOKEN_URL = "https://accounts.google.com/o/oauth2/token";
private static final String EXPORT_URL = "https://www.google.com/reader/subscriptions/export";
public static String getCallbackUrl() {
RequestCycle cycle = RequestCycle.get();
UrlRenderer renderer = cycle.getUrlRenderer();
return renderer.renderFullUrl(Url.parse(cycle.urlFor(
GoogleImportCallbackPage.class, null).toString()));
}
public GoogleImportCallbackPage(PageParameters params) {
HttpServletRequest request = WicketUtils.getHttpServletRequest();
StringBuffer urlBuffer = request.getRequestURL();
if (request.getQueryString() != null) {
urlBuffer.append('?').append(request.getQueryString());
}
AuthorizationCodeResponseUrl responseUrl = new AuthorizationCodeResponseUrl(
urlBuffer.toString());
String code = responseUrl.getCode();
if (responseUrl.getError() != null) {
throw new DisplayException(responseUrl.getError());
} else if (code == null) {
throw new DisplayException("Missing authorization code");
} else {
ApplicationSettings settings = applicationSettingsService.get();
String redirectUri = getCallbackUrl();
String clientId = settings.getGoogleClientId();
String clientSecret = settings.getGoogleClientSecret();
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
AuthorizationCodeTokenRequest tokenRequest = new AuthorizationCodeTokenRequest(
httpTransport, jsonFactory, new GenericUrl(TOKEN_URL), code);
tokenRequest.setRedirectUri(redirectUri);
tokenRequest.put("client_id", clientId);
tokenRequest.put("client_secret", clientSecret);
tokenRequest.setGrantType("authorization_code");
try {
TokenResponse tokenResponse = tokenRequest.execute();
String accessToken = tokenResponse.getAccessToken();
HttpRequest httpRequest = httpTransport.createRequestFactory()
.buildGetRequest(new GenericUrl(EXPORT_URL));
BearerToken.authorizationHeaderAccessMethod().intercept(
httpRequest, accessToken);
String opml = httpRequest.execute().parseAsString();
String state = responseUrl.getState();
importer.importOpml(userService.findById(Long.valueOf(state)),
opml);
} catch (Exception e) {
throw new DisplayException(e);
}
}
setResponsePage(getApplication().getHomePage());
}
}

View File

@@ -0,0 +1,52 @@
package com.commafeed.frontend.pages;
import java.net.URISyntaxException;
import javax.inject.Inject;
import org.apache.http.client.utils.URIBuilder;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.request.flow.RedirectToUrlException;
import org.jboss.logging.Logger;
import com.commafeed.backend.dao.ApplicationSettingsService;
import com.commafeed.backend.model.ApplicationSettings;
import com.commafeed.frontend.CommaFeedSession;
@SuppressWarnings("serial")
public class GoogleImportRedirectPage extends WebPage {
private static Logger log = Logger
.getLogger(GoogleImportRedirectPage.class);
private static final String SCOPE = "https://www.google.com/reader/subscriptions/export";
private static final String AUTH_URL = "https://accounts.google.com/o/oauth2/auth";
@Inject
ApplicationSettingsService applicationSettingsService;
public GoogleImportRedirectPage() {
ApplicationSettings settings = applicationSettingsService.get();
String clientId = settings.getGoogleClientId();
String redirectUri = GoogleImportCallbackPage.getCallbackUrl();
try {
URIBuilder builder = new URIBuilder(AUTH_URL);
builder.addParameter("redirect_uri", redirectUri);
builder.addParameter("response_type", "code");
builder.addParameter("scope", SCOPE);
builder.addParameter("approval_prompt", "force");
builder.addParameter("client_id", clientId);
builder.addParameter("state",
String.valueOf(CommaFeedSession.get().getUser().getId()));
throw new RedirectToUrlException(builder.build().toString());
} catch (URISyntaxException e) {
log.error(e.getMessage(), e);
}
}
}

View File

@@ -5,6 +5,7 @@ import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import com.commafeed.frontend.rest.resources.AdminSettingsREST;
import com.commafeed.frontend.rest.resources.AdminUsersREST;
import com.commafeed.frontend.rest.resources.EntriesREST;
import com.commafeed.frontend.rest.resources.SessionREST;
@@ -24,6 +25,7 @@ public class RESTApplication extends Application {
set.add(EntriesREST.class);
set.add(SettingsREST.class);
set.add(AdminUsersREST.class);
set.add(AdminSettingsREST.class);
set.add(SessionREST.class);
return set;
}

View File

@@ -0,0 +1,33 @@
package com.commafeed.frontend.rest.resources;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import com.commafeed.backend.dao.ApplicationSettingsService;
import com.commafeed.backend.model.ApplicationSettings;
import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.frontend.SecurityCheck;
@SecurityCheck(Role.ADMIN)
@Path("admin/settings")
public class AdminSettingsREST {
@Inject
ApplicationSettingsService applicationSettingsService;
@Path("get")
@GET
public ApplicationSettings get() {
return applicationSettingsService.get();
}
@Path("save")
@POST
public Response save(ApplicationSettings settings) {
applicationSettingsService.save(settings);
return Response.ok().build();
}
}

View File

@@ -3,10 +3,13 @@ package com.commafeed.frontend.utils.exception;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import de.agilecoders.wicket.Bootstrap;
public class DisplayExceptionPage extends WebPage {
private static final long serialVersionUID = 1L;
@@ -36,4 +39,9 @@ public class DisplayExceptionPage extends WebPage {
return t;
}
@Override
public void renderHead(IHeaderResponse response) {
Bootstrap.renderHead(response);
}
}