Skip to content

Instantly share code, notes, and snippets.

@moo2u2
Created October 8, 2023 02:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moo2u2/3212cf9139321d92c2b435f24da8d132 to your computer and use it in GitHub Desktop.
Save moo2u2/3212cf9139321d92c2b435f24da8d132 to your computer and use it in GitHub Desktop.
Sitecore "normal mode" plugin with support for parsing Sitecore item security permissions
// Removes components from placeholders (in the page layout) if given role is not authorized to view them
function removeComponents(placeholders: PlaceholdersData, role: string) {
for (let placeholder in placeholders) {
for (let i = 0; i < placeholders[placeholder].length; i++) {
if ('fields' in placeholders[placeholder][i] || 'placeholders' in placeholders[placeholder][i]) {
const componentRendering = placeholders[placeholder][i] as ComponentRendering;
if (componentRendering?.fields) {
// @ts-expect-error
if('data' in componentRendering.fields && componentRendering.fields.data.datasource?.security) {
// @ts-expect-error
if (notAuthorized(parseSecurityField(componentRendering.fields.data.datasource?.security?.value).value, role)) {
placeholders[placeholder].splice(i--, 1);
}
} else if(securityFieldName in componentRendering.fields) {
if (notAuthorized((componentRendering.fields[securityFieldName] as SecurityField).value, role)) {
placeholders[placeholder].splice(i--, 1);
}
}
}
if (componentRendering.placeholders) {
removeComponents(componentRendering.placeholders, role);
}
}
}
}
}
class NormalModePlugin implements Plugin {
private dictionaryService: DictionaryService;
private layoutService: LayoutService;
order = 0;
constructor() {
this.dictionaryService = dictionaryServiceFactory.create();
this.layoutService = layoutServiceFactory.create();
}
async exec(props: SitecorePageProps, context: MemberPropsContext | GetStaticPropsContext) {
if (context.preview) return props;
/**
* Normal mode
*/
// Get normalized Sitecore item path
const path = extractPath(context.params);
// Use context locale if Next.js i18n is configured, otherwise use language defined in package.json
props.locale = context.locale ?? pkg.config.language;
// Fetch layout data, passing on req/res for SSR
props.layoutData = await this.layoutService.fetchLayoutData(
path,
props.locale,
// eslint-disable-next-line prettier/prettier
isServerSidePropsContext(context) ? (context as GetServerSidePropsContext).req : undefined,
isServerSidePropsContext(context) ? (context as GetServerSidePropsContext).res : undefined
);
const session = isServerSidePropsContext(context) ? (context as MemberPropsContext).session : null;
// Calculate roles (stored in the session) which are unauthorized to view page / components
const userRoles = getUserRoles(session);
if ((props.layoutData && !('sitecore' in props.layoutData)) || !props.layoutData?.sitecore?.route) {
props.notFound = true;
} else if (isServerSidePropsContext(context) && props.layoutData.sitecore.route.fields && securityFieldName in props.layoutData.sitecore.route.fields) {
// Check the security field of the page to see if it should be inaccessible certain user roles
const securityField = props.layoutData.sitecore.route.fields[securityFieldName] as SecurityField;
if (anyNotAuthorized(securityField.value, userRoles)) {
props.secure = true;
}
}
// Remove components from the layout which do not match user's permissions
if ('sitecore' in props.layoutData && props.layoutData.sitecore.route?.placeholders) {
// @ts-expect-error
userRoles.forEach(role => removeComponents(props.layoutData.sitecore.route.placeholders, role));
}
// Fetch dictionary data
props.dictionary = await this.dictionaryService.fetchDictionaryData(props.locale);
return props;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment