From 62fa586aee5b12725661416b2050a54d50665250 Mon Sep 17 00:00:00 2001 From: Ola Okelola <10857143+lolopinto@users.noreply.github.com> Date: Mon, 13 Jan 2025 23:16:34 -0800 Subject: [PATCH] fix 1865 (#1872) --- .../generated/mutations/mutation_type.ts | 2 + .../mutations/user_auth_jwt2_type.ts | 69 +++++++++++++++++++ .../simple/src/graphql/generated/schema.gql | 7 ++ .../simple/src/graphql/generated/schema.ts | 2 + examples/simple/src/graphql/mutations/auth.ts | 56 +++++++++++++++ .../src/graphql/mutations/auth_types.ts | 20 ++++++ internal/graphql/custom_ts.go | 15 ++-- 7 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 examples/simple/src/graphql/generated/mutations/user_auth_jwt2_type.ts diff --git a/examples/simple/src/graphql/generated/mutations/mutation_type.ts b/examples/simple/src/graphql/generated/mutations/mutation_type.ts index c61575e36..71198e0f1 100644 --- a/examples/simple/src/graphql/generated/mutations/mutation_type.ts +++ b/examples/simple/src/graphql/generated/mutations/mutation_type.ts @@ -39,6 +39,7 @@ import { UserCreateType } from "./user/user_create_type"; import { UserDelete2Type } from "./user/user_delete2_type"; import { UserDeleteType } from "./user/user_delete_type"; import { UserEditType } from "./user/user_edit_type"; +import { UserAuthJWT2Type } from "./user_auth_jwt2_type"; import { UserAuthJWTType } from "./user_auth_jwt_type"; import { UserAuthType } from "./user_auth_type"; import { UserStatisticsCreateType } from "./user_statistics/user_statistics_create_type"; @@ -81,6 +82,7 @@ export const MutationType = new GraphQLObjectType({ phoneNumberEdit: PhoneNumberEditType, userAuth: UserAuthType, userAuthJWT: UserAuthJWTType, + userAuthJWT2: UserAuthJWT2Type, userCreate: UserCreateType, userDelete: UserDeleteType, userDelete2: UserDelete2Type, diff --git a/examples/simple/src/graphql/generated/mutations/user_auth_jwt2_type.ts b/examples/simple/src/graphql/generated/mutations/user_auth_jwt2_type.ts new file mode 100644 index 000000000..2ef5dbeb2 --- /dev/null +++ b/examples/simple/src/graphql/generated/mutations/user_auth_jwt2_type.ts @@ -0,0 +1,69 @@ +/** + * Copyright whaa whaa + * Generated by github.com/lolopinto/ent/ent, DO NOT EDIT. + */ + +import { + GraphQLFieldConfig, + GraphQLFieldConfigMap, + GraphQLID, + GraphQLNonNull, + GraphQLObjectType, + GraphQLResolveInfo, + GraphQLString, +} from "graphql"; +import { RequestContext } from "@snowtop/ent"; +import { AuthResolver } from "../../mutations/auth"; +import { UserAuthJWTLogin } from "../../mutations/auth_types"; +import { ExampleViewer as ExampleViewerAlias } from "../../../viewer/viewer"; + +interface UserAuthJWT2Args { + emailAddress: string; + password: string; +} + +export const UserAuthJWTLoginType = new GraphQLObjectType({ + name: "UserAuthJWTLogin", + fields: (): GraphQLFieldConfigMap< + UserAuthJWTLogin, + RequestContext + > => ({ + token: { + type: new GraphQLNonNull(GraphQLString), + }, + viewerID: { + type: new GraphQLNonNull(GraphQLID), + }, + }), + isTypeOf(obj) { + return obj instanceof UserAuthJWTLogin; + }, +}); + +export const UserAuthJWT2Type: GraphQLFieldConfig< + undefined, + RequestContext, + UserAuthJWT2Args +> = { + type: new GraphQLNonNull(UserAuthJWTLoginType), + description: "authenticate a user with JWT", + args: { + emailAddress: { + description: "", + type: new GraphQLNonNull(GraphQLString), + }, + password: { + description: "", + type: new GraphQLNonNull(GraphQLString), + }, + }, + resolve: async ( + _source, + args, + context: RequestContext, + _info: GraphQLResolveInfo, + ) => { + const r = new AuthResolver(); + return r.userAuthJWT2(context, args.emailAddress, args.password); + }, +}; diff --git a/examples/simple/src/graphql/generated/schema.gql b/examples/simple/src/graphql/generated/schema.gql index 6f25a0109..a15ab09fd 100644 --- a/examples/simple/src/graphql/generated/schema.gql +++ b/examples/simple/src/graphql/generated/schema.gql @@ -1094,6 +1094,11 @@ input UserAuthJWTInput { password: String! } +type UserAuthJWTLogin { + token: String! + viewerID: ID! +} + type UserAuthJWTPayload { token: String! viewerID: ID! @@ -1787,6 +1792,8 @@ type Mutation { userAuth(input: UserAuthInput!): UserAuthPayload! """authenticate a user with JWT""" userAuthJWT(input: UserAuthJWTInput!): UserAuthJWTPayload! + """authenticate a user with JWT""" + userAuthJWT2(emailAddress: String!, password: String!): UserAuthJWTLogin! userCreate(input: UserCreateInput!): UserCreatePayload! userDelete(input: UserDeleteInput!): UserDeletePayload! userDelete2(input: DeleteUserInput2!): DeleteUserInput2Payload! diff --git a/examples/simple/src/graphql/generated/schema.ts b/examples/simple/src/graphql/generated/schema.ts index 5ae42d11a..39d7b53a5 100644 --- a/examples/simple/src/graphql/generated/schema.ts +++ b/examples/simple/src/graphql/generated/schema.ts @@ -158,6 +158,7 @@ import { UserEditInputType, UserEditPayloadType, } from "./mutations/user/user_edit_type"; +import { UserAuthJWTLoginType } from "./mutations/user_auth_jwt2_type"; import { UserAuthJWTInputType, UserAuthJWTPayloadType, @@ -397,6 +398,7 @@ export default new GraphQLSchema({ PhoneAvailableArgType, UserAuthInputType, UserAuthJWTInputType, + UserAuthJWTLoginType, UserAuthJWTPayloadType, UserAuthPayloadType, AddressCreateInputType, diff --git a/examples/simple/src/graphql/mutations/auth.ts b/examples/simple/src/graphql/mutations/auth.ts index 30419eb1b..e6463abca 100644 --- a/examples/simple/src/graphql/mutations/auth.ts +++ b/examples/simple/src/graphql/mutations/auth.ts @@ -11,6 +11,7 @@ import { User } from "../../ent"; import { UserAuthInput, UserAuthJWTInput, + UserAuthJWTLogin, UserAuthJWTPayload, UserAuthPayload, } from "./auth_types"; @@ -125,6 +126,61 @@ export class AuthResolver { return new UserAuthJWTPayload(encodeGQLID(user), token); } + @gqlMutation({ + class: "AuthResolver", + name: "userAuthJWT2", + type: "UserAuthJWTLogin", + description: "authenticate a user with JWT", + async: true, + args: [ + gqlContextType(), + { + name: "emailAddress", + type: "String", + }, + { + name: "password", + type: "String", + }, + ], + }) + async userAuthJWT2( + context: RequestContext, + emailAddress: string, + password: string, + ): Promise { + const [viewer, token] = await useAndVerifyAuthJWT( + context, + async () => { + const data = await User.validateEmailPassword(emailAddress, password); + return data?.id; + }, + { + secretOrKey: "secret", + signInOptions: { + algorithm: "HS256", + audience: "https://foo.com/website", + issuer: "https://foo.com", + expiresIn: "1h", + }, + }, + User.loaderOptions(), + // don't store this in session since we're using JWT here + { + session: false, + }, + ); + if (!viewer) { + throw new Error("not the right credentials"); + } + const user = await viewer?.viewer(); + if (!user) { + throw new Error("not the right credentials"); + } + + return new UserAuthJWTLogin(encodeGQLID(user), token); + } + @gqlMutation({ class: "AuthResolver", name: "phoneAvailable", diff --git a/examples/simple/src/graphql/mutations/auth_types.ts b/examples/simple/src/graphql/mutations/auth_types.ts index e60816e8e..a1818fd2a 100644 --- a/examples/simple/src/graphql/mutations/auth_types.ts +++ b/examples/simple/src/graphql/mutations/auth_types.ts @@ -80,3 +80,23 @@ export class UserAuthJWTPayload { this.viewerID = viewerID; } } + +@gqlObjectType() +export class UserAuthJWTLogin { + @gqlField({ + class: "UserAuthJWTLogin", + type: GraphQLString, + }) + token: string; + + @gqlField({ + class: "UserAuthJWTLogin", + type: GraphQLID, + }) + viewerID: ID; + + constructor(viewerID: ID, token: string) { + this.token = token; + this.viewerID = viewerID; + } +} diff --git a/internal/graphql/custom_ts.go b/internal/graphql/custom_ts.go index 757e152ce..a89817fff 100644 --- a/internal/graphql/custom_ts.go +++ b/internal/graphql/custom_ts.go @@ -261,7 +261,7 @@ type fieldConfigBuilder interface { getArg() string getName() string getResolveMethodArg() string - getTypeImports(processor *codegen.Processor, s *gqlSchema) []*tsimport.ImportPath + getTypeImports(processor *codegen.Processor, cd *CustomData, s *gqlSchema) []*tsimport.ImportPath getArgs(s *gqlSchema) []*fieldConfigArg getReturnTypeHint() string getArgMap(cd *CustomData) map[string]*CustomObject @@ -305,7 +305,7 @@ func (mfcg *mutationFieldConfigBuilder) getResolveMethodArg() string { return mfcg.field.getResolveMethodArg() } -func (mfcg *mutationFieldConfigBuilder) getTypeImports(processor *codegen.Processor, s *gqlSchema) []*tsimport.ImportPath { +func (mfcg *mutationFieldConfigBuilder) getTypeImports(processor *codegen.Processor, cd *CustomData, s *gqlSchema) []*tsimport.ImportPath { if len(mfcg.field.Results) != 1 { panic(fmt.Errorf("invalid number of results for custom field %s", mfcg.field.FunctionName)) } @@ -322,10 +322,11 @@ func (mfcg *mutationFieldConfigBuilder) getTypeImports(processor *codegen.Proces if imp != nil { ret = append(ret, imp) } else { - ret = append(ret, &tsimport.ImportPath{ - // TODO we should pass this in instead of automatically doing this - Import: names.ToClassType(mfcg.field.GraphQLName, "PayloadType"), + // local import file which exists in the same file + // i.e. UserAuthPayload -> UserAuthPayloadType + // UserAuthLogin -> UserAuthLoginType + Import: names.ToClassType(r.Type, "Type"), ImportPath: "", }) } @@ -396,7 +397,7 @@ func (qfcg *queryFieldConfigBuilder) getResolveMethodArg() string { return qfcg.field.getResolveMethodArg() } -func (qfcg *queryFieldConfigBuilder) getTypeImports(processor *codegen.Processor, s *gqlSchema) []*tsimport.ImportPath { +func (qfcg *queryFieldConfigBuilder) getTypeImports(processor *codegen.Processor, cd *CustomData, s *gqlSchema) []*tsimport.ImportPath { if len(qfcg.field.Results) != 1 { panic("invalid number of results for custom field") } @@ -647,7 +648,7 @@ func buildFieldConfigFrom(builder fieldConfigBuilder, processor *codegen.Process Description: field.Description, Arg: builder.getArg(), ResolveMethodArg: builder.getResolveMethodArg(), - TypeImports: builder.getTypeImports(processor, s), + TypeImports: builder.getTypeImports(processor, cd, s), ArgImports: argImports, // reserve and use them. no questions asked ReserveAndUseImports: field.ExtraImports,