mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-09 15:05:35 +00:00
feat: store avatar and user name
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE `user` ADD COLUMN `name` VARCHAR(191) NULL AFTER `email`,
|
||||
ADD COLUMN `image` VARCHAR(191) NULL AFTER `name`;
|
||||
@@ -12,9 +12,11 @@ datasource db {
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
google_id String @unique
|
||||
email String @unique
|
||||
id Int @id @default(autoincrement())
|
||||
google_id String @unique
|
||||
email String @unique
|
||||
name String?
|
||||
image String?
|
||||
|
||||
categories Category[]
|
||||
links Link[]
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { User } from 'next-auth';
|
||||
import prisma from 'utils/prisma';
|
||||
import { Profile } from 'next-auth';
|
||||
|
||||
export default async function createUser(profile: Profile) {
|
||||
export default async function createUser(user: User) {
|
||||
return await prisma.user.create({
|
||||
data: {
|
||||
email: profile.email,
|
||||
google_id: profile.sub,
|
||||
email: user.email,
|
||||
google_id: user.id,
|
||||
name: user.name,
|
||||
image: user.image,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { Profile } from 'next-auth';
|
||||
import prisma from 'utils/prisma';
|
||||
|
||||
export default async function getUserByProfileProvider(profile: Profile) {
|
||||
return await prisma.user.findFirst({
|
||||
where: {
|
||||
google_id: profile.sub,
|
||||
email: profile.email,
|
||||
},
|
||||
});
|
||||
}
|
||||
11
src/lib/user/getUserByUserProvider.ts
Normal file
11
src/lib/user/getUserByUserProvider.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { User } from 'next-auth';
|
||||
import prisma from 'utils/prisma';
|
||||
|
||||
export default async function getUserByUserProvider(user: User) {
|
||||
return await prisma.user.findFirst({
|
||||
where: {
|
||||
google_id: user.id,
|
||||
email: user.email,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
import { User } from 'next-auth';
|
||||
import prisma from '../../utils/prisma';
|
||||
import { Profile } from 'next-auth';
|
||||
|
||||
export default async function updateUser(profile: Profile) {
|
||||
export default async function updateUser(user: User) {
|
||||
return await prisma.user.update({
|
||||
where: {
|
||||
email: profile.email,
|
||||
google_id: profile.sub,
|
||||
email: user.email,
|
||||
google_id: user.id,
|
||||
},
|
||||
data: {
|
||||
email: profile.email,
|
||||
google_id: profile.sub,
|
||||
email: user.email,
|
||||
google_id: user.id,
|
||||
name: user.name,
|
||||
image: user.image,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
import PATHS from 'constants/paths';
|
||||
import NextAuth, { NextAuthOptions, Profile } from 'next-auth';
|
||||
import GoogleProvider from 'next-auth/providers/google';
|
||||
import getUserByProfileProvider from 'lib/user/getUserByProfileProvider';
|
||||
import createUser from 'lib/user/createUser';
|
||||
import getUserByUserProvider from 'lib/user/getUserByUserProvider';
|
||||
import updateUser from 'lib/user/updateUser';
|
||||
import NextAuth, { NextAuthOptions, User } from 'next-auth';
|
||||
import GoogleProvider from 'next-auth/providers/google';
|
||||
import prisma from 'utils/prisma';
|
||||
|
||||
const authLogger = (profile: Profile, ...args: any[]) =>
|
||||
console.log(
|
||||
'[AUTH]',
|
||||
profile.email,
|
||||
`(${profile.name} - ${profile.sub})`,
|
||||
...args,
|
||||
);
|
||||
const authLogger = (user: User, ...args: any[]) =>
|
||||
console.log('[AUTH]', user.email, `(${user.name} - ${user.id})`, ...args);
|
||||
const redirectUser = (errorKey: string) => `${PATHS.LOGIN}?error=${errorKey}`;
|
||||
|
||||
const checkProvider = (provider: string) => provider === 'google';
|
||||
const checkAccountDataReceived = (profile: Profile) =>
|
||||
!!profile?.sub && !!profile?.email;
|
||||
const checkAccountDataReceived = (user: User) => !!user?.id && !!user?.email;
|
||||
|
||||
const cookieOptions = {
|
||||
sameSite: 'None',
|
||||
@@ -47,30 +41,30 @@ export const authOptions = {
|
||||
});
|
||||
return user ? session : undefined;
|
||||
},
|
||||
async signIn({ account: accountParam, profile }) {
|
||||
async signIn({ account: accountParam, user }) {
|
||||
if (!checkProvider(accountParam.provider)) {
|
||||
authLogger(profile, 'rejected : forbidden provider');
|
||||
authLogger(user, 'rejected : forbidden provider');
|
||||
return redirectUser('AUTH_REQUIRED');
|
||||
}
|
||||
|
||||
if (!checkAccountDataReceived(profile)) {
|
||||
authLogger(profile, 'rejected : missing data from provider', profile);
|
||||
if (!checkAccountDataReceived(user)) {
|
||||
authLogger(user, 'rejected : missing data from provider', user);
|
||||
return redirectUser('MISSING_PROVIDER_VALUES');
|
||||
}
|
||||
|
||||
try {
|
||||
const isUserExists = await getUserByProfileProvider(profile);
|
||||
const isUserExists = await getUserByUserProvider(user);
|
||||
if (isUserExists) {
|
||||
await updateUser(profile);
|
||||
authLogger(profile, 'success : user updated');
|
||||
await updateUser(user);
|
||||
authLogger(user, 'success : user updated');
|
||||
} else {
|
||||
await createUser(profile);
|
||||
authLogger(profile, 'success : user created');
|
||||
await createUser(user);
|
||||
authLogger(user, 'success : user created');
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
authLogger(profile, 'rejected : unhandled error');
|
||||
authLogger(user, 'rejected : unhandled error');
|
||||
console.error(error);
|
||||
return redirectUser('AUTH_ERROR');
|
||||
}
|
||||
|
||||
14
src/types/types.d.ts
vendored
14
src/types/types.d.ts
vendored
@@ -1,4 +1,5 @@
|
||||
import { Category, User } from '@prisma/client';
|
||||
import { Profile } from 'next-auth';
|
||||
|
||||
export type CategoryWithLinks = Category & {
|
||||
author: User;
|
||||
@@ -23,3 +24,16 @@ export interface Favicon {
|
||||
type: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface GoogleProfile extends Profile {
|
||||
iss: string;
|
||||
azp: string;
|
||||
aud: string;
|
||||
email_verified: boolean;
|
||||
at_hash: string;
|
||||
picture: string;
|
||||
given_name: string;
|
||||
locale: string;
|
||||
iat: number;
|
||||
exp: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user