Line data Source code
1 : // Copyright (C) 2009 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.account; 16 : 17 : import com.google.auto.value.AutoValue; 18 : import com.google.common.base.MoreObjects; 19 : import com.google.common.collect.ImmutableMap; 20 : import com.google.common.collect.ImmutableSet; 21 : import com.google.gerrit.common.Nullable; 22 : import com.google.gerrit.entities.Account; 23 : import com.google.gerrit.entities.NotifyConfig.NotifyType; 24 : import com.google.gerrit.extensions.client.DiffPreferencesInfo; 25 : import com.google.gerrit.extensions.client.EditPreferencesInfo; 26 : import com.google.gerrit.extensions.client.GeneralPreferencesInfo; 27 : import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey; 28 : import com.google.gerrit.server.account.externalids.ExternalId; 29 : import com.google.gerrit.server.account.externalids.ExternalIdNotes; 30 : import com.google.gerrit.server.account.externalids.ExternalIds; 31 : import com.google.gerrit.server.config.CachedPreferences; 32 : import java.io.IOException; 33 : import java.util.Collection; 34 : import java.util.Optional; 35 : import org.eclipse.jgit.lib.ObjectId; 36 : 37 : /** 38 : * Superset of all information related to an Account. This includes external IDs, project watches, 39 : * and properties from the account config file. AccountState maps one-to-one to Account. 40 : * 41 : * <p>Most callers should not construct AccountStates directly but rather lookup accounts via the 42 : * account cache (see {@link AccountCache#get(Account.Id)}). 43 : */ 44 : @AutoValue 45 152 : public abstract class AccountState { 46 : /** 47 : * Creates an AccountState from the given account config. 48 : * 49 : * @param externalIds class to access external IDs 50 : * @param accountConfig the account config, must already be loaded 51 : * @param defaultPreferences the default preferences for this Gerrit installation 52 : * @return the account state, {@link Optional#empty()} if the account doesn't exist 53 : * @throws IOException if accessing the external IDs fails 54 : */ 55 : public static Optional<AccountState> fromAccountConfig( 56 : ExternalIds externalIds, AccountConfig accountConfig, CachedPreferences defaultPreferences) 57 : throws IOException { 58 145 : return fromAccountConfig(externalIds, accountConfig, null, defaultPreferences); 59 : } 60 : 61 : /** 62 : * Creates an AccountState from the given account config. 63 : * 64 : * <p>If external ID notes are provided the revision of the external IDs branch from which the 65 : * external IDs for the account should be loaded is taken from the external ID notes. If external 66 : * ID notes are not given the revision of the external IDs branch is taken from the account 67 : * config. Updating external IDs is done via {@link ExternalIdNotes} and if external IDs were 68 : * updated the revision of the external IDs branch in account config is outdated. Hence after 69 : * updating external IDs the external ID notes must be provided. 70 : * 71 : * @param externalIds class to access external IDs 72 : * @param accountConfig the account config, must already be loaded 73 : * @param extIdNotes external ID notes, must already be loaded, may be {@code null} 74 : * @param defaultPreferences the default preferences for this Gerrit installation 75 : * @return the account state, {@link Optional#empty()} if the account doesn't exist 76 : * @throws IOException if accessing the external IDs fails 77 : */ 78 : public static Optional<AccountState> fromAccountConfig( 79 : ExternalIds externalIds, 80 : AccountConfig accountConfig, 81 : @Nullable ExternalIdNotes extIdNotes, 82 : CachedPreferences defaultPreferences) 83 : throws IOException { 84 151 : if (!accountConfig.getLoadedAccount().isPresent()) { 85 4 : return Optional.empty(); 86 : } 87 151 : Account account = accountConfig.getLoadedAccount().get(); 88 : 89 : Optional<ObjectId> extIdsRev = 90 151 : extIdNotes != null 91 151 : ? Optional.ofNullable(extIdNotes.getRevision()) 92 151 : : accountConfig.getExternalIdsRev(); 93 : ImmutableSet<ExternalId> extIds = 94 151 : extIdsRev.isPresent() 95 151 : ? externalIds.byAccount(account.id(), extIdsRev.get()) 96 151 : : ImmutableSet.of(); 97 : 98 : // Don't leak references to AccountConfig into the AccountState, since it holds a reference to 99 : // an open Repository instance. 100 151 : ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyType>> projectWatches = 101 151 : accountConfig.getProjectWatches(); 102 : 103 151 : return Optional.of( 104 : new AutoValue_AccountState( 105 : account, 106 : extIds, 107 151 : ExternalId.getUserName(extIds), 108 : projectWatches, 109 151 : Optional.of(defaultPreferences), 110 151 : Optional.of(accountConfig.asCachedPreferences()))); 111 : } 112 : 113 : /** 114 : * Creates an AccountState for a given account with no external IDs, no project watches and 115 : * default preferences. 116 : * 117 : * @param account the account 118 : * @return the account state 119 : */ 120 : public static AccountState forAccount(Account account) { 121 151 : return forAccount(account, ImmutableSet.of()); 122 : } 123 : 124 : /** 125 : * Creates an AccountState for a given account and external IDs. 126 : * 127 : * @param account the account 128 : * @return the account state 129 : */ 130 : public static AccountState forCachedAccount( 131 : CachedAccountDetails account, CachedPreferences defaultConfig, ExternalIds externalIds) 132 : throws IOException { 133 151 : ImmutableSet<ExternalId> extIds = externalIds.byAccount(account.account().id()); 134 151 : return new AutoValue_AccountState( 135 151 : account.account(), 136 : extIds, 137 151 : ExternalId.getUserName(extIds), 138 151 : account.projectWatches(), 139 151 : Optional.of(defaultConfig), 140 151 : Optional.of(account.preferences())); 141 : } 142 : 143 : /** 144 : * Creates an AccountState for a given account with no project watches and default preferences. 145 : * 146 : * @param account the account 147 : * @param extIds the external IDs 148 : * @return the account state 149 : */ 150 : public static AccountState forAccount(Account account, Collection<ExternalId> extIds) { 151 152 : return new AutoValue_AccountState( 152 : account, 153 152 : ImmutableSet.copyOf(extIds), 154 152 : ExternalId.getUserName(extIds), 155 152 : ImmutableMap.of(), 156 152 : Optional.empty(), 157 152 : Optional.empty()); 158 : } 159 : 160 : /** Get the cached account metadata. */ 161 : public abstract Account account(); 162 : /** The external identities that identify the account holder. */ 163 : public abstract ImmutableSet<ExternalId> externalIds(); 164 : /** 165 : * Get the username, if one has been declared for this user. 166 : * 167 : * <p>The username is the {@link ExternalId} using the scheme {@link ExternalId#SCHEME_USERNAME}. 168 : * 169 : * @return the username, {@link Optional#empty()} if the user has no username, or if the username 170 : * is empty 171 : */ 172 : public abstract Optional<String> userName(); 173 : /** The project watches of the account. */ 174 : public abstract ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyType>> projectWatches(); 175 : /** The general preferences of the account. */ 176 : 177 : /** The general preferences of the account. */ 178 : public GeneralPreferencesInfo generalPreferences() { 179 106 : return CachedPreferences.general( 180 106 : defaultPreferences(), userPreferences().orElse(CachedPreferences.EMPTY)); 181 : } 182 : 183 : /** The diff preferences of the account. */ 184 : public DiffPreferencesInfo diffPreferences() { 185 1 : return CachedPreferences.diff( 186 1 : defaultPreferences(), userPreferences().orElse(CachedPreferences.EMPTY)); 187 : } 188 : 189 : /** The edit preferences of the account. */ 190 : public EditPreferencesInfo editPreferences() { 191 1 : return CachedPreferences.edit( 192 1 : defaultPreferences(), userPreferences().orElse(CachedPreferences.EMPTY)); 193 : } 194 : 195 : @Override 196 : public final String toString() { 197 0 : MoreObjects.ToStringHelper h = MoreObjects.toStringHelper(this); 198 0 : h.addValue(account().id()); 199 0 : return h.toString(); 200 : } 201 : 202 : /** Gerrit's default preferences as stored in {@code preferences.config}. */ 203 : protected abstract Optional<CachedPreferences> defaultPreferences(); 204 : 205 : /** User preferences as stored in {@code preferences.config}. */ 206 : protected abstract Optional<CachedPreferences> userPreferences(); 207 : }