Commit cbb0512e authored by Matija Obreza's avatar Matija Obreza
Browse files

Editor for OAuth Client details

parent bf7d1a68
...@@ -135,7 +135,7 @@ module.exports = function(grunt) { ...@@ -135,7 +135,7 @@ module.exports = function(grunt) {
'bower_components/tinymce/tinymce.jquery.js', 'bower_components/tinymce/themes/modern/theme.js', 'bower_components/tinymce/plugins/link/plugin.js', 'bower_components/tinymce/tinymce.jquery.js', 'bower_components/tinymce/themes/modern/theme.js', 'bower_components/tinymce/plugins/link/plugin.js',
'bower_components/tinymce/plugins/autolink/plugin.js', 'bower_components/tinymce/plugins/code/plugin.js', 'bower_components/leaflet/dist/leaflet.js', 'bower_components/tinymce/plugins/autolink/plugin.js', 'bower_components/tinymce/plugins/code/plugin.js', 'bower_components/leaflet/dist/leaflet.js',
'bower_components/leaflet-locationfilter/src/locationfilter.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/jquery-ui/jquery-ui.js', 'bower_components/leaflet-locationfilter/src/locationfilter.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/jquery-ui/jquery-ui.js',
'bower_components/jquery-ui/ui/autocomplete.js', 'bower_components/jstree/dist/jstree.min.js' ], 'bower_components/jquery-ui/ui/autocomplete.js', 'bower_components/jstree/dist/jstree.min.js', 'bower_components/jquery-serialize-object/jquery.serialize-object.js' ],
dest : '<%= app.dist1 %>/js/libraries.js', dest : '<%= app.dist1 %>/js/libraries.js',
}, },
app1 : { app1 : {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
"fontawesome": "~4.4.0", "fontawesome": "~4.4.0",
"highcharts": "~4.1.8", "highcharts": "~4.1.8",
"highmaps-beta": "highmaps#~1.0.1", "highmaps-beta": "highmaps#~1.0.1",
"jstree": "~3.2.1" "jstree": "~3.2.1",
"jquery-serialize-object": "^2.5.0"
} }
} }
/** /*
* Copyright 2014 Global Crop Diversity Trust * Copyright 2017 Global Crop Diversity Trust
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
**/ */
package org.genesys2.server.servlet.controller.admin; package org.genesys2.server.servlet.controller.admin;
...@@ -23,11 +23,13 @@ import com.fasterxml.jackson.annotation.JsonView; ...@@ -23,11 +23,13 @@ import com.fasterxml.jackson.annotation.JsonView;
import org.genesys.blocks.model.JsonViews; import org.genesys.blocks.model.JsonViews;
import org.genesys.blocks.oauth.model.AccessToken; import org.genesys.blocks.oauth.model.AccessToken;
import org.genesys.blocks.oauth.model.OAuthClient; import org.genesys.blocks.oauth.model.OAuthClient;
import org.genesys.blocks.oauth.model.OAuthRole;
import org.genesys.blocks.oauth.model.RefreshToken; import org.genesys.blocks.oauth.model.RefreshToken;
import org.genesys.blocks.oauth.service.OAuthClientDetailsService; import org.genesys.blocks.oauth.service.OAuthClientDetailsService;
import org.genesys.blocks.oauth.service.OAuthTokenStoreService; import org.genesys.blocks.oauth.service.OAuthTokenStoreService;
import org.genesys2.server.servlet.controller.BaseController; import org.genesys2.server.servlet.controller.BaseController;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
...@@ -36,9 +38,10 @@ import org.springframework.web.bind.annotation.RequestBody; ...@@ -36,9 +38,10 @@ import org.springframework.web.bind.annotation.RequestBody;
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.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/** /**
* Allow administrators to manage OAuth API keys. * Allow administrators to manage OAuth clients and keys.
*/ */
@Controller @Controller
@RequestMapping(OAuthManagementController.CONTROLLER_PATH) @RequestMapping(OAuthManagementController.CONTROLLER_PATH)
...@@ -126,6 +129,8 @@ public class OAuthManagementController extends BaseController { ...@@ -126,6 +129,8 @@ public class OAuthManagementController extends BaseController {
public String editClient(Model model, @PathVariable("id") String clientId) { public String editClient(Model model, @PathVariable("id") String clientId) {
final OAuthClient client = clientDetailsService.getClient(clientId); final OAuthClient client = clientDetailsService.getClient(clientId);
model.addAttribute("clientDetails", client); model.addAttribute("clientDetails", client);
model.addAttribute("ROLE_CLIENT", OAuthRole.CLIENT);
model.addAttribute("ROLE_TRUSTED_CLIENT", OAuthRole.TRUSTED_CLIENT);
return VIEW_PATH + "/edit"; return VIEW_PATH + "/edit";
} }
...@@ -150,13 +155,14 @@ public class OAuthManagementController extends BaseController { ...@@ -150,13 +155,14 @@ public class OAuthManagementController extends BaseController {
return "redirect:" + CONTROLLER_PATH + "/"; return "redirect:" + CONTROLLER_PATH + "/";
} }
@RequestMapping(value = "/save-client", method = RequestMethod.POST, params = { "id", "version", "action-save" }) @RequestMapping(value = "/save-client", method = RequestMethod.POST, params = { "id", "version", "action-save" }, consumes = { MediaType.APPLICATION_JSON_VALUE }, produces = {
public String saveExistinClient(Model model, @RequestBody @JsonView(JsonViews.Protected.class) OAuthClient updates, @RequestParam("id") long id, MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody OAuthClient saveExistingClient(Model model, @RequestBody @JsonView(JsonViews.Protected.class) OAuthClient updates, @RequestParam("id") long id,
@RequestParam("version") int version) { @RequestParam("version") int version) {
final OAuthClient clientDetails = clientDetailsService.updateClient(id, version, updates); final OAuthClient clientDetails = clientDetailsService.updateClient(id, version, updates);
return "redirect:" + CONTROLLER_PATH + "/" + clientDetails.getId() + "/edit"; return clientDetails;
} }
@PreAuthorize("hasRole('ADMINISTRATOR')") @PreAuthorize("hasRole('ADMINISTRATOR')")
......
...@@ -682,6 +682,14 @@ oauth-client.access-token.refreshTokenValiditySeconds=Refresh token validity ...@@ -682,6 +682,14 @@ oauth-client.access-token.refreshTokenValiditySeconds=Refresh token validity
oauth-client.access-token.defaultDuration=Use default oauth-client.access-token.defaultDuration=Use default
oauth-client.title=Client title oauth-client.title=Client title
oauth-client.description=Description oauth-client.description=Description
oauth-client.authorities=Granted authorities
oauth-client.registeredRedirectUri=Redirect URIs
oauth-client.resourceIds=Resource IDs
oauth-client.scope=Scopes
oauth-client.authorizedGrantTypes=Grant types
oauth-client.autoApprove=Auto-approve
oauth-client.autoApproveScopes=Auto-approved scopes
oauth2.error.invalid_client=Invalid Client ID. Validate your client_id and client_secret parameters. oauth2.error.invalid_client=Invalid Client ID. Validate your client_id and client_secret parameters.
team.user.enter.email=Enter user email team.user.enter.email=Enter user email
......
...@@ -20,20 +20,50 @@ ...@@ -20,20 +20,50 @@
<div class="row"> <div class="row">
<label class="col-lg-2 control-label"><spring:message code="oauth-client.title"/></label> <label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.title"/></label>
<div class="col-lg-10"><c:out value="${clientDetails.title}" /></div> <div class="col-lg-9 col-md-8"><c:out value="${clientDetails.title}" /></div>
</div> </div>
<div class="row"> <div class="row">
<label class="col-lg-2 control-label"><spring:message code="oauth-client.description"/></label> <label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.description"/></label>
<div class="col-lg-10"><c:out value="${clientDetails.description}" /></div> <div class="col-lg-9 col-md-8"><c:out value="${clientDetails.description}" /></div>
</div> </div>
<div class="row"> <div class="row">
<label class="col-lg-2 control-label"><spring:message code="oauth-client.id"/></label> <label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.id"/></label>
<div class="col-lg-10"><c:out value="${clientDetails.clientId}" /></div> <div class="col-lg-9 col-md-8"><c:out value="${clientDetails.clientId}" /></div>
</div> </div>
<div class="row"> <div class="row">
<label class="col-lg-2 control-label"><spring:message code="oauth-client.secret"/></label> <label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.secret"/></label>
<div class="col-lg-10"><c:out value="${clientDetails.clientSecret}" /></div> <div class="col-lg-9 col-md-8"><c:out value="${clientDetails.clientSecret}" /></div>
</div>
<!-- Extras -->
<div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.authorities"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.authorities}" /></div>
</div>
<div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.registeredRedirectUri"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.registeredRedirectUri}" /></div>
</div>
<div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.resourceIds"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.resourceIds}" /></div>
</div>
<div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.scope"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.scope}" /></div>
</div>
<div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.authorizedGrantTypes"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.authorizedGrantTypes}" /></div>
</div>
<div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.autoApprove"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.autoApprove}" /></div>
</div>
<div class="row">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.autoApproveScopes"/></label>
<div class="col-lg-9 col-md-8"><c:out value="${clientDetails.autoApproveScopes}" /></div>
</div> </div>
<security:authorize access="hasRole('ADMINISTRATOR')"> <security:authorize access="hasRole('ADMINISTRATOR')">
......
...@@ -3,82 +3,193 @@ ...@@ -3,82 +3,193 @@
<%@ include file="/WEB-INF/jsp/init.jsp" %> <%@ include file="/WEB-INF/jsp/init.jsp" %>
<html> <html>
<head> <head>
<title><spring:message code="oauth-client.page.profile.title" arguments="${clientDetails.clientId}" /></title> <title><spring:message code="oauth-client.page.profile.title" arguments="${clientDetails.clientId}"/></title>
</head> </head>
<body> <body>
<form role="form" class="form-horizontal validate" action="<c:url value="/admin/oauth-clients/save-client" />" method="post"> <form role="form" class="form-horizontal validate" action="<c:url value='/admin/oauth-clients/save-client' />" method="post">
<c:if test="${clientDetails.id gt 0}"> <c:if test="${clientDetails.id gt 0}">
<input type="hidden" name="id" value="${clientDetails.id}" /> <input type="hidden" name="id" value="${clientDetails.id}"/>
</c:if> </c:if>
<c:if test="${clientDetails == null}"> <input type="hidden" name="version" value="${clientDetails.version}"/>
<input type="hidden" name="newClient" value="new" /> <input type="hidden" name="clientId" value="${clientDetails.clientId}"/>
</c:if> <c:if test="${clientDetails == null}">
<div class="form-group"> <input type="hidden" name="newClient" value="new"/>
<label for="clientId" class="col-lg-2 control-label"><spring:message code="oauth-client.id" /></label> </c:if>
<div class="col-lg-10"> <div class="form-group">
<span class="form-control"><c:out value="${clientDetails.clientId}" /></span> <label for="clientId" class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.id"/></label>
<div class="col-lg-9 col-md-8">
<span class="form-control"><c:out value="${clientDetails.clientId}"/></span>
</div>
</div> </div>
</div> <div class="form-group">
<div class="form-group"> <label for="secret" class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.secret"/></label>
<label for="secret" class="col-lg-2 control-label"><spring:message code="oauth-client.secret" /></label> <div class="col-lg-9 col-md-8">
<div class="col-lg-10"> <input type="text" name="clientSecret" class="form-control" value="<c:out value='${clientDetails.clientSecret}' />"/>
<input type="text" name="client_secret" class="form-control" value="<c:out value="${clientDetails.clientSecret}" />" /> </div>
</div> </div>
</div> <div class="form-group">
<div class="form-group"> <label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.title"/></label>
<label for="redirectUri" class="col-lg-2 control-label"><spring:message code="oauth-client.title" /></label> <div class="col-lg-9 col-md-8">
<div class="col-lg-10"> <input type="text" name="title" class="form-control" value="<c:out value='${clientDetails.title}' />"/>
<input type="text" name="title" class="form-control" value="<c:out value="${clientDetails.title}" />" /> </div>
</div>
</div>
<div class="form-group">
<label for="redirectUri" class="col-lg-2 control-label"><spring:message code="oauth-client.description" /></label>
<div class="col-lg-10">
<textarea name="description" class="form-control"><c:out value="${clientDetails.description}" /></textarea>
</div>
</div>
<div class="form-group">
<label for="redirectUri" class="col-lg-2 control-label"><spring:message code="oauth-client.redirect.uri" /></label>
<div class="col-lg-10">
<textarea id="redirectUri" name="redirect" class="form-control"><c:out value="${clientDetails.redirect}" /></textarea>
<p class="help-block">oob,urn:ietf:wg:oauth:2.0:oob</p>
</div>
</div>
<div class="form-group">
<label for="redirectUri" class="col-lg-2 control-label"><spring:message code="oauth-client.access-token.accessTokenValiditySeconds" /></label>
<div class="col-lg-10">
<input type="text" name="accessTokenValidity" class="form-control" placeholder="<spring:message code="oauth-client.access-token.defaultDuration" />" value="<c:out value="${clientDetails.accessTokenValidity}" />" />
</div>
</div>
<div class="form-group">
<label for="redirectUri" class="col-lg-2 control-label"><spring:message code="oauth-client.access-token.refreshTokenValiditySeconds" /></label>
<div class="col-lg-10">
<input type="text" name="refreshTokenValidity" class="form-control" placeholder="<spring:message code="oauth-client.access-token.defaultDuration" />" value="<c:out value="${clientDetails.refreshTokenValidity}" />" />
</div>
</div>
<%--
<div class="form-group">
<label for="redirectUri" class="col-lg-2 control-label"><spring:message code="oauth-client.clientType" /></label>
<div class="col-lg-10">
<select id="clientType" name="clientType" class="form-control">
<option value="WEBAPP">Web application</option>
<option value="SERVICE">Service</option>
<option value="PACKAGED">Packaged</option>
</select>
</div>
</div>
--%>
<div class="form-group">
<div class="col-lg-offset-2 col-lg-10">
<input type="submit" name="action-save" value="<spring:message code="save"/>" class="btn btn-primary" />
<input type="submit" name="action-delete" value="<spring:message code="delete"/>" class="btn btn-default" />
<a class="btn btn-default" href="<c:url value="/admin/oauth-clients/" />" class="btn"> <spring:message code="cancel" />
</a>
</div> </div>
</div> <div class="form-group">
<!-- CSRF protection --> <label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.description"/></label>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <div class="col-lg-9 col-md-8">
</form> <textarea name="description" class="form-control"><c:out value="${clientDetails.description}"/></textarea>
</body> </div>
</html> </div>
<div class="form-group">
<label for="redirectUri" class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.redirect.uri"/></label>
<div class="col-lg-9 col-md-8">
<textarea style="min-height: 150px" id="redirectUri" name="redirect" class="form-control"><c:forEach items="${clientDetails.registeredRedirectUri}" var="uri"><c:out value="${uri}" />
</c:forEach></textarea>
<p class="help-block">One per line. For OOB: <code>oob</code>, <code>urn:ietf:wg:oauth:2.0:oob</code></p>
<ul>
<c:forEach items="${clientDetails.registeredRedirectUri}" var="uri">
<li><c:out value="${uri}"/></li>
</c:forEach>
</ul>
</div>
</div>
<div class="form-group">
<label for="redirectUri" class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.access-token.accessTokenValiditySeconds"/></label>
<div class="col-lg-9 col-md-8">
<input type="text" name="accessTokenValidity" class="form-control" placeholder="<spring:message code='oauth-client.access-token.defaultDuration' />" value="<c:out value='${clientDetails.accessTokenValidity}' />"/>
</div>
</div>
<div class="form-group">
<label for="redirectUri" class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.access-token.refreshTokenValiditySeconds"/></label>
<div class="col-lg-9 col-md-8">
<input type="text" name="refreshTokenValidity" class="form-control" placeholder="<spring:message code='oauth-client.access-token.defaultDuration'/>" value="<c:out value='${clientDetails.refreshTokenValidity}'/>"/>
</div>
</div>
<!-- Extras -->
<div class="form-group">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.authorities"/></label>
<div class="col-lg-9 col-md-8">
<div class="checkbox">
<label><input type="checkbox" name="roles[]" ${clientDetails.authorities.contains(ROLE_CLIENT) ? 'checked' : '' } value="CLIENT"/>
CLIENT</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="roles[]" ${clientDetails.authorities.contains(ROLE_TRUSTED_CLIENT) ? 'checked' : '' } value="TRUSTED_CLIENT"/>
TRUSTED_CLIENT</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.resourceIds"/></label>
<div class="col-lg-9 col-md-8">
<div class="form-control-static">
<c:out value="${clientDetails.resourceIds}"/>
</div>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.scope"/></label>
<div class="col-lg-9 col-md-8">
<div class="checkbox">
<label><input type="checkbox" name="scopes[]" ${clientDetails.scope.contains('read') ? 'checked' : '' } value="read"/>
Read</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="scopes[]" ${clientDetails.scope.contains('write') ? 'checked' : '' } value="write"/>
Write</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.authorizedGrantTypes"/></label>
<div class="col-lg-9 col-md-8">
<div class="checkbox">
<label><input type="checkbox" name="grantTypes[]" ${clientDetails.authorizedGrantTypes.contains('authorization_code') ? 'checked' : '' } value="authorization_code"/>
Authorization code</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="grantTypes[]" ${clientDetails.authorizedGrantTypes.contains('password') ? 'checked' : '' } value="password"/>
Password</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="grantTypes[]" ${clientDetails.authorizedGrantTypes.contains('refresh_token') ? 'checked' : '' } value="refresh_token"/>
Refresh token</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="grantTypes[]" ${clientDetails.authorizedGrantTypes.contains('client_credentials') ? 'checked' : '' } value="client_credentials"/>
Client credentials</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.autoApprove"/></label>
<div class="col-lg-9 col-md-8">
<div class="radio">
<label>
<input type="radio" name="autoApprove" ${clientDetails.autoApprove ? '' : 'checked' } value="false">Do not auto approve</label>
</div>
<div class="radio">
<label>
<input type="radio" name="autoApprove" ${clientDetails.autoApprove ? 'checked' : '' } value="true">Auto approve</label>
</div>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 col-md-4 control-label"><spring:message code="oauth-client.autoApproveScopes"/></label>
<div class="col-lg-9 col-md-8">
<div class="checkbox">
<label><input type="checkbox" name="autoApproveScopes[]" ${clientDetails.autoApproveScopes.contains('read') ? 'checked' : '' } value="read"/>
Read</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="autoApproveScopes[]" ${clientDetails.autoApproveScopes.contains('write') ? 'checked' : '' } value="write"/>
Write</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-3 col-lg-9">
<input type="button" onClick="return submitJson(this.form);" value="<spring:message code='save' />" class="btn btn-primary"/>
<input type="button" name="action-delete" value="<spring:message code='delete' />" class="btn btn-default"/>
<a class="btn btn-default" href="<c:url value='/admin/oauth-clients/' />" class="btn">
<spring:message code="cancel"/>
</a>
</div>
</div>
<!-- CSRF protection -->
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
<content tag="javascript">
<script type="text/javascript">
function submitJson(form) {
// console.log('Submitting as JSON', form);
var data = $(form).serializeObject();
delete data['_csrf'];
data.redirectUris = data.redirect.split('\n').map(function(x) { return x.trim(); });
delete data.redirect;
console.log(data);
$.ajax({
url: form.action + "?action-save=1&id=" + data.id + "&version=" + data.version,
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
data: (data === null
? null
: JSON.stringify(data)),
success: function (response) {
// console.log('saved', response);
window.location = window.location;
}
});
return false;
}
</script>
</content>
</body>
</html>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment