All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.aroma.banana.authentication.service.data.TokenRepositoryInMemory Maven / Gradle / Ivy

Go to download

Part of the Banana Service Project. Simplicity is paramount. The Authentication service is responsible for the creation, storage, and verification of Application Tokens and User Tokens.

The newest version!
/*
 * Copyright 2015 Aroma Tech.
 *
 * Licensed 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.
 */

package tech.aroma.banana.authentication.service.data;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tech.aroma.banana.thrift.exceptions.InvalidTokenException;
import tech.sirwellington.alchemy.annotations.designs.patterns.StrategyPattern;

import static java.time.Instant.now;
import static tech.aroma.banana.authentication.service.AuthenticationAssertions.tokenInRepository;
import static tech.sirwellington.alchemy.annotations.designs.patterns.StrategyPattern.Role.CONCRETE_BEHAVIOR;
import static tech.sirwellington.alchemy.arguments.Arguments.checkThat;
import static tech.sirwellington.alchemy.arguments.assertions.Assertions.notNull;
import static tech.sirwellington.alchemy.arguments.assertions.StringAssertions.nonEmptyString;

/**
 *
 * @author SirWellington
 */
@StrategyPattern(role = CONCRETE_BEHAVIOR)
final class TokenRepositoryInMemory implements TokenRepository
{

    private final static Logger LOG = LoggerFactory.getLogger(TokenRepositoryInMemory.class);

    private final Map tokens = Maps.newConcurrentMap();
    private final Map> tokensByOwner = Maps.newConcurrentMap();
    private final Map tokenExpiration = Maps.newConcurrentMap();

    @Override
    public boolean doesTokenExist(String tokenId) throws IllegalArgumentException
    {
        checkThat(tokenId).is(nonEmptyString());

        if (!tokens.containsKey(tokenId))
        {
            return false;
        }

        if (isExpired(tokenId))
        {
            LOG.debug("Token is now expired. Removing it. {}", tokenId);
            removeToken(tokenId);
            return false;
        }
        
        return true;
    }


    @Override
    public Token getToken(String tokenId) throws TException
    {
        checkThat(tokenId)
            .is(nonEmptyString())
            .throwing(InvalidTokenException.class)
            .is(tokenInRepository(this));

        if (isExpired(tokenId))
        {
            removeToken(tokenId);
        }

        return tokens.get(tokenId);
    }

    @Override
    public void saveToken(Token token) throws TException
    {
        checkThat(token)
            .usingMessage("token is null")
            .is(notNull());
        
        checkThat(token.getTokenType())
            .usingMessage("tokenType is required")
            .is(notNull());
        
        Instant expiration = token.getTimeOfExpiration();
        checkThat(expiration)
            .usingMessage("token is missing an expiration date.")
            .is(notNull());
        
        String tokenId = token.getTokenId();
        String ownerId = token.getOwnerId();
        
        checkThat(tokenId, ownerId)
            .usingMessage("tokenId and ownerId must be present in Token")
            .are(nonEmptyString());
            
        tokens.put(tokenId, token);
        tokenExpiration.put(tokenId, expiration);
        
        List ownerTokens = tokensByOwner.getOrDefault(ownerId, Lists.newArrayList());
        ownerTokens.add(token);
        tokensByOwner.put(ownerId, ownerTokens);
    }

    @Override
    public List getTokensBelongingTo(String ownerId) throws IllegalArgumentException
    {
        checkThat(ownerId).is(nonEmptyString());
        
        List allTokens = tokensByOwner.getOrDefault(ownerId, Lists.newArrayList());
        
        //Sending a separate list ensures we send a defensive copy.
        List results = Lists.newArrayList();
        
        for (Token token : allTokens)
        {
            String tokenId = token.getTokenId();
            if (isExpired(tokenId))
            {
                removeToken(tokenId);
                continue;
            }
            results.add(token);
        }
        
        return results;
    }

    @Override
    public void deleteToken(String tokenId) throws IllegalArgumentException
    {
        checkThat(tokenId).is(nonEmptyString());
        
        removeToken(tokenId);
    }

    private boolean isExpired(String tokenId)
    {
        Instant now = now();
        Instant expiration = tokenExpiration.get(tokenId);

        if (expiration == null)
        {
            return false;
        }
        
        return expiration.isBefore(now);
    }

    private void removeToken(String tokenId)
    {
        tokenExpiration.remove(tokenId);
        Token token = tokens.remove(tokenId);
        
        //Token never existed
        if (token == null)
        {
            return;
        }
        
        String ownerId = token.getOwnerId();
        
        List tokens = tokensByOwner.get(ownerId);
        
        if (tokens != null)
        {
            tokens.remove(token);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy