summaryrefslogtreecommitdiffstats
path: root/idrop-web
diff options
context:
space:
mode:
authorMike Conway <mikeconway@Mike-Conways-MacBook-Pro.local>2011-05-15 15:40:41 (GMT)
committer Mike Conway <mikeconway@Mike-Conways-MacBook-Pro.local>2011-05-15 15:40:41 (GMT)
commit653ecadf8246b7404b1c4a570a1f6bf0b23316c0 (patch)
tree02bb1fa48c8e85e17312ee4be510792c95fdeb58 /idrop-web
parent742f1f68b91f0d79d51d76ed3d270557cf4026d1 (diff)
downloadQCG-Data-653ecadf8246b7404b1c4a570a1f6bf0b23316c0.zip
QCG-Data-653ecadf8246b7404b1c4a570a1f6bf0b23316c0.tar.gz
QCG-Data-653ecadf8246b7404b1c4a570a1f6bf0b23316c0.tar.bz2
acl mgmnt in web
Diffstat (limited to 'idrop-web')
-rw-r--r--idrop-web/grails-app/conf/Config.groovy2
-rw-r--r--idrop-web/grails-app/controllers/org/irods/mydrop/controller/SharingController.groovy67
-rw-r--r--idrop-web/grails-app/views/error.gsp56
-rw-r--r--idrop-web/grails-app/views/sharing/aclDialog.gsp24
-rw-r--r--idrop-web/release_notes.txt15
-rw-r--r--idrop-web/test/unit/org/irods/mydrop/controller/SharingControllerTests.groovy21
-rw-r--r--idrop-web/web-app/js/mydrop/home.js86
7 files changed, 179 insertions, 92 deletions
diff --git a/idrop-web/grails-app/conf/Config.groovy b/idrop-web/grails-app/conf/Config.groovy
index 2dbcef2..1556fe8 100644
--- a/idrop-web/grails-app/conf/Config.groovy
+++ b/idrop-web/grails-app/conf/Config.groovy
@@ -93,7 +93,7 @@ log4j = {
'net.sf.ehcache.hibernate'
info 'org.irods.mydrop'
- info 'org.irods.jargon'
+ debug 'org.irods.jargon'
info 'grails.app'
warn 'org.mortbay.log',
diff --git a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/SharingController.groovy b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/SharingController.groovy
index a5c2ecd..87e93b2 100644
--- a/idrop-web/grails-app/controllers/org/irods/mydrop/controller/SharingController.groovy
+++ b/idrop-web/grails-app/controllers/org/irods/mydrop/controller/SharingController.groovy
@@ -1,6 +1,8 @@
package org.irods.mydrop.controller
+import grails.converters.JSON
+
import org.irods.jargon.core.connection.IRODSAccount
import org.irods.jargon.core.exception.JargonException
import org.irods.jargon.core.exception.JargonRuntimeException
@@ -9,6 +11,7 @@ import org.irods.jargon.core.pub.CollectionAO
import org.irods.jargon.core.pub.CollectionAndDataObjectListAndSearchAO
import org.irods.jargon.core.pub.DataObjectAO
import org.irods.jargon.core.pub.IRODSAccessObjectFactory
+import org.irods.jargon.core.pub.UserAO
import org.irods.jargon.core.pub.domain.DataObject
import org.springframework.security.core.context.SecurityContextHolder
@@ -82,15 +85,18 @@ class SharingController {
log.info "params: ${params}"
// if a user is provided, this will be an edit, otherwise, it's a create
- def userName = params['userName'];
+ def userName = params['userName']
def absPath = params['absPath']
+ def isCreate = params['create']
+
if (!absPath) {
log.error "no absPath in request for prepareAclDialog()"
throw new JargonException("a path was not supplied")
}
- render(view:"aclDialog", model:[absPath:absPath, userName:userName, userPermissionEnum:FilePermissionEnum.listAllValues()])
+
+ render(view:"aclDialog", model:[absPath:absPath, userName:userName, userPermissionEnum:FilePermissionEnum.listAllValues(), isCreate:isCreate])
}
@@ -101,9 +107,10 @@ class SharingController {
def updateAcl = {
log.info "updating ACL"
log.info "params: ${params}"
- def userName = params['userName'];
+ def userName = params['userName']
def acl = params['acl']
def absPath = params['absPath']
+ def isCreate = params['create']
if (!userName) {
@@ -117,13 +124,17 @@ class SharingController {
if (!absPath) {
throw new JargonException("absPath not supplied")
}
+
+ if (!isCreate) {
+ isCreate = true
+ }
log.info("updateACL userName: ${userName} acl: ${acl} absPath: ${absPath}")
CollectionAndDataObjectListAndSearchAO collectionAndDataObjectListAndSearchAO = irodsAccessObjectFactory.getCollectionAndDataObjectListAndSearchAO(irodsAccount)
def retObj = collectionAndDataObjectListAndSearchAO.getFullObjectForType(absPath)
-
+
def isDataObject = retObj instanceof DataObject
// FIXME: add this into the file object superclass in jargon-core
@@ -131,6 +142,16 @@ class SharingController {
if (isDataObject) {
log.debug("setting ACLs for a data object")
DataObjectAO dataObjectAO = irodsAccessObjectFactory.getDataObjectAO(irodsAccount)
+
+ // if creating a new ACL, an ACL cannot already exist
+
+ if (isCreate) {
+ def existingPermission = dataObjectAO.getPermissionForDataObjectForUserName(absPath, userName)
+ if (existingPermission) {
+ response.sendError(500,"The given user already has a sharing permission")
+ return
+ }
+ }
if (acl == "READ") {
dataObjectAO.setAccessPermissionRead(irodsAccount.getZone(), absPath, userName)
@@ -144,6 +165,15 @@ class SharingController {
} else {
log.debug("setting ACLs for collection")
CollectionAO collectionAO = irodsAccessObjectFactory.getCollectionAO(irodsAccount)
+
+ if (isCreate) {
+ def existingPermission = collectionAO.getPermissionForUserName(absPath, userName)
+ if (existingPermission) {
+ response.sendError(500,"The given user already has a sharing permission")
+ return
+ }
+ }
+
if (acl == "READ") {
collectionAO.setAccessPermissionRead(irodsAccount.getZone(), absPath, userName, true)
} else if (acl == "WRITE") {
@@ -159,4 +189,33 @@ class SharingController {
render "OK"
}
+
+ /**
+ * List the users in iRODS based on user name. A 'term' parameter may be supplied, in which case, a LIKE% query will be used to find
+ * matching user names. This method returns JSON as expected for the JQuery UI autocomplete text box
+ */
+ def listUsersForAutocomplete = {
+
+ log.info("listUsersForAutocomplete")
+ def term = params['term']
+ if (!term) {
+ term = ""
+ }
+ log.info("term:${term}")
+
+ UserAO userAO = irodsAccessObjectFactory.getUserAO(irodsAccount)
+
+ def userList = userAO.findUserNameLike(term);
+ def jsonBuff = []
+
+
+ userList.each {
+ jsonBuff.add(
+ ["label": it]
+ )
+ }
+
+ render jsonBuff as JSON
+
+ }
}
diff --git a/idrop-web/grails-app/views/error.gsp b/idrop-web/grails-app/views/error.gsp
index cfc512a..1f00821 100644
--- a/idrop-web/grails-app/views/error.gsp
+++ b/idrop-web/grails-app/views/error.gsp
@@ -1,54 +1,4 @@
-<html>
- <head>
- <title>Grails Runtime Exception</title>
- <style type="text/css">
- .message {
- border: 1px solid black;
- padding: 5px;
- background-color:#E9E9E9;
- }
- .stack {
- border: 1px solid black;
- padding: 5px;
- overflow:auto;
- height: 300px;
- }
- .snippet {
- padding: 5px;
- background-color:white;
- border:1px solid black;
- margin:3px;
- font-family:courier;
- }
- </style>
- </head>
- <body>
- <h1>Grails Runtime Exception</h1>
- <h2>Error Details</h2>
-
- <div class="message">
- <strong>Error ${request.'javax.servlet.error.status_code'}:</strong> ${request.'javax.servlet.error.message'.encodeAsHTML()}<br/>
- <strong>Servlet:</strong> ${request.'javax.servlet.error.servlet_name'}<br/>
- <strong>URI:</strong> ${request.'javax.servlet.error.request_uri'}<br/>
- <g:if test="${exception}">
- <strong>Exception Message:</strong> ${exception.message?.encodeAsHTML()} <br />
- <strong>Caused by:</strong> ${exception.cause?.message?.encodeAsHTML()} <br />
- <strong>Class:</strong> ${exception.className} <br />
- <strong>At Line:</strong> [${exception.lineNumber}] <br />
- <strong>Code Snippet:</strong><br />
- <div class="snippet">
- <g:each var="cs" in="${exception.codeSnippet}">
- ${cs?.encodeAsHTML()}<br />
- </g:each>
- </div>
- </g:if>
- </div>
- <g:if test="${exception}">
- <h2>Stack Trace</h2>
- <div class="stack">
- <pre><g:each in="${exception.stackTraceLines}">${it.encodeAsHTML()}<br/></g:each></pre>
- </div>
- </g:if>
- </body>
-</html> \ No newline at end of file
+ <span>
+ ${request.'javax.servlet.error.message'.encodeAsHTML()}<br/>
+ </span> \ No newline at end of file
diff --git a/idrop-web/grails-app/views/sharing/aclDialog.gsp b/idrop-web/grails-app/views/sharing/aclDialog.gsp
index 54f3094..f668be5 100644
--- a/idrop-web/grails-app/views/sharing/aclDialog.gsp
+++ b/idrop-web/grails-app/views/sharing/aclDialog.gsp
@@ -1,20 +1,32 @@
-<div id="aclDialogDiv">
-<div id="aclDialogMessageArea">
- <!-- message area for acl dialogs -->
-</div>
+<div id="aclDialogDiv" class="roundedContainer">
+ <div id="aclDialogMessageArea" style="width:90%;">
+ <!-- message area for acl dialogs -->
+ </div>
<div style="clear: both;">
<g:form controller="sharing" action="updateAcl" method="post"
name="aclUpdateForm">
<fieldset id="verticalForm">
+ <g:hiddenField name="isCreate" value="${isCreate}" />
<label for="absPath">Path:</label>
- <g:textField name="absPath" value="${absPath}" readonly="true" />
+ <g:textArea name="absPath" value="${absPath}" readonly="true" />
<br /> <label for="userName">User Name:</label>
<g:textField id="userName" name="userName" value="${userName}" />
<br /> <label for="acl">Share Type:</label>
<g:select name="acl" from="${userPermissionEnum}" />
<br />
-
+ <div id="detailsDialogToolbar" class="fg-toolbar ui-widget-header">
+ <div id="detailsDialogMenu" class="fg-buttonset fg-buttonset-multi"
+ style="float: left, clear : both; width: 90%;">
+ <button type="button" id="updateAclDetailButton"
+ class="ui-state-default ui-corner-all" value="addAcl"
+ onclick="submitAclDialog()")>Save</button>
+ <button type="button" id="cancelAddAclButton"
+ class="ui-state-default ui-corner-all" value="cancelAdd"
+ onclick="closeAclAddDialog()")>Cancel</button>
+ </div>
+ </div>
</fieldset>
</g:form>
</div>
</div>
+s \ No newline at end of file
diff --git a/idrop-web/release_notes.txt b/idrop-web/release_notes.txt
index 94fe819..7539918 100644
--- a/idrop-web/release_notes.txt
+++ b/idrop-web/release_notes.txt
@@ -5,7 +5,9 @@ TODO:
global
- *revise error handling - global error strategy (simple text message coming back? wrapped in flash?)
+ *revise error handling - global error strategy (simple text message coming back? wrapped in flash?) - see home.js for acl errors, update ajax error
+ *redo prepare for call .message selector to clear all messages
+ *css 90% for message and toolbar defaults
*sizing of main panel
*wierd init sizing
*no expand when hide rhs bar
@@ -26,8 +28,14 @@ global
*upload success?
*Acl
- *acl update success/error
*crud
+ * add
+ * add when no perms
+ xxx* add when exists
+ * add when user not exists
+ *edit - none = delete
+ *delete
+ *delete when not there
*user dnd
*table sizing
@@ -38,15 +46,14 @@ global
*users
*list users on system in rhs as table w/search?
+ *dnd file to user
*metadata
*crud
-
*home
*remove 'last activity' for now
*quota
*quick load
-*lc revisions for jq 1.5s
\ No newline at end of file
diff --git a/idrop-web/test/unit/org/irods/mydrop/controller/SharingControllerTests.groovy b/idrop-web/test/unit/org/irods/mydrop/controller/SharingControllerTests.groovy
index d84a35d..916afac 100644
--- a/idrop-web/test/unit/org/irods/mydrop/controller/SharingControllerTests.groovy
+++ b/idrop-web/test/unit/org/irods/mydrop/controller/SharingControllerTests.groovy
@@ -1,5 +1,6 @@
package org.irods.mydrop.controller
+import grails.converters.*
import grails.test.ControllerUnitTestCase
import java.util.Properties
@@ -11,6 +12,7 @@ import org.irods.jargon.core.pub.CollectionAndDataObjectListAndSearchAO
import org.irods.jargon.core.pub.DataObjectAO
import org.irods.jargon.core.pub.IRODSAccessObjectFactory
import org.irods.jargon.core.pub.IRODSFileSystem
+import org.irods.jargon.core.pub.UserAO
import org.irods.jargon.core.pub.domain.Collection
import org.irods.jargon.core.pub.domain.DataObject
import org.irods.jargon.core.pub.domain.UserFilePermission
@@ -155,4 +157,23 @@ class SharingControllerTests extends ControllerUnitTestCase {
shouldFail(JargonException) { controller.prepareAclDialog() }
}
+
+ void listUsersForAutocomplete() {
+ def testUser = "t"
+ def irodsAccessObjectFactory = Mockito.mock(IRODSAccessObjectFactory.class)
+ UserAO userAO = Mockito.mock(UserAO.class)
+ List<String> retUsers = new ArrayList<String>();
+ retUsers.add("test1");
+ retUsers.add('test2');
+ Mockito.when(userAO.findUserNameLike(testUser)).thenReturn(retUsers);
+ Mockito.when(irodsAccessObjectFactory.getUserAO(irodsAccount)).thenReturn(userAO)
+
+ controller.irodsAccessObjectFactory = irodsAccessObjectFactory
+ controller.irodsAccount = irodsAccount
+ controller.params.term = testUser
+ controller.listUsersForAutocomplete()
+
+ def jsonResult = JSON.parse(controllerResponse)
+ assertNotNull("missing json result", jsonResult)
+ }
}
diff --git a/idrop-web/web-app/js/mydrop/home.js b/idrop-web/web-app/js/mydrop/home.js
index a2f23a8..92381ea 100644
--- a/idrop-web/web-app/js/mydrop/home.js
+++ b/idrop-web/web-app/js/mydrop/home.js
@@ -301,16 +301,21 @@ function aclUpdate(value, settings, userName) {
/**
* Prepare the dialog to allow create of ACL data
*/
-function prepareAclDialog() {
+function prepareAclDialog(isNew) {
if (selectedPath == null) {
alert("No path is selected, Share cannot be set");
return;
}
+ if (isNew == null) {
+ isNew = true;
+ }
+
var url = "/sharing/prepareAclDialog";
var params = {
- absPath : selectedPath
+ absPath : selectedPath,
+ create : true
}
lcSendValueWithParamsAndPlugHtmlInDiv(url, params, "", function(data) {
@@ -327,22 +332,20 @@ function prepareAclDialog() {
*/
function showAclDialog(data) {
lcPrepareForCall();
-
- $("#aclDialogArea").html(data);
- $("#aclDialogArea").dialog({
- "width" : 400,
- "modal" : true,
- "buttons" : {
- "Ok" : function() {
- submitAclDialog();
- },
- "Cancel" : function() {
- $(this).dialog("close");
- }
- },
- "title" : "Edit Share Permission"
+ $("#aclDialogArea").html(data).fadeIn('slow');
+ var mySource = context + "/sharing/listUsersForAutocomplete";
+ $("#userName").autocomplete({
+ minLength : 3,
+ source : mySource
});
+ /**
+ * $("#aclDialogArea").html(data); $("#aclDialogArea").dialog({ "width" :
+ * 400, "modal" : true, "buttons" : { "Ok" : function() { submitAclDialog(); },
+ * "Cancel" : function() { $(this).dialog("close"); } }, "title" : "Edit
+ * Share Permission" });
+ */
+
}
function submitAclDialog() {
@@ -366,6 +369,8 @@ function submitAclDialog() {
throw "no collection or data object selected";
}
+ var isCreate = $('[name=isCreate]').val();
+
lcShowBusyIconInDiv(aclDialogMessageSelector);
var params = {
@@ -377,19 +382,52 @@ function submitAclDialog() {
var jqxhr = $.post(context + aclUpdateUrl, params,
function(data, status, xhr) {
lcClearDivAndDivClass(aclDialogMessageSelector);
-
}, "html").error(
- function() {
+ function(xhr, status, error) {
setMessageInArea(aclDialogMessageSelector,
- "Error saving sharing permissions");
- }).success(function() {
- $("#aclDialogArea").dialog("close");
+ xhr.responseText);
+ }).success(
+ function() {
+ if (isCreate) {
+ addRowToAclDetailsTable(userName, acl);
+ alert("adding row to table");
+ }
+ closeAclAddDialog();
+ setMessageInArea("#aclMessageArea",
+ "Sharing permission saved successfully");
- // FIXME: add new row in table
+
+ });
- // updateBrowseDetailsForPathBasedOnCurrentModel(selectedPath);
- setMessage("Sharing permission saved successfully")
+}
+function closeAclAddDialog() {
+ $("#aclDialogArea").hide().fadeOut('slow', new function() {
+ $("#aclDialogArea").html("")
});
}
+
+function addRowToAclDetailsTable(userName, permission) {
+ // var nNodes = aclDetailsTable.fnGetNodes( );
+ alert("adding row");
+ var idxs = $("#aclDetailsTable")
+ .dataTable()
+ .fnAddData(
+ [
+ "<input id=\"selectedAcl\" type=\"checkbox\" name=\"selectedAcl\">",
+ userName, permission ], true);
+ var newNode = $("#aclDetailsTable").dataTable().fnGetNodes()[idxs[0]];
+ $(newNode).attr("id", userName);
+ alert("new node=" + newNode);
+}
+
+
+
+function deleteAcl() {
+ var aclSelectors = $('[name=selectedAcl]').filter(':checked').each(function() {
+ var val = this;
+ alert(val);
+ });
+
+}