Loading

Zugriff auf Inhaltsobjekte über Funktionen mit programmgesteuerter Freigabe in ContentDocumentLink

Veröffentlichungsdatum: Oct 13, 2022
Beschreibung

Terminologie

Inhaltsdokument: Ein Dokument, das in eine Bibliothek in Salesforce CRM Content oder Salesforce Files hochgeladen wurde.

Inhaltsversion: Eine bestimmte Version eines Dokuments in Salesforce CRM Content oder Salesforce Files. Ein Inhaltsdokument kann mehrere Inhaltsversionen haben.

Inhaltsdokument-Link:
Der Link zwischen einem Salesforce CRM Content-Dokument oder einer Salesforce-Datei und dem Ort, an dem es bzw. sie freigegeben ist. Eine Datei kann für andere Benutzer, Gruppen, Datensätze und Salesforce CRM Content-Bibliotheken freigegeben werden.
 

Dokument-Linkerstellung und Inhaltszugriff:

Es gibt zwei Arten des Inhaltszugriffs:
  1. Funktion greift auf ihren eigenen Inhalt zu
  2. Funktion greift auf den Inhalt eines anderen Benutzers zu
Wenn eine Funktion neuen Inhalt erstellt, ist der Cloud-Integrationsbenutzer Inhaber dieses Inhalts, sodass die Funktionen darauf zugreifen können. Dies ist das einfachere Szenario. Das häufigere Szenario besteht jedoch darin, dass der Inhalt bereits vorhanden ist und eine Funktion darauf zugreifen muss.
 

Funktion greift auf ihren eigenen Inhalt zu

Eine Funktion kann Inhalt erstellen und ihn über den REST-API-Endpunkt einfügen unter:
services/data/vXX.X/sobjects/ContentVersion

Dadurch wird der Cloud-Integrationsbenutzer automatisch zum Inhaber des Inhalts und der Funktion (sowie anderen Benutzern) wird der Zugriff auf diesen Inhalt ermöglicht. Dokument-Links werden automatisch eingefügt, es sind also keine weiteren Schritte erforderlich.

Funktion greift auf den Inhalt eines anderen Benutzers zu

Wir müssen in "ContentDocumentLink" einen Datensatz erstellen, der den Inhalt mit dem Benutzer verknüpft, für den er freigegeben wird. In diesem Fall ist der Benutzer der Cloud-Integrationsbenutzer. Dies kann über Apex erfolgen, nachdem der Inhalt erstellt wurde, oder über Data Loader, nachdem der Inhalt hochgeladen wurde.

Im Folgenden finden Sie ein Beispiel für Apex-Code, der zum Erstellen von Inhalt (d. h. ContentVersion-Datensatz) und zum Verknüpfen des Inhalts mit "ContentDocumentLink" (d. h. ContentDocumentLink-Datensatz) verwendet wird.
 
//Create Document
//Note: This example creates the content in Apex
//We could also load content via Data Loader.
ContentVersion cv = new ContentVersion();
cv.Title = 'Test Document';
cv.PathOnClient = 'TestDocument.pdf';
cv.VersionData = Blob.valueOf('Test Content');
cv.IsMajorVersion = true;
Insert cv;
 
//Get Content Documents
Id conDocId = [SELECT ContentDocumentId FROM ContentVersion WHERE Id =:cv.Id].ContentDocumentId;
 
//Create ContentDocumentLink 
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = conDocId;
//Label would contain the user id of the cloud integration user (obtained separately)
cdl.LinkedEntityId = Label.Platform_User_Id;
//V - Viewer permission. C - Collaborator permission. I - Inferred permission
cdl.ShareType = 'V';
Insert cdl;

Hier wird die ContentDocumentId aus der ContentVersion abgerufen (die Version des Dokuments, die zuvor erstellt wurde – hier nicht dargestellt).

Die LinkedEntityId bezieht sich auf die ID des Cloud-Integrationsbenutzers. Sie muss im Voraus ermittelt und an diesen Code übergeben werden oder von diesem Code aus als globale Variable (oder über den Plattform-Cache) zugänglich sein.

Sobald wir einen Eintrag in ContentDocumentLink (wie oben) erstellt haben, kann eine Funktion normalerweise über das SDK auf den Inhalt zugreifen.

Ermitteln der ID des Cloud-Integrationsbenutzers
Da der Cloud-Integrationsbenutzer in Salesforce nicht wie andere Benutzer angezeigt wird, kann die ID dieses Benutzers auf eine der folgenden Arten ermittelt werden:

1. Wir können das Benutzerobjekt abfragen und den Benutzernamen für CloudIntegrationUser ermitteln. Der Benutzername der Cloud-Integration lautet cloud@ + 18-stellige "orgId" in Kleinbuchstaben. Siehe unten stehende SOQL-Abfrage 
SELECT Id, UserName from User WHERE username like 'cloud@00d%'

2. Durch Einfügen eines Datensatzes durch die Funktion. Die ID des Benutzers, der diesen Datensatz eingefügt hat, ist die des Cloud-Integrationsbenutzers.

Sobald die ID ermittelt wurde, kann sie zur Verwendung durch den oben gezeigten Apex-Code gespeichert werden.
Der folgende Code zeigt eine Funktion, die auf ein bestimmtes Inhaltsdokument zugreift, nachdem die Freigabe wie oben gezeigt eingerichtet wurde.
// Purposefully selecting another file NOT owned by the platform integration user
// (Hardcoded platform integration user Id - to be replaced with a more dynamic ID 
// merge in the query)
let contentQuery = "SELECT Id 
                    FROM ContentVersion 
                    WHERE OwnerId != '0055f0000057ROYAA2' 
                    ORDER BY CreatedDate DESC LIMIT 1";
let queryResults = await context.org.dataApi.query(contentQuery);
let contId = "";
for (const downItem of queryResults.records) {
    contId = downItem.fields["Id"];
    break;
}

// File Id for download
logger.info("contId: " + JSON.parse(JSON.stringify(contId)));

// Print
logger.info("DOWNLOAD LATEST FILE NOT OWNED BY FUNCTIONS USER");

await request
    .get(
        context.org.baseUrl +
        "/services/data/v54.0/sobjects/ContentVersion/" +
        contId +
        "/VersionData"
    )
    .auth(null, null, true, context.org.dataApi.accessToken)
    .on("error", function (err) {
        logger.info("Exception: " + err);
    })
    .pipe(
        fs.createWriteStream("./tempFiles/downFile.csv", { encoding: "utf8" })
    )
    .on("finish", doSomethingAfterDownload);    
}

Hinweis 1

Der Code versucht absichtlich, auf Inhalt zuzugreifen, der von einem anderen Benutzer als dem Cloud Integrationsbenutzer erstellt wurde. Wenn der Inhalt erfolgreich in "ContentDocumentLink" freigegeben wurde (wie oben gezeigt), kann diese Funktion erfolgreich auf den Inhalt zugreifen.

Hinweis 2

Wenn der Funktionscode auf Inhalt zugreift, der vom Cloud-Integrationsbenutzer erstellt wurde, ist es nicht notwendig, ihn über "ContentDocumentLink" freizugeben (da dieser automatisch erstellt wurde). In diesem Fall könnte problemlos auf den Inhalt zugegriffen werden.

Automatisierte Dokument-Linkerstellung

Es ist möglich, die Erstellung der Datensätze für Dokument-Links zu automatisieren, wenn neuer Inhalt erstellt wird. Folgendes Beispiel zeigt, wie sich dies bewerkstelligen lässt.

Beispiel-Auslösercode

Der folgende Code ist der Auslöser, der einen ContentDocumentLink-Datensatz erstellt, wenn ein ContentVersion-Datensatz erstellt wird (erfordert die Platform_User_Id aus dem vorigen Beispiel, die für die Erstellung von Dokument-Links erforderlich ist).
 
trigger ContentVersionTrigger on ContentVersion (after insert) {
    ContentVersionTriggerHelper.triggerHelper(
        Trigger.operationType, 
        Trigger.new, 
        Trigger.oldMap);
}
public with sharing class ContentVersionTriggerHelper {
    public static void triggerHelper(
        System.TriggerOperation operationType,
        List<ContentVersion> newList,
        Map<Id, ContentVersion> oldMap
    ) {
        switch on operationType {
            when AFTER_INSERT{
                List<ContentVersion> docsToProcess = getDocsToShare(newList);
                if(!docsToProcess.isEmpty()){
                    shareWithIntegrationUser(docsToProcess);
                }
            }
        }
    }

    public static List<ContentVersion> getDocsToShare(List<ContentVersion> allDocuments){
        List<ContentVersion> docsToProcess = new List<ContentVersion>();
        for(ContentVersion cVer : allDocuments){
            if(cDoc.OwnerId != Label.Platform_User_Id){
                docsToProcess.add(cVer);
            }
        }
        return docsToProcess;
    } 

    public static void shareWithIntegrationUser(List<ContentVersion> documents){
        List<ContentDocumentLink> shareLinks = new List<ContentDocumentLink>();
        for(ContentVersion cVer : documents){
            ContentDocumentLink cdl = new ContentDocumentLink();
            cdl.ContentDocumentId = cVer.ContentDocumentId;
            cdl.LinkedEntityId = Label.Platform_User_Id;
            cdl.ShareType = 'V';
            shareLinks.add(cdl);
        }
        Database.insert(shareLinks,false);
    }
}
 

Überlegungen und Risiken

  • Nachdem ein Inhaltsdokument-Link freigegeben wurde, kann er von jeder Funktion aufgerufen werden. Um den Zugriff auf das Dokument in Zukunft zu verhindern, muss seine Freigabe in "ContentDocumentLink" explizit aufgehoben werden. Dieser Ansatz ermöglicht den Zugriff auf das Dokument für alle Funktionen oder keine, da alle Funktionen als Cloud-Integrationsbenutzer ausgeführt werden.
  • Die Benutzer-ID des Cloud-Integrationsbenutzers muss manuell ermittelt und in den Apex-Auslöser eingefügt werden. Dazu muss die ID in einer benutzerdefinierten Einstellung, einem benutzerdefinierten Objekt oder einer benutzerdefinierten Bezeichnung gespeichert werden. Alternativ kann sie im Plattform-Cache gespeichert und von dort abgerufen werden. Außerdem kann sich die Benutzer-ID nach einer Organisationsmigration ändern, sodass die Freigaben mit der neuen ID neu erstellt werden müssen.
  • Dokumente müssen einzeln freigegeben werden, indem für jedes Dokument eine Datensatzfreigabe erstellt wird. Dies könnte bei einer großen Anzahl von Dokumenten zu Problemen in Bezug auf die Skalierbarkeit führen.
Nummer des Knowledge-Artikels

000393095

 
Laden
Salesforce Help | Article