Bootstraping Strapi Role Permissions
So the code below is from a file called PROJECT/STRAPI/config/functions/bootstrap.js This automates creating the content types and content with information we keep in an excel spreadsheet. But in order to use those content types, there are roles and permissions that have to be activated so the web ui can access them. Basically, we do not want to manually go into the Strapi UI to create your user, create content types, create content or update the permissions. We want a script to do all of that.
'use strict'
Our Environment Variables
require('dotenv').config({ path:'../.env' })
Excel Spreadsheet Holding our data (attached)
const XLSX = require('xlsx')
const BOOTSTRAP_DATA = XLSX.readFile(process.env.BOOTSTRAP_DATA).Sheets
Variables pulled from .env
const ADMIN_USERNAME = process.env.ADMIN_USERNAME
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD
const ADMIN_EMAIL = process.env.ADMIN_EMAIL
Reading in the XLSX
async function bootstrap_resource(resource_type, resource_service) {
strapi.log.info(`Bootstrapping ${resource_type}`)
const resources = XLSX.utils.sheet_to_json(BOOTSTRAP_DATA[resource_type])
for (let resource of resources) {
if (await resource_service.count(resource) === 0) {
strapi.log.warn(`Bootstrapping ${resource_type}: ${JSON.stringify(resource)}`)
await resource_service.create(resource)
}
}
}
Creating the initial USER for strapi
async function bootstrap_admin() {
strapi.log.info(`Bootstrapping Admin`)
const admin_orm = strapi.admin.queries('administrator', 'admin')
const admins = await admin_orm.find({username: ADMIN_USERNAME})
if ( admins.length === 0) {
const blocked = false
const username = ADMIN_USERNAME
const password = await strapi.admin.services.auth.hashPassword(ADMIN_PASSWORD)
const email = ADMIN_EMAIL
const user = { blocked, username, password, email }
const data = await admin_orm.create(user)
strapi.log.warn(`Bootstrapped Admin User: ${JSON.stringify(user)}`)
}
}
The following are get_roles() - required for get_permissions(), and get_permissions() is required for enable_permissions() This is where we turn on those content types so the web ui can see it.
async function get_roles() {
const role_orm = strapi.plugins['users-permissions'].queries('role', 'users-permissions')
const role_list = await role_orm.find({}, [])
const roles = {}
for (let role of role_list) {
roles[ role._id ] = role
roles[ role.name ] = role
}
return roles
}
async function get_permissions( selected_role, selected_type, selected_controller ) {
const roles = await get_roles()
const permission_orm = strapi.plugins['users-permissions'].queries('permission', 'users-permissions')
let permission_list = await permission_orm.find({_limit: 999}, [])
if ( selected_role ) permission_list = permission_list.filter( ({ role }) => `${role}` === `${roles[selected_role]._id}` )
if ( selected_type ) permission_list = permission_list.filter( ({ type }) => `${type}` === `${selected_type}` )
if ( selected_controller ) permission_list = permission_list.filter( ({ controller }) => `${controller}` === `${selected_controller}` )
return permission_list
}
async function enable_permissions(role, type, controller) {
strapi.log.info(`Setting '${controller}' permissions for '${role}'`)
const permission_orm = strapi.plugins['users-permissions'].queries('permission', 'users-permissions')
const permissions = await get_permissions(role, type, controller)
for (let { _id } of permissions) {
permission_orm.update({ _id }, { enabled: true })
}
}
Finally, we run the program
module.exports = async next => {
await bootstrap_admin()
await bootstrap_resource( 'Clients', strapi.services.client )
await bootstrap_resource( 'Menus', strapi.services.menu )
enable_permissions('Public', 'application', 'client' )
enable_permissions('Public', 'application', 'github' )
enable_permissions('Public', 'application', 'menu' )
enable_permissions('Public', 'application', 'confluence' )
next()
}
Take out my comments and you have the entire bootstrap.js file. The images below show the 3 tabs of the demo.xlsx workbook that is used to populate everything.
Finally, showing the results. Menus (content), permissions set and the public website using Nuxt.
Building on both of the previous answers, it seems you can get away with a single loop and in that you can set permissions for both public
and authenticated
users.
This was written against strapi 3.2.4
and I'm using NodeJS 12 so things like the spread operator ...
are available.
const permOrm = strapi.query('permission', 'users-permissions')
const perms = await permOrm.find({ type: 'application' })
for (const curr of perms) {
if (curr.role.type === 'authenticated') {
strapi.log.info(
`Allowing authenticated to call ${curr.controller}.${curr.action}`,
)
permOrm.update({ id: curr.id }, { ...curr, enabled: true })
continue
}
// permission is for public
const isReadEndpoint = ['find', 'findone', 'count'].includes(curr.action)
if (isReadEndpoint) {
strapi.log.info(
`Allowing public to call ${curr.controller}.${curr.action}`,
)
permOrm.update({ id: curr.id }, { ...curr, enabled: true })
continue
}
// TODO add custom logic for any non-standard actions here
strapi.log.info(
`Disallowing public from calling ${curr.controller}.${curr.action}`,
)
permOrm.update({ id: curr.id }, { ...curr, enabled: false })
}