@stonecrop/casl-middleware 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -0
- package/dist/casl-middleware.d.ts +158 -0
- package/dist/casl-middleware.js +40571 -0
- package/dist/casl-middleware.js.map +1 -0
- package/dist/casl_middleware.tsbuildinfo +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +3 -0
- package/dist/src/middleware/ability.d.ts +55 -0
- package/dist/src/middleware/ability.d.ts.map +1 -0
- package/dist/src/middleware/ability.js +139 -0
- package/dist/src/middleware/graphql.d.ts +11 -0
- package/dist/src/middleware/graphql.d.ts.map +1 -0
- package/dist/src/middleware/graphql.js +120 -0
- package/dist/src/middleware/introspection.d.ts +71 -0
- package/dist/src/middleware/introspection.d.ts.map +1 -0
- package/dist/src/middleware/introspection.js +169 -0
- package/dist/src/middleware/jwt.d.ts +114 -0
- package/dist/src/middleware/jwt.d.ts.map +1 -0
- package/dist/src/middleware/jwt.js +291 -0
- package/dist/src/middleware/postgraphile.d.ts +7 -0
- package/dist/src/middleware/postgraphile.d.ts.map +1 -0
- package/dist/src/middleware/postgraphile.js +80 -0
- package/dist/src/middleware/yoga.d.ts +15 -0
- package/dist/src/middleware/yoga.d.ts.map +1 -0
- package/dist/src/middleware/yoga.js +32 -0
- package/dist/src/tsdoc-metadata.json +11 -0
- package/dist/src/types/index.d.ts +114 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +0 -0
- package/dist/tests/ability.test.d.ts +2 -0
- package/dist/tests/ability.test.d.ts.map +1 -0
- package/dist/tests/ability.test.js +125 -0
- package/dist/tests/helpers/test-utils.d.ts +46 -0
- package/dist/tests/helpers/test-utils.d.ts.map +1 -0
- package/dist/tests/helpers/test-utils.js +92 -0
- package/dist/tests/introspection.test.d.ts +2 -0
- package/dist/tests/introspection.test.d.ts.map +1 -0
- package/dist/tests/introspection.test.js +368 -0
- package/dist/tests/jwt.test.d.ts +2 -0
- package/dist/tests/jwt.test.d.ts.map +1 -0
- package/dist/tests/jwt.test.js +371 -0
- package/dist/tests/middleware.test.d.ts +2 -0
- package/dist/tests/middleware.test.d.ts.map +1 -0
- package/dist/tests/middleware.test.js +184 -0
- package/dist/tests/postgraphile-plugin.test.d.ts +2 -0
- package/dist/tests/postgraphile-plugin.test.d.ts.map +1 -0
- package/dist/tests/postgraphile-plugin.test.js +56 -0
- package/dist/tests/setup.d.ts +2 -0
- package/dist/tests/setup.d.ts.map +1 -0
- package/dist/tests/setup.js +11 -0
- package/dist/tests/user-roles.test.d.ts +2 -0
- package/dist/tests/user-roles.test.d.ts.map +1 -0
- package/dist/tests/user-roles.test.js +157 -0
- package/dist/tests/yoga-plugin.test.d.ts +2 -0
- package/dist/tests/yoga-plugin.test.d.ts.map +1 -0
- package/dist/tests/yoga-plugin.test.js +47 -0
- package/package.json +91 -0
- package/src/index.ts +15 -0
- package/src/middleware/ability.ts +191 -0
- package/src/middleware/graphql.ts +157 -0
- package/src/middleware/introspection.ts +258 -0
- package/src/middleware/jwt.ts +394 -0
- package/src/middleware/postgraphile.ts +93 -0
- package/src/middleware/yoga.ts +39 -0
- package/src/types/index.ts +133 -0
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# CASL GraphQL Middleware
|
|
2
|
+
|
|
3
|
+
A middleware solution for integrating CASL authorization with GraphQL servers, with specific support for Postgraphile and Nuxt GraphQL Server.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- CASL integration with GraphQL resolvers
|
|
8
|
+
- Framework-specific helpers for Postgraphile and Nuxt
|
|
9
|
+
- Type-safe ability definitions
|
|
10
|
+
- Support for field-level permissions
|
|
11
|
+
- Ability to combine multiple authorization rules
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @stonecrop/casl-middleware
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Basic Usage
|
|
20
|
+
|
|
21
|
+
### Core Middleware
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { createCaslMiddleware } from '@stonecrop/casl-middleware'
|
|
25
|
+
|
|
26
|
+
const middleware = createCaslMiddleware({
|
|
27
|
+
subjectMap: {
|
|
28
|
+
User: 'User',
|
|
29
|
+
Item: 'Item'
|
|
30
|
+
},
|
|
31
|
+
fieldPermissions: {
|
|
32
|
+
'Item.price': [{ action: 'read', subject: 'item' }]
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Postgraphile Integration
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// graphile.config.js
|
|
41
|
+
import { pglCaslPlugin } from '@stonecrop/casl-middleware'
|
|
42
|
+
import { postgraphile } from 'postgraphile'
|
|
43
|
+
|
|
44
|
+
export default {
|
|
45
|
+
pgServices: [
|
|
46
|
+
makePgService({
|
|
47
|
+
connectionString: 'postgres://testuser:testpass@postgres:5432/testdb',
|
|
48
|
+
schemas: ['public'],
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
plugins: [pglCaslPlugin],
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Testing Abilities in GraphiQL
|
|
56
|
+
|
|
57
|
+
Create an ability:
|
|
58
|
+
```graphql
|
|
59
|
+
mutation CreateAbility {
|
|
60
|
+
createAbility(input: {
|
|
61
|
+
userId: "123",
|
|
62
|
+
roles: ["admin"]
|
|
63
|
+
}) {
|
|
64
|
+
success
|
|
65
|
+
ability
|
|
66
|
+
message
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Test protected queries:
|
|
72
|
+
```graphql
|
|
73
|
+
query GetSecretData {
|
|
74
|
+
getSecretData {
|
|
75
|
+
id
|
|
76
|
+
content
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Development
|
|
82
|
+
|
|
83
|
+
### Prerequisites
|
|
84
|
+
|
|
85
|
+
- Node.js >= 20
|
|
86
|
+
- pnpm
|
|
87
|
+
- Docker and Docker Compose
|
|
88
|
+
|
|
89
|
+
### Local Development
|
|
90
|
+
|
|
91
|
+
1. Clone the repository:
|
|
92
|
+
```bash
|
|
93
|
+
git clone <repository-url>
|
|
94
|
+
cd casl-middleware
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
2. Install dependencies:
|
|
98
|
+
```bash
|
|
99
|
+
pnpm install
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
3. Run the Postgraphile example:
|
|
103
|
+
```bash
|
|
104
|
+
pnpm dev:postgraphile
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Project Structure
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
.
|
|
111
|
+
├── examples/
|
|
112
|
+
│ └── postgraphile/ # Postgraphile example implementation
|
|
113
|
+
├── src/
|
|
114
|
+
│ ├── middleware/ # Core CASL middleware
|
|
115
|
+
│ ├── types/ # TypeScript types
|
|
116
|
+
│ └── index.ts # Main exports
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Framework Support
|
|
120
|
+
|
|
121
|
+
### Postgraphile
|
|
122
|
+
- Implements CASL as a Postgraphile plugin
|
|
123
|
+
- Supports ability creation and management
|
|
124
|
+
- Integrates with Postgraphile's schema extension system
|
|
125
|
+
|
|
126
|
+
### Nuxt GraphQL Server
|
|
127
|
+
- Provides middleware for Nuxt's GraphQL module
|
|
128
|
+
- Handles ability creation on request
|
|
129
|
+
- Integrates with Nuxt's context system
|
|
130
|
+
|
|
131
|
+
## Contributing
|
|
132
|
+
|
|
133
|
+
1. Fork the repository
|
|
134
|
+
2. Create your feature branch
|
|
135
|
+
3. Commit your changes
|
|
136
|
+
4. Push to the branch
|
|
137
|
+
5. Create a new Pull Request
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
MIT License
|
|
142
|
+
|
|
143
|
+
## TODOs
|
|
144
|
+
|
|
145
|
+
- [ ] Add comprehensive test suite
|
|
146
|
+
- [ ] Add more framework integrations
|
|
147
|
+
- [ ] Implement ability persistence
|
|
148
|
+
- [ ] Add more examples for different use cases
|
|
149
|
+
- [ ] Add documentation for advanced usage scenarios
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { GraphileConfig as GraphileConfig_2 } from 'postgraphile/graphile-build';
|
|
2
|
+
import { GraphQLResolveInfo } from 'graphql';
|
|
3
|
+
import { PureAbility } from '@casl/ability';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Function type for building user abilities
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
declare type AbilityBuilderFunction = (user?: Context['user']) => Promise<AppAbility> | AppAbility;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Response type for ability creation mutations
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
export declare interface AbilityResponse {
|
|
16
|
+
/** Whether the ability was created successfully */
|
|
17
|
+
success: boolean;
|
|
18
|
+
/** The created ability rules */
|
|
19
|
+
ability: any;
|
|
20
|
+
/** Success or error message */
|
|
21
|
+
message: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* CASL ability type for authorization with flexible subject types
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export declare type AppAbility = PureAbility<[string, any], any>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* GraphQL context with CASL ability and user information
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export declare interface Context {
|
|
35
|
+
/** CASL ability instance for authorization checks */
|
|
36
|
+
ability?: AppAbility;
|
|
37
|
+
/** Current authenticated user */
|
|
38
|
+
user?: User;
|
|
39
|
+
/** Additional context properties */
|
|
40
|
+
[key: string]: any;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create ability using a provided builder function
|
|
45
|
+
* @param user - User information for building the ability
|
|
46
|
+
* @param builderFn - Function to build the ability
|
|
47
|
+
* @returns Promise resolving to the created ability
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
export declare const createAbility: (user?: Context["user"], builderFn?: AbilityBuilderFunction) => Promise<AppAbility>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Input type for creating a new ability
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export declare interface CreateAbilityInput {
|
|
57
|
+
/** User ID to create ability for */
|
|
58
|
+
userId: string;
|
|
59
|
+
/** Array of role names to assign */
|
|
60
|
+
roles: string[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Creates CASL authorization middleware for GraphQL resolvers
|
|
65
|
+
* @param options - Configuration options for the middleware
|
|
66
|
+
* @returns Middleware function that wraps resolvers with authorization checks
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
export declare const createCaslMiddleware: (options?: MiddlewareOptions) => (resolve: ResolverFn, root: any, args: any, context: Context, info: GraphQLResolveInfo) => Promise<any>;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Detects the subject type from an object for CASL authorization
|
|
73
|
+
* @param object - The object to detect the subject type from
|
|
74
|
+
* @returns The subject type string
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
export declare const detectSubjectType: (object: any) => string;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Field-level permission definition for fine-grained access control
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
export declare interface FieldPermission {
|
|
84
|
+
/** CASL action (e.g., 'read', 'write') */
|
|
85
|
+
action: string;
|
|
86
|
+
/** Subject/resource type to apply permission to */
|
|
87
|
+
subject: string;
|
|
88
|
+
/** Specific field name (optional) */
|
|
89
|
+
field?: string;
|
|
90
|
+
/** Conditional rules for permission */
|
|
91
|
+
conditions?: any;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Middleware function that wraps a GraphQL resolver with authorization logic
|
|
96
|
+
* @public
|
|
97
|
+
*/
|
|
98
|
+
export declare type MiddlewareFn = (resolve: ResolverFn, root: any, args: any, context: Context, info: GraphQLResolveInfo) => Promise<any> | any;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Configuration options for CASL middleware
|
|
102
|
+
* @public
|
|
103
|
+
*/
|
|
104
|
+
export declare interface MiddlewareOptions {
|
|
105
|
+
/** Mapping of GraphQL types to authorization subjects */
|
|
106
|
+
subjectMap?: Record<string, string>;
|
|
107
|
+
/** Mapping of GraphQL operations to CASL actions */
|
|
108
|
+
actionMap?: Record<string, string>;
|
|
109
|
+
/** Field-level permission rules */
|
|
110
|
+
fieldPermissions?: Record<string, FieldPermission[]>;
|
|
111
|
+
/** Custom function to build user abilities */
|
|
112
|
+
abilityBuilder?: AbilityBuilderFunction;
|
|
113
|
+
/** Enable debug logging */
|
|
114
|
+
debug?: boolean;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* PostGraphile plugin for CASL authorization
|
|
119
|
+
* @public
|
|
120
|
+
*/
|
|
121
|
+
export declare const pglCaslPlugin: GraphileConfig_2.Plugin;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Plugin configuration options for framework integrations
|
|
125
|
+
* @public
|
|
126
|
+
*/
|
|
127
|
+
export declare interface PluginOptions extends MiddlewareOptions {
|
|
128
|
+
/** Custom function to build user abilities */
|
|
129
|
+
abilityBuilder?: AbilityBuilderFunction;
|
|
130
|
+
/** Ability caching configuration */
|
|
131
|
+
cacheOptions?: {
|
|
132
|
+
/** Time-to-live in milliseconds */
|
|
133
|
+
ttl?: number;
|
|
134
|
+
/** Function to generate cache key from user */
|
|
135
|
+
key?: (user?: User) => string;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* GraphQL resolver function type
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
export declare type ResolverFn = (root: any, args: any, context: Context, info: GraphQLResolveInfo) => Promise<any> | any;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* User information for authorization
|
|
147
|
+
* @public
|
|
148
|
+
*/
|
|
149
|
+
export declare interface User {
|
|
150
|
+
/** Unique identifier for the user */
|
|
151
|
+
id: string;
|
|
152
|
+
/** Array of role names assigned to the user */
|
|
153
|
+
roles?: string[];
|
|
154
|
+
/** Additional user properties */
|
|
155
|
+
[key: string]: any;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { }
|