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