blob: a0c095dbedaf9af6ba795a27d8f0d0c51ee2e444 [file] [log] [blame]
// Copyright (C) 2025 The Android Open Source Project
//
// 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 com.google.gerrit.server.account;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.entities.Account;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
/** Read/write authentication tokens by user ID using a cache for faster access. */
public class CachingAuthTokenAccessor implements AuthTokenAccessor {
public interface Factory {
CachingAuthTokenAccessor create(AuthTokenAccessor accessor);
}
private final AuthTokenCache authTokenCache;
private final AuthTokenAccessor accessor;
@AssistedInject
CachingAuthTokenAccessor(
AuthTokenCache authTokenCache, @Assisted AuthTokenAccessor directAuthTokenAccessor) {
this.authTokenCache = authTokenCache;
this.accessor = directAuthTokenAccessor;
}
@Override
public List<AuthToken> getValidTokens(Account.Id accountId) {
return getTokens(accountId).stream().filter(t -> !t.isExpired()).toList();
}
@Override
public List<AuthToken> getTokens(Account.Id accountId) {
return authTokenCache.get(accountId);
}
@Override
public Optional<AuthToken> getToken(Account.Id accountId, String id) {
return getTokens(accountId).stream().filter(token -> token.id().equals(id)).findFirst();
}
@Override
public synchronized void addTokens(Account.Id accountId, Collection<AuthToken> tokens)
throws IOException, ConfigInvalidException, InvalidAuthTokenException {
accessor.addTokens(accountId, tokens);
authTokenCache.evict(accountId);
}
@Override
@CanIgnoreReturnValue
public synchronized AuthToken addToken(
Account.Id accountId, String id, String hashedToken, Optional<Instant> expiration)
throws IOException, ConfigInvalidException, InvalidAuthTokenException {
AuthToken token = accessor.addToken(accountId, id, hashedToken, expiration);
authTokenCache.evict(accountId);
return token;
}
@Override
public AuthToken addPlainToken(
Account.Id accountId, String id, String token, Optional<Instant> expiration)
throws IOException, ConfigInvalidException, InvalidAuthTokenException {
AuthToken authToken = accessor.addPlainToken(accountId, id, token, expiration);
authTokenCache.evict(accountId);
return authToken;
}
@Override
public void deleteToken(Account.Id accountId, String id)
throws IOException, ConfigInvalidException, InvalidAuthTokenException {
accessor.deleteToken(accountId, id);
authTokenCache.evict(accountId);
}
@Override
public void deleteAllTokens(Account.Id accountId)
throws IOException, ConfigInvalidException, InvalidAuthTokenException {
accessor.deleteAllTokens(accountId);
authTokenCache.evict(accountId);
}
@Override
public void updateToken(Account.Id accountId, AuthToken token)
throws IOException, ConfigInvalidException, InvalidAuthTokenException {
accessor.updateToken(accountId, token);
authTokenCache.evict(accountId);
}
}