| /* |
| * 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); |
| } |
| } |
| } |