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

com.google.gerrit.server.account.AccountState Maven / Gradle / Ivy

There is a newer version: 3.10.0-rc4
Show newest version
// Copyright (C) 2009 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 static com.google.gerrit.server.account.ExternalId.SCHEME_MAILTO;
import static com.google.gerrit.server.account.ExternalId.SCHEME_USERNAME;

import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.CurrentUser.PropertyKey;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.WatchConfig.NotifyType;
import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.codec.DecoderException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AccountState {
  private static final Logger logger = LoggerFactory.getLogger(AccountState.class);

  public static final Function ACCOUNT_ID_FUNCTION =
      a -> a.getAccount().getId();

  private final Account account;
  private final Set internalGroups;
  private final Collection externalIds;
  private final Map> projectWatches;
  private Cache, Object> properties;

  public AccountState(
      Account account,
      Set actualGroups,
      Collection externalIds,
      Map> projectWatches) {
    this.account = account;
    this.internalGroups = actualGroups;
    this.externalIds = externalIds;
    this.projectWatches = projectWatches;
    this.account.setUserName(getUserName(externalIds));
  }

  /** Get the cached account metadata. */
  public Account getAccount() {
    return account;
  }

  /**
   * Get the username, if one has been declared for this user.
   *
   * 

The username is the {@link ExternalId} using the scheme {@link ExternalId#SCHEME_USERNAME}. */ public String getUserName() { return account.getUserName(); } public boolean checkPassword(String password, String username) { if (password == null) { return false; } for (ExternalId id : getExternalIds()) { // Only process the "username:$USER" entry, which is unique. if (!id.isScheme(SCHEME_USERNAME) || !username.equals(id.key().id())) { continue; } String hashedStr = id.password(); if (!Strings.isNullOrEmpty(hashedStr)) { try { return HashedPassword.decode(hashedStr).checkPassword(password); } catch (DecoderException e) { logger.error("DecoderException for user {}: {}", username, e.getMessage()); return false; } } } return false; } /** The external identities that identify the account holder. */ public Collection getExternalIds() { return externalIds; } /** The project watches of the account. */ public Map> getProjectWatches() { return projectWatches; } /** The set of groups maintained directly within the Gerrit database. */ public Set getInternalGroups() { return internalGroups; } public static String getUserName(Collection ids) { for (ExternalId extId : ids) { if (extId.isScheme(SCHEME_USERNAME)) { return extId.key().id(); } } return null; } public static Set getEmails(Collection ids) { Set emails = new HashSet<>(); for (ExternalId extId : ids) { if (extId.isScheme(SCHEME_MAILTO)) { emails.add(extId.key().id()); } } return emails; } /** * Lookup a previously stored property. * *

All properties are automatically cleared when the account cache invalidates the {@code * AccountState}. This method is thread-safe. * * @param key unique property key. * @return previously stored value, or {@code null}. */ @Nullable public T get(PropertyKey key) { Cache, Object> p = properties(false); if (p != null) { @SuppressWarnings("unchecked") T value = (T) p.getIfPresent(key); return value; } return null; } /** * Store a property for later retrieval. * *

This method is thread-safe. * * @param key unique property key. * @param value value to store; or {@code null} to clear the value. */ public void put(PropertyKey key, @Nullable T value) { Cache, Object> p = properties(value != null); if (p != null) { @SuppressWarnings("unchecked") PropertyKey k = (PropertyKey) key; if (value != null) { p.put(k, value); } else { p.invalidate(k); } } } private synchronized Cache, Object> properties(boolean allocate) { if (properties == null && allocate) { properties = CacheBuilder.newBuilder() .concurrencyLevel(1) .initialCapacity(16) // Use weakKeys to ensure plugins that garbage collect will also // eventually release data held in any still live AccountState. .weakKeys() .build(); } return properties; } }