@RequestMapping(method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  public String listResourceSets(Model m, Authentication auth) {
    ensureOAuthScope(auth, SystemScopeService.UMA_PROTECTION_SCOPE);

    String owner = auth.getName();

    Collection<ResourceSet> resourceSets = Collections.emptySet();
    if (auth instanceof OAuth2Authentication) {
      // if it's an OAuth mediated call, it's on behalf of a client, so look that up too
      OAuth2Authentication o2a = (OAuth2Authentication) auth;
      resourceSets =
          resourceSetService.getAllForOwnerAndClient(owner, o2a.getOAuth2Request().getClientId());
    } else {
      // otherwise get everything for the current user
      resourceSets = resourceSetService.getAllForOwner(owner);
    }

    // build the entity here and send to the display

    Set<String> ids = new HashSet<>();
    for (ResourceSet resourceSet : resourceSets) {
      ids.add(
          resourceSet
              .getId()
              .toString()); // add them all as strings so that gson renders them properly
    }

    m.addAttribute(JsonEntityView.ENTITY, ids);
    return JsonEntityView.VIEWNAME;
  }
  @RequestMapping(
      value = "/{id}",
      method = RequestMethod.PUT,
      consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
      produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  public String updateResourceSet(
      @PathVariable("id") Long id, @RequestBody String jsonString, Model m, Authentication auth) {
    ensureOAuthScope(auth, SystemScopeService.UMA_PROTECTION_SCOPE);

    ResourceSet newRs = parseResourceSet(jsonString);

    if (newRs == null // there was no resource set in the body
        || Strings.isNullOrEmpty(newRs.getName()) // there was no name (required)
        || newRs.getScopes() == null // there were no scopes (required)
        || newRs.getId() == null
        || !newRs.getId().equals(id) // the IDs didn't match
    ) {

      logger.warn("Resource set registration missing one or more required fields.");

      m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
      m.addAttribute(
          JsonErrorView.ERROR_MESSAGE, "Resource request was missing one or more required fields.");
      return JsonErrorView.VIEWNAME;
    }

    ResourceSet rs = resourceSetService.getById(id);

    if (rs == null) {
      m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
      m.addAttribute(JsonErrorView.ERROR, "not_found");
      return JsonErrorView.VIEWNAME;
    } else {
      if (!auth.getName().equals(rs.getOwner())) {

        logger.warn(
            "Unauthorized resource set request from bad user; expected "
                + rs.getOwner()
                + " got "
                + auth.getName());

        // it wasn't issued to this user
        m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
        return JsonErrorView.VIEWNAME;
      } else {

        ResourceSet saved = resourceSetService.update(rs, newRs);

        m.addAttribute(JsonEntityView.ENTITY, saved);
        m.addAttribute(
            ResourceSetEntityAbbreviatedView.LOCATION, config.getIssuer() + URL + "/" + rs.getId());
        return ResourceSetEntityAbbreviatedView.VIEWNAME;
      }
    }
  }
  @RequestMapping(
      value = "/{id}",
      method = RequestMethod.DELETE,
      produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  public String deleteResourceSet(@PathVariable("id") Long id, Model m, Authentication auth) {
    ensureOAuthScope(auth, SystemScopeService.UMA_PROTECTION_SCOPE);

    ResourceSet rs = resourceSetService.getById(id);

    if (rs == null) {
      m.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
      m.addAttribute(JsonErrorView.ERROR, "not_found");
      return JsonErrorView.VIEWNAME;
    } else {
      if (!auth.getName().equals(rs.getOwner())) {

        logger.warn(
            "Unauthorized resource set request from bad user; expected "
                + rs.getOwner()
                + " got "
                + auth.getName());

        // it wasn't issued to this user
        m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
        return JsonErrorView.VIEWNAME;
      } else if (auth instanceof OAuth2Authentication
          && !((OAuth2Authentication) auth)
              .getOAuth2Request()
              .getClientId()
              .equals(rs.getClientId())) {

        logger.warn(
            "Unauthorized resource set request from bad client; expected "
                + rs.getClientId()
                + " got "
                + ((OAuth2Authentication) auth).getOAuth2Request().getClientId());

        // it wasn't issued to this client
        m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
        return JsonErrorView.VIEWNAME;
      } else {

        // user and client matched
        resourceSetService.remove(rs);

        m.addAttribute(HttpCodeView.CODE, HttpStatus.NO_CONTENT);
        return HttpCodeView.VIEWNAME;
      }
    }
  }
  @RequestMapping(
      value = "/{id}",
      method = RequestMethod.GET,
      produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
  public String readResourceSet(@PathVariable("id") Long id, Model m, Authentication auth) {
    ensureOAuthScope(auth, SystemScopeService.UMA_PROTECTION_SCOPE);

    ResourceSet rs = resourceSetService.getById(id);

    if (rs == null) {
      m.addAttribute("code", HttpStatus.NOT_FOUND);
      m.addAttribute("error", "not_found");
      return JsonErrorView.VIEWNAME;
    } else {

      rs = validateScopes(rs);

      if (!auth.getName().equals(rs.getOwner())) {

        logger.warn(
            "Unauthorized resource set request from wrong user; expected "
                + rs.getOwner()
                + " got "
                + auth.getName());

        // it wasn't issued to this user
        m.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
        return JsonErrorView.VIEWNAME;
      } else {
        m.addAttribute(JsonEntityView.ENTITY, rs);
        return ResourceSetEntityView.VIEWNAME;
      }
    }
  }
  @RequestMapping(
      method = RequestMethod.POST,
      produces = MimeTypeUtils.APPLICATION_JSON_VALUE,
      consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
  public String createResourceSet(@RequestBody String jsonString, Model m, Authentication auth) {
    ensureOAuthScope(auth, SystemScopeService.UMA_PROTECTION_SCOPE);

    ResourceSet rs = parseResourceSet(jsonString);

    if (rs == null) { // there was no resource set in the body
      logger.warn("Resource set registration missing body.");

      m.addAttribute("code", HttpStatus.BAD_REQUEST);
      m.addAttribute("error_description", "Resource request was missing body.");
      return JsonErrorView.VIEWNAME;
    }

    if (auth instanceof OAuth2Authentication) {
      // if it's an OAuth mediated call, it's on behalf of a client, so store that
      OAuth2Authentication o2a = (OAuth2Authentication) auth;
      rs.setClientId(o2a.getOAuth2Request().getClientId());
      rs.setOwner(auth.getName()); // the username is going to be in the auth object
    } else {
      // this one shouldn't be called if it's not OAuth
      m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
      m.addAttribute(JsonErrorView.ERROR_MESSAGE, "This call must be made with an OAuth token");
      return JsonErrorView.VIEWNAME;
    }

    rs = validateScopes(rs);

    if (Strings.isNullOrEmpty(rs.getName()) // there was no name (required)
        || rs.getScopes() == null // there were no scopes (required)
    ) {

      logger.warn("Resource set registration missing one or more required fields.");

      m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
      m.addAttribute(
          JsonErrorView.ERROR_MESSAGE, "Resource request was missing one or more required fields.");
      return JsonErrorView.VIEWNAME;
    }

    ResourceSet saved = resourceSetService.saveNew(rs);

    m.addAttribute(HttpCodeView.CODE, HttpStatus.CREATED);
    m.addAttribute(JsonEntityView.ENTITY, saved);
    m.addAttribute(
        ResourceSetEntityAbbreviatedView.LOCATION, config.getIssuer() + URL + "/" + saved.getId());

    return ResourceSetEntityAbbreviatedView.VIEWNAME;
  }