You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

UserSessionRule.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  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.
  10. *
  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.
  15. *
  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.
  19. */
  20. package org.sonar.server.tester;
  21. import com.google.common.base.Preconditions;
  22. import java.util.Collection;
  23. import java.util.List;
  24. import java.util.Optional;
  25. import javax.annotation.CheckForNull;
  26. import javax.annotation.Nullable;
  27. import org.junit.rules.TestRule;
  28. import org.junit.runner.Description;
  29. import org.junit.runners.model.Statement;
  30. import org.sonar.db.component.ComponentDto;
  31. import org.sonar.db.permission.OrganizationPermission;
  32. import org.sonar.db.project.ProjectDto;
  33. import org.sonar.db.user.GroupDto;
  34. import org.sonar.db.user.UserDto;
  35. import org.sonar.server.user.UserSession;
  36. import static com.google.common.base.Preconditions.checkNotNull;
  37. import static com.google.common.base.Preconditions.checkState;
  38. /**
  39. * {@code UserSessionRule} is intended to be used as a {@link org.junit.Rule} to easily manage {@link UserSession} in
  40. * unit tests.
  41. * <p>
  42. * It can be used as a {@link org.junit.ClassRule} but be careful not to modify its states from inside tests methods
  43. * unless you purposely want to have side effects between each tests.
  44. * </p>
  45. * <p>
  46. * One can define user session behavior which should apply on all tests directly on the property, eg.:
  47. * <pre>
  48. * {@literal @}Rule
  49. * public UserSessionRule userSession = UserSessionRule.standalone().login("admin").setOrganizationPermissions(OrganizationPermissions.SYSTEM_ADMIN);
  50. * </pre>
  51. * </p>
  52. * <p>
  53. * Behavior defined at property-level can obviously be override at test method level. For example, one could define
  54. * all methods to use an authenticated session such as presented above but can easily overwrite that behavior in a
  55. * specific test method as follow:
  56. * <pre>
  57. * {@literal @}Test
  58. * public void test_method() {
  59. * userSession.standalone();
  60. * {@literal [...]}
  61. * }
  62. * </pre>
  63. * </p>
  64. * <p>
  65. * {@code UserSessionRule}, emulates by default an anonymous
  66. * session. Therefore, call {@code UserSessionRule.standalone()} is equivalent to calling
  67. * {@code UserSessionRule.standalone().anonymous()}.
  68. * </p>
  69. * <p>
  70. * To emulate an identified user, either use method {@link #logIn(String)} if you want to specify the user's login, or
  71. * method {@link #logIn()} which will do the same but using the value of {@link #DEFAULT_LOGIN} as the user's login
  72. * (use the latest override if you don't care about the actual value of the login, it will save noise in your test).
  73. * </p>
  74. */
  75. public class UserSessionRule implements TestRule, UserSession {
  76. private static final String DEFAULT_LOGIN = "default_login";
  77. private UserSession currentUserSession;
  78. private UserSessionRule() {
  79. anonymous();
  80. }
  81. public static UserSessionRule standalone() {
  82. return new UserSessionRule();
  83. }
  84. /**
  85. * Log in with the default login {@link #DEFAULT_LOGIN}
  86. */
  87. public UserSessionRule logIn() {
  88. return logIn(DEFAULT_LOGIN);
  89. }
  90. /**
  91. * Log in with the specified login
  92. */
  93. public UserSessionRule logIn(String login) {
  94. setCurrentUserSession(new MockUserSession(login));
  95. return this;
  96. }
  97. /**
  98. * Log in with the specified login
  99. */
  100. public UserSessionRule logIn(UserDto userDto) {
  101. setCurrentUserSession(new MockUserSession(userDto));
  102. return this;
  103. }
  104. /**
  105. * Disconnect/go anonymous
  106. */
  107. public UserSessionRule anonymous() {
  108. setCurrentUserSession(new AnonymousMockUserSession());
  109. return this;
  110. }
  111. public UserSessionRule setRoot() {
  112. ensureMockUserSession().setRoot(true);
  113. return this;
  114. }
  115. public UserSessionRule setNonRoot() {
  116. ensureMockUserSession().setRoot(false);
  117. return this;
  118. }
  119. public UserSessionRule setSystemAdministrator() {
  120. ensureMockUserSession().setSystemAdministrator(true);
  121. return this;
  122. }
  123. public UserSessionRule setNonSystemAdministrator() {
  124. ensureMockUserSession().setSystemAdministrator(false);
  125. return this;
  126. }
  127. public UserSessionRule setExternalIdentity(IdentityProvider identityProvider, ExternalIdentity externalIdentity) {
  128. ensureMockUserSession().setExternalIdentity(identityProvider, externalIdentity);
  129. return this;
  130. }
  131. public UserSessionRule setInternalIdentity() {
  132. ensureMockUserSession().setInternalIdentity();
  133. return this;
  134. }
  135. @Override
  136. public Statement apply(Statement statement, Description description) {
  137. return this.statement(statement);
  138. }
  139. private Statement statement(final Statement base) {
  140. return new Statement() {
  141. public void evaluate() throws Throwable {
  142. UserSessionRule.this.before();
  143. try {
  144. base.evaluate();
  145. } finally {
  146. UserSessionRule.this.after();
  147. }
  148. }
  149. };
  150. }
  151. protected void before() {
  152. setCurrentUserSession(currentUserSession);
  153. }
  154. protected void after() {
  155. this.currentUserSession = null;
  156. }
  157. public void set(UserSession userSession) {
  158. checkNotNull(userSession);
  159. setCurrentUserSession(userSession);
  160. }
  161. public UserSessionRule registerComponents(ComponentDto... componentDtos) {
  162. ensureAbstractMockUserSession().registerComponents(componentDtos);
  163. return this;
  164. }
  165. public UserSessionRule addProjectPermission(String projectPermission, ComponentDto... components) {
  166. ensureAbstractMockUserSession().addProjectPermission(projectPermission, components);
  167. return this;
  168. }
  169. public UserSessionRule addProjectPermission(String projectPermission, ProjectDto projectDto) {
  170. ensureAbstractMockUserSession().addProjectPermission(projectPermission, projectDto);
  171. return this;
  172. }
  173. public UserSessionRule addPermission(OrganizationPermission permission) {
  174. ensureAbstractMockUserSession().addPermission(permission);
  175. return this;
  176. }
  177. /**
  178. * Groups that user is member of. User must be logged in. An exception
  179. * is thrown if session is anonymous.
  180. */
  181. public UserSessionRule setGroups(GroupDto... groups) {
  182. ensureMockUserSession().setGroups(groups);
  183. return this;
  184. }
  185. public UserSessionRule setName(@Nullable String s) {
  186. ensureMockUserSession().setName(s);
  187. return this;
  188. }
  189. private AbstractMockUserSession ensureAbstractMockUserSession() {
  190. checkState(currentUserSession instanceof AbstractMockUserSession, "rule state can not be changed if a UserSession has explicitly been provided");
  191. return (AbstractMockUserSession) currentUserSession;
  192. }
  193. private MockUserSession ensureMockUserSession() {
  194. checkState(currentUserSession instanceof MockUserSession, "rule state can not be changed if a UserSession has explicitly been provided");
  195. return (MockUserSession) currentUserSession;
  196. }
  197. private void setCurrentUserSession(UserSession userSession) {
  198. this.currentUserSession = Preconditions.checkNotNull(userSession);
  199. }
  200. @Override
  201. public boolean hasComponentPermission(String permission, ComponentDto component) {
  202. return currentUserSession.hasComponentPermission(permission, component);
  203. }
  204. @Override
  205. public boolean hasProjectPermission(String permission, ProjectDto project) {
  206. return currentUserSession.hasProjectPermission(permission, project);
  207. }
  208. @Override
  209. public boolean hasComponentUuidPermission(String permission, String componentUuid) {
  210. return currentUserSession.hasComponentUuidPermission(permission, componentUuid);
  211. }
  212. @Override
  213. public List<ComponentDto> keepAuthorizedComponents(String permission, Collection<ComponentDto> components) {
  214. return currentUserSession.keepAuthorizedComponents(permission, components);
  215. }
  216. @Override
  217. public List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects) {
  218. return currentUserSession.keepAuthorizedProjects(permission, projects);
  219. }
  220. @Override
  221. @CheckForNull
  222. public String getLogin() {
  223. return currentUserSession.getLogin();
  224. }
  225. @Override
  226. @CheckForNull
  227. public String getUuid() {
  228. return currentUserSession.getUuid();
  229. }
  230. @Override
  231. @CheckForNull
  232. public String getName() {
  233. return currentUserSession.getName();
  234. }
  235. @Override
  236. public Collection<GroupDto> getGroups() {
  237. return currentUserSession.getGroups();
  238. }
  239. @Override
  240. public Optional<IdentityProvider> getIdentityProvider() {
  241. return currentUserSession.getIdentityProvider();
  242. }
  243. @Override
  244. public Optional<ExternalIdentity> getExternalIdentity() {
  245. return currentUserSession.getExternalIdentity();
  246. }
  247. @Override
  248. public boolean isLoggedIn() {
  249. return currentUserSession.isLoggedIn();
  250. }
  251. @Override
  252. public boolean isRoot() {
  253. return currentUserSession.isRoot();
  254. }
  255. @Override
  256. public UserSession checkIsRoot() {
  257. return currentUserSession.checkIsRoot();
  258. }
  259. @Override
  260. public UserSession checkLoggedIn() {
  261. currentUserSession.checkLoggedIn();
  262. return this;
  263. }
  264. @Override
  265. public boolean hasPermission(OrganizationPermission permission) {
  266. return currentUserSession.hasPermission(permission);
  267. }
  268. @Override
  269. public UserSession checkPermission(OrganizationPermission permission) {
  270. currentUserSession.checkPermission(permission);
  271. return this;
  272. }
  273. @Override
  274. public UserSession checkComponentPermission(String projectPermission, ComponentDto component) {
  275. currentUserSession.checkComponentPermission(projectPermission, component);
  276. return this;
  277. }
  278. @Override
  279. public UserSession checkProjectPermission(String projectPermission, ProjectDto project) {
  280. currentUserSession.checkProjectPermission(projectPermission, project);
  281. return this;
  282. }
  283. @Override
  284. public UserSession checkComponentUuidPermission(String permission, String componentUuid) {
  285. currentUserSession.checkComponentUuidPermission(permission, componentUuid);
  286. return this;
  287. }
  288. @Override
  289. public boolean isSystemAdministrator() {
  290. return currentUserSession.isSystemAdministrator();
  291. }
  292. @Override
  293. public UserSession checkIsSystemAdministrator() {
  294. currentUserSession.checkIsSystemAdministrator();
  295. return this;
  296. }
  297. }