acs-cli 0.0.9
A command line interface to the Alfresco Content Services REST API
Keywords: alfresco acs rest cli

ACS-CLI
=======

What is it?
-----------

A command line tool for accessing Alfresco Content Services repository
servers through the public REST APIs.

The motivation for building this tool is two-fold: firstly as an
interesting way for me to learn python; and secondly it's the tool I
always wish existed. The code probably isn't very *pythonic* or well
organised, but hopefully this will get better :-)

Installation
------------

Use (python3) pip to install:

::

    pip3 install acs-cli

To try this out in docker with a self-destructing temporary container:

::

    mward@holly:~$ docker run -it --rm ubuntu:16.04
    root@f957e9b7154f:/# apt update && apt install -y python3 python3-pip
    root@f957e9b7154f:/# pip3 install acs-cli


Warning
-------

This is a proof of concept and must be considered *alpha* quality
software at best.

Getting help
------------

You can ask for help at the program, API/command or subcommand levels, for example:

::

    # Get help on the program:
    $ acs --help

    # Get help on using the sites API:
    $ acs sites --help

    # Get help on using list-sites:
    $ acs sites list-sites --help

    # Get help on using the login command:
    $ acs login --help

Shell tab completion
--------------------

Tab completion can be enabled by adding the following to your ``.bashrc``:

::

    eval "$(register-python-argcomplete acs)"

Example usage
-------------

Without any arguments, you may log in to http://localhost:8080/alfresco
using the username 'admin' and will be prompted for a password.

::

    mward@holly:~$ acs login
    Logging in admin to http://localhost:8080/alfresco
    Password:
    mward@holly:acs-cli$

Use the ``--username`` or ``--password`` options to log in with
different credentials:

::

    mward@holly:~$ acs login --username=asmith --password=ban4n4@!

Once logged in, APIs may be exercised by using the general format:

::

    acs api-collection api-command [options...] <arguments...>

Here we see site creation:

::

    mward@holly:~$ acs sites create-site --id accounting --title 'Accounting Collaboration' --description 'Site for collaboration relating to the accounting process' --visibility PRIVATE
    {
        "entry": {
            "id": "accounting",
            "guid": "ee6d721d-e3b0-4299-a51f-afd4b59bfece",
            "visibility": "PRIVATE",
            "preset": "site-dashboard",
            "description": "Site for collaboration relating to the accounting process",
            "title": "Accounting Collaboration",
            "role": "SiteManager"
        }
    }

...and here we see the people API being used to create a person entity:

::

    mward@holly:~$ acs people create-person --id bsmith --first-name Brian --email brian.smith@example.com --password password --json-data '{ "lastName":"Smith", "properties":{"papi:jabber":"myjabber@jabber.example.com"} }'
    {
        "entry": {
            "id": "bsmith",
            "company": {},
            "lastName": "Smith",
            "aspectNames": [
                "papi:comms"
            ],
            "firstName": "Brian",
            "properties": {
                "papi:jabber": "myjabber@jabber.example.com"
            },
            "enabled": true,
            "email": "brian.smith@example.com",
            "emailNotificationsEnabled": true
        }
    }

Note: the custom property ``papi:jabber`` has previously been enabled in this example, by installing a custom dynamic model into the repository server.
The custom model's properties/aspects are not normally available.

The ``--json-data`` property can carry an arbitrary JSON payload to be sent to the REST API endpoint. You can mix and match this with
the convenient named arguments (e.g. ``--email``), however if a key is supplied in both methods then an error will be raised.

All API operations accept the ``--query`` option to specify a JMESPath
expression. Here for example, we choose to only display the ``id`` and
``email`` fields of the returned ``entry`` object:

::

    mward@holly:~$ acs people get-person --person-id=jbloggs --query 'entry.[id,email]'
    [
        "jbloggs",
        "jbloggs@example.com"
    ]

And here, we use the ``--query`` option to view ``id``, ``firstName``
and ``email`` of *each* entry in the list of people:

::

    mward@holly:~$ acs people list-people --query='list.entries[].entry.[id,firstName,email]'
    [
        [
            "admin",
            "Administrator",
            "admin@alfresco.com"
        ],
        [
            "guest",
            "Guest",
            null
        ],
        [
            "jbloggs",
            "Joe",
            "jbloggs@example.com"
        ]
    ]

Any *list* operation that may be paged can be used with the
``--max-items`` and ``--skip-count`` options, used here to show two
results after skipping the first 4. This may be thought of as showing
the *third* page of results.

::

    mward@holly:~$ acs people list-people --query='list.entries[].entry.[firstName]' --max-items=2 --skip-count=4
    [
        [
            "Joe10"
        ],
        [
            "Joe11"
        ]
    ]

The ``sites list-sites`` API command may be used to list "sites".
This is a paged API and here we use it without the
``--max-items`` and ``--skip-count`` options which default to 10 and 0
respectively:

::

    mward@holly:~$ acs sites list-sites --query='list.entries[].entry'
    [
        {
            "title": "accounts",
            "role": "SiteManager",
            "guid": "80dbd63c-3dbf-4005-bd16-e324fa8b4517",
            "id": "accounts",
            "visibility": "PUBLIC",
            "preset": "site-dashboard"
        },
        {
            "title": "Sample: Web Site Design Project",
            "guid": "b4cff62a-664d-4d45-9302-98723eac1319",
            "id": "swsdp",
            "visibility": "PUBLIC",
            "description": "This is a Sample Alfresco Team site.",
            "preset": "site-dashboard"
        }
    ]

In this example, we create a folder within the "My Files" folder for jbloggs:

::

    mward@holly:~$ acs nodes create-node --node-id=-my- --node-type=cm:folder --name=my_notes --json-data '{"properties":{"cm:title":"My daily notes"}}'
    {
        "entry": {
            "createdByUser": {
                "displayName": "Joe Bloggs",
                "id": "jbloggs"
            },
            "modifiedAt": "2017-04-07T13:36:55.848+0000",
            "id": "190a4896-1492-4142-9cd3-7f80d8012514",
            "createdAt": "2017-04-07T13:36:55.848+0000",
            "modifiedByUser": {
                "displayName": "Joe Bloggs",
                "id": "jbloggs"
            },
            "properties": {
                "cm:title": "My daily notes"
            },
            "name": "my_notes",
            "aspectNames": [
                "cm:titled",
                "cm:auditable"
            ],
            "isFile": false,
            "isFolder": true,
            "parentId": "29dd6a63-da4c-4f96-8edb-ad9808fa198b",
            "nodeType": "cm:folder"
        }
    }

The alias ``-my-`` is used for the node where the child folder will be created.

The common server-side filtering and projection API parameters are supported, using similarly named command line
options such as ``--include``, ``--fields`` and ``--where``.
For example, we can use the where clause to view site membership of PRIVATE sites, and restrict
the returned fields to ``role`` and ``id``:

::

    mward@holly:~$ acs sites list-site-memberships --person-id admin --where="(visibility='PUBLIC')" --fields=id,role
    {
        "list": {
            "pagination": {
                "count": 19,
                "totalItems": 19,
                "hasMoreItems": false,
                "maxItems": 100,
                "skipCount": 0
            },
            "entries": [
                {
                    "entry": {
                        "role": "SiteManager",
                        "id": "swsdp"
                    }
                },
                {
                    "entry": {
                        "role": "SiteManager",
                        "id": "site-e26b050b"
                    }
                },
                {
                    "entry": {
            ...

You may ask what the difference between these and the ``--query`` options are. The ``--query`` option provides support
for post-response filtering and manipulation through the JMESPath query language. JMESPath is a very powerful yet
simple way to manipulate the response object but since it is performed as a post-response processing stage, may affect
paging (e.g. the paging details may say that there are more results than are present in the final results). Also by
using the server-side functionality of ``include``, ``fields`` and ``where``, you may conserve bandwidth by reducing the
number of results transmitted "over the wire".