Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"dependencies": {
"datatables.net": "^2.3.2",
"datatables.net-bs5": "^2.3.2",
"dattatable": "^2.11.61",
"gd-sprest-bs": "^10.15.21",
"dattatable": "^2.11.62",
"gd-sprest-bs": "^10.15.30",
"jquery": "^3.7.1",
"moment": "^2.30.1"
},
Expand Down
185 changes: 141 additions & 44 deletions src/ds.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { List, LoadingDialog } from "dattatable";
import {
Components, ContextInfo, DirectorySession, GroupSiteManager, Helper,
Search, Site, SPTypes, Types, Web, v2
Search, SensitivityLabels, Site, SPTypes, Types, Web, v2
} from "gd-sprest-bs";
import { Security } from "./security";
import Strings from "./strings";
Expand Down Expand Up @@ -45,6 +45,7 @@ export interface ISensitivityLabel {
desc: string;
id: string;
name: string;
tooltip: string;
}

/**
Expand Down Expand Up @@ -414,6 +415,32 @@ export class DataSource {
});
}

// Loads the drive for a list name
static getDriveIdForList(webId: string, listName: string): PromiseLike<string> {
// Return a promise
return new Promise((resolve, reject) => {
// Get the libraries for this site
v2.sites({ siteId: DataSource.Site.Id, webId }).drives().execute(resp => {
// Find the target drive
let drive = resp.results.find(a => { return a.name == listName; });

// Resolve the request
resolve(drive?.id);
}, reject);
});
}

// Returns the group id from the login name
static getGroupId(loginName: string): string {
// Get the group id from the login name
let userInfo = loginName.split('|');
let groupInfo = userInfo[userInfo.length - 1];
let groupId = groupInfo.split('_')[0];

// Ensure it's a guid and return null if it's not
return /^[{]?[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}[}]?$/.test(groupId) ? groupId : null;
}

// List
private static _list: List<IListItem> = null;
static get List(): List<IListItem> { return this._list; }
Expand Down Expand Up @@ -481,24 +508,13 @@ export class DataSource {
});
}

// Returns the group id from the login name
static getGroupId(loginName: string): string {
// Get the group id from the login name
let userInfo = loginName.split('|');
let groupInfo = userInfo[userInfo.length - 1];
let groupId = groupInfo.split('_')[0];

// Ensure it's a guid and return null if it's not
return /^[{]?[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}[}]?$/.test(groupId) ? groupId : null;
}

// Loads the files for a drive
static loadFiles(webId: string, listName?: string, folder?: Types.SP.Folder): PromiseLike<Types.Microsoft.Graph.driveItem[]> {
static loadFiles(webId: string, listName?: string, folder?: Types.SP.Folder, onFile?: (file: Types.Microsoft.Graph.driveItem) => void): PromiseLike<Types.Microsoft.Graph.driveItem[]> {
let files = [];

// Loads the files for a drive
let getFiles = (driveId: string, folder: string = "") => {
let drive = v2.sites({ siteId: this.Site.Id, webId }).drives(driveId);
let drive = v2.sites({ siteId: this.Site.Id, webId, targetInfo: { disableProcessing: true } }).drives(driveId);

// Return a promise
return new Promise(resolve => {
Expand All @@ -510,9 +526,12 @@ export class DataSource {
Top: 5000
}).execute(resp => {
// Parse the items
Helper.Executor(resp.results, driveItem => {
Helper.Executor(resp["d"].value, (driveItem: Types.Microsoft.Graph.driveItem) => {
// See if this is a file
if (driveItem.file) {
// Process the file
onFile ? onFile(driveItem) : null;

// Append the file
files.push(driveItem);
} else {
Expand Down Expand Up @@ -554,6 +573,42 @@ export class DataSource {
});
}

// Loads the items for a list
static loadItems(props: {
listId?: string;
listName?: string,
query: Types.IODataQuery,
onItem?: (items: Types.SP.ListItemOData) => void,
webUrl: string
}): PromiseLike<Types.SP.ListItemOData[]> {
// Return a promise
return new Promise((resolve, reject) => {
// Default the settings
props.query = props.query || {};
props.query.GetAllItems = true;
props.query.Top = props.query.Top || 5000;

// Get the list
let web = Web(props.webUrl, {
disableProcessing: true,
requestDigest: DataSource.SiteContext.FormDigestValue,
callbackQuery: props.onItem ? items => {
// Call the event
items.forEach(item => { props.onItem(item); });
} : null
});

// Get the items
(props.listName ? web.Lists(props.listName) : web.Lists().getById(props.listId)).Items().query(props.query).execute(
items => {
// Resolve the request
resolve(items.results);
},
reject
)
});
}

// Loads the sensitivity labels for the current user
private static _sensitivityLabels: ISensitivityLabel[] = null;
static get HasSensitivityLabels(): boolean { return this._sensitivityLabels?.length > 0; }
Expand All @@ -570,45 +625,87 @@ export class DataSource {
private static loadSensitivityLabels() {
// Return a promise
return new Promise(resolve => {
// Load the group context
GroupSiteManager().getGroupCreationContext().execute(resp => {
// Clear the labels
this._sensitivityLabels = [];
this._sensitivityLabelItems = [
{
text: "",
value: null
// Clear the labels
this._sensitivityLabels = [];
this._sensitivityLabelItems = [
{
text: "",
value: null
}
];

// Get the sensitivity labels for the user
SensitivityLabels.getLabelsForUser().execute(labels => {
// Parse the labels
for (let i = 0; i < labels.results.length; i++) {
let label = labels.results[i];

// Parse the sub-labels
for (let j = 0; j < label.sublabels.length; j++) {
let subLabel = label.sublabels[j];
let labelName = `${label.displayName} \\ ${subLabel.displayName}`;

// Append the label and item
this._sensitivityLabels.push({
desc: subLabel.description,
id: subLabel.id,
name: labelName,
tooltip: subLabel.tooltip
});
this._sensitivityLabelItems.push({
data: subLabel,
text: labelName,
value: subLabel.id
});
}
];

// Parse the sensitivity labels
for (let i = 0; i < resp.DataClassificationOptionsNew.results.length; i++) {
let result = resp.DataClassificationOptionsNew.results[i];
let desc = resp.ClassificationDescriptionsNew.results.filter(i => { return i.Key == result.Value; })[0];

// Append the label and item
this._sensitivityLabels.push({
desc: desc ? desc.Value : "",
id: result.Key,
name: result.Value
});
this._sensitivityLabelItems.push({
text: result.Value,
value: result.Key
});
}

// Resolve the request
resolve(null);
}, resolve);
}, () => {
// Load the group context
GroupSiteManager().getGroupCreationContext().execute(resp => {
// Parse the sensitivity labels
for (let i = 0; i < resp.DataClassificationOptionsNew.results.length; i++) {
let result = resp.DataClassificationOptionsNew.results[i];
let desc = resp.ClassificationDescriptionsNew.results.filter(i => { return i.Key == result.Value; })[0];

// Append the label and item
this._sensitivityLabels.push({
desc: desc ? desc.Value : "",
id: result.Key,
name: result.Value,
tooltip: ""
});
this._sensitivityLabelItems.push({
text: result.Value,
value: result.Key
});
}

// Resolve the request
resolve(null);
}, resolve);
});
});
}

// Site Context
private static _siteContext: Types.SP.ContextWebInformation = null;
static get SiteContext(): Types.SP.ContextWebInformation { return this._siteContext; }
static refreshContext() {
// Attach to the refresh token event in the library
ContextInfo.enableRefreshToken(() => {
// Get the web context of the current web
ContextInfo.getWeb(this._siteContext.WebFullUrl).execute(context => {
// Set the site context
this._siteContext = context.GetContextWebInformation;
});
});
}

// Loads the site collection information
private static _site: Types.SP.SiteOData = null;
static get Site(): Types.SP.SiteOData { return this._site; }
private static _siteContext: Types.SP.ContextWebInformation = null;
static get SiteContext(): Types.SP.ContextWebInformation { return this._siteContext; }
static get SiteCustomScriptsEnabled(): boolean { return Helper.hasPermissions(DataSource.Site.RootWeb.EffectiveBasePermissions, SPTypes.BasePermissionTypes.AddAndCustomizePages); }
private static _siteItems: Components.IDropdownItem[] = null;
static get SiteItems(): Components.IDropdownItem[] { return this._siteItems; }
Expand Down
63 changes: 35 additions & 28 deletions src/reports/dlp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,21 @@ export class DLP {
this._elSubNav.children[0].innerHTML = "Analyzing Library";
this._elSubNav.children[1].innerHTML = "Getting all files in this library...";

// Get the item ids for this library
Web(webUrl, { requestDigest: DataSource.SiteContext.FormDigestValue }).Lists(libTitle).Items().query({
Expand: ["Author"],
GetAllItems: true,
Select: ["Author/Title", "FileLeafRef", "FileRef", "File_x0020_Type", "Id"],
Top: 5000
}).execute(items => {
let batchRequests = 0;
let completed = 0;

// Update the dialog
this._elSubNav.children[1].innerHTML = "Creating batch job for files...";
// Create the list for the batch requests
let batchRequests = 0;
let completed = 0;
let list = Web(webUrl, { requestDigest: DataSource.SiteContext.FormDigestValue }).Lists().getById(libId);

// Parse the items and create the batch job
let list = Web(webUrl, { requestDigest: DataSource.SiteContext.FormDigestValue }).Lists(libTitle);
items.results.forEach(item => {
// Get the item ids for this library
let itemCounter = 0;
DataSource.loadItems({
webUrl,
listId: libId,
query: {
Expand: ["Author"],
Select: ["Author/Title", "FileLeafRef", "FileRef", "File_x0020_Type", "Id"],
},
onItem: item => {
// Create a batch request to get the dlp policy on this item
list.Items(item.Id).GetDlpPolicyTip().batch(result => {
// Ensure a policy exists
Expand Down Expand Up @@ -138,8 +137,11 @@ export class DLP {
// Increment the counter and update the dialog
this._elSubNav.children[1].innerHTML = `Batch Requests Processed ${++completed} of ${batchRequests}...`;
}, batchRequests++ % 25 == 0);
});

// Update the dialog
this._elSubNav.children[1].innerHTML = `Creating Batch Requests - Processed ${++itemCounter} items...`;
}
}).then(() => {
// Update the dialog
this._elSubNav.children[1].innerHTML = `Executing Batch Request for ${batchRequests} items...`;

Expand Down Expand Up @@ -168,17 +170,19 @@ export class DLP {
let batchRequests = 0;
let completed = 0;

// Set the list
let list = Web(webUrl, { requestDigest: DataSource.SiteContext.FormDigestValue }).Lists(lib.Title);

// Get the item ids for this library
Web(webUrl, { requestDigest: DataSource.SiteContext.FormDigestValue }).Lists(lib.Title).Items().query({
Expand: ["Author"],
GetAllItems: true,
Select: ["Author/Title", "FileLeafRef", "FileRef", "File_x0020_Type", "Id"],
Top: 5000
}).execute(items => {
let list = Web(webUrl, { requestDigest: DataSource.SiteContext.FormDigestValue }).Lists(lib.Title);

// Parse the items and create the batch job
items.results.forEach(item => {
let itemCounter = 0;
DataSource.loadItems({
webUrl,
listId: lib.Id,
query: {
Expand: ["Author"],
Select: ["Author/Title", "FileLeafRef", "FileRef", "File_x0020_Type", "Id"]
},
onItem: item => {
let analyzeFile = true;

// See if the file extensions are provided
Expand Down Expand Up @@ -226,14 +230,17 @@ export class DLP {
this._elSubNav.children[1].innerHTML = `Batch Requests Processed ${++completed} of ${batchRequests}...`;
}, batchRequests++ % 25 == 0);
}
});

// Update the dialog
this._elSubNav.children[1].innerHTML = `Creating Batch Requests - Processed ${++itemCounter} items...`;
}
}).then(() => {
// Update the dialog
this._elSubNav.children[1].innerHTML = `Executing Batch Request for ${batchRequests} items...`;

// Execute the batch request
list.execute(resolve);
});
}, resolve);
});
}).then(resolve);
});
Expand Down
Loading