PageRenderTime 52ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/uma-server/src/main/java/org/mitre/uma/web/PolicyAPI.java

http://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server
Java | 391 lines | 215 code | 79 blank | 97 comment | 41 complexity | f6acd5d6c6b160e42681ecf4bcd1c240 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright 2018 The MIT Internet Trust Consortium
  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. package org.mitre.uma.web;
  17. import java.util.Collection;
  18. import java.util.HashSet;
  19. import java.util.Set;
  20. import org.mitre.openid.connect.view.HttpCodeView;
  21. import org.mitre.openid.connect.view.JsonEntityView;
  22. import org.mitre.openid.connect.view.JsonErrorView;
  23. import org.mitre.openid.connect.web.RootController;
  24. import org.mitre.uma.model.Claim;
  25. import org.mitre.uma.model.Policy;
  26. import org.mitre.uma.model.ResourceSet;
  27. import org.mitre.uma.service.ResourceSetService;
  28. import org.slf4j.Logger;
  29. import org.slf4j.LoggerFactory;
  30. import org.springframework.beans.factory.annotation.Autowired;
  31. import org.springframework.http.HttpStatus;
  32. import org.springframework.security.access.prepost.PreAuthorize;
  33. import org.springframework.security.core.Authentication;
  34. import org.springframework.stereotype.Controller;
  35. import org.springframework.ui.Model;
  36. import org.springframework.util.MimeTypeUtils;
  37. import org.springframework.web.bind.annotation.PathVariable;
  38. import org.springframework.web.bind.annotation.RequestBody;
  39. import org.springframework.web.bind.annotation.RequestMapping;
  40. import org.springframework.web.bind.annotation.RequestMethod;
  41. import com.google.common.collect.Sets;
  42. import com.google.gson.Gson;
  43. /**
  44. * API for managing policies on resource sets.
  45. *
  46. * @author jricher
  47. *
  48. */
  49. @Controller
  50. @RequestMapping("/" + PolicyAPI.URL)
  51. @PreAuthorize("hasRole('ROLE_USER')")
  52. public class PolicyAPI {
  53. // Logger for this class
  54. private static final Logger logger = LoggerFactory.getLogger(PolicyAPI.class);
  55. public static final String URL = RootController.API_URL + "/resourceset";
  56. public static final String POLICYURL = "/policy";
  57. private Gson gson = new Gson();
  58. @Autowired
  59. private ResourceSetService resourceSetService;
  60. /**
  61. * List all resource sets for the current user
  62. * @param m
  63. * @param auth
  64. * @return
  65. */
  66. @RequestMapping(value = "", method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  67. public String getResourceSetsForCurrentUser(Model m, Authentication auth) {
  68. Collection<ResourceSet> resourceSets = resourceSetService.getAllForOwner(auth.getName());
  69. m.addAttribute(JsonEntityView.ENTITY, resourceSets);
  70. return JsonEntityView.VIEWNAME;
  71. }
  72. /**
  73. * Get the indicated resource set
  74. * @param rsid
  75. * @param m
  76. * @param auth
  77. * @return
  78. */
  79. @RequestMapping(value = "/{rsid}", method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  80. public String getResourceSet(@PathVariable (value = "rsid") Long rsid, Model m, Authentication auth) {
  81. ResourceSet rs = resourceSetService.getById(rsid);
  82. if (rs == null) {
  83. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  84. return HttpCodeView.VIEWNAME;
  85. }
  86. if (!rs.getOwner().equals(auth.getName())) {
  87. logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName());
  88. // authenticated user didn't match the owner of the resource set
  89. m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
  90. return HttpCodeView.VIEWNAME;
  91. }
  92. m.addAttribute(JsonEntityView.ENTITY, rs);
  93. return JsonEntityView.VIEWNAME;
  94. }
  95. /**
  96. * Delete the indicated resource set
  97. * @param rsid
  98. * @param m
  99. * @param auth
  100. * @return
  101. */
  102. @RequestMapping(value = "/{rsid}", method = RequestMethod.DELETE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  103. public String deleteResourceSet(@PathVariable (value = "rsid") Long rsid, Model m, Authentication auth) {
  104. ResourceSet rs = resourceSetService.getById(rsid);
  105. if (rs == null) {
  106. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  107. return HttpCodeView.VIEWNAME;
  108. }
  109. if (!rs.getOwner().equals(auth.getName())) {
  110. logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName());
  111. // authenticated user didn't match the owner of the resource set
  112. m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
  113. return HttpCodeView.VIEWNAME;
  114. }
  115. resourceSetService.remove(rs);
  116. m.addAttribute(HttpCodeView.CODE, HttpStatus.NO_CONTENT);
  117. return HttpCodeView.VIEWNAME;
  118. }
  119. /**
  120. * List all the policies for the given resource set
  121. * @param rsid
  122. * @param m
  123. * @param auth
  124. * @return
  125. */
  126. @RequestMapping(value = "/{rsid}" + POLICYURL, method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  127. public String getPoliciesForResourceSet(@PathVariable (value = "rsid") Long rsid, Model m, Authentication auth) {
  128. ResourceSet rs = resourceSetService.getById(rsid);
  129. if (rs == null) {
  130. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  131. return HttpCodeView.VIEWNAME;
  132. }
  133. if (!rs.getOwner().equals(auth.getName())) {
  134. logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName());
  135. // authenticated user didn't match the owner of the resource set
  136. m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
  137. return HttpCodeView.VIEWNAME;
  138. }
  139. m.addAttribute(JsonEntityView.ENTITY, rs.getPolicies());
  140. return JsonEntityView.VIEWNAME;
  141. }
  142. /**
  143. * Create a new policy on the given resource set
  144. * @param rsid
  145. * @param m
  146. * @param auth
  147. * @return
  148. */
  149. @RequestMapping(value = "/{rsid}" + POLICYURL, method = RequestMethod.POST, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  150. public String createNewPolicyForResourceSet(@PathVariable (value = "rsid") Long rsid, @RequestBody String jsonString, Model m, Authentication auth) {
  151. ResourceSet rs = resourceSetService.getById(rsid);
  152. if (rs == null) {
  153. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  154. return HttpCodeView.VIEWNAME;
  155. }
  156. if (!rs.getOwner().equals(auth.getName())) {
  157. logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName());
  158. // authenticated user didn't match the owner of the resource set
  159. m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
  160. return HttpCodeView.VIEWNAME;
  161. }
  162. Policy p = gson.fromJson(jsonString, Policy.class);
  163. if (p.getId() != null) {
  164. logger.warn("Tried to add a policy with a non-null ID: " + p.getId());
  165. m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
  166. return HttpCodeView.VIEWNAME;
  167. }
  168. for (Claim claim : p.getClaimsRequired()) {
  169. if (claim.getId() != null) {
  170. logger.warn("Tried to add a policy with a non-null claim ID: " + claim.getId());
  171. m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
  172. return HttpCodeView.VIEWNAME;
  173. }
  174. }
  175. rs.getPolicies().add(p);
  176. ResourceSet saved = resourceSetService.update(rs, rs);
  177. // find the new policy object
  178. Collection<Policy> newPolicies = Sets.difference(new HashSet<>(saved.getPolicies()), new HashSet<>(rs.getPolicies()));
  179. if (newPolicies.size() == 1) {
  180. Policy newPolicy = newPolicies.iterator().next();
  181. m.addAttribute(JsonEntityView.ENTITY, newPolicy);
  182. return JsonEntityView.VIEWNAME;
  183. } else {
  184. logger.warn("Unexpected result trying to add a new policy object: " + newPolicies);
  185. m.addAttribute(HttpCodeView.CODE, HttpStatus.INTERNAL_SERVER_ERROR);
  186. return HttpCodeView.VIEWNAME;
  187. }
  188. }
  189. /**
  190. * Get a specific policy
  191. * @param rsid
  192. * @param pid
  193. * @param m
  194. * @param auth
  195. * @return
  196. */
  197. @RequestMapping(value = "/{rsid}" + POLICYURL + "/{pid}", method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  198. public String getPolicy(@PathVariable (value = "rsid") Long rsid, @PathVariable (value = "pid") Long pid, Model m, Authentication auth) {
  199. ResourceSet rs = resourceSetService.getById(rsid);
  200. if (rs == null) {
  201. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  202. return HttpCodeView.VIEWNAME;
  203. }
  204. if (!rs.getOwner().equals(auth.getName())) {
  205. logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName());
  206. // authenticated user didn't match the owner of the resource set
  207. m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
  208. return HttpCodeView.VIEWNAME;
  209. }
  210. for (Policy policy : rs.getPolicies()) {
  211. if (policy.getId().equals(pid)) {
  212. // found it!
  213. m.addAttribute(JsonEntityView.ENTITY, policy);
  214. return JsonEntityView.VIEWNAME;
  215. }
  216. }
  217. // if we made it this far, we haven't found it
  218. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  219. return HttpCodeView.VIEWNAME;
  220. }
  221. /**
  222. * Update a specific policy
  223. * @param rsid
  224. * @param pid
  225. * @param jsonString
  226. * @param m
  227. * @param auth
  228. * @return
  229. */
  230. @RequestMapping(value = "/{rsid}" + POLICYURL + "/{pid}", method = RequestMethod.PUT, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  231. public String setClaimsForResourceSet(@PathVariable (value = "rsid") Long rsid, @PathVariable (value = "pid") Long pid, @RequestBody String jsonString, Model m, Authentication auth) {
  232. ResourceSet rs = resourceSetService.getById(rsid);
  233. if (rs == null) {
  234. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  235. return HttpCodeView.VIEWNAME;
  236. }
  237. if (!rs.getOwner().equals(auth.getName())) {
  238. logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName());
  239. // authenticated user didn't match the owner of the resource set
  240. m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
  241. return HttpCodeView.VIEWNAME;
  242. }
  243. Policy p = gson.fromJson(jsonString, Policy.class);
  244. if (!pid.equals(p.getId())) {
  245. logger.warn("Policy ID mismatch, expected " + pid + " got " + p.getId());
  246. m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
  247. return HttpCodeView.VIEWNAME;
  248. }
  249. for (Policy policy : rs.getPolicies()) {
  250. if (policy.getId().equals(pid)) {
  251. // found it!
  252. // find the existing claim IDs, make sure we're not overwriting anything from another policy
  253. Set<Long> claimIds = new HashSet<>();
  254. for (Claim claim : policy.getClaimsRequired()) {
  255. claimIds.add(claim.getId());
  256. }
  257. for (Claim claim : p.getClaimsRequired()) {
  258. if (claim.getId() != null && !claimIds.contains(claim.getId())) {
  259. logger.warn("Tried to add a policy with a an unmatched claim ID: got " + claim.getId() + " expected " + claimIds);
  260. m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
  261. return HttpCodeView.VIEWNAME;
  262. }
  263. }
  264. // update the existing object with the new values
  265. policy.setClaimsRequired(p.getClaimsRequired());
  266. policy.setName(p.getName());
  267. policy.setScopes(p.getScopes());
  268. resourceSetService.update(rs, rs);
  269. m.addAttribute(JsonEntityView.ENTITY, policy);
  270. return JsonEntityView.VIEWNAME;
  271. }
  272. }
  273. // if we made it this far, we haven't found it
  274. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  275. return HttpCodeView.VIEWNAME;
  276. }
  277. /**
  278. * Delete a specific policy
  279. * @param rsid
  280. * @param pid
  281. * @param m
  282. * @param auth
  283. * @return
  284. */
  285. @RequestMapping(value = "/{rsid}" + POLICYURL + "/{pid}", method = RequestMethod.DELETE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  286. public String deleteResourceSet(@PathVariable ("rsid") Long rsid, @PathVariable (value = "pid") Long pid, Model m, Authentication auth) {
  287. ResourceSet rs = resourceSetService.getById(rsid);
  288. if (rs == null) {
  289. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  290. m.addAttribute(JsonErrorView.ERROR, "not_found");
  291. return JsonErrorView.VIEWNAME;
  292. }
  293. if (!auth.getName().equals(rs.getOwner())) {
  294. logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName());
  295. // it wasn't issued to this user
  296. m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
  297. return JsonErrorView.VIEWNAME;
  298. }
  299. for (Policy policy : rs.getPolicies()) {
  300. if (policy.getId().equals(pid)) {
  301. // found it!
  302. rs.getPolicies().remove(policy);
  303. resourceSetService.update(rs, rs);
  304. m.addAttribute(HttpCodeView.CODE, HttpStatus.NO_CONTENT);
  305. return HttpCodeView.VIEWNAME;
  306. }
  307. }
  308. // if we made it this far, we haven't found it
  309. m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  310. return HttpCodeView.VIEWNAME;
  311. }
  312. }