1
- import { gql , makeExtendSchemaPlugin , Resolvers } from "graphile-utils" ;
1
+ import { PgClassExpressionStep } from "@dataplan/pg" ;
2
+ import { access , SafeError } from "grafast" ;
3
+ import { gql , makeExtendSchemaPlugin , Plans , Resolvers } from "graphile-utils" ;
2
4
3
- import { OurGraphQLContext } from "../graphile.config " ;
5
+ import type { } from "../middleware/installPostGraphile " ;
4
6
import { ERROR_MESSAGE_OVERRIDES } from "../utils/handleErrors" ;
5
7
6
8
const PassportLoginPlugin = makeExtendSchemaPlugin ( ( build ) => {
@@ -14,7 +16,7 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
14
16
}
15
17
16
18
type RegisterPayload {
17
- user: User! @pgField
19
+ user: User!
18
20
}
19
21
20
22
input LoginInput {
@@ -23,7 +25,7 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
23
25
}
24
26
25
27
type LoginPayload {
26
- user: User! @pgField
28
+ user: User!
27
29
}
28
30
29
31
type LogoutPayload {
@@ -85,12 +87,40 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
85
87
resetPassword(input: ResetPasswordInput!): ResetPasswordPayload
86
88
}
87
89
` ;
90
+ const userSource = build . input . pgSources . find ( ( s ) => s . name === "users" ) ;
91
+ const currentUserIdSource = build . input . pgSources . find (
92
+ ( s ) => s . name === "current_user_id"
93
+ ) ;
94
+ if ( ! userSource || ! currentUserIdSource ) {
95
+ throw new Error (
96
+ "Couldn't find either the 'users' or 'current_user_id' source"
97
+ ) ;
98
+ }
99
+ const plans : Plans = {
100
+ RegisterPayload : {
101
+ user ( $obj ) {
102
+ const $userId = access ( $obj , "userId" ) ;
103
+ return userSource . get ( { id : $userId } ) ;
104
+ } ,
105
+ } ,
106
+ LoginPayload : {
107
+ user ( ) {
108
+ const $userId = currentUserIdSource . execute ( ) as PgClassExpressionStep <
109
+ any ,
110
+ any ,
111
+ any ,
112
+ any ,
113
+ any
114
+ > ;
115
+ return userSource . get ( { id : $userId } ) ;
116
+ } ,
117
+ } ,
118
+ } ;
88
119
const resolvers : Resolvers = {
89
120
Mutation : {
90
- async register ( _mutation , args , context : OurGraphQLContext , resolveInfo ) {
91
- const { selectGraphQLResultFromTable } = resolveInfo . graphile ;
121
+ async register ( _mutation , args , context : Grafast . Context ) {
92
122
const { username, password, email, name, avatarUrl } = args . input ;
93
- const { rootPgPool, login, pgClient } = context ;
123
+ const { rootPgPool, login, pgSettings } = context ;
94
124
try {
95
125
// Create a user and create a session for it in the proccess
96
126
const {
@@ -123,28 +153,15 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
123
153
}
124
154
125
155
if ( details . session_id ) {
126
- // Store into transaction
127
- await pgClient . query (
128
- `select set_config('jwt.claims.session_id', $1, true)` ,
129
- [ details . session_id ]
130
- ) ;
156
+ // Update pgSettings so future queries will use the new session
157
+ pgSettings ! [ "jwt.claims.session_id" ] = details . session_id ;
131
158
132
159
// Tell Passport.js we're logged in
133
160
await login ( { session_id : details . session_id } ) ;
134
161
}
135
162
136
- // Fetch the data that was requested from GraphQL, and return it
137
- const sql = build . pgSql ;
138
- const [ row ] = await selectGraphQLResultFromTable (
139
- sql . fragment `app_public.users` ,
140
- ( tableAlias , sqlBuilder ) => {
141
- sqlBuilder . where (
142
- sql . fragment `${ tableAlias } .id = ${ sql . value ( details . user_id ) } `
143
- ) ;
144
- }
145
- ) ;
146
163
return {
147
- data : row ,
164
+ userId : details . user_id ,
148
165
} ;
149
166
} catch ( e : any ) {
150
167
const { code } = e ;
@@ -155,6 +172,7 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
155
172
...Object . keys ( ERROR_MESSAGE_OVERRIDES ) ,
156
173
] ;
157
174
if ( safeErrorCodes . includes ( code ) ) {
175
+ // TODO: make SafeError
158
176
throw e ;
159
177
} else {
160
178
console . error (
@@ -167,10 +185,9 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
167
185
}
168
186
}
169
187
} ,
170
- async login ( _mutation , args , context : OurGraphQLContext , resolveInfo ) {
171
- const { selectGraphQLResultFromTable } = resolveInfo . graphile ;
188
+ async login ( _mutation , args , context : Grafast . Context ) {
172
189
const { username, password } = args . input ;
173
- const { rootPgPool, login, pgClient } = context ;
190
+ const { rootPgPool, login, pgSettings } = context ;
174
191
try {
175
192
// Call our login function to find out if the username/password combination exists
176
193
const {
@@ -191,29 +208,15 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
191
208
await login ( { session_id : session . uuid } ) ;
192
209
}
193
210
194
- // Get session_id from PG
195
- await pgClient . query (
196
- `select set_config('jwt.claims.session_id', $1, true)` ,
197
- [ session . uuid ]
198
- ) ;
211
+ // Update pgSettings so future queries will use the new session
212
+ pgSettings ! [ "jwt.claims.session_id" ] = session . uuid ;
199
213
200
- // Fetch the data that was requested from GraphQL, and return it
201
- const sql = build . pgSql ;
202
- const [ row ] = await selectGraphQLResultFromTable (
203
- sql . fragment `app_public.users` ,
204
- ( tableAlias , sqlBuilder ) => {
205
- sqlBuilder . where (
206
- sql . fragment `${ tableAlias } .id = app_public.current_user_id()`
207
- ) ;
208
- }
209
- ) ;
210
- return {
211
- data : row ,
212
- } ;
214
+ return { } ;
213
215
} catch ( e : any ) {
214
216
const code = e . extensions ?. code ?? e . code ;
215
217
const safeErrorCodes = [ "LOCKD" , "CREDS" ] ;
216
218
if ( safeErrorCodes . includes ( code ) ) {
219
+ // TODO: throw SafeError
217
220
throw e ;
218
221
} else {
219
222
console . error ( e ) ;
@@ -224,21 +227,18 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
224
227
}
225
228
} ,
226
229
227
- async logout ( _mutation , _args , context : OurGraphQLContext , _resolveInfo ) {
228
- const { pgClient, logout } = context ;
229
- await pgClient . query ( "select app_public.logout();" ) ;
230
+ async logout ( _mutation , _args , context : Grafast . Context ) {
231
+ const { pgSettings, withPgClient, logout } = context ;
232
+ await withPgClient ( pgSettings , ( pgClient ) =>
233
+ pgClient . query ( { text : "select app_public.logout();" } )
234
+ ) ;
230
235
await logout ( ) ;
231
236
return {
232
237
success : true ,
233
238
} ;
234
239
} ,
235
240
236
- async resetPassword (
237
- _mutation ,
238
- args ,
239
- context : OurGraphQLContext ,
240
- _resolveInfo
241
- ) {
241
+ async resetPassword ( _mutation , args , context : Grafast . Context ) {
242
242
const { rootPgPool } = context ;
243
243
const { userId, resetToken, newPassword, clientMutationId } =
244
244
args . input ;
@@ -264,6 +264,7 @@ const PassportLoginPlugin = makeExtendSchemaPlugin((build) => {
264
264
} ;
265
265
return {
266
266
typeDefs,
267
+ plans,
267
268
resolvers,
268
269
} ;
269
270
} ) ;
0 commit comments