Skip to content

Commit 943ed81

Browse files
authored
Features/teams (#137)
* feat(auth): add teams and team members to auth plugin * feat(orm): add methods and repository methods to resources and orm class ' * feat(orm): add ctx to method instance and repository instances * feat(auth): add integration tests for teams / team invites * feat(auth): add tests for team invites * feat(auth): add team model methods * test(auth): fix broken auth tests with new teams functionality * feat(auth): fix broken tests
1 parent 7cb32cd commit 943ed81

File tree

37 files changed

+1151
-314
lines changed

37 files changed

+1151
-314
lines changed

examples/blog/index.js

+83-77
Original file line numberDiff line numberDiff line change
@@ -6,83 +6,89 @@ const { graphql } = require('@tensei/graphql')
66
const { mde, markdown } = require('@tensei/mde')
77

88
const {
9-
tensei,
10-
welcome,
11-
cors,
12-
resource,
13-
text,
14-
textarea,
15-
dateTime,
16-
slug,
17-
array,
18-
hasMany,
19-
belongsTo,
20-
boolean,
9+
tensei,
10+
welcome,
11+
cors,
12+
resource,
13+
text,
14+
textarea,
15+
dateTime,
16+
slug,
17+
array,
18+
hasMany,
19+
belongsTo,
20+
boolean
2121
} = require('@tensei/core')
2222

2323
module.exports = tensei()
24-
.root(__dirname)
25-
.resources([
26-
resource('Post')
27-
.fields([
28-
text('Title').rules('required'),
29-
slug('Slug').creationRules('required', 'unique:slug').unique().from('Title'),
30-
markdown('Description').creationRules('required', 'max:255'),
31-
textarea('Content').nullable().rules('required'),
32-
dateTime('Published At').creationRules('required'),
33-
belongsTo('Category').alwaysLoad(),
34-
array('Procedure')
35-
.of('string')
36-
.rules('min:3', 'max:10')
37-
.creationRules('required'),
38-
array('Prices')
39-
.nullable()
40-
.of('decimal')
41-
.rules('max:10', 'min:2')
42-
.creationRules('required')
43-
])
44-
.icon('library')
45-
.displayField('Title'),
46-
resource('Category')
47-
.fields([
48-
text('Name').notNullable().rules('required'),
49-
textarea('Description'),
50-
belongsTo('User').nullable(),
51-
hasMany('Post')
52-
])
53-
.disableAutoFilters()
54-
.displayField('Name')
55-
])
56-
.plugins([
57-
welcome(),
58-
cms().plugin(),
59-
auth()
60-
.verifyEmails()
61-
.twoFactorAuth()
62-
.social('google', {
63-
key: process.env.GOOGLE_KEY,
64-
secret: process.env.GOOGLE_SECRET,
65-
clientCallback: 'http://localhost:1234'
66-
})
67-
.setup(({ user }) => {
68-
user.fields([
69-
hasMany('Category'),
70-
boolean('Accepted Terms And Conditions').rules('required').default(false)
71-
])
72-
})
73-
.configureTokens({
74-
accessTokenExpiresIn: 60
75-
})
76-
.refreshTokens()
77-
.plugin(),
78-
rest().plugin(),
79-
graphql().plugin(),
80-
cors(),
81-
mde().plugin()
82-
])
83-
// .databaseConfig({
84-
// type: 'sqlite',
85-
// dbName: 'db.sqlite',
86-
// })
87-
.start()
88-
.catch(console.error)
24+
.root(__dirname)
25+
.resources([
26+
resource('Post')
27+
.fields([
28+
text('Title').rules('required'),
29+
slug('Slug')
30+
.creationRules('required', 'unique:slug')
31+
.unique()
32+
.from('Title'),
33+
markdown('Description').creationRules('required', 'max:255'),
34+
textarea('Content').nullable().rules('required'),
35+
dateTime('Published At').creationRules('required'),
36+
belongsTo('Category').alwaysLoad(),
37+
array('Procedure')
38+
.of('string')
39+
.rules('min:3', 'max:10')
40+
.creationRules('required'),
41+
array('Prices')
42+
.nullable()
43+
.of('decimal')
44+
.rules('max:10', 'min:2')
45+
.creationRules('required')
46+
])
47+
.icon('library')
48+
.displayField('Title'),
49+
resource('Category')
50+
.fields([
51+
text('Name').notNullable().rules('required'),
52+
textarea('Description'),
53+
belongsTo('User').nullable(),
54+
hasMany('Post')
55+
])
56+
.displayField('Name')
57+
])
58+
.plugins([
59+
welcome(),
60+
cms().plugin(),
61+
auth()
62+
.teams()
63+
.verifyEmails()
64+
.twoFactorAuth()
65+
.social('google', {
66+
key: process.env.GOOGLE_KEY,
67+
secret: process.env.GOOGLE_SECRET,
68+
clientCallback: 'http://localhost:1234'
69+
})
70+
.setup(({ user }) => {
71+
user.fields([
72+
hasMany('Category'),
73+
boolean('Accepted Terms And Conditions')
74+
.creationRules('required')
75+
.default(false)
76+
])
77+
})
78+
.configureTokens({
79+
accessTokenExpiresIn: 60 * 60 * 60 * 60 * 60
80+
})
81+
.refreshTokens()
82+
.plugin(),
83+
rest().plugin(),
84+
graphql().plugin(),
85+
cors(),
86+
mde().plugin()
87+
])
88+
.databaseConfig({
89+
type: 'sqlite',
90+
dbName: 'db.sqlite'
91+
// debug: true
92+
})
93+
.start()
94+
.catch(console.error)

examples/typescript/src/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ export default tensei()
5252
belongsTo('User').nullable(),
5353
hasMany('Post')
5454
])
55-
.disableAutoFilters()
5655
.displayField('Name')
5756
])
5857
.plugins([

packages/auth/auth.config.d.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { AnyEntity } from '@mikro-orm/core'
2-
import { UserEntity } from './src/config'
3-
import { GraphQLPluginContext } from '@tensei/common'
2+
import { GraphQLPluginContext, DataPayload } from '@tensei/common'
43

54
declare module '@tensei/common' {
65
interface GraphQLPluginContext {
7-
user: UserEntity
6+
// @ts-ignore
7+
user: import('@tensei/orm').UserModel & DataPayload
8+
// @ts-ignore
9+
team: import('@tensei/orm').TeamModel
810
}
911
}

packages/auth/auth.d.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { Mail } from '@tensei/mail'
2-
import { UserEntity } from './src/config'
32
import { AnyEntity } from '@mikro-orm/core'
3+
import { DataPayload } from '@tensei/common'
44
import { SessionData } from 'express-session'
55
import * as Formatter from 'express-response-formatter'
66

77
declare global {
88
namespace Express {
99
export interface Request {
10-
user: UserEntity
10+
// @ts-ignore
11+
user: import('@tensei/orm').UserModel & DataPayload
12+
// @ts-ignore
13+
team: import('@tensei/orm').TeamModel
1114
verifyTwoFactorAuthToken: (token: string | number) => boolean
1215
}
1316
}

packages/auth/src/config.ts

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { AnyEntity } from '@mikro-orm/core'
44
import { UserRole } from '@tensei/common'
55
import { ApiContext } from '@tensei/common'
66
import { DataPayload } from '@tensei/common'
7+
import { PermissionContract } from 'teams/Permission'
78

89
export interface GrantConfig {
910
key: string
@@ -29,6 +30,8 @@ export type AuthResources = {
2930
permission: ResourceContract
3031
passwordReset: ResourceContract
3132
token: ResourceContract
33+
team: ResourceContract
34+
membership: ResourceContract
3235
}
3336

3437
export enum TokenTypes {
@@ -45,14 +48,17 @@ export interface AuthPluginConfig {
4548
fields: FieldContract[]
4649
userResource: string
4750
tokenResource: string
51+
teamResource: string
4852
prefix: string
53+
teamPermissions: PermissionContract[]
4954
autoFillUser: boolean
5055
autoFilterForUser: boolean
5156
excludedPathsFromCsrf: string[]
5257
enableRefreshTokens?: boolean
5358
registered?: (ctx: ApiContext) => Promise<void> | void
5459
roleResource: string
5560
permissionResource: string
61+
teams: boolean
5662
rolesAndPermissions: boolean
5763
passwordResetResource: string
5864
apiPath: string

0 commit comments

Comments
 (0)