Jump to content

How to control eprint workflow based on a user field

From EPrints Documentation

NOTE: This was originally written based on experience of an EPrints 3.3.10 install. It has been updated following a post on the EP-Tech list Restrict sepcific editor only upload in specific divisions (May 2026), and seems to work against a v3.4.6 archive.

Task[edit]

How to control the EPrint workflow, only show options (e.g. divisions/collections) that a user can deposit into? e.g.

  • A user belongs to a specific division and can only assign sub-divisions from their division
  • We have many 'collections'. Each EPrint belongs to one collection. Users can only deposit items into specific collections.

Divisions example[edit]

This is based on the default 'divisions', and is suitable for a user that belongs to one division. This approach won't work if you need to restrict to multiple divisions.

Add field to user, to control the division (or sub-divisions) they can deposit to[edit]

$c->add_dataset_field( "user",
  {
    name => 'deposit_division',
    type => 'subject',
    top => 'divisions',
    # NB This is NOT a multiple field.
  }
);

Add phrases for user field[edit]

These should be added to a suitable phrase file within the archive configuration

  <epp:phrase id="user_fieldname_deposit_division">Deposit division</epp:phrase>
  <epp:phrase id="user_fieldhelp_deposit_division">If the user should only be allowed to deposit under one division, please add it here.</epp:phrase>

Add new user field to the 'user admin' workflow[edit]

E.g. workflows/user/default.xml, in the 'usertype' stage, which is only visible to admins

  <component><field ref="deposit_division"/></component>

Update eprint workflow[edit]

Edit the eprint workflow (workflows/eprint/default.xml) to check whether the user has a deposit_division set. If they do, use that as the 'top' attribute for the divisions component. The 'as_string' is needed, otherwise the rendered version of the division will be used instead of the underlying value.

  <!-- 
    comment-out old divisions:
      <component><field ref="divisions" /></component>
    and use the following instead
  -->
  <epc:choose>
    <epc:when test="$current_user{deposit_division}.is_set()">
      <component><field ref="divisions" top="{$current_user{deposit_division}.as_string()}" /></component>
    </epc:when>
    <epc:otherwise>
      <component><field ref="divisions" /></component>
    </epc:otherwise>
  </epc:choose>

Test, deploy[edit]

Run ~/bin/epadmin test ARCHIVEID and if all OK, restart Apache. Now (as an admin user), you should be able to set a 'deposit division' for a user. Once set, that user should only see the section of 'divisions' below the value you have set for them.

If you just want to add a specific division to an EPrint, based on the value in the user profile, this can be achieved via eprint_fields_default or eprint_fields_automatic using something similar to this (see the 'Adding a default' section below):

my $repo = $eprint->repository;

if( defined $repo->current_user )
{
  my $user = $repo->current_user;        

  if( $user->exists_and_set( "deposit_division" ) )
  {
     my $division = $user->value( "deposit_division" );
     $eprint->set_value( "divisions", [ $division ] );
  }
}

Collections example[edit]

Configuration of metafields[edit]

  • Create a namedset with the collections in it:

~/archives/ARCHIVEID/cfg/namedsets/collections

# A list of collections - remember to add the relevant phrases!
library
art_gallery
university_newspapers
lab_equipment
  • Add the metafield to both the eprint and the user. This can be done in a few different ways, this is one:

Edit ~/archives/ARCHIVEID/cfg/cfg.d/eprint_fields.pl, adding:

{
        name => 'collection',
        type => 'namedset',
        set_name => "collections",
},

Edit ~/archives/ARCHIVEID/cfg/cfg.d/user_fields.pl, adding:

{
        name => 'collection',
        type => 'namedset',
        set_name => "collections",
        multiple => 1, #Allows a user to have rights to more than one collection
},

Add to user workflow[edit]

Edit ~/archives/ARCHIVEID/cfg/workflows/user/default.xml. We only want admin staff to be able to assign collections, so the field is added to the 'usertype' stage:

  <stage name="usertype">
      <component><field ref="usertype"/></component>
      <component><field ref="username"/></component>
      <component><field ref="collection"/></component>
      <component><field ref="roles"/></component>
  </stage>

This allows one or more collections to be assigned to a user.

Add to EPrint workflow[edit]

To render only the collections that have been assigned to a user, we need to get the 'collection's from the owning user, join them into a comma-separated string and use that as the 'options' for the eprint collection field.

<component><field ref="collection" options="{join($item{userid}.as_item(){collection},',')}"/></component>

We could also have used $current_user - which would be OK if the $current_user will have rights to more collections than the owning user.

Update database and restart webserver[edit]

Update the database how you normally do it (web interface or commandline) and reload the server config. Test it works :o)

Adding a default[edit]

If a user has no collections assigned in their profile, what should happen? We could either:

  • always set a default collection in user_fields_default.pl
  • use eprint_fields_default.pl to set a default collection for the eprint.
$c->{set_eprint_defaults} = sub
{
  my( $data, $repository ) = @_;

  my $user = $repository->current_user();

  if( defined $user && $user->is_set( "collection" ) )
  {
    my $collections = $user->get_value( "collection" );
    if( scalar @$collections == 1 ){
      $data->{collection} = @$collections[0];
      #We may also want to set some default metadata on items in this collection?
      #Do it here - as we know we've got one collection!
      if( $data->{collection} eq 'university_newspapers' ){
        $data->{type} = "newspaper";
        ...
      }
    }
  }
}

If a user only has access to one collection, the value should be set automatically and the field not shown in the workflow.

  <flow>
    <epc:choose>
      <epc:when test="$STAFF_ONLY = 'TRUE'">
        <!-- Allow editors to choose any collection -->
        <stage ref="collection"/>
      </epc:when>
      <epc:otherwise test="length( $item{userid}.as_item(){collection} ) gt 1">
        <!-- If someone has access to more than one collection, offer their collections -->
        <stage ref="collection"/>
      </epc:otherwise>
    </epc:choose>
    ...
  </flow>

  <stage name="collection">
    <epc:if test="$STAFF_ONLY = 'TRUE'">
        <component><field ref="collection" required="yes" /></component>
    </epc:if>
    <epc:if test="$STAFF_ONLY != 'TRUE'">
        <component><field ref="collection" required="yes" options="{join($item{userid}.as_item(){collection},',')}"/></component>
    </epc:if>
  </stage>