Skip to content

Commit

Permalink
Add delete and retrieveAll endpoints for client metadata
Browse files Browse the repository at this point in the history
[#109263482] https://www.pivotaltracker.com/story/show/109263482

Signed-off-by: Jonathan Lo <jlo@us.ibm.com>
Signed-off-by: Madhura Bhave <mbhave@pivotal.io>
  • Loading branch information
mbhave authored and cf-identity committed Jan 21, 2016
1 parent fa19840 commit e54f06c
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 120 deletions.
Expand Up @@ -27,12 +27,10 @@ public class ClientMetadata {
private String appIcon; private String appIcon;
private int version; private int version;


@JsonIgnore
public String getClientId() { public String getClientId() {
return clientId; return clientId;
} }


@JsonIgnore
public void setClientId(String clientId) { public void setClientId(String clientId) {
this.clientId = clientId; this.clientId = clientId;
} }
Expand Down
@@ -1,15 +1,30 @@
package org.cloudfoundry.identity.uaa.client; package org.cloudfoundry.identity.uaa.client;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cloudfoundry.identity.uaa.web.ConvertingExceptionView;
import org.cloudfoundry.identity.uaa.web.ExceptionReport;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.NoSuchClientException; import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.View;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;


/******************************************************************************* /*******************************************************************************
* Cloud Foundry * Cloud Foundry
Expand All @@ -28,27 +43,57 @@ public class ClientMetadataAdminEndpoints {


private ClientMetadataProvisioning clientMetadataProvisioning; private ClientMetadataProvisioning clientMetadataProvisioning;
private ClientDetailsService clients; private ClientDetailsService clients;
private HttpMessageConverter<?>[] messageConverters;

private static Log logger = LogFactory.getLog(ClientMetadataAdminEndpoints.class);


@RequestMapping(value = "/oauth/clients/{client}/meta", method = RequestMethod.POST) @RequestMapping(value = "/oauth/clients/{client}/meta", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED) @ResponseStatus(HttpStatus.CREATED)
public ClientMetadata createClientMetadata(@RequestBody ClientMetadata clientMetadata, public ClientMetadata createClientMetadata(@RequestBody ClientMetadata clientMetadata,
@PathVariable("client") String clientId) @PathVariable("client") String clientId) {
throws ClientNotFoundException {
try { try {
clients.loadClientByClientId(clientId); clients.loadClientByClientId(clientId);
clientMetadata.setClientId(clientId);
return clientMetadataProvisioning.create(clientMetadata);
} catch (NoSuchClientException nsce) { } catch (NoSuchClientException nsce) {
throw new ClientNotFoundException(clientId ); throw new ClientMetadataException("No client found with id: " + clientId, HttpStatus.NOT_FOUND);
} catch (DuplicateKeyException e) {
throw new ClientMetadataException("Client metadata already exists for this clientId: " + clientId, HttpStatus.CONFLICT);
} }


clientMetadata.setClientId(clientId);
return clientMetadataProvisioning.create(clientMetadata);
} }


// GET // GET
@RequestMapping(value = "/oauth/clients/{client}/meta", method = RequestMethod.GET) @RequestMapping(value = "/oauth/clients/{client}/meta", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK) @ResponseStatus(HttpStatus.OK)
public ClientMetadata retrieveClientMetadata(@PathVariable("client") String clientId) { public ClientMetadata retrieveClientMetadata(@PathVariable("client") String clientId) {
return clientMetadataProvisioning.retrieve(clientId); try {
return clientMetadataProvisioning.retrieve(clientId);
} catch (EmptyResultDataAccessException erdae) {
throw new ClientMetadataException("No client metadata found for " + clientId, HttpStatus.NOT_FOUND);
}
}

// GET
@RequestMapping(value = "/oauth/clients/meta", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public List<ClientMetadata> retrieveAllClientMetadata() {
return clientMetadataProvisioning.retrieveAll();
}

@RequestMapping(value = "/oauth/clients/{client}/meta", method = RequestMethod.DELETE)
@ResponseStatus(HttpStatus.OK)
public ClientMetadata deleteClientMetadata(@PathVariable("client") String clientId, @RequestHeader(value = "If-Match", required = false) Integer etag) {
if (etag == null) {
throw new ClientMetadataException("Missing If-Match header", HttpStatus.BAD_REQUEST);
}
try {
return clientMetadataProvisioning.delete(clientId, etag);
} catch (EmptyResultDataAccessException erdae) {
throw new ClientMetadataException("No client metadata found for " + clientId, HttpStatus.NOT_FOUND);
} catch (OptimisticLockingFailureException olfe) {
throw new ClientMetadataException(olfe.getMessage(), HttpStatus.PRECONDITION_FAILED);
}
} }


// PUT (Update) // PUT (Update)
Expand All @@ -58,11 +103,24 @@ public ClientMetadata updateClientMetadata(@RequestBody ClientMetadata clientMet
@RequestHeader(value = "If-Match", required = false) Integer etag, @RequestHeader(value = "If-Match", required = false) Integer etag,
@PathVariable("client") String clientId) { @PathVariable("client") String clientId) {
if (etag == null) { if (etag == null) {
throw new ClientMetadataException("Missing If-Match header", HttpStatus.PRECONDITION_FAILED); throw new ClientMetadataException("Missing If-Match header", HttpStatus.BAD_REQUEST);
} }


clientMetadata.setVersion(etag); clientMetadata.setVersion(etag);
return clientMetadataProvisioning.update(clientId, clientMetadata); try {
return clientMetadataProvisioning.update(clientId, clientMetadata);
} catch (OptimisticLockingFailureException olfe) {
throw new ClientMetadataException(olfe.getMessage(), HttpStatus.PRECONDITION_FAILED);
}
}

@ExceptionHandler
public View handleException(ClientMetadataException cme, HttpServletRequest request) {
logger.error("Unhandled exception in client metadata admin endpoints.", cme);

boolean trace = request.getParameter("trace") != null && !request.getParameter("trace").equals("false");
return new ConvertingExceptionView(new ResponseEntity<>(new ExceptionReport(cme, trace, cme.getExtraInfo()),
cme.getStatus()), messageConverters);
} }


// DELETE // DELETE
Expand All @@ -76,4 +134,8 @@ public void setClientMetadataProvisioning(ClientMetadataProvisioning clientMetad
public void setClients(ClientDetailsService clients) { public void setClients(ClientDetailsService clients) {
this.clients = clients; this.clients = clients;
} }

public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) {
this.messageConverters = messageConverters;
}
} }
Expand Up @@ -17,10 +17,6 @@


import java.util.Map; import java.util.Map;


/**
* @author Luke Taylor
* @author Dave Syer
*/
public class ClientMetadataException extends UaaException { public class ClientMetadataException extends UaaException {


private final HttpStatus status; private final HttpStatus status;
Expand Down

This file was deleted.

This file was deleted.

Expand Up @@ -41,6 +41,7 @@ public class JdbcClientMetadataProvisioning implements ClientMetadataProvisionin


private static final String CLIENT_METADATA_FIELDS = "id, client_id, identity_zone_id, show_on_home_page, app_launch_url, app_icon, version"; private static final String CLIENT_METADATA_FIELDS = "id, client_id, identity_zone_id, show_on_home_page, app_launch_url, app_icon, version";
private static final String CLIENT_METADATA_QUERY = "select " + CLIENT_METADATA_FIELDS + " from oauth_client_metadata where client_id=? and identity_zone_id=?"; private static final String CLIENT_METADATA_QUERY = "select " + CLIENT_METADATA_FIELDS + " from oauth_client_metadata where client_id=? and identity_zone_id=?";
private static final String CLIENT_METADATAS_QUERY = "select " + CLIENT_METADATA_FIELDS + " from oauth_client_metadata where identity_zone_id=?";
private static final String CLIENT_METADATA_CREATE = "insert into oauth_client_metadata(" + CLIENT_METADATA_FIELDS + ") values (?,?,?,?,?,?,?)"; private static final String CLIENT_METADATA_CREATE = "insert into oauth_client_metadata(" + CLIENT_METADATA_FIELDS + ") values (?,?,?,?,?,?,?)";
private static final String CLIENT_METADATA_UPDATE_FIELDS = "show_on_home_page, app_launch_url, app_icon, version"; private static final String CLIENT_METADATA_UPDATE_FIELDS = "show_on_home_page, app_launch_url, app_icon, version";
private static final String CLIENT_METADATA_UPDATE = "update oauth_client_metadata set " + CLIENT_METADATA_UPDATE_FIELDS.replace(",", "=?,") + "=?" + " where client_id=? and identity_zone_id=? and version=?"; private static final String CLIENT_METADATA_UPDATE = "update oauth_client_metadata set " + CLIENT_METADATA_UPDATE_FIELDS.replace(",", "=?,") + "=?" + " where client_id=? and identity_zone_id=? and version=?";
Expand All @@ -61,47 +62,39 @@ public void setTemplate(JdbcTemplate template) {
@Override @Override
public List<ClientMetadata> retrieveAll() { public List<ClientMetadata> retrieveAll() {
logger.debug("Retrieving UI details for all client"); logger.debug("Retrieving UI details for all client");
return template.query(CLIENT_METADATA_QUERY, mapper, IdentityZoneHolder.get().getId()); return template.query(CLIENT_METADATAS_QUERY, mapper, IdentityZoneHolder.get().getId());
} }


@Override @Override
public ClientMetadata retrieve(String clientId) { public ClientMetadata retrieve(String clientId) {
logger.debug("Retrieving UI details for client: " + clientId); logger.debug("Retrieving UI details for client: " + clientId);
try { return template.queryForObject(CLIENT_METADATA_QUERY, mapper, clientId, IdentityZoneHolder.get().getId());
return template.queryForObject(CLIENT_METADATA_QUERY, mapper, clientId, IdentityZoneHolder.get().getId());
} catch (EmptyResultDataAccessException erdae) {
throw new ClientMetadataNotFoundException("No existing metadata found for client " + clientId);
}
} }


@Override @Override
public ClientMetadata create(ClientMetadata resource) { public ClientMetadata create(ClientMetadata resource) {
logger.debug("Creating new UI details for client: " + resource.getClientId()); logger.debug("Creating new UI details for client: " + resource.getClientId());
final String id = UUID.randomUUID().toString(); final String id = UUID.randomUUID().toString();
try { template.update(CLIENT_METADATA_CREATE, new PreparedStatementSetter() {
template.update(CLIENT_METADATA_CREATE, new PreparedStatementSetter() { @Override
@Override public void setValues(PreparedStatement ps) throws SQLException {
public void setValues(PreparedStatement ps) throws SQLException { int pos = 1;
int pos = 1; ps.setString(pos++, id);
ps.setString(pos++, id); ps.setString(pos++, resource.getClientId());
ps.setString(pos++, resource.getClientId()); ps.setString(pos++, IdentityZoneHolder.get().getId());
ps.setString(pos++, IdentityZoneHolder.get().getId()); ps.setBoolean(pos++, resource.isShowOnHomePage());
ps.setBoolean(pos++, resource.isShowOnHomePage()); URL appLaunchUrl = resource.getAppLaunchUrl();
URL appLaunchUrl = resource.getAppLaunchUrl(); ps.setString(pos++, appLaunchUrl == null ? null : appLaunchUrl.toString());
ps.setString(pos++, appLaunchUrl == null ? null : appLaunchUrl.toString()); String appIcon = resource.getAppIcon();
String appIcon = resource.getAppIcon(); if (appIcon != null) {
if (appIcon != null) { byte[] decodedAppIcon = Base64.decode(appIcon.getBytes());
byte[] decodedAppIcon = Base64.decode(appIcon.getBytes()); ps.setBinaryStream(pos++, new ByteArrayInputStream(decodedAppIcon), (int) decodedAppIcon.length);
ps.setBinaryStream(pos++, new ByteArrayInputStream(decodedAppIcon), (int) decodedAppIcon.length); } else {
} else { ps.setBinaryStream(pos++, new ByteArrayInputStream(new byte[] {}), (int) 0);
ps.setBinaryStream(pos++, new ByteArrayInputStream(new byte[] {}), (int) 0);
}
ps.setInt(pos++, 1);
} }
}); ps.setInt(pos++, 1);
} catch (DuplicateKeyException e) { }
throw new IdpAlreadyExistsException(e.getMostSpecificCause().getMessage()); });
}
return retrieve(resource.getClientId()); return retrieve(resource.getClientId());
} }


Expand Down
@@ -1,11 +1,11 @@
CREATE TABLE oauth_client_metadata ( CREATE TABLE oauth_client_metadata (
id VARCHAR(255) NOT NULL, id VARCHAR(255) NOT NULL,
client_id VARCHAR(255) NOT NULL, client_id VARCHAR(255) NOT NULL UNIQUE,
identity_zone_id VARCHAR(36) NOT NULL, identity_zone_id VARCHAR(36) NOT NULL,
show_on_home_page BOOLEAN DEFAULT TRUE NOT NULL, show_on_home_page BOOLEAN DEFAULT TRUE NOT NULL,
app_launch_url VARCHAR(1024), app_launch_url VARCHAR(1024),
app_icon BLOB, app_icon BLOB,
version INT DEFAULT 0 NOT NULL, version INT DEFAULT 0 NOT NULL,
PRIMARY KEY (id), PRIMARY KEY (id),
CONSTRAINT FK_client_details FOREIGN KEY (client_id,identity_zone_id) REFERENCES oauth_client_details(client_id,identity_zone_id) CONSTRAINT FK_client_details FOREIGN KEY (client_id,identity_zone_id) REFERENCES oauth_client_details(client_id,identity_zone_id)
); );
@@ -1,11 +1,11 @@
CREATE TABLE oauth_client_metadata ( CREATE TABLE oauth_client_metadata (
id VARCHAR(255) NOT NULL, id VARCHAR(255) NOT NULL,
client_id VARCHAR(255) NOT NULL, client_id VARCHAR(255) NOT NULL UNIQUE,
identity_zone_id VARCHAR(36) NOT NULL, identity_zone_id VARCHAR(36) NOT NULL,
show_on_home_page BOOLEAN DEFAULT TRUE NOT NULL, show_on_home_page BOOLEAN DEFAULT TRUE NOT NULL,
app_launch_url VARCHAR(1024), app_launch_url VARCHAR(1024),
app_icon MEDIUMBLOB, app_icon MEDIUMBLOB,
version INT DEFAULT 0 NOT NULL, version INT DEFAULT 0 NOT NULL,
PRIMARY KEY (id), PRIMARY KEY (id),
CONSTRAINT FK_client_details FOREIGN KEY (client_id,identity_zone_id) REFERENCES oauth_client_details(client_id,identity_zone_id) CONSTRAINT FK_client_details FOREIGN KEY (client_id,identity_zone_id) REFERENCES oauth_client_details(client_id,identity_zone_id)
); );
@@ -1,11 +1,11 @@
CREATE TABLE oauth_client_metadata ( CREATE TABLE oauth_client_metadata (
id VARCHAR(256) NOT NULL, id VARCHAR(256) NOT NULL,
client_id VARCHAR(256) NOT NULL, client_id VARCHAR(256) NOT NULL UNIQUE,
identity_zone_id VARCHAR(36) NOT NULL, identity_zone_id VARCHAR(36) NOT NULL,
show_on_home_page BOOLEAN DEFAULT TRUE NOT NULL, show_on_home_page BOOLEAN DEFAULT TRUE NOT NULL,
app_launch_url VARCHAR(1024), app_launch_url VARCHAR(1024),
app_icon BYTEA, app_icon BYTEA,
version INT DEFAULT 0 NOT NULL, version INT DEFAULT 0 NOT NULL,
PRIMARY KEY (id), PRIMARY KEY (id),
CONSTRAINT FK_client_details FOREIGN KEY (client_id,identity_zone_id) REFERENCES oauth_client_details(client_id,identity_zone_id) CONSTRAINT FK_client_details FOREIGN KEY (client_id,identity_zone_id) REFERENCES oauth_client_details(client_id,identity_zone_id)
); );

0 comments on commit e54f06c

Please sign in to comment.