Project

General

Profile

Download (3.81 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2021 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.api.security;
10

    
11
import java.security.SecureRandom;
12
import java.util.Base64;
13
import java.util.Base64.Encoder;
14
import java.util.Date;
15
import java.util.HashMap;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Optional;
19
import java.util.stream.Collectors;
20

    
21
import org.apache.log4j.Logger;
22

    
23
import eu.etaxonomy.cdm.model.permission.User;
24

    
25
/**
26
 * @author a.kohlbecker
27
 * @since Nov 18, 2021
28
 */
29
public abstract class AbstractRequestTokenStore<T extends AbstractRequestToken>  implements IAbstractRequestTokenStore<T> {
30

    
31
    public static final int TOKEN_LENGTH = 50;
32
    protected static Logger logger = Logger.getLogger(AbstractRequestTokenStore.class);
33
    protected Map<String, T> tokenList = new HashMap<>();
34
    private Integer tokenLifetimeMinutes = null;
35

    
36

    
37
    @Override
38
    public T create(User user) {
39
        clearExpiredTokens();
40
        assert user != null;
41
        assert !user.getEmailAddress().isEmpty();
42
        String randomToken = generateRandomToken();
43
        int tokenLifetimeMinutes = getTokenLifetimeMinutes();
44
        T token = createNewToken(user, randomToken, tokenLifetimeMinutes);
45
        tokenList.put(token.getToken(), token);
46
        return token;
47
    }
48

    
49
    protected String generateRandomToken() {
50
        SecureRandom random = new SecureRandom();
51
        byte bytes[] = new byte[TOKEN_LENGTH];
52
        random.nextBytes(bytes);
53
        Encoder encoder = Base64.getUrlEncoder().withoutPadding();
54
        String token = encoder.encodeToString(bytes);
55
        return token;
56
    }
57

    
58
    @Override
59
    public Optional<T> findResetRequest(String token) {
60
        clearExpiredTokens();
61
        T resetRequest = tokenList.get(token);
62
        if(isEligibleResetRequest(resetRequest)) {
63
            return Optional.of(resetRequest);
64
        }
65
        return Optional.empty();
66
    }
67

    
68
    @Override
69
    public boolean isEligibleToken(String token) {
70
        clearExpiredTokens();
71
        T resetRequest = tokenList.get(token);
72
        return isEligibleResetRequest(resetRequest);
73
    }
74

    
75
    protected boolean isEligibleResetRequest(T resetRequest) {
76
        if(resetRequest == null) {
77
            logger.info("isEligibleToken() : PasswordResetRequest must not be null");
78
            return false;
79
        }
80
        if(resetRequest.getExpiryDate().before(new Date())) {
81
            tokenList.remove(resetRequest.getToken());
82
            logger.info("isEligibleToken() : Token is expired, and has been deleted now.");
83
            return false;
84
        }
85
        return true;
86
    }
87

    
88
    /**
89
     * To be called periodically to remove expired tokens.
90
     *
91
     * @return the number of expired tokens that have been cleared
92
     */
93
    protected int clearExpiredTokens() {
94
        Date now = new Date();
95
        List<String> expiredTokens = tokenList.values().stream().filter(t -> t.getExpiryDate().before(now)).map(t -> t.getToken()).collect(Collectors.toList());
96
        expiredTokens.stream().forEach(tstr -> tokenList.remove(tstr));
97
        return expiredTokens.size();
98
    }
99

    
100
    /**
101
     * Removes the token from the store
102
     *
103
     * @param token
104
     * @return true if the token to be remove has existed, otherwise false
105
     */
106
    @Override
107
    public boolean remove(String token) {
108
        clearExpiredTokens();
109
        return tokenList.remove(token) != null;
110
    }
111

    
112
    public int getTokenLifetimeMinutes() {
113
        return this.tokenLifetimeMinutes != null ? this.tokenLifetimeMinutes : TOKEN_LIFETIME_MINUTES_DEFAULT;
114
    }
115

    
116
    @Override
117
    public void setTokenLifetimeMinutes(int tokenLifetimeMinutes) {
118
        this.tokenLifetimeMinutes = tokenLifetimeMinutes;
119
    }
120

    
121

    
122
}
(2-2/7)