Skip to content

Commit

Permalink
feat(common): add auto fills and auto filters to resources
Browse files Browse the repository at this point in the history
add .disableAutoFills() and .disableAutoFilters() to resources
  • Loading branch information
bahdcoder committed Apr 5, 2021
1 parent 5b9b908 commit 255f2ce
Show file tree
Hide file tree
Showing 20 changed files with 236 additions and 50 deletions.
3 changes: 2 additions & 1 deletion examples/blog/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ tensei()
.fields([
text('Name').notNullable().rules('required'),
textarea('Description'),
belongsTo('User').nullable(),
hasMany('Post')
])
.displayField('Name')
Expand All @@ -46,7 +47,7 @@ tensei()
welcome(),
cms().plugin(),
auth().rolesAndPermissions()
.cookieSessions()
// .cookieSessions()
.plugin(),
rest().plugin(),
graphql().plugin()
Expand Down
2 changes: 2 additions & 0 deletions packages/auth/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export interface AuthPluginConfig {
userResource: string
tokenResource: string
prefix: string
autoFillUser: boolean
autoFilterForUser: boolean
excludedPathsFromCsrf: string[]
enableRefreshTokens?: boolean
registered?: (ctx: ApiContext) => Promise<void> | void
Expand Down
84 changes: 84 additions & 0 deletions packages/auth/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Dayjs from 'dayjs'
import crypto from 'crypto'
import Bcrypt from 'bcryptjs'
import Jwt from 'jsonwebtoken'
import { ReferenceType } from '@mikro-orm/core'
import { validateAll } from 'indicative/validator'
import {
plugin,
Expand All @@ -17,6 +18,7 @@ import {
hasMany,
boolean,
select,
filter,
password,
graphQlQuery,
GraphQLPluginContext,
Expand Down Expand Up @@ -55,6 +57,8 @@ class Auth {
setupFn: AuthSetupFn
} = {
prefix: '',
autoFillUser: true,
autoFilterForUser: true,
tokenResource: 'Token',
enableRefreshTokens: false,
userResource: 'User',
Expand Down Expand Up @@ -476,6 +480,78 @@ class Auth {
return this
}

public noAutofillUser() {
this.config.autoFillUser = false

return this
}

public noAutoFilters() {
this.config.autoFilterForUser = false

return this
}

private registerAutofillUserHooks(resources: ResourceContract[]) {
resources
.filter(
resource =>
resource.data.fields.find(
field =>
field.relatedProperty.reference ===
ReferenceType.MANY_TO_ONE &&
field.relatedProperty.type ===
this.config.userResource
) && !resource.data.disableAutoFills
)
.forEach(resource => {
resource.beforeCreate(({ entity, em }, { request }) => {
if (request.user && request.user.id) {
em.assign(entity, {
user: request.user.id
})
}
})
})
}

private registerAutoFilterUserHooks(resources: ResourceContract[]) {
resources
.filter(
resource =>
resource.data.fields.find(
field =>
field.relatedProperty.reference ===
ReferenceType.MANY_TO_ONE &&
field.relatedProperty.type ===
this.config.userResource
) && !resource.data.disableAutoFilters
)
.forEach(resource => {
resource.filters([
filter(
`${this.resources.user.data.label} ${resource.data.label}`
)
.default()
.noArgs()
.query((args, request) =>
request.user && request.user.id
? {
[this.resources.user.data.snakeCaseName]:
request.user.id
}
: resource.data.noTimestamps
? false
: {
created_at: Dayjs()
.add(1, 'month')
.toDate()
}
)
])
})
}

public plugin() {
return plugin('Auth')
.extra(this.config)
Expand Down Expand Up @@ -530,6 +606,14 @@ class Auth {
extendGraphQlTypeDefs([this.extendGraphQLTypeDefs(gql)])
extendGraphQlQueries(this.extendGraphQlQueries())
extendRoutes(this.extendRoutes())

if (this.config.autoFillUser) {
this.registerAutofillUserHooks(currentCtx().resources)
}

if (this.config.autoFilterForUser) {
this.registerAutoFilterUserHooks(currentCtx().resources)
}
}
)

Expand Down
4 changes: 2 additions & 2 deletions packages/cli/_templates/default/new/package.json.ejs.t
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ to: <%= h.changeCase.param(name) %>/package.json
"build": "yarn build:server && yarn build:client"
},
"devDependencies": {
"@tensei/common": "^0.8.0",
"@tensei/components": "^0.8.0",
"@tensei/common": "^0.8.1",
"@tensei/components": "^0.8.1",
"autoprefixer": "^10.2.4",
"cross-env": "^7.0.3",
"laravel-mix": "^6.0.5",
Expand Down
10 changes: 9 additions & 1 deletion packages/cms/plugin.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { SessionData } from 'express-session'
import { User } from '@tensei/common'

declare global {
namespace Express {
export interface Request {
user: User
}
}
}

declare module 'express-session' {
interface SessionData {
Expand Down
2 changes: 1 addition & 1 deletion packages/cms/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ class CmsPlugin {
query: RouteContract
) => {
const authorized = await Promise.all(
query.config.authorize.map(fn => fn(ctx))
query.config.authorize.map(fn => fn(ctx as any))
)

if (
Expand Down
3 changes: 2 additions & 1 deletion packages/cms/tsconfig.server.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
"types": [
"@types/jest",
"@types/express-session",
"express-response-formatter"
"express-response-formatter",
]
},
"include": ["plugin.d.ts"],
"exclude": [
"__tests__",
"build",
Expand Down
32 changes: 28 additions & 4 deletions packages/common/src/resources/Resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ export class Resource<ResourceType = {}> implements ResourceContract {
authorizedToUpdate: AuthorizeFunction[]
authorizedToDelete: AuthorizeFunction[]
authorizedToRunAction: AuthorizeFunction[]
authorizedToFetchRelation: AuthorizeFunction[]
} = {
authorizedToShow: [],
authorizedToFetch: [],
authorizedToCreate: [],
authorizedToUpdate: [],
authorizedToDelete: [],
authorizedToRunAction: []
authorizedToRunAction: [],
authorizedToFetchRelation: []
}

public dashboardAuthorizeCallbacks: {
Expand Down Expand Up @@ -109,8 +111,20 @@ export class Resource<ResourceType = {}> implements ResourceContract {
return this
}

public disableAutoFilters() {
this.data.disableAutoFilters = true

return this
}

public disableAutoFills() {
this.data.disableAutoFills = true

return this
}

public filters(filters: FilterContract[]) {
this.data.filters = filters
this.data.filters = [...this.data.filters, ...filters]

return this
}
Expand Down Expand Up @@ -140,6 +154,8 @@ export class Resource<ResourceType = {}> implements ResourceContract {
.hideOnIndex()
.hideOnUpdate()
],
disableAutoFills: false,
disableAutoFilters: false,
actions: [],
table: '',
name: '',
Expand Down Expand Up @@ -251,7 +267,15 @@ export class Resource<ResourceType = {}> implements ResourceContract {
return this
}

public canCreate(authorizeFunction: AuthorizeFunction) {
public canFetchRelation(authorizeFunction: AuthorizeFunction) {
this.authorizeCallbacks.authorizedToFetchRelation.push(
authorizeFunction
)

return this
}

public canInsert(authorizeFunction: AuthorizeFunction) {
this.authorizeCallbacks.authorizedToCreate.push(authorizeFunction)

return this
Expand Down Expand Up @@ -291,7 +315,7 @@ export class Resource<ResourceType = {}> implements ResourceContract {
return this
}

public canCreateOnDashboard(authorizeFunction: AuthorizeFunction) {
public canInsertOnDashboard(authorizeFunction: AuthorizeFunction) {
this.dashboardAuthorizeCallbacks.authorizedToCreate.push(
authorizeFunction
)
Expand Down
2 changes: 0 additions & 2 deletions packages/common/src/utils/Validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ export class Validator {
])
).join('|')

console.log('_________________', field.arrayValidationRules)

if (field.relatedProperty.reference) {
const relatedResource = this.resourcesMap[
field.relatedProperty.type!
Expand Down
4 changes: 2 additions & 2 deletions packages/common/typings/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ declare module '@tensei/common/config' {
roles: UserRole[]
permissions: string[]
}
type AuthorizeFunction<ModelType = any> = (
ctx: GraphQLPluginContext
type AuthorizeFunction<RequestType = Request> = (
ctx: RequestType
) => boolean | Promise<boolean>
type HookFunction<EntityType = DataPayload> = (
payload: EventArgs<EntityType>,
Expand Down
1 change: 0 additions & 1 deletion packages/common/typings/express.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ declare global {
}
mailer: MailManagerContract
config: Config
user: User
orm: MikroORM
storage: StorageManager
manager: EntityManager
Expand Down
10 changes: 8 additions & 2 deletions packages/common/typings/resources.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ declare module '@tensei/common/resources' {
table: string
icon: SupportedIcons
group: string
disableAutoFilters: boolean
disableAutoFills: boolean
slug: string
label: string
groupSlug: string
Expand Down Expand Up @@ -75,6 +77,7 @@ declare module '@tensei/common/resources' {
authorizedToUpdate: AuthorizeFunction[]
authorizedToDelete: AuthorizeFunction[]
authorizedToRunAction: AuthorizeFunction[]
authorizedToFetchRelation: AuthorizeFunction[]
}
dashboardAuthorizeCallbacks: {
authorizedToShow: AuthorizeFunction[]
Expand Down Expand Up @@ -104,6 +107,8 @@ declare module '@tensei/common/resources' {
hideOnUpdateApi(): this
hideOnDeleteApi(): this
hideOnFetchApi(): this
disableAutoFills(): this
disableAutoFilters(): this
showOnInsertSubscription(): this
showOnUpdateSubscription(): this
showOnDeleteSubscription(): this
Expand All @@ -116,13 +121,14 @@ declare module '@tensei/common/resources' {
permissions(permissions: Permission[]): this
canShow(authorizeFunction: AuthorizeFunction): this
canFetch(authorizeFunction: AuthorizeFunction): this
canCreate(authorizeFunction: AuthorizeFunction): this
canFetchRelation(authorizeFunction: AuthorizeFunction): this
canInsert(authorizeFunction: AuthorizeFunction): this
canUpdate(authorizeFunction: AuthorizeFunction): this
canDelete(authorizeFunction: AuthorizeFunction): this
canRunAction(authorizeFunction: AuthorizeFunction): this
canShowOnDashboard(authorizeFunction: AuthorizeFunction): this
canFetchOnDashboard(authorizeFunction: AuthorizeFunction): this
canCreateOnDashboard(authorizeFunction: AuthorizeFunction): this
canInsertOnDashboard(authorizeFunction: AuthorizeFunction): this
canUpdateOnDashboard(authorizeFunction: AuthorizeFunction): this
canDeleteOnDashboard(authorizeFunction: AuthorizeFunction): this
canRunActionOnDashboard(authorizeFunction: AuthorizeFunction): this
Expand Down
21 changes: 15 additions & 6 deletions packages/components/src/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ function toPascalCase(iconName: string) {
.replace(new RegExp(/[^\w\s]/, 'g'), '')
.replace(
new RegExp(/\s+(.)(\w+)/, 'g'),
// @ts-ignore
($1, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`
// @ts-ignore
($1, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`
)
.replace(new RegExp(/\s/, 'g'), '')
.replace(new RegExp(/\w/), s => s.toUpperCase());
.replace(new RegExp(/\w/), s => s.toUpperCase())
}

const Icon: React.FC<IconProps> = ({
Expand All @@ -35,13 +35,22 @@ const Icon: React.FC<IconProps> = ({
console.log('@@@@@@->', icon)
const iconName = `${toPascalCase(icon)}Icon`

const Icon = (Icons as any)[iconName] || (Icons as any)[`${icon}Icon`] || (Icons as any)[icon]
const Icon =
(Icons as any)[iconName] ||
(Icons as any)[`${icon}Icon`] ||
(Icons as any)[icon]

if (! Icon) {
if (!Icon) {
return null
}

return <Icon width={width} height={height} color={active ? activeFill : fill} />
return (
<Icon
width={width}
height={height}
color={active ? activeFill : fill}
/>
)
}

export default Icon
2 changes: 1 addition & 1 deletion packages/core/Tensei.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export class Tensei implements TenseiContract {
query: RouteContract
) => {
const authorized = await Promise.all(
query.config.authorize.map(fn => fn(ctx))
query.config.authorize.map(fn => fn(ctx as any))
)

if (
Expand Down
Loading

0 comments on commit 255f2ce

Please sign in to comment.