11import type { Prisma , User } from "@trigger.dev/database" ;
22import type { GitHubProfile } from "remix-auth-github" ;
3+ import type { GoogleProfile } from "remix-auth-google" ;
34import { prisma } from "~/db.server" ;
45import { env } from "~/env.server" ;
56import {
@@ -20,7 +21,14 @@ type FindOrCreateGithub = {
2021 authenticationExtraParams : Record < string , unknown > ;
2122} ;
2223
23- type FindOrCreateUser = FindOrCreateMagicLink | FindOrCreateGithub ;
24+ type FindOrCreateGoogle = {
25+ authenticationMethod : "GOOGLE" ;
26+ email : User [ "email" ] ;
27+ authenticationProfile : GoogleProfile ;
28+ authenticationExtraParams : Record < string , unknown > ;
29+ } ;
30+
31+ type FindOrCreateUser = FindOrCreateMagicLink | FindOrCreateGithub | FindOrCreateGoogle ;
2432
2533type LoggedInUser = {
2634 user : User ;
@@ -35,6 +43,9 @@ export async function findOrCreateUser(input: FindOrCreateUser): Promise<LoggedI
3543 case "MAGIC_LINK" : {
3644 return findOrCreateMagicLinkUser ( input ) ;
3745 }
46+ case "GOOGLE" : {
47+ return findOrCreateGoogleUser ( input ) ;
48+ }
3849 }
3950}
4051
@@ -162,6 +173,103 @@ export async function findOrCreateGithubUser({
162173 } ;
163174}
164175
176+ export async function findOrCreateGoogleUser ( {
177+ email,
178+ authenticationProfile,
179+ authenticationExtraParams,
180+ } : FindOrCreateGoogle ) : Promise < LoggedInUser > {
181+ assertEmailAllowed ( email ) ;
182+
183+ const name = authenticationProfile . _json . name ;
184+ let avatarUrl : string | undefined = undefined ;
185+ if ( authenticationProfile . photos [ 0 ] ) {
186+ avatarUrl = authenticationProfile . photos [ 0 ] . value ;
187+ }
188+ const displayName = authenticationProfile . displayName ;
189+ const authProfile = authenticationProfile
190+ ? ( authenticationProfile as unknown as Prisma . JsonObject )
191+ : undefined ;
192+ const authExtraParams = authenticationExtraParams
193+ ? ( authenticationExtraParams as unknown as Prisma . JsonObject )
194+ : undefined ;
195+
196+ const authIdentifier = `google:${ authenticationProfile . id } ` ;
197+
198+ const existingUser = await prisma . user . findUnique ( {
199+ where : {
200+ authIdentifier,
201+ } ,
202+ } ) ;
203+
204+ const existingEmailUser = await prisma . user . findUnique ( {
205+ where : {
206+ email,
207+ } ,
208+ } ) ;
209+
210+ if ( existingEmailUser && ! existingUser ) {
211+ // Link existing email account to Google auth
212+ const user = await prisma . user . update ( {
213+ where : {
214+ email,
215+ } ,
216+ data : {
217+ authenticationMethod : "GOOGLE" ,
218+ authenticationProfile : authProfile ,
219+ authenticationExtraParams : authExtraParams ,
220+ avatarUrl,
221+ authIdentifier,
222+ } ,
223+ } ) ;
224+
225+ return {
226+ user,
227+ isNewUser : false ,
228+ } ;
229+ }
230+
231+ if ( existingEmailUser && existingUser ) {
232+ // User already linked to Google, update profile info
233+ const user = await prisma . user . update ( {
234+ where : {
235+ id : existingUser . id ,
236+ } ,
237+ data : {
238+ avatarUrl,
239+ authenticationProfile : authProfile ,
240+ authenticationExtraParams : authExtraParams ,
241+ } ,
242+ } ) ;
243+
244+ return {
245+ user,
246+ isNewUser : false ,
247+ } ;
248+ }
249+
250+ const user = await prisma . user . upsert ( {
251+ where : {
252+ authIdentifier,
253+ } ,
254+ update : { } ,
255+ create : {
256+ authenticationProfile : authProfile ,
257+ authenticationExtraParams : authExtraParams ,
258+ name,
259+ avatarUrl,
260+ displayName,
261+ authIdentifier,
262+ email,
263+ authenticationMethod : "GOOGLE" ,
264+ } ,
265+ } ) ;
266+
267+ return {
268+ user,
269+ isNewUser : ! existingUser ,
270+ } ;
271+ }
272+
165273export type UserWithDashboardPreferences = User & {
166274 dashboardPreferences : DashboardPreferences ;
167275} ;
0 commit comments