001/*
002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu
016 */
017package org.nuxeo.shell.automation.cmds;
018
019import java.util.HashMap;
020
021import jline.ANSIBuffer;
022
023import org.nuxeo.ecm.automation.client.model.DocRef;
024import org.nuxeo.shell.Argument;
025import org.nuxeo.shell.Command;
026import org.nuxeo.shell.Context;
027import org.nuxeo.shell.Parameter;
028import org.nuxeo.shell.Shell;
029import org.nuxeo.shell.ShellConsole;
030import org.nuxeo.shell.ShellException;
031import org.nuxeo.shell.automation.DocRefCompletor;
032import org.nuxeo.shell.automation.RemoteContext;
033import org.nuxeo.shell.automation.Scripting;
034import org.nuxeo.shell.utils.ANSICodes;
035import org.nuxeo.shell.utils.StringUtils;
036
037/**
038 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
039 */
040@Command(name = "perms", help = "Set or view permissions on a document")
041public class Perms implements Runnable {
042
043    @Context
044    protected RemoteContext ctx;
045
046    @Parameter(name = "-acl", hasValue = true, help = "The ACL to view or modify. If not specified then in write mode the local ACL is used and in view mode all acls are printed.")
047    protected String acl;
048
049    @Parameter(name = "-remove", hasValue = false, help = "Remove the given acl.")
050    protected boolean remove;
051
052    @Parameter(name = "-grant", hasValue = true, help = "If used the ACL will be modified by granting the specified permission on the specified user. The grant value format is \"user:permission\".")
053    protected String grant;
054
055    @Parameter(name = "-deny", hasValue = true, help = "If used the ACL will be modified by denying the specified permission on the specified user. The deny value format is \"user:permission\".")
056    protected String deny;
057
058    @Argument(name = "doc", index = 0, required = false, completor = DocRefCompletor.class, help = "The target document. If not specified the current document is used. To use UID references prefix them with 'doc:'.")
059    protected String path;
060
061    public void run() {
062        DocRef doc = ctx.resolveRef(path);
063        try {
064            if (remove) {
065                removeAcl(doc, acl);
066            } else if (grant == null && deny == null) {
067                printAcl(ctx.getShell().getConsole(), doc, acl);
068            } else {
069                setAcl(doc, acl, grant, deny);
070            }
071        } catch (ShellException e) {
072            throw e;
073        } catch (Exception e) {
074            throw new ShellException("Failed to set property on " + doc, e);
075        }
076    }
077
078    protected void setAcl(DocRef doc, String acl, String grant, String deny) throws Exception {
079        if (grant != null) {
080            String[] ar = StringUtils.split(grant, ':', true);
081            if (ar.length != 2) {
082                throw new ShellException("Invalid grant expression: Use \"user:permission\".");
083            }
084            ctx.getDocumentService().setPermission(doc, ar[0], ar[1], acl, true);
085        }
086        if (deny != null) {
087            String[] ar = StringUtils.split(deny, ':', true);
088            if (ar.length != 2) {
089                throw new ShellException("Invalid deny expression: Use \"user:permission\".");
090            }
091            ctx.getDocumentService().setPermission(doc, ar[0], ar[1], acl, false);
092        }
093    }
094
095    protected void printAcl(ShellConsole console, DocRef doc, String acl) throws Exception {
096        HashMap<String, Object> ctx = new HashMap<String, Object>();
097        if (acl != null) {
098            ctx.put("acl", acl);
099        }
100        ctx.put("ref", doc.toString());
101        String result = Scripting.run("scripts/printAcl.groovy", ctx, null);
102        ANSIBuffer buf = Shell.get().newANSIBuffer();
103        ANSICodes.appendTemplate(buf, result, false);
104        console.println(buf.toString());
105    }
106
107    protected void removeAcl(DocRef doc, String acl) throws Exception {
108        if (acl == null) {
109            throw new ShellException("In remove mode the -acl parameter is required!");
110        }
111        ctx.getDocumentService().removeAcl(doc, acl);
112    }
113
114}