1   /*
2    * Copyright (C) 2010 Atlassian
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package it;
18  
19  import com.atlassian.jira.rest.client.BasicComponentNameExtractionFunction;
20  import com.atlassian.jira.rest.client.IntegrationTestUtil;
21  import com.atlassian.jira.rest.client.IterableMatcher;
22  import com.atlassian.jira.rest.client.TestUtil;
23  import com.atlassian.jira.rest.client.annotation.Restore;
24  import com.atlassian.jira.rest.client.domain.AssigneeType;
25  import com.atlassian.jira.rest.client.domain.BasicComponent;
26  import com.atlassian.jira.rest.client.domain.Component;
27  import com.atlassian.jira.rest.client.domain.input.ComponentInput;
28  import com.atlassian.jira.rest.client.internal.ServerVersionConstants;
29  import com.atlassian.jira.rest.client.internal.json.TestConstants;
30  import com.google.common.collect.Iterables;
31  import org.junit.Test;
32  
33  import javax.ws.rs.core.Response;
34  
35  import static org.junit.Assert.*;
36  
37  @Restore(TestConstants.DEFAULT_JIRA_DUMP_FILE)
38  public class JerseyComponentRestClientTest extends AbstractJerseyRestClientTest {
39  
40  	@Test
41  	public void testGetComponent() throws Exception {
42  		final BasicComponent basicComponent = TestUtil.findEntityByName(client.getProjectClient().getProject("TST", pm).getComponents(), "Component A");
43  		final Component component = client.getComponentClient().getComponent(basicComponent.getSelf(), pm);
44  		assertEquals("Component A", component.getName());
45  		assertEquals("this is some description of component A", component.getDescription());
46  		assertEquals(IntegrationTestUtil.USER_ADMIN_LATEST, component.getLead());
47  	}
48  
49  	@Test
50  	public void testGetComponentOnJira4xOrNewerShouldContainNotNullId() throws Exception {
51  		if (!isJira4x4OrNewer()) {
52  			return;
53  		}
54  		final BasicComponent basicComponent = TestUtil.findEntityByName(client.getProjectClient().getProject("TST", pm).getComponents(), "Component A");
55  		final Component component = client.getComponentClient().getComponent(basicComponent.getSelf(), pm);
56  		assertEquals("Component A", component.getName());
57  		assertEquals("this is some description of component A", component.getDescription());
58  		assertEquals(Long.valueOf(10000), component.getId());
59  		assertEquals(IntegrationTestUtil.USER_ADMIN_LATEST, component.getLead());
60  	}
61  
62  	@Test
63  	public void testGetInvalidComponent() throws Exception {
64  		final BasicComponent basicComponent = Iterables.get(client.getProjectClient().getProject("TST", pm).getComponents(), 0);
65  		final String uriForUnexistingComponent = basicComponent.getSelf().toString() + "1234";
66  		TestUtil.assertErrorCode(Response.Status.NOT_FOUND,  "The component with id "
67  				+ TestUtil.getLastPathSegment(basicComponent.getSelf()) + "1234 does not exist.", new Runnable() {
68  			@Override
69  			public void run() {
70  				client.getComponentClient().getComponent(TestUtil.toUri(uriForUnexistingComponent), pm);
71  			}
72  		});
73  	}
74  
75  	@Test
76  	public void testGetComponentFromRestrictedProject() throws Exception {
77  		final BasicComponent basicComponent = Iterables.getOnlyElement(client.getProjectClient().getProject("RST", pm).getComponents());
78  		assertEquals("One Great Component", client.getComponentClient().getComponent(basicComponent.getSelf(), pm).getName());
79  
80  		// now as unauthorized user
81  		setClient(TestConstants.USER2_USERNAME, TestConstants.USER2_PASSWORD);
82  		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ?
83  				      	"The component with id 10010 does not exist." : "The user user does not have permission to complete this operation.", new Runnable() {
84  			@Override
85  			public void run() {
86  				client.getComponentClient().getComponent(basicComponent.getSelf(), pm).getName();
87  			}
88  		});
89  
90  		setAnonymousMode();
91  		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ?
92  				      	"The component with id 10010 does not exist." : "This user does not have permission to complete this operation.", new Runnable() {
93  			@Override
94  			public void run() {
95  				client.getComponentClient().getComponent(basicComponent.getSelf(), pm).getName();
96  			}
97  		});
98  	}
99  
100 	@Test
101 	public void testCreateAndRemoveComponent() {
102 		if (!isJira4x4OrNewer()) {
103 			return;
104 		}
105 		final Iterable<BasicComponent> components = client.getProjectClient().getProject("TST", pm).getComponents();
106 		assertEquals(2, Iterables.size(components));
107 		final BasicComponent basicComponent = Iterables.get(components, 0);
108 		final BasicComponent basicComponent2 = Iterables.get(components, 1);
109 		final String componentName = "my component";
110 		final ComponentInput componentInput = new ComponentInput(componentName, "a description", null, null);
111 		final Component component = client.getComponentClient().createComponent("TST", componentInput, pm);
112 		assertEquals(componentInput.getName(), component.getName());
113 		assertEquals(componentInput.getDescription(), component.getDescription());
114 		assertNull(component.getLead());
115 		assertProjectHasComponents(basicComponent.getName(), basicComponent2.getName(), componentName);
116 
117 		client.getComponentClient().removeComponent(basicComponent.getSelf(), null, pm);
118 		assertProjectHasComponents(basicComponent2.getName(), componentName);
119 		client.getComponentClient().removeComponent(basicComponent2.getSelf(), null, pm);
120 		assertProjectHasComponents(componentName);
121 		client.getComponentClient().removeComponent(component.getSelf(), null, pm);
122 		assertProjectHasComponents();
123 
124 	}
125 
126 	@Test
127 	public void testCreateAndRemoveComponentAsUnauthorizedUsers() {
128 		if (!isJira4x4OrNewer()) {
129 			return;
130 		}
131 		final Iterable<BasicComponent> components = client.getProjectClient().getProject("TST", pm).getComponents();
132 		assertEquals(2, Iterables.size(components));
133 		final BasicComponent basicComponent = Iterables.get(components, 0);
134 		final BasicComponent basicComponent2 = Iterables.get(components, 1);
135 
136 		final ComponentInput componentInput = new ComponentInput("my component", "a description", null, null);
137 		setUser1();
138 
139 		final Response.Status expectedForbiddenErrorCode = (doesJiraReturnCorrectErrorCodeForForbiddenOperation()) ? Response.Status.FORBIDDEN : Response.Status.UNAUTHORIZED;
140 		TestUtil.assertErrorCode(expectedForbiddenErrorCode, "The user wseliga does not have permission to complete this operation.", new Runnable() {
141 			@Override
142 			public void run() {
143 				client.getComponentClient().removeComponent(basicComponent.getSelf(), null, pm);
144 			}
145 		});
146 		TestUtil.assertErrorCode(expectedForbiddenErrorCode, "You cannot edit the configuration of this project.", new Runnable() {
147 			@Override
148 			public void run() {
149 				client.getComponentClient().createComponent("TST", componentInput, pm);
150 			}
151 		});
152 
153 		setAnonymousMode();
154 		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ?
155 				      	"The component with id 10000 does not exist." : "This user does not have permission to complete this operation.", new Runnable() {
156 			@Override
157 			public void run() {
158 				client.getComponentClient().removeComponent(basicComponent.getSelf(), null, pm);
159 			}
160 		});
161 
162 		if (IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER) {
163 			TestUtil.assertErrorCode(Response.Status.NOT_FOUND, "No project could be found with key 'TST'.", new Runnable() {
164 				@Override
165 				public void run() {
166 					client.getComponentClient().createComponent("TST", componentInput, pm);
167 				}
168 			});
169 		} else {
170 			// IMO for anonymous access still Response.Status.UNAUTHORIZED should be returned - JRADEV-7671
171 			TestUtil.assertErrorCode(expectedForbiddenErrorCode, "You cannot edit the configuration of this project.", new Runnable() {
172 				@Override
173 				public void run() {
174 					client.getComponentClient().createComponent("TST", componentInput, pm);
175 				}
176 			});
177 		}
178 
179 
180 		setAdmin();
181 		// now let's try to add a component with colliding name
182 		final ComponentInput dupeComponentInput = new ComponentInput(basicComponent.getName(), "a description", null, null);
183 		TestUtil.assertErrorCode(Response.Status.BAD_REQUEST, "A component with the name Component A already exists in this project.", new Runnable() {
184 			@Override
185 			public void run() {
186 				client.getComponentClient().createComponent("TST", dupeComponentInput, pm);
187 			}
188 		});
189 
190 		// now let's try to add a component for a non existing project
191 		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, "No project could be found with key 'FAKE'.", new Runnable() {
192 			@Override
193 			public void run() {
194 				client.getComponentClient().createComponent("FAKE", componentInput, pm);
195 			}
196 		});
197 
198 	}
199 
200 
201 	@SuppressWarnings({"ConstantConditions"})
202 	@Test
203 	public void testCreateComponentWithLead() {
204 		if (!isJira4x4OrNewer()) {
205 			return;
206 		}
207 		final ComponentInput componentInput = new ComponentInput("my component name", "a description", "admin", AssigneeType.COMPONENT_LEAD);
208 		final Component component = client.getComponentClient().createComponent("TST", componentInput, pm);
209 		assertNotNull(component.getAssigneeInfo());
210 		assertEquals(IntegrationTestUtil.USER_ADMIN_LATEST, component.getAssigneeInfo().getAssignee());
211 		assertEquals(AssigneeType.COMPONENT_LEAD, component.getAssigneeInfo().getAssigneeType());
212 		assertTrue(component.getAssigneeInfo().isAssigneeTypeValid());
213 		assertEquals(IntegrationTestUtil.USER_ADMIN_LATEST, component.getAssigneeInfo().getRealAssignee());
214 		assertEquals(AssigneeType.COMPONENT_LEAD, component.getAssigneeInfo().getRealAssigneeType());
215 
216 		final ComponentInput componentInput2 = new ComponentInput("my component name2", "a description", IntegrationTestUtil.USER1.getName(), AssigneeType.UNASSIGNED);
217 		final Component component2 = client.getComponentClient().createComponent("TST", componentInput2, pm);
218 		assertNotNull(component2.getAssigneeInfo());
219 		assertNull(component2.getAssigneeInfo().getAssignee());
220 		assertEquals(AssigneeType.UNASSIGNED, component2.getAssigneeInfo().getAssigneeType());
221 		assertFalse(component2.getAssigneeInfo().isAssigneeTypeValid());
222 		assertEquals(IntegrationTestUtil.USER_ADMIN_LATEST, component2.getAssigneeInfo().getRealAssignee());
223 		assertEquals(AssigneeType.PROJECT_DEFAULT, component2.getAssigneeInfo().getRealAssigneeType());
224 	}
225 
226 
227 	@Test
228 	public void testUpdateComponent() {
229 		if (!isJira4x4OrNewer()) {
230 			return;
231 		}
232 		final BasicComponent basicComponent = Iterables.get(client.getProjectClient().getProject("TST", pm).getComponents(), 0);
233 		final Component component = client.getComponentClient().getComponent(basicComponent.getSelf(), pm);
234 		final String newName = basicComponent.getName() + "updated";
235 		Component adjustedComponent = new Component(component.getSelf(), component.getId(), newName, component.getDescription(), component.getLead(), component.getAssigneeInfo());
236 
237 		Component updatedComponent = client.getComponentClient().updateComponent(basicComponent.getSelf(), new ComponentInput(newName, null, null, null), pm);
238 		assertEquals(adjustedComponent, updatedComponent);
239 		assertEquals(adjustedComponent, client.getComponentClient().getComponent(basicComponent.getSelf(), pm));
240 
241 		final String newDescription = "updated description";
242 		adjustedComponent = new Component(component.getSelf(), component.getId(), newName, newDescription, IntegrationTestUtil.USER1_LATEST, component.getAssigneeInfo());
243 		updatedComponent = client.getComponentClient().updateComponent(basicComponent.getSelf(), new ComponentInput(null, newDescription, IntegrationTestUtil.USER1.getName(), null), pm);
244 		assertEquals(adjustedComponent, updatedComponent);
245 
246 		final Component.AssigneeInfo ai = component.getAssigneeInfo();
247 		adjustedComponent = new Component(component.getSelf(), component.getId(), newName, newDescription, IntegrationTestUtil.USER1_LATEST,
248 				new Component.AssigneeInfo(IntegrationTestUtil.USER1_LATEST, AssigneeType.COMPONENT_LEAD, IntegrationTestUtil.USER1_LATEST, AssigneeType.COMPONENT_LEAD, true));
249 
250 		updatedComponent = client.getComponentClient().updateComponent(basicComponent.getSelf(), new ComponentInput(null, newDescription, IntegrationTestUtil.USER1.getName(), AssigneeType.COMPONENT_LEAD), pm);
251 		assertEquals(adjustedComponent, updatedComponent);
252 
253 
254 		// now with non-assignable assignee (thus we are inheriting assignee from project settings and component-level settings are ignored)
255 		adjustedComponent = new Component(component.getSelf(), component.getId(), newName, newDescription, IntegrationTestUtil.USER2_LATEST,
256 				new Component.AssigneeInfo(IntegrationTestUtil.USER2_LATEST, AssigneeType.COMPONENT_LEAD, IntegrationTestUtil.USER_ADMIN_LATEST, AssigneeType.PROJECT_DEFAULT, false));
257 
258 		updatedComponent = client.getComponentClient().updateComponent(basicComponent.getSelf(), new ComponentInput(null, newDescription, IntegrationTestUtil.USER2.getName(), AssigneeType.COMPONENT_LEAD), pm);
259 		assertEquals(adjustedComponent, updatedComponent);
260 
261 	}
262 
263 
264 	@Test
265 	public void testGetComponentRelatedIssuesCount() {
266 		if (!isJira4x4OrNewer()) {
267 			return;
268 		}
269 		final BasicComponent bc = TestUtil.findEntityByName(client.getProjectClient().getProject("TST", pm).getComponents(), "Component A");
270 		assertEquals(1, client.getComponentClient().getComponentRelatedIssuesCount(bc.getSelf(), pm));
271 		final ComponentInput componentInput = new ComponentInput("my component name", "a description", "admin", AssigneeType.COMPONENT_LEAD);
272 		final Component component = client.getComponentClient().createComponent("TST", componentInput, pm);
273 		assertEquals(0, client.getComponentClient().getComponentRelatedIssuesCount(component.getSelf(), pm));
274 
275 		client.getComponentClient().removeComponent(bc.getSelf(), component.getSelf(), pm);
276 		assertEquals(1, client.getComponentClient().getComponentRelatedIssuesCount(component.getSelf(), pm));
277 
278 		// smelly error code/message returned here - JRA-25062
279 		setAnonymousMode();
280 		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ?
281 				      	"The component with id 10000 does not exist." : "This user does not have permission to complete this operation.", new Runnable() {
282 			@Override
283 			public void run() {
284 				client.getComponentClient().getComponentRelatedIssuesCount(component.getSelf(), pm);
285 			}
286 		});
287 
288 		setAdmin();
289 		final BasicComponent restrictedComponent = Iterables.getOnlyElement(client.getProjectClient().getProject("RST", pm).getComponents());
290 		setUser1();
291 		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ?
292 				      	"The component with id 10010 does not exist." : "The user wseliga does not have permission to complete this operation.", new Runnable() {
293 			@Override
294 			public void run() {
295 				client.getComponentClient().getComponentRelatedIssuesCount(restrictedComponent.getSelf(), pm);
296 			}
297 		});
298 
299 		setAdmin();
300 		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, "The component with id " + TestUtil.getLastPathSegment(restrictedComponent.getSelf())
301 				+ "999 does not exist.", new Runnable() {
302 			@Override
303 			public void run() {
304 				client.getComponentClient().getComponentRelatedIssuesCount(TestUtil.toUri(restrictedComponent.getSelf() + "999"), pm);
305 			}
306 		});
307 
308 	}
309 
310 
311 	private boolean doesJiraReturnCorrectErrorCodeForForbiddenOperation() {
312 		return client.getMetadataClient().getServerInfo(pm).getBuildNumber() >= ServerVersionConstants.BN_JIRA_5;
313 	}
314 
315 
316 	private void assertProjectHasComponents(String ...names) {
317 		assertThat(Iterables.transform(client.getProjectClient().getProject("TST", pm).getComponents(),
318 				new BasicComponentNameExtractionFunction()), IterableMatcher.hasOnlyElements(names));
319 	}
320 
321 }