Line data Source code
1 : // Copyright (C) 2018 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.externalids; 16 : 17 : import com.google.auto.value.AutoValue; 18 : import com.google.common.base.Strings; 19 : import com.google.common.collect.ImmutableMap; 20 : import com.google.common.collect.ImmutableSetMultimap; 21 : import com.google.gerrit.entities.Account; 22 : import com.google.gerrit.proto.Protos; 23 : import com.google.gerrit.server.cache.proto.Cache.AllExternalIdsProto; 24 : import com.google.gerrit.server.cache.proto.Cache.AllExternalIdsProto.ExternalIdProto; 25 : import com.google.gerrit.server.cache.serialize.CacheSerializer; 26 : import com.google.gerrit.server.cache.serialize.ObjectIdConverter; 27 : import java.util.stream.Stream; 28 : 29 : /** Cache value containing all external IDs. */ 30 : @AutoValue 31 151 : public abstract class AllExternalIds { 32 : static AllExternalIds create(Stream<ExternalId> externalIds) { 33 151 : ImmutableMap.Builder<ExternalId.Key, ExternalId> byKey = ImmutableMap.builder(); 34 151 : ImmutableSetMultimap.Builder<Account.Id, ExternalId> byAccount = ImmutableSetMultimap.builder(); 35 151 : ImmutableSetMultimap.Builder<String, ExternalId> byEmail = ImmutableSetMultimap.builder(); 36 151 : externalIds.forEach( 37 : id -> { 38 151 : byKey.put(id.key(), id); 39 151 : byAccount.put(id.accountId(), id); 40 151 : if (!Strings.isNullOrEmpty(id.email())) { 41 139 : byEmail.put(id.email(), id); 42 : } 43 151 : }); 44 : 45 151 : return new AutoValue_AllExternalIds(byKey.build(), byAccount.build(), byEmail.build()); 46 : } 47 : 48 : static AllExternalIds create( 49 : ImmutableMap<ExternalId.Key, ExternalId> byKey, 50 : ImmutableSetMultimap<Account.Id, ExternalId> byAccount, 51 : ImmutableSetMultimap<String, ExternalId> byEmail) { 52 147 : return new AutoValue_AllExternalIds(byKey, byAccount, byEmail); 53 : } 54 : 55 : public abstract ImmutableMap<ExternalId.Key, ExternalId> byKey(); 56 : 57 : public abstract ImmutableSetMultimap<Account.Id, ExternalId> byAccount(); 58 : 59 : public abstract ImmutableSetMultimap<String, ExternalId> byEmail(); 60 : 61 152 : enum Serializer implements CacheSerializer<AllExternalIds> { 62 152 : INSTANCE; 63 : 64 : @Override 65 : public byte[] serialize(AllExternalIds object) { 66 1 : ObjectIdConverter idConverter = ObjectIdConverter.create(); 67 1 : AllExternalIdsProto.Builder allBuilder = AllExternalIdsProto.newBuilder(); 68 1 : object.byAccount().values().stream() 69 1 : .map(extId -> toProto(idConverter, extId)) 70 1 : .forEach(allBuilder::addExternalId); 71 1 : return Protos.toByteArray(allBuilder.build()); 72 : } 73 : 74 : private static ExternalIdProto toProto(ObjectIdConverter idConverter, ExternalId externalId) { 75 : ExternalIdProto.Builder b = 76 1 : ExternalIdProto.newBuilder() 77 1 : .setKey(externalId.key().get()) 78 1 : .setAccountId(externalId.accountId().get()) 79 1 : .setIsCaseInsensitive(externalId.isCaseInsensitive()); 80 1 : if (externalId.email() != null) { 81 1 : b.setEmail(externalId.email()); 82 : } 83 1 : if (externalId.password() != null) { 84 1 : b.setPassword(externalId.password()); 85 : } 86 1 : if (externalId.blobId() != null) { 87 1 : b.setBlobId(idConverter.toByteString(externalId.blobId())); 88 : } 89 1 : return b.build(); 90 : } 91 : 92 : @Override 93 : public AllExternalIds deserialize(byte[] in) { 94 1 : ObjectIdConverter idConverter = ObjectIdConverter.create(); 95 1 : return create( 96 1 : Protos.parseUnchecked(AllExternalIdsProto.parser(), in).getExternalIdList().stream() 97 1 : .map(proto -> toExternalId(idConverter, proto))); 98 : } 99 : 100 : private static ExternalId toExternalId(ObjectIdConverter idConverter, ExternalIdProto proto) { 101 1 : return ExternalId.create( 102 1 : ExternalId.Key.parse(proto.getKey(), proto.getIsCaseInsensitive()), 103 1 : Account.id(proto.getAccountId()), 104 : // ExternalId treats null and empty strings the same, so no need to distinguish here. 105 1 : proto.getEmail(), 106 1 : proto.getPassword(), 107 1 : !proto.getBlobId().isEmpty() ? idConverter.fromByteString(proto.getBlobId()) : null); 108 : } 109 : } 110 : }