@pnp/spfx-controls-react
Version:
Reusable React controls for SharePoint Framework solutions
350 lines • 17.4 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import * as React from 'react';
import { PermissionLevel } from '.';
import { SPHttpClient } from '@microsoft/sp-http';
import { SPPermission } from '@microsoft/sp-page-context';
import * as telemetry from '../../common/telemetry';
import { Spinner } from '@fluentui/react/lib/Spinner';
var SecurityTrimmedControl = /** @class */ (function (_super) {
__extends(SecurityTrimmedControl, _super);
function SecurityTrimmedControl(props) {
var _this = _super.call(this, props) || this;
_this.state = {
allowRender: false,
loading: true
};
telemetry.track('SecurityTrimmedControl', {});
return _this;
}
/**
* componentDidMount lifecycle method
*/
SecurityTrimmedControl.prototype.componentDidMount = function () {
this.checkPermissions();
};
/**
* componentDidUpdate lifecycle method
*/
SecurityTrimmedControl.prototype.componentDidUpdate = function (prevProps, prevState) {
// Check permissions only if necessary
if (prevProps.level !== this.props.level ||
prevProps.permissions !== this.props.permissions ||
prevProps.relativeLibOrListUrl !== this.props.relativeLibOrListUrl ||
prevProps.remoteSiteUrl !== this.props.remoteSiteUrl ||
prevProps.folderPath !== this.props.folderPath ||
prevProps.itemId !== this.props.itemId) {
this.checkPermissions();
}
};
/**
* Check if the user has the permissions to render the element
*/
SecurityTrimmedControl.prototype.checkPermissions = function () {
var _a = this.props, context = _a.context, level = _a.level;
// Check if the permission level needs to be checked on the current site
if (level === PermissionLevel.currentWeb || level === PermissionLevel.currentList) {
// Get the permission scope
var permissions = (level === PermissionLevel.currentWeb ? context.pageContext.web : context.pageContext.list).permissions;
// Check the user its permissions
if (permissions.hasAllPermissions.apply(permissions, this.props.permissions)) {
this.setState({
allowRender: true,
loading: false
});
}
else {
this.setState({
allowRender: false,
loading: false
});
}
}
else if (level === PermissionLevel.remoteWeb) {
// Check permissions on remote site
this.checkRemoteSitePermissions()
.then(function () {
// no-op;
}).catch(function () {
// no-op;
});
}
else if (level === PermissionLevel.remoteListOrLib) {
// Check permissions on remote list/library
this.checkRemoteListOrLibPermissions()
.then(function () {
// no-op;
})
.catch(function () {
// no-op;
});
}
else if (level === PermissionLevel.remoteListItem) {
this.checkRemoteListItem()
.then(function () {
// no-op;
})
.catch(function () {
// no-op;
});
}
else if (level === PermissionLevel.remoteFolder) {
this.checkRemoteFolder()
.then(function () {
// no-op;
})
.catch(function () {
// no-op;
});
}
};
/**
* Check the user its permissions on the remote site
*/
SecurityTrimmedControl.prototype.checkRemoteSitePermissions = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, context, remoteSiteUrl, permissions, _i, permissions_1, permission, apiUrl, result;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this.props, context = _a.context, remoteSiteUrl = _a.remoteSiteUrl, permissions = _a.permissions;
if (!(remoteSiteUrl && permissions)) return [3 /*break*/, 5];
_i = 0, permissions_1 = permissions;
_b.label = 1;
case 1:
if (!(_i < permissions_1.length)) return [3 /*break*/, 4];
permission = permissions_1[_i];
apiUrl = "".concat(remoteSiteUrl, "/_api/web/DoesUserHavePermissions(@v)?@v=").concat(JSON.stringify(permission.value));
return [4 /*yield*/, context.spHttpClient.get(apiUrl, SPHttpClient.configurations.v1).then(function (data) { return data.json(); })];
case 2:
result = _b.sent();
// Check if a result was retrieved
if (result) {
// Check if an error was retrieved
if (result.error) {
// Do not allow rendering when there was an error
this.setState({
allowRender: false,
loading: false
});
console.error("Error retrieved while checking user's remote site permissions.");
return [2 /*return*/];
}
// Check the result value
if (typeof result.value !== "undefined" && result.value === false) {
this.setState({
allowRender: false,
loading: false
});
return [2 /*return*/];
}
}
else {
this.setState({
allowRender: false,
loading: false
});
console.error("No result value was retrieved when checking the user's remote site permissions.");
return [2 /*return*/];
}
_b.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4:
// Render the controls when the permissions were OK for the user
this.setState({
allowRender: true,
loading: false
});
_b.label = 5;
case 5: return [2 /*return*/];
}
});
});
};
/**
* Check the user its permissions on the remote list or library
*/
SecurityTrimmedControl.prototype.checkRemoteListOrLibPermissions = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, remoteSiteUrl, relativeLibOrListUrl, permissions, apiUrl, hasPermissions;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this.props, remoteSiteUrl = _a.remoteSiteUrl, relativeLibOrListUrl = _a.relativeLibOrListUrl, permissions = _a.permissions;
if (!(remoteSiteUrl && relativeLibOrListUrl && permissions)) return [3 /*break*/, 2];
apiUrl = "".concat(remoteSiteUrl, "/_api/web/GetList(@listUrl)/EffectiveBasePermissions?@listUrl='").concat(encodeURIComponent(relativeLibOrListUrl), "'");
return [4 /*yield*/, this.checkRemotePermissions(apiUrl)];
case 1:
hasPermissions = _b.sent();
this.setState({
allowRender: hasPermissions,
loading: false
});
_b.label = 2;
case 2: return [2 /*return*/];
}
});
});
};
/**
* Check permissions on item level
*/
SecurityTrimmedControl.prototype.checkRemoteListItem = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, remoteSiteUrl, relativeLibOrListUrl, permissions, itemId, apiUrl, hasPermissions;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this.props, remoteSiteUrl = _a.remoteSiteUrl, relativeLibOrListUrl = _a.relativeLibOrListUrl, permissions = _a.permissions, itemId = _a.itemId;
if (!(remoteSiteUrl && relativeLibOrListUrl && permissions && itemId)) return [3 /*break*/, 2];
apiUrl = "".concat(remoteSiteUrl, "/_api/web/GetList(@listUrl)/Items(").concat(itemId, ")/EffectiveBasePermissions?@listUrl='").concat(encodeURIComponent(relativeLibOrListUrl), "'");
return [4 /*yield*/, this.checkRemotePermissions(apiUrl)];
case 1:
hasPermissions = _b.sent();
this.setState({
allowRender: hasPermissions,
loading: false
});
_b.label = 2;
case 2: return [2 /*return*/];
}
});
});
};
/**
* Check permissions on folder
*/
SecurityTrimmedControl.prototype.checkRemoteFolder = function () {
return __awaiter(this, void 0, void 0, function () {
var _a, remoteSiteUrl, relativeLibOrListUrl, permissions, folderPath, folderByServerRelativeUrl, apiUrl, hasPermissions;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this.props, remoteSiteUrl = _a.remoteSiteUrl, relativeLibOrListUrl = _a.relativeLibOrListUrl, permissions = _a.permissions, folderPath = _a.folderPath;
if (!(remoteSiteUrl && relativeLibOrListUrl && permissions && folderPath)) return [3 /*break*/, 2];
folderByServerRelativeUrl = "".concat(encodeURIComponent(relativeLibOrListUrl), "/").concat(encodeURIComponent(folderPath));
apiUrl = "".concat(remoteSiteUrl, "/_api/web/GetFolderByServerRelativeUrl(@folderByServerRelativeUrl)/ListItemAllFields/EffectiveBasePermissions?@folderByServerRelativeUrl='").concat(folderByServerRelativeUrl, "'");
return [4 /*yield*/, this.checkRemotePermissions(apiUrl)];
case 1:
hasPermissions = _b.sent();
this.setState({
allowRender: hasPermissions,
loading: false
});
_b.label = 2;
case 2: return [2 /*return*/];
}
});
});
};
/**
* Check the permissions
*
* @param apiUrl
*/
SecurityTrimmedControl.prototype.checkRemotePermissions = function (apiUrl) {
return __awaiter(this, void 0, void 0, function () {
var _a, context, permissions, data, result, permission, hasPermissions;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = this.props, context = _a.context, permissions = _a.permissions;
return [4 /*yield*/, context.spHttpClient.get(apiUrl, SPHttpClient.configurations.v1)];
case 1:
data = _b.sent();
if (!(data && data.ok)) return [3 /*break*/, 3];
return [4 /*yield*/, data.json()];
case 2:
result = _b.sent();
// Check if an error was retrieved
if (result.error) {
// Do not allow rendering when there was an error
console.error("Error retrieved while checking permissions");
return [2 /*return*/, false];
}
// Check the result high and low value are returned
if (typeof result.High !== "undefined" && typeof result.Low !== "undefined") {
permission = new SPPermission(result);
hasPermissions = permission.hasAllPermissions.apply(permission, permissions);
return [2 /*return*/, hasPermissions];
}
return [3 /*break*/, 4];
case 3:
console.error("No result value was retrieved when checking the user's permissions.");
return [2 /*return*/, false];
case 4: return [2 /*return*/];
}
});
});
};
/**
* Default React render method
*/
SecurityTrimmedControl.prototype.render = function () {
var className = this.props.className;
if (this.state.loading && this.props.showLoadingAnimation) {
return React.createElement(Spinner, null);
}
if (this.state.allowRender) {
return React.createElement("div", { className: className ? className : "" }, this.props.children);
}
else if (this.props.noPermissionsControl) {
return this.props.noPermissionsControl;
}
return null;
};
return SecurityTrimmedControl;
}(React.Component));
export { SecurityTrimmedControl };
//# sourceMappingURL=SecurityTrimmedControl.js.map