Modify item permissions

Warning

Manually modifying permissions may lead, in case of a mistake, to a search interface end user accessing content they shouldn’t be able to access.

As with any pre-push extension, if your script takes too long or fails due to an error, Coveo will index your items as they are in your content system, without applying your script. This can also result in content access issues in your search interface.

Before you write an extension that modifies permissions, ensure that you’ve selected the Same users and groups as in your current permission system content security option for your source. If you haven’t, or if your source doesn’t support this option, Coveo will overwrite the permissions of each content item with the source-level permissions to ensure coherent behavior.

The script creates an Extensions folder under the COVEO_LOGS_ROOT folder (if it doesn’t already exist) and a subfolder named after the source ID. The script logs relevant information about each crawled item in a .log file in that folder.

Tip
Leading practice

Apply the extension to a duplicate of your production source with a name that clearly indicates it’s for testing purposes only. In this test source, crawl only a small subset of content for faster debugging and to limit the log file size.

Only after fully testing and validating the pre-push extension in the test source should you apply it to your production source.

After you apply this extension, rebuild the source.

# Import required Python libraries. Add non-Python standard libraries to the requirements.txt file.
import os
import sys
import logging
from logging.handlers import TimedRotatingFileHandler
import json

# Initialize a rotating log handler
log_folder = os.path.join(
    os.getenv('COVEO_LOGS_ROOT'),
    'Extensions',
    os.getenv('SOURCE_ID', 'unknown')
)
os.makedirs(log_folder, exist_ok=True)

fname = f"{os.getenv('OPERATION_TYPE','unknown')}_{os.getenv('OPERATION_ID','unknown')}.log"
fpath = os.path.join(log_folder, fname)

handler = TimedRotatingFileHandler(fpath, when='midnight')
handler.suffix = "%Y-%m-%d"

formatter = logging.Formatter(
    fmt='%(asctime)s.%(msecs)03d %(levelname)s %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
handler.setFormatter(formatter)

logging.basicConfig(level=logging.INFO, handlers=[handler])

# -----------------------------------------------------------------
# Extension entry point. The do_extension function must be defined.
# -----------------------------------------------------------------
def do_extension(body):

    # Log basic item info
    document_id = body.get('DocumentId', '<missing>')
    logging.info("BEGIN processing item: %s", document_id)

    # Start of permissions logic
    permissionsDict = body['Permissions'][0]
    permissionsSetDict = permissionsDict['PermissionSets'][0]
    allowedPermissionsList = permissionsSetDict['AllowedPermissions']

    # Add a new allowed user
    name = "Bob@coveo.com"
    logging.info("Adding allowed permission for: %s", name)

    myNewAllowedMember = {
        "IdentityType": "USER",
        "SecurityProvider": "Email Security Provider",
        "Identity": name,
        "AdditionalInfo": {}
    }

    allowedPermissionsList.append(myNewAllowedMember)

    # Optional: record a minimal log summary inside the body
    body['prepushlog'] = f"Added permission for: {name}"

    # Log the updated permissions section as well
    updated_permissions = json.dumps(allowedPermissionsList, indent=2, ensure_ascii=False)
    logging.info("Updated AllowedPermissions:\n%s", updated_permissions)

    logging.info("END processing document: %s", document_id)

    return body