De toegang tot G-drive is standaard voor een gebruiker naar zijn " my drive" gedeelte.
Echter binnen een domain maak je hoofdzakelijk gebruik van "shared drives" , die je toelaten om data te bewaren voor de toekomst.
Een shared drive heeft één of meerdere managers en een eigen rechtensysteem.
De eigenaar voor de data op de shared drive is de drive zelf en niet een bepaalde user, waardoor de data bewaard blijft, ook als de user niet meer bestaat.
Om toegang te hebben tot de extra functies binnen GAS moeten volgende services toegevoegd worden en moet je via de GCP voldoende rechten hebben om deze te gebruiken.
De functie geeft je een lijst van de aangemaakte shared drives binnen je domain.
Het gebruik van de helperfunctie getPermissionsList_(), geeft ons de extra info over de gebruikers die toegang hebben tot de drive.
/**
* Enable Drive Advanced API in services
*/
/**
* getSharedDrives
* @return {array} array of objects
*
* Object:
* -name: Name of shared drive
* -kind: drive#drive
* -id: driveId
* -Users[]
* .driveId
* .driveName
* .role : - owner - organizer - fileOrganizer - writer - reader
* .type : - user - group - domain - anyone
*
*/
function getSharedDrives() {
let page = '';
let pageToken = '';
let SharedDriveList = [];
do {
page = Drive.Drives.list({
//change to your domain name
domain: 'myuba.be',
maxResults: 10,
pageToken: pageToken,
projection: 'full',
})
SharedDriveList = SharedDriveList.concat(page.items)
pageToken = page.nextPageToken;
} while (pageToken)
//return object
for (dr = 0; dr < SharedDriveList.length; dr++) {
// Users[].0= email
// Users[].1=fileOrganizer|organizer
// Users[].2=group|user
SharedDriveList[dr].Users = getPermissionsList_(SharedDriveList[dr].id, SharedDriveList[dr].name)
}
return SharedDriveList;
Logger.log('einde')
}
De array die je terug krijgt bevat users van een specifieke drive, met hun rol, email en type.
Vermits deze functie standaard ingesteld is om enkel mydrive te raadplegen, moet je de de parameter "supportAllDrives=true" zetten in de argumenten van de aanroep.
Zoniet bekom je niet de rechten op een shared drive.
/**
* Helper function
* getPermissionsList_
* @param {string} driveId, string with driveId
* @param {string} driveName, string with driveName
* @return {array} array of objects
* Users[]
* .driveId
* .driveName
* .role : - owner - organizer - fileOrganizer - writer - reader
* .type : - user - group - domain - anyone
*/
function getPermissionsList_(driveId, driveName) {
// THIS IS IMPORTANT! The default value is false, so the call won't
// work with shared drives unless you change this via optional arguments
const args = {
supportsAllDrives: true
};
// Use advanced service to get the permissions list for the shared drive
let pList = Drive.Permissions.list(driveId, args);
//Put email and role in an array
let editors = pList.items;
var arr = [];
for (var i = 0; i < editors.length; i++) {
let permissions = {}
permissions.driveId = driveId
permissions.driveName = driveName
permissions.role = editors[i].role
permissions.email = editors[i].emailAddress
permissions.type = editors[i].type
arr.push(permissions)
}
return arr
Logger.log(arr);
}
Volgende functie laat je toe om met behulp van een object, via de GAS api een user rechten te geven op een shared drive.
Het principe van een object meegeven aan een functie die aan de server zijde wat uitvoert, is standaard binnen Google.
De structuur van het object kan complex zijn en daarom is het noodzakelijk om de API ref te raadplegen.
/**
* Helperfunction
* setPermissionsList_
* @param {object}
*
*/
function setPermissionsList_({ driveId, role, email, type }) {
//role can be - owner - organizer - fileOrganizer - writer - reader
//type can be - user - group - domain - anyone
const response = Drive.Permissions.insert(
{
role: role,
type: 'user',
value: email,
type: type,
},
driveId,
{
supportsAllDrives: true,
sendNotificationEmails: true,
fields: 'emailAddress,role',
}
);
console.log('Shared Drive shared with %s', response.emailAddress);
}
Volgende functie geeft je als admin een map met een overzicht van alle gebruikers en shared drives en welke rechten zij daartoe hebben.
Vermits het aanpassen van de rechten ook via de admin console of door een manager kan gebeuren is dit overzicht noodzakelijk om fouten te kunnen detecteren.
Het is sterk aangeraden om enkel bij het updaten of aanmaken van gebruikers de initiële rechten toe te kennen.
Het verwijderen van de toegang tot een bepaald deel doe je best "manueel" zodat je eventueel manueel toegekende rechten door een andere manager niet vernietigd.
Doordat het toekennen van gebruikers aan een sheared drive meestal gebeurt vanuit het toekennen van een group, is de werkwijze best om niet "individuele" gebruikers rechten te geven, maar eerste deze gebruikers aan een group toe te voegen.
Hierdoor krijgen zij automatische de rechten op een specifiekje shared drive en worden hen ook de rechten automatische ontnomen, als zij hun lidmaatschap in de groep verliezen.
Deze werkwijze spaart je heel wat administratie.
/**
* MapDriveUserRole
* 2d table of users and shared drives and their role/type
*
*
*
*/
function MapDriveUserRole(sheetname) {
try {
let SharedDrivelist = getSharedDrives()
let arr = [[]]
arr.shift()
// create header row = all shared drives
var headers = []
let Emails = []
for (let s = 0; s < SharedDrivelist.length; s++) {
headers[s] = SharedDrivelist[s].name
for (let u = 0; u < SharedDrivelist[s].Users.length; u++) {
Emails.push(SharedDrivelist[s].Users[u].email)
}
}
headers.sort()
headers.unshift('Email')
arr.push(headers)
// create Unique user list based on addresses used in shared drives
var UEmails = []
let ue = 0
for (let i = 0; i < Emails.length; i++) {
let idx = UEmails.indexOf(Emails[i])
if (idx == -1) {
UEmails[ue] = Emails[i]
ue++
}
}
UEmails.sort()
//Create 2D array
for (let r = 0; r < UEmails.length; r++) {
let rec = new Array(headers.length)
rec[0] = UEmails[r]
arr.push(rec)
}
// fill array
for (let s = 0; s < SharedDrivelist.length; s++) {
// column nmmer
let col = headers.indexOf(SharedDrivelist[s].name)
//get user info
for (let u = 0; u < SharedDrivelist[s].Users.length; u++) {
let row = UEmails.indexOf(SharedDrivelist[s].Users[u].email) + 1
arr[row][col] = SharedDrivelist[s].Users[u].role
}
}
let Sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetname);
Sheet.getRange(1, 1, arr.length, arr[0].length).setValues(arr);
SpreadsheetApp.flush();
Logger.log('einde')
} catch (e) {
Logger.log(e)
}
}
Binnen de shared drive kan je niet zomaar files copieren met DriveApp maar dien je gebruik te maken van de Drive API.
De volgende code laat je toe om een file te kopieren.
De naam van de nieuwe file vind je in title, waardoor je niet gebonden bent aan de "copy from" filename.
De id van de bron file moet meegegeven worden, alsook de id van de destination folder.
Wanneer je een nieuwe file gecreëerd hebt, heeft deze automatisch de rechten en kan je deze eenvoudig toevoegen (verplaatsen) naar de destination_folder.
Hier kan je de standaard DriveApp gebruiken.
let data = Drive.Files.copy({ parents: [{ id: dest_dirID }], title }, sourcefileID, {
supportsAllDrives: true,
fields: 'title,embedLink',
});
var file = DriveApp.getFileById(file_create.getId());
//STAP5 Voeg deze toe aan de destination folder.
dest_folder.addFile(file);
De DriveApp method GetFilesByName werkt uitsluitend op het mydrive stuk.
var file_info = DriveApp.getFilesByName(Emails.EmailInfo[r]);
Deze kan je niet gebruiken om files bij hun naam te vinden op de shared drive, waardoor het copieren van een file met een specifieke naam (vb template file) niet op deze wijze lukt.
Wat wel lukt is de file benaderen met zijn id vanuit DriveApp.
Om de file op een shared drive terug te vinden aan de hand van zijn naam, kan je enkel gebruik maken van de Drive.Files.list method, met als titel de naam van de file en de zoekfunctie op alle drives .
Drive.Files.list.
Nadien kan je wel met de ID toegang krijgen via de DriveApp lib.
Wanneer je corpora= "drive" gebruikt, moet je de ID van de shared drive meegeven waarop gezocht moet worden.
const res = Drive.Files.list({ corpora: "drive", driveId: driveID , includeItemsFromAllDrives: true, supportsAllDrives: true, maxResults: 1000, q: `title='${filename}'` });
Deze vind je terug als je de shared drive opend op het hoogtes niveau, in de url:
https://drive.google.com/drive/folders/0AIK9039F_k-iUk...
Wanneer je echter over alle drives heen wil zoeken, kan je dit enkel door gebruik te maken van de userKey en de Corpora allDrives.
const res = Drive.Files.list({ userKey: CurrentUserID, corpora: "allDrives", includeItemsFromAllDrives: true, supportsAllDrives: true, maxResults: 1000, q: `title='${filename}'` });
/**
* Helperfunction
* get info of a file accessible by the current user, even of a shared drive.
If multiple files with same name, only last file will be used
* fileInfo(filename)
* @param{string} filename, name to be found
* @return{object} fileinfo, {fileid and parentid}
*/
function fileInfo(filename) {
var CurrentUserID = Session.getActiveUser().getEmail()
const res = Drive.Files.list({ userKey: CurrentUserID, corpora: "allDrives", includeItemsFromAllDrives: true, supportsAllDrives: true, maxResults: 1000, q: `title='${filename}'` });
var fileinfo = { id: "", parentid: "" }
res.items.forEach(e => {
var file = DriveApp.getFileById(e.id)
fileinfo.id = file.getId()
fileinfo.parentid = file.getParents().next().getId()
})
return fileinfo
}
de setSharing bepaalt de permissions van een file.
let file = DriveApp.getFileById(ssId);
let permissions = file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); //iedereen die de link kent mag de file zien
De functies worden gebruikt om de credential file te lezen, maar kunnen ook gebruikt worden om andere data, die als JSON file wordt bewaard in te lezen in een Apps Script.
Deze functie vormt de URL van een geshared file om in de File ID, zodat deze verder bruikbaar wordt voor acties.
/**
* Get file ID from URL
* @param{string} url of file
* @return {string} file ID
*/
function getFileIdFromDriveUrl(url) {
var match = url.match(/([a-z0-9_-]{25,})[$/&?]/i);
return match ? match[1] : null;
}
Het lezen van de keyfile, credentials, die gegenereerd worden in GCP voor toegang tot bepaalde bibs, data etc, vereist de toegang tot de als file bewaarde JSON gegevens.
Het is noodzakelijk dat de gebruiker van het script toegangsrechten heeft tot de betreffende file, anders kan deze niet ingelezen worden.
Dit wordt de user die verhoogde rechten heeft om de configuratie van de add-on met succes te kunnen uitvoeren.
Andere geberuikers waarmee de sheet gedeeld zal worden, kunnen dit niet uitvoeren.
De data zal ingelezen worden en toegekend worden aan de properties van het "document".
Hierdoor kan iedere gebruiker van het document, gebruik maken van dezelfde toegangsrechten.
Echter, wanneer men het document copieerd, zelf er code wil op loslaten (door Apps Script te starten of via andere wegen), toegang zoekt tot deze gegevens, zal dit niet lukken.
/**
* Read JSON key file and copy key info to Scrip properies
* Use: Key is stored as a private document.
* who needs the Apps script can copy the code and requests the author access to the file.
* He will get a link to the file, that has to be past into the userproperties of the script.
* through a user dialog.
* @param {string} URL to keyfile
* @return {bool} true of ok
*/
function readKeyFile(fileURL) {
try {
var files = DriveApp.getFileById(getFileIdFromDriveUrl(fileURL));
var content = files.getBlob().getDataAsString();
var json = JSON.parse(content);
//setdata(json);
let docProperties = PropertiesService.getDocumentProperties();
docProperties.setProperty('project_id', json.project_id);
// docProperties.setProperty('private_key_id', json.private_key_id);
docProperties.setProperty('private_key', json.private_key);
docProperties.setProperty('client_email', json.client_email);
// docProperties.setProperty('client_id', json.client_id);
// docProperties.setProperty('auth_uri', json.auth_uri);
// docProperties.setProperty('token_uri', json.token_uri);
// docProperties.setProperty('auth_provider_x509_cert_url', json.auth_provider_x509_cert_url);
// docProperties.setProperty('client_x509_cert_url', json.client_x509_cert_url);
return true
} catch (e) {
var ui = SpreadsheetApp.getUi();
ui.alert(e)
return false
Logger.log(e);
}
}