Skip to content

Commit

Permalink
feat(cms): add users & roles to the cms sidebar menu
Browse files Browse the repository at this point in the history
  • Loading branch information
Frantz Kati committed Feb 11, 2021
1 parent 4b5bb65 commit eda1e3c
Show file tree
Hide file tree
Showing 26 changed files with 236 additions and 110 deletions.
7 changes: 6 additions & 1 deletion examples/blog/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ tensei()
.displayField('Title'),
resource('Category')
.fields([
text('Name'),
text('Name').notNullable().rules('required'),
textarea('Description'),
hasMany('Post')
])
Expand All @@ -32,5 +32,10 @@ tensei()
media().plugin(),
graphql().plugin(),
])
.databaseConfig({
type: 'sqlite',
debug: true,
dbName: 'tensei'
})
.start()
.catch(console.error)
4 changes: 4 additions & 0 deletions examples/blog/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"watch": ["node_modules/", "index.js"],
"ext": "js, css"
}
25 changes: 21 additions & 4 deletions packages/auth/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ class Auth {
.displayField('Name')
.hideOnDeleteApi()
.hideOnUpdateApi()
.hideFromNavigation()
.group('Users & Permissions')
}

Expand All @@ -366,6 +367,8 @@ class Auth {
belongsToMany(this.config.permissionResource).owner()
])
.displayField('Name')
.hideFromNavigation()
.hideOnUpdateApi()
.group('Users & Permissions')
}

Expand Down Expand Up @@ -494,10 +497,24 @@ class Auth {
])
}

const { app, serverUrl, clientUrl, currentCtx, routes } = config
const {
app,
serverUrl,
clientUrl,
currentCtx,
routes,
setPluginConfig
} = config

this.forceRemoveInsertUserQueries(config.graphQlQueries)

setPluginConfig('auth', {
rolesAndPermissions: this.config.rolesAndPermissions,
user: this.resources.user.serialize(),
role: this.resources.role.serialize(),
permission: this.resources.permission.serialize()
})

if (this.socialAuthEnabled()) {
const { register } = require('@tensei/social-auth')

Expand Down Expand Up @@ -586,7 +603,7 @@ class Auth {
({ user }) =>
user &&
user[this.getPermissionUserKey()]?.includes(
`fetch:${slug}`
`index:${slug}`
)
)
}
Expand Down Expand Up @@ -652,12 +669,12 @@ class Auth {
)
}

if (id === `fetch_${slugPlural}`) {
if (id === `index_${slugPlural}`) {
return route.authorize(
({ user }) =>
user &&
user[this.getPermissionUserKey()]?.includes(
`fetch:${slugPlural}`
`index:${slugPlural}`
)
)
}
Expand Down
26 changes: 16 additions & 10 deletions packages/auth/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,25 @@ const getPermissionsToInsert = async (
) => {
const permissions: Permission[] = []

resources.forEach(resource => {
;['insert', 'fetch', 'show', 'update', 'delete'].forEach(operation => {
permissions.push(`${operation}:${resource.data.slug}`)
})
resources
.filter(resource => !resource.data.hideOnApi)
.forEach(resource => {
;['insert', 'index', 'show', 'update', 'delete'].forEach(
operation => {
permissions.push(`${operation}:${resource.data.slug}`)
}
)

resource.data.actions.forEach(action => {
permissions.push(`run:${resource.data.slug}:${action.data.slug}`)
})
resource.data.actions.forEach(action => {
permissions.push(
`run:${resource.data.slug}:${action.data.slug}`
)
})

resource.data.permissions.forEach(permission => {
permissions.push(permission)
resource.data.permissions.forEach(permission => {
permissions.push(permission)
})
})
})

const existingPermissions: any[] = (
await em.find(permissionResource.data.pascalCaseName, {
Expand Down
85 changes: 55 additions & 30 deletions packages/cms/pages/Settings/ManageRole.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
TextInput,
Textarea,
Label,
Checkbox
Checkbox,
ResourceContract
} from '@tensei/components'

import DeleteModal from '../../components/DeleteModal'
Expand All @@ -23,6 +24,7 @@ export interface ResourceProps {
onCreate?: () => void
onUpdate?: () => void
creating: boolean
resource?: ResourceContract
setCreating: (creating: boolean) => void
deleting: AbstractData | null
setDeleting: (deleting: any) => void
Expand Down Expand Up @@ -58,26 +60,33 @@ const ManageUser: React.FC<ResourceProps> = ({
onCreate,
onUpdate,
creating,
resource = window.Tensei.state.resourcesMap['admin-roles'],
setCreating,
deleting,
setDeleting,
setEditing,
editing
}) => {
const permissionsInputKey =
resource.slug === 'admin-roles'
? 'admin_permissions'
: window.Tensei.state.config.pluginsConfig.auth.permission
.snakeCaseNamePlural
const descriptionInputKey =
resource.slug === 'admin-roles' ? 'description' : 'slug'
const [loading, setLoading] = useState(false)
const [form, setForm] = useState<AbstractData>({
name: '',
description: '',
admin_permissions: []
[descriptionInputKey]: '',
[permissionsInputKey]: []
})
const [errors, setErrors] = useState<AbstractData>({})
const [permissionSlugs, setPermissionSlugs] = useState<string[]>([])
const [permissions, setPermissions] = useState<AbstractData[]>([])
const [accordions, setAccordions] = useState<number[]>([])
const resource = window.Tensei.state.resourcesMap['admin-roles']

const onSubmit = () => {
form.admin_permissions = permissionSlugs
form[permissionsInputKey] = permissionSlugs
.map(slug => {
const permission = permissions.find(p => p.slug === slug)

Expand All @@ -103,7 +112,7 @@ const ManageUser: React.FC<ResourceProps> = ({
}

window.Tensei.success(
`Admin role ${editing ? 'updated' : 'created'}.`
`${resource.label} ${editing ? 'updated' : 'created'}.`
)

if (editing) {
Expand All @@ -130,7 +139,9 @@ const ManageUser: React.FC<ResourceProps> = ({

setLoading(false)
window.Tensei.error(
`Failed ${editing ? 'updating' : 'creating'} admin role.`
`Failed ${
editing ? 'updating' : 'creating'
} ${resource.name.toLowerCase()}.`
)
})
}
Expand All @@ -139,18 +150,26 @@ const ManageUser: React.FC<ResourceProps> = ({
if (editing) {
setForm({
name: editing.name,
description: editing.description
[descriptionInputKey]: editing[descriptionInputKey]
})

setPermissionSlugs(
editing.admin_permissions.map((p: any) => p.slug)
editing[permissionsInputKey].map((p: any) => p.slug)
)
}
}, [editing])

useEffect(() => {
window.Tensei.client.get('admin-permissions').then(({ data }) => {
setPermissions(data.data)
})
window.Tensei.client
.get(
resource.slug === 'admin-roles'
? 'admin-permissions'
: window.Tensei.state.config.pluginsConfig.auth.permission
.slug
)
.then(({ data }) => {
setPermissions(data.data)
})
}, [])

useEffect(() => {
Expand All @@ -169,7 +188,9 @@ const ManageUser: React.FC<ResourceProps> = ({
}
}

const resources = window.Tensei.state.resources
const resources = window.Tensei.state.resources.filter(r =>
resource.slug === 'admin-roles' ? r : !r.hideOnApi
)

return (
<>
Expand Down Expand Up @@ -206,22 +227,24 @@ const ManageUser: React.FC<ResourceProps> = ({
}
/>
</div>
<div className="mb-5">
<Textarea
label="Description"
name="description"
id="description"
placeholder="Description"
value={form.description}
error={errors.description as string}
onChange={event =>
setForm({
...form,
description: event.target.value
})
}
/>
</div>
{descriptionInputKey === 'description' ? (
<div className="mb-5">
<Textarea
label="Description"
name="description"
id="description"
placeholder="Description"
value={form.description}
error={errors.description as string}
onChange={event =>
setForm({
...form,
description: event.target.value
})
}
/>
</div>
) : null}
<div className="mb-8">
<Label label="Select Permissions" id="permissions" />

Expand Down Expand Up @@ -392,7 +415,9 @@ const ManageUser: React.FC<ResourceProps> = ({
className="ml-3"
success
>
{editing ? 'Update' : 'Create Role'}
{editing
? 'Update'
: `Create ${resource.name.toLowerCase()}`}
</Button>
</div>
</div>
Expand Down
Loading

0 comments on commit eda1e3c

Please sign in to comment.