mirror of
https://github.com/wassname/talk.git
synced 2026-07-13 17:45:56 +08:00
feat: added @auth directive
This commit is contained in:
@@ -19,7 +19,6 @@
|
||||
"start:webpackDevServer": "node ./scripts/start.js",
|
||||
"start": "node dist/index.js",
|
||||
"test": "node scripts/test.js --env=jsdom",
|
||||
"watch:types": "nodemon --config ./config/nodemon/types.json",
|
||||
"watch": "NODE_ENV=development ts-node ./scripts/watcher/bin/watcher.ts ./config/watcher.ts"
|
||||
},
|
||||
"author": "",
|
||||
@@ -112,7 +111,6 @@
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"jest": "^23.2.0",
|
||||
"loader-utils": "^1.1.0",
|
||||
"nodemon": "^1.17.5",
|
||||
"npm-run-all": "^4.1.3",
|
||||
"postcss-flexbugs-fixes": "^3.3.1",
|
||||
"postcss-font-magician": "^2.2.1",
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { User } from "talk-server/models/user";
|
||||
|
||||
export interface CommonContextOptions {
|
||||
user?: User;
|
||||
}
|
||||
|
||||
export default class CommonContext {
|
||||
public user?: User;
|
||||
|
||||
constructor({ user }: CommonContextOptions) {
|
||||
this.user = user;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,39 @@
|
||||
import { DirectiveResolverFn } from "graphql-tools";
|
||||
|
||||
const auth: DirectiveResolverFn = (next, src, args, context) => {
|
||||
return next().then(str => {
|
||||
if (typeof str === "string") {
|
||||
return str.toUpperCase();
|
||||
import CommonContext from "talk-server/graph/common/context";
|
||||
import { GQLUSER_ROLE } from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
|
||||
export interface AuthDirectiveArgs {
|
||||
roles?: GQLUSER_ROLE[];
|
||||
userIDField?: string;
|
||||
}
|
||||
|
||||
const auth: DirectiveResolverFn<
|
||||
Record<string, string | undefined>,
|
||||
CommonContext
|
||||
> = (next, src, { roles, userIDField }: AuthDirectiveArgs, { user }) => {
|
||||
// If there is a user on the request.
|
||||
if (user) {
|
||||
// If the role and user owner checks are disabled, then allow them based on
|
||||
// their authenticated status.
|
||||
if (!roles && !userIDField) {
|
||||
return next();
|
||||
}
|
||||
return str;
|
||||
});
|
||||
|
||||
// And the user has the expected role.
|
||||
if (roles && roles.includes(user.role)) {
|
||||
// Let the request continue.
|
||||
return next();
|
||||
}
|
||||
|
||||
// Or the item is owned by the specific user.
|
||||
if (userIDField && src[userIDField] && src[userIDField] === user.id) {
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: return better error.
|
||||
throw new Error("not authorized");
|
||||
};
|
||||
|
||||
export default auth;
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { Db } from "mongodb";
|
||||
import CommonContext from "talk-server/graph/common/context";
|
||||
|
||||
export interface ManagementContextOptions {
|
||||
db: Db;
|
||||
}
|
||||
|
||||
export default class ManagementContext {
|
||||
export default class ManagementContext extends CommonContext {
|
||||
public db: Db;
|
||||
|
||||
constructor({ db }: ManagementContextOptions) {
|
||||
super({});
|
||||
|
||||
this.db = db;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Db } from "mongodb";
|
||||
import CommonContext from "talk-server/graph/common/context";
|
||||
import { Tenant } from "talk-server/models/tenant";
|
||||
import { User } from "talk-server/models/user";
|
||||
import loaders from "./loaders";
|
||||
@@ -10,16 +11,16 @@ export interface TenantContextOptions {
|
||||
user?: User;
|
||||
}
|
||||
|
||||
export default class TenantContext {
|
||||
export default class TenantContext extends CommonContext {
|
||||
public loaders: ReturnType<typeof loaders>;
|
||||
public mutators: ReturnType<typeof mutators>;
|
||||
public db: Db;
|
||||
public tenant: Tenant;
|
||||
public user?: User;
|
||||
|
||||
constructor({ user, tenant, db }: TenantContextOptions) {
|
||||
super({ user });
|
||||
|
||||
this.tenant = tenant;
|
||||
this.user = user;
|
||||
this.loaders = loaders(this);
|
||||
this.mutators = mutators(this);
|
||||
this.db = db;
|
||||
|
||||
@@ -2,7 +2,14 @@
|
||||
## Custom Directives
|
||||
################################################################################
|
||||
|
||||
directive @auth(roles: [USER_ROLE!]!) on FIELD_DEFINITION
|
||||
"""
|
||||
auth is a directive that will enforce authorization rules on the schema
|
||||
definition. It will restrict the viewer of the field based on roles or if the
|
||||
`userIDField` is specified, it will see if the current users ID equals the field
|
||||
specified. This allows users that own a specific resource (like a comment, or a
|
||||
flag) see their own content, but restrict it to everyone else.
|
||||
"""
|
||||
directive @auth(roles: [USER_ROLE!], userIDField: String) on FIELD_DEFINITION
|
||||
|
||||
################################################################################
|
||||
## Custom Scalar Types
|
||||
@@ -195,7 +202,7 @@ type Settings {
|
||||
autoCloseStream when true will auto close the stream when the `closeTimeout`
|
||||
amount of seconds have been reached.
|
||||
"""
|
||||
autoCloseStream: Boolean!
|
||||
autoCloseStream: Boolean! @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
customCssUrl is the URL of the custom CSS used to display on the frontend.
|
||||
@@ -254,12 +261,12 @@ type Settings {
|
||||
"""
|
||||
wordlist will return a given list of words.
|
||||
"""
|
||||
wordlist: WordlistSettings @auth(roles: [ADMIN])
|
||||
wordlist: WordlistSettings @auth(roles: [ADMIN, MODERATOR])
|
||||
|
||||
"""
|
||||
domains will return a given list of whitelisted domains.
|
||||
"""
|
||||
domains: [String!] @auth(roles: [ADMIN])
|
||||
domains: [String!] @auth(roles: [ADMIN]) @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
auth contains all the settings related to authentication and authorization.
|
||||
@@ -294,7 +301,7 @@ type User {
|
||||
"""
|
||||
role is the current role of the User.
|
||||
"""
|
||||
role: USER_ROLE!
|
||||
role: USER_ROLE! @auth(roles: [ADMIN, MODERATOR], userIDField: "id")
|
||||
}
|
||||
|
||||
################################################################################
|
||||
@@ -561,7 +568,7 @@ type Mutation {
|
||||
"""
|
||||
createComment will create a Comment as the current logged in User.
|
||||
"""
|
||||
createComment(input: CreateCommentInput!): CreateCommentPayload
|
||||
createComment(input: CreateCommentInput!): CreateCommentPayload @auth
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
||||
Reference in New Issue
Block a user