diff --git a/docs/UserGuide/src/main/markdown/frontend.md b/docs/UserGuide/src/main/markdown/frontend.md index a25b38c7f84..30b194e1033 100644 --- a/docs/UserGuide/src/main/markdown/frontend.md +++ b/docs/UserGuide/src/main/markdown/frontend.md @@ -19,6 +19,7 @@ Chapter 3. Frontend * [Deleting files and directories](#deleting-files-and-directories) * [Creating directories](#creating-directories) * [Moving and renaming](#moving-and-renaming) + * [Changing group-ownership](#changing-group-ownership) * [Modifying QoS](#modifying-qos) * [Managing extended attributes](#managing-extended-attributes) + [QoS Management](#qos-management) @@ -907,6 +908,50 @@ code, and the response entity is the JSON object: } ``` +### Changing group-ownership + +The POSIX permission model describes how a file or directory has two +ownerships: a personal (or user) owner and a group owner. These two +identities are used to determine which operations any individual is +allowed to make. + +A common goal is to grant specific access to a file or directory to a +group of people the people outside this group are denied; for example, +making a file readable only to members of a group. This is possible +by establishing a group (within dCache) that represents the target +group of people, and assign the corresponding gid as group-owner of +the file or directory. The desired access may then be specified for +the group-owner. + +Sometimes a file or directory has the wrong group-owner: either +because of changing permissions policy or the file was uploaded using +a client that does not allow specifying the desired group-owner. In +these circumstances, the group-owner must be changed. + +You are only allowed to change the group-ownership of files or +directories you own (as the personal- or user owner). You are also +only allowed to change group-ownership to a group of which you are +already a member. + +Changing group-ownership is done by making a POST request to the +resource representing the file or directory; for example, to change +the group-ownership of the file `/Users/paul/my-data`, the POST +request would target `/api/v1/namespace/Users/paul/my-data`. + +The POST request must contain a JSON object with the `action` property +set to `chgrp`, and the `gid` property containing an integer value, +which is the desired group owner. + +The following example requests the target have gid 1000 as the new +group-owner: + +```json +{ + "action": "chgrp", + "gid": 1000 +} +``` + ### Modifying QoS Each file or directory has a corresponding QoS value. To modify this diff --git a/modules/dcache-frontend/src/main/java/org/dcache/restful/resources/namespace/FileResources.java b/modules/dcache-frontend/src/main/java/org/dcache/restful/resources/namespace/FileResources.java index dcf90239755..c1a01c31b4f 100644 --- a/modules/dcache-frontend/src/main/java/org/dcache/restful/resources/namespace/FileResources.java +++ b/modules/dcache-frontend/src/main/java/org/dcache/restful/resources/namespace/FileResources.java @@ -301,7 +301,15 @@ public Response cmrResources(@ApiParam(value="Path of file or directory to be mo + "where the JSON Object's key is " + "the attribute name and the " + "corresponding JSON Object's " - + "value is this attribute's value.", + + "value is this attribute's value." + + "\n" + + "If action is 'chgrp' then the " + + "command requests the change of " + + "group-owner of the target file " + + "or directory. The value of the " + + "JSON object 'gid' item is the " + + "numerical value of the desired " + + "new group-owner.", required = true, examples = @Example({ @ExampleProperty(mediaType = "MV", @@ -335,7 +343,12 @@ public Response cmrResources(@ApiParam(value="Path of file or directory to be mo + " \"attr-1\",\n" + " \"attr-2\"\n" + " ]\n" - + "}")})) + + "}"), + @ExampleProperty(mediaType = "CHGRP", + value = "{\n" + + " \"action\" : \"chgrp\"\n" + + " \"gid\" : 1000\n" + + "}")})) String requestPayload) { try { @@ -391,6 +404,10 @@ public Response cmrResources(@ApiParam(value="Path of file or directory to be mo } pnfsHandler.writeExtendedAttribute(path, attributes, mode); break; + case "chgrp": + int gid = reqPayload.getInt("gid"); + pnfsHandler.setFileAttributes(path, FileAttributes.ofGid(gid)); + break; } } catch (FileNotFoundCacheException e) { throw new NotFoundException(e);