blob: baebb320d10d739d7102bf50b67e9d9a98a27ce0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*/
package org.apache.roller.weblogger.business.jpa;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.UUID;
import jakarta.persistence.TypedQuery;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthException;
import net.oauth.OAuthMessage;
import net.oauth.OAuthProblemException;
import net.oauth.OAuthServiceProvider;
import net.oauth.OAuthValidator;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.OAuthManager;
import org.apache.roller.weblogger.business.Weblogger;
import org.apache.roller.weblogger.pojos.OAuthAccessorRecord;
import org.apache.roller.weblogger.pojos.OAuthConsumerRecord;
/**
* JPA based OAuth manager implementation.
*/
public class JPAOAuthManagerImpl implements OAuthManager {
private final Weblogger roller;
private final JPAPersistenceStrategy strategy;
private final OAuthValidator validator;
/**
* The logger instance for this class.
*/
private static final Log log = LogFactory.getFactory().getInstance(JPAOAuthManagerImpl.class);
@com.google.inject.Inject
public JPAOAuthManagerImpl(
Weblogger roller,
JPAPersistenceStrategy strategy,
OAuthValidator validator) {
this.roller = roller;
this.strategy = strategy;
this.validator = validator;
}
@Override
public OAuthServiceProvider getServiceProvider() {
return new OAuthServiceProvider(
roller.getUrlStrategy().getOAuthRequestTokenURL(),
roller.getUrlStrategy().getOAuthAuthorizationURL(),
roller.getUrlStrategy().getOAuthAccessTokenURL());
}
@Override
public OAuthValidator getValidator() {
return validator;
}
@Override
public OAuthConsumer getConsumer(
OAuthMessage requestMessage)
throws IOException, OAuthProblemException {
OAuthConsumer consumer;
// try to load from local cache if not throw exception
String consumer_key = requestMessage.getConsumerKey();
consumer = getConsumerByKey(consumer_key);
if(consumer == null) {
throw new OAuthProblemException("token_rejected");
}
return consumer;
}
/**
* Get the access token and token secret for the given oauth_token.
*/
@Override
public OAuthAccessor getAccessor(OAuthMessage requestMessage)
throws IOException, OAuthProblemException {
String consumerToken = requestMessage.getToken();
OAuthAccessor accessor = null;
if (StringUtils.isNotEmpty(consumerToken)) {
// caller provided a token, it better be good or else
accessor = getAccessorByToken(consumerToken);
if (accessor == null) {
throw new OAuthProblemException("token_expired");
}
}
String consumerKey = requestMessage.getConsumerKey();
if (accessor == null && StringUtils.isNotEmpty(consumerKey)) {
// caller provided contumer key, do we have an accessor yet
accessor = getAccessorByKey(consumerKey);
}
return accessor;
}
/**
* Set the access token
*/
@Override
public void markAsAuthorized(OAuthAccessor accessor, String userId)
throws OAuthException {
try {
OAuthAccessorRecord record = (OAuthAccessorRecord) strategy.load(
OAuthAccessorRecord.class, accessor.consumer.consumerKey);
record.setUserName(userId);
record.setAuthorized(Boolean.TRUE);
strategy.store(record);
} catch (WebloggerException ex) {
throw new OAuthException("ERROR: setting authorization flag", ex);
}
}
/**
* Generate a fresh request token and secret for a consumer.
* @throws OAuthException
*/
@Override
public void generateRequestToken(
OAuthAccessor accessor)
throws OAuthException {
// generate oauth_token and oauth_secret
String consumer_key = accessor.consumer.consumerKey;
// generate token and secret based on consumer_key
// for now use md5 of name + current time as token
String token_data = consumer_key + System.nanoTime();
String token = DigestUtils.md5Hex(token_data);
// for now use md5 of name + current time + token as secret
String secret_data = consumer_key + System.nanoTime() + token;
String secret = DigestUtils.md5Hex(secret_data);
accessor.requestToken = token;
accessor.tokenSecret = secret;
accessor.accessToken = null;
// add to the local cache
addAccessor(accessor);
}
/**
* Generate a fresh request token and secret for a consumer.
* @throws OAuthException
*/
@Override
public void generateAccessToken(OAuthAccessor accessor)
throws OAuthException {
try {
// generate oauth_token and oauth_secret
// generate token and secret based on consumer_key
String consumer_key = accessor.consumer.consumerKey;
OAuthAccessorRecord record = (OAuthAccessorRecord) strategy.load(
OAuthAccessorRecord.class, accessor.consumer.consumerKey);
// for now use md5 of name + current time as token
String token_data = consumer_key + System.nanoTime();
String token = DigestUtils.md5Hex(token_data);
record.setRequestToken(null);
record.setAccessToken(token);
strategy.store(record);
} catch (WebloggerException ex) {
throw new OAuthException("ERROR: generating access token", ex);
}
}
@Override
public OAuthConsumer addConsumer(String username, String consumerKey) throws OAuthException {
OAuthConsumerRecord record = new OAuthConsumerRecord();
record.setConsumerKey(consumerKey);
record.setUserName(username);
record.setConsumerSecret(UUID.randomUUID().toString());
try {
strategy.store(record);
} catch (WebloggerException ex) {
throw new OAuthException("ERROR storing accessor", ex);
}
return new OAuthConsumer(null,
record.getConsumerKey(),
record.getConsumerSecret(),
getServiceProvider());
}
@Override
public OAuthConsumer addConsumer(String consumerKey)
throws OAuthException, WebloggerException {
if (getConsumer() == null) {
return addConsumer(null, consumerKey);
} else {
throw new OAuthException("ERROR: cannot have more than one site-wide consumer");
}
}
@Override
public OAuthConsumer getConsumer() throws WebloggerException {
OAuthConsumerRecord record = null;
try {
TypedQuery<OAuthConsumerRecord> q = strategy.getNamedQuery("OAuthConsumerRecord.getSiteWideConsumer",
OAuthConsumerRecord.class);
record = q.getSingleResult();
} catch (Exception ex) {
log.debug("ERROR fetching site-wide consumer", ex);
}
if (record != null) {
return new OAuthConsumer(
null,
record.getConsumerKey(),
record.getConsumerSecret(),
getServiceProvider());
}
return null;
}
@Override
public OAuthConsumer getConsumerByUsername(String username) throws WebloggerException {
OAuthConsumerRecord record = null;
try {
TypedQuery<OAuthConsumerRecord> q = strategy.getNamedQuery("OAuthConsumerRecord.getByUsername",
OAuthConsumerRecord.class);
q.setParameter(1, username);
record = q.getSingleResult();
} catch (Exception ex) {
log.debug("ERROR fetching consumer", ex);
}
if (record != null) {
OAuthConsumer consumer = new OAuthConsumer(
null,
record.getConsumerKey(),
record.getConsumerSecret(),
getServiceProvider());
consumer.setProperty("userName", record.getUserName());
return consumer;
}
return null;
}
//--------------------------------------------- package protected internals
OAuthConsumer consumerFromRecord(OAuthConsumerRecord record) {
OAuthConsumer consumer = null;
if (record != null) {
consumer = new OAuthConsumer(
null,
record.getConsumerKey(),
record.getConsumerSecret(),
getServiceProvider());
if (record.getUserName() != null) {
consumer.setProperty("userId", record.getUserName());
}
}
return consumer;
}
OAuthAccessor accessorFromRecord(OAuthAccessorRecord record) {
OAuthAccessor accessor = null;
if (record != null) {
accessor =
new OAuthAccessor(getConsumerByKey(record.getConsumerKey()));
accessor.accessToken = record.getAccessToken();
accessor.requestToken = record.getRequestToken();
accessor.tokenSecret = record.getTokenSecret();
if (record.getAuthorized() != null) {
accessor.setProperty("authorized", record.getAuthorized());
}
if (record.getUserName() != null) {
accessor.setProperty("userId", record.getUserName());
}
}
return accessor;
}
OAuthConsumer getConsumerByKey(String consumerKey) {
OAuthConsumerRecord record = null;
try {
TypedQuery<OAuthConsumerRecord> q = strategy.getNamedQuery("OAuthConsumerRecord.getByConsumerKey",
OAuthConsumerRecord.class);
q.setParameter(1, consumerKey);
record = q.getSingleResult();
} catch (Exception ex) {
log.debug("ERROR fetching consumer", ex);
}
return consumerFromRecord(record);
}
void addAccessor(OAuthAccessor accessor) throws OAuthException {
OAuthAccessorRecord record = new OAuthAccessorRecord();
record.setConsumerKey(accessor.consumer.consumerKey);
record.setRequestToken(accessor.requestToken);
record.setAccessToken(accessor.accessToken);
record.setTokenSecret(accessor.tokenSecret);
if (accessor.getProperty("userId") != null) {
record.setUserName((String)accessor.getProperty("userId"));
}
if (record.getCreated() != null) {
record.setCreated(record.getCreated());
} else {
record.setCreated(new Timestamp(new Date().getTime()));
}
if (record.getUpdated() != null) {
record.setUpdated(record.getUpdated());
} else {
record.setUpdated(record.getCreated());
}
if (accessor.getProperty("authorized") != null) {
record.setAuthorized((Boolean)accessor.getProperty("authorized"));
}
try {
strategy.store(record);
} catch (WebloggerException ex) {
throw new OAuthException("ERROR storing accessor", ex);
}
}
OAuthAccessor getAccessorByKey(String consumerKey) {
OAuthAccessorRecord record = null;
try {
TypedQuery<OAuthAccessorRecord> q = strategy.getNamedQuery("OAuthAccessorRecord.getByKey",
OAuthAccessorRecord.class);
q.setParameter(1, consumerKey);
record = q.getSingleResult();
} catch (Exception ex) {
log.debug("ERROR fetching accessor", ex);
}
return accessorFromRecord(record);
}
OAuthAccessor getAccessorByToken(String token) {
OAuthAccessorRecord record = null;
try {
TypedQuery<OAuthAccessorRecord> q = strategy.getNamedQuery("OAuthAccessorRecord.getByToken",
OAuthAccessorRecord.class);
q.setParameter(1, token);
record = q.getSingleResult();
} catch (Exception ex) {
log.debug("ERROR fetching accessor", ex);
}
return accessorFromRecord(record);
}
void removeConsumer(OAuthConsumer consumer) throws OAuthException {
try {
strategy.remove(OAuthConsumerRecord.class, consumer.consumerKey);
} catch (WebloggerException ex) {
throw new OAuthException("ERROR removing consumer", ex);
}
}
void removeAccessor(OAuthAccessor accessor) throws OAuthException {
try {
strategy.remove(OAuthAccessorRecord.class, accessor.consumer.consumerKey);
} catch (WebloggerException ex) {
throw new OAuthException("ERROR removing accessor", ex);
}
}
}