3 * Copyright (C) 2009-2022 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.tester;
22 import com.google.common.collect.HashMultimap;
23 import com.google.common.collect.ImmutableSet;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.HashSet;
28 import java.util.Optional;
30 import java.util.stream.Collectors;
31 import org.sonar.api.web.UserRole;
32 import org.sonar.db.component.ComponentDto;
33 import org.sonar.db.permission.GlobalPermission;
34 import org.sonar.db.portfolio.PortfolioDto;
35 import org.sonar.db.project.ProjectDto;
36 import org.sonar.server.user.AbstractUserSession;
38 import static com.google.common.base.Preconditions.checkArgument;
40 public abstract class AbstractMockUserSession<T extends AbstractMockUserSession> extends AbstractUserSession {
41 private static final Set<String> PUBLIC_PERMISSIONS = ImmutableSet.of(UserRole.USER, UserRole.CODEVIEWER); // FIXME to check with Simon
43 private final Class<T> clazz;
44 private final HashMultimap<String, String> projectUuidByPermission = HashMultimap.create();
45 private final Set<GlobalPermission> permissions = new HashSet<>();
46 private final Map<String, String> projectUuidByComponentUuid = new HashMap<>();
47 private final Map<String, Set<String>> applicationProjects = new HashMap<>();
48 private final Map<String, Set<String>> portfolioProjects = new HashMap<>();
49 private final Set<String> projectPermissions = new HashSet<>();
50 private boolean systemAdministrator = false;
51 private boolean resetPassword = false;
53 protected AbstractMockUserSession(Class<T> clazz) {
57 public T addPermission(GlobalPermission permission) {
58 permissions.add(permission);
59 return clazz.cast(this);
63 protected boolean hasPermissionImpl(GlobalPermission permission) {
64 return permissions.contains(permission);
68 * Use this method to register public root component and non root components the UserSession must be aware of.
69 * (ie. this method can be used to emulate the content of the DB)
71 public T registerComponents(ComponentDto... components) {
72 Arrays.stream(components)
73 .forEach(component -> {
74 if (component.projectUuid().equals(component.uuid()) && !component.isPrivate()) {
75 this.projectUuidByPermission.put(UserRole.USER, component.uuid());
76 this.projectUuidByPermission.put(UserRole.CODEVIEWER, component.uuid());
77 this.projectPermissions.add(UserRole.USER);
78 this.projectPermissions.add(UserRole.CODEVIEWER);
80 this.projectUuidByComponentUuid.put(component.uuid(), component.projectUuid());
82 return clazz.cast(this);
85 public T registerProjects(ProjectDto... projects) {
86 Arrays.stream(projects)
88 if (!project.isPrivate()) {
89 this.projectUuidByPermission.put(UserRole.USER, project.getUuid());
90 this.projectUuidByPermission.put(UserRole.CODEVIEWER, project.getUuid());
91 this.projectPermissions.add(UserRole.USER);
92 this.projectPermissions.add(UserRole.CODEVIEWER);
94 this.projectUuidByComponentUuid.put(project.getUuid(), project.getUuid());
96 return clazz.cast(this);
99 public T registerApplication(ComponentDto application, ComponentDto... appProjects) {
100 registerComponents(application);
101 registerComponents(appProjects);
103 var appProjectsUuid = Arrays.stream(appProjects)
104 .map(ComponentDto::uuid)
105 .collect(Collectors.toSet());
106 this.applicationProjects.put(application.uuid(), appProjectsUuid);
108 return clazz.cast(this);
111 public T registerApplication(ProjectDto application, ProjectDto... appProjects) {
112 registerProjects(application);
113 registerProjects(appProjects);
115 var appProjectsUuid = Arrays.stream(appProjects)
116 .map(ProjectDto::getUuid)
117 .collect(Collectors.toSet());
118 this.applicationProjects.put(application.getUuid(), appProjectsUuid);
120 return clazz.cast(this);
123 public T registerPortfolios(PortfolioDto... portfolios) {
124 Arrays.stream(portfolios)
125 .forEach(portfolio -> {
126 if (!portfolio.isPrivate()) {
127 this.projectUuidByPermission.put(UserRole.USER, portfolio.getUuid());
128 this.projectUuidByPermission.put(UserRole.CODEVIEWER, portfolio.getUuid());
129 this.projectPermissions.add(UserRole.USER);
130 this.projectPermissions.add(UserRole.CODEVIEWER);
132 this.projectUuidByComponentUuid.put(portfolio.getUuid(), portfolio.getUuid());
134 return clazz.cast(this);
137 public T registerPortfolioProjects(PortfolioDto portfolio, ProjectDto... portfolioProjects) {
138 registerPortfolios(portfolio);
139 registerProjects(portfolioProjects);
141 Set<String> portfolioProjectsUuid = Arrays.stream(portfolioProjects)
142 .map(ProjectDto::getUuid)
143 .collect(Collectors.toSet());
145 this.portfolioProjects.put(portfolio.getUuid(), portfolioProjectsUuid);
147 return clazz.cast(this);
150 public T addProjectPermission(String permission, ComponentDto... components) {
151 Arrays.stream(components).forEach(component -> {
153 component.isPrivate() || !PUBLIC_PERMISSIONS.contains(permission),
154 "public component %s can't be granted public permission %s", component.uuid(), permission);
156 registerComponents(components);
157 this.projectPermissions.add(permission);
158 Arrays.stream(components)
159 .forEach(component -> this.projectUuidByPermission.put(permission, component.projectUuid()));
160 return clazz.cast(this);
163 public T addProjectPermission(String permission, ProjectDto... projects) {
164 Arrays.stream(projects).forEach(component -> {
166 component.isPrivate() || !PUBLIC_PERMISSIONS.contains(permission),
167 "public component %s can't be granted public permission %s", component.getUuid(), permission);
169 registerProjects(projects);
170 this.projectPermissions.add(permission);
171 Arrays.stream(projects)
172 .forEach(project -> this.projectUuidByPermission.put(permission, project.getUuid()));
173 return clazz.cast(this);
176 public T addPortfolioPermission(String permission, PortfolioDto... portfolios) {
177 Arrays.stream(portfolios).forEach(component -> {
179 component.isPrivate() || !PUBLIC_PERMISSIONS.contains(permission),
180 "public component %s can't be granted public permission %s", component.getUuid(), permission);
182 registerPortfolios(portfolios);
183 this.projectPermissions.add(permission);
184 Arrays.stream(portfolios)
185 .forEach(portfolio -> this.projectUuidByPermission.put(permission, portfolio.getUuid()));
186 return clazz.cast(this);
190 protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
191 return Optional.ofNullable(projectUuidByComponentUuid.get(componentUuid));
195 protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
196 return projectPermissions.contains(permission) && projectUuidByPermission.get(permission).contains(projectUuid);
200 protected boolean hasChildProjectsPermission(String permission, String applicationUuid) {
201 return applicationProjects.containsKey(applicationUuid) && applicationProjects.get(applicationUuid)
203 .allMatch(projectUuid -> projectPermissions.contains(permission) && projectUuidByPermission.get(permission).contains(projectUuid));
207 protected boolean hasPortfolioChildProjectsPermission(String permission, String portfolioUuid) {
208 return portfolioProjects.containsKey(portfolioUuid) && portfolioProjects.get(portfolioUuid)
210 .allMatch(projectUuid -> projectPermissions.contains(permission) && projectUuidByPermission.get(permission).contains(projectUuid));
213 public T setSystemAdministrator(boolean b) {
214 this.systemAdministrator = b;
215 return clazz.cast(this);
219 public boolean isSystemAdministrator() {
220 return systemAdministrator;
223 public T setResetPassword(boolean b) {
224 this.resetPassword = b;
225 return clazz.cast(this);
229 public boolean shouldResetPassword() {
230 return resetPassword;