Line data Source code
1 : // Copyright (C) 2015 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.restapi.group; 16 : 17 : import static com.google.common.collect.ImmutableList.toImmutableList; 18 : import static java.util.Comparator.comparing; 19 : 20 : import com.google.gerrit.entities.AccountGroup; 21 : import com.google.gerrit.entities.AccountGroupByIdAudit; 22 : import com.google.gerrit.entities.AccountGroupMemberAudit; 23 : import com.google.gerrit.entities.GroupDescription; 24 : import com.google.gerrit.entities.InternalGroup; 25 : import com.google.gerrit.extensions.common.AccountInfo; 26 : import com.google.gerrit.extensions.common.GroupAuditEventInfo; 27 : import com.google.gerrit.extensions.common.GroupInfo; 28 : import com.google.gerrit.extensions.restapi.AuthException; 29 : import com.google.gerrit.extensions.restapi.Response; 30 : import com.google.gerrit.extensions.restapi.RestReadView; 31 : import com.google.gerrit.extensions.restapi.Url; 32 : import com.google.gerrit.server.account.AccountLoader; 33 : import com.google.gerrit.server.account.GroupBackend; 34 : import com.google.gerrit.server.account.GroupCache; 35 : import com.google.gerrit.server.config.AllUsersName; 36 : import com.google.gerrit.server.git.GitRepositoryManager; 37 : import com.google.gerrit.server.group.GroupResource; 38 : import com.google.gerrit.server.group.InternalGroupDescription; 39 : import com.google.gerrit.server.group.db.Groups; 40 : import com.google.gerrit.server.permissions.PermissionBackendException; 41 : import com.google.inject.Inject; 42 : import com.google.inject.Singleton; 43 : import java.io.IOException; 44 : import java.util.ArrayList; 45 : import java.util.List; 46 : import java.util.Map; 47 : import org.eclipse.jgit.errors.ConfigInvalidException; 48 : import org.eclipse.jgit.lib.Repository; 49 : 50 : @Singleton 51 : public class GetAuditLog implements RestReadView<GroupResource> { 52 : private final AccountLoader.Factory accountLoaderFactory; 53 : private final AllUsersName allUsers; 54 : private final GroupCache groupCache; 55 : private final GroupJson groupJson; 56 : private final GroupBackend groupBackend; 57 : private final Groups groups; 58 : private final GitRepositoryManager repoManager; 59 : 60 : @Inject 61 : public GetAuditLog( 62 : AccountLoader.Factory accountLoaderFactory, 63 : AllUsersName allUsers, 64 : GroupCache groupCache, 65 : GroupJson groupJson, 66 : GroupBackend groupBackend, 67 : Groups groups, 68 146 : GitRepositoryManager repoManager) { 69 146 : this.accountLoaderFactory = accountLoaderFactory; 70 146 : this.allUsers = allUsers; 71 146 : this.groupCache = groupCache; 72 146 : this.groupJson = groupJson; 73 146 : this.groupBackend = groupBackend; 74 146 : this.groups = groups; 75 146 : this.repoManager = repoManager; 76 146 : } 77 : 78 : @Override 79 : public Response<List<? extends GroupAuditEventInfo>> apply(GroupResource rsrc) 80 : throws AuthException, NotInternalGroupException, IOException, ConfigInvalidException, 81 : PermissionBackendException { 82 2 : GroupDescription.Internal group = 83 2 : rsrc.asInternalGroup().orElseThrow(NotInternalGroupException::new); 84 2 : if (!rsrc.getControl().isOwner()) { 85 0 : throw new AuthException("Not group owner"); 86 : } 87 : 88 2 : AccountLoader accountLoader = accountLoaderFactory.create(true); 89 : 90 2 : List<GroupAuditEventInfo> auditEvents = new ArrayList<>(); 91 : 92 2 : try (Repository allUsersRepo = repoManager.openRepository(allUsers)) { 93 : for (AccountGroupMemberAudit auditEvent : 94 2 : groups.getMembersAudit(allUsersRepo, group.getGroupUUID())) { 95 2 : AccountInfo member = accountLoader.get(auditEvent.memberId()); 96 : 97 2 : auditEvents.add( 98 2 : GroupAuditEventInfo.createAddUserEvent( 99 2 : accountLoader.get(auditEvent.addedBy()), auditEvent.addedOn(), member)); 100 : 101 2 : if (!auditEvent.isActive()) { 102 1 : auditEvents.add( 103 1 : GroupAuditEventInfo.createRemoveUserEvent( 104 1 : accountLoader.get(auditEvent.removedBy().orElse(null)), 105 1 : auditEvent.removedOn().orElse(null), 106 : member)); 107 : } 108 2 : } 109 2 : List<AccountGroupByIdAudit> subGroupsAudit = 110 2 : groups.getSubgroupsAudit(allUsersRepo, group.getGroupUUID()); 111 2 : Map<AccountGroup.UUID, InternalGroup> groups = 112 2 : groupCache.get( 113 2 : subGroupsAudit.stream().map(a -> a.includeUuid()).collect(toImmutableList())); 114 2 : for (AccountGroupByIdAudit auditEvent : subGroupsAudit) { 115 1 : AccountGroup.UUID includedGroupUUID = auditEvent.includeUuid(); 116 1 : InternalGroup includedGroup = groups.get(includedGroupUUID); 117 : GroupInfo member; 118 1 : if (includedGroup != null) { 119 1 : member = groupJson.format(new InternalGroupDescription(includedGroup)); 120 : } else { 121 1 : member = new GroupInfo(); 122 1 : member.id = Url.encode(includedGroupUUID.get()); 123 1 : GroupDescription.Basic groupDescription = groupBackend.get(includedGroupUUID); 124 1 : if (groupDescription != null) { 125 1 : member.name = groupDescription.getName(); 126 : } 127 : } 128 : 129 1 : auditEvents.add( 130 1 : GroupAuditEventInfo.createAddGroupEvent( 131 1 : accountLoader.get(auditEvent.addedBy()), auditEvent.addedOn(), member)); 132 : 133 1 : if (!auditEvent.isActive()) { 134 1 : auditEvents.add( 135 1 : GroupAuditEventInfo.createRemoveGroupEvent( 136 1 : accountLoader.get(auditEvent.removedBy().orElse(null)), 137 1 : auditEvent.removedOn().orElse(null), 138 : member)); 139 : } 140 1 : } 141 : } 142 : 143 2 : accountLoader.fill(); 144 : 145 : // sort by date and then reverse so that the newest audit event comes first 146 2 : auditEvents.sort(comparing((GroupAuditEventInfo a) -> a.date).reversed()); 147 2 : return Response.ok(auditEvents); 148 : } 149 : }