replaced email with username
This commit is contained in:
parent
3993615071
commit
97ca682c0a
|
@ -43,7 +43,7 @@ export default function TeamManagement({
|
||||||
canDelete: false,
|
canDelete: false,
|
||||||
user: {
|
user: {
|
||||||
name: "",
|
name: "",
|
||||||
email: "",
|
username: "",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ export default function TeamManagement({
|
||||||
canDelete: false,
|
canDelete: false,
|
||||||
user: {
|
user: {
|
||||||
name: "",
|
name: "",
|
||||||
email: "",
|
username: "",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -146,32 +146,32 @@ export default function TeamManagement({
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
value={member.user.email}
|
value={member.user.username}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setMember({
|
setMember({
|
||||||
...member,
|
...member,
|
||||||
user: { ...member.user, email: e.target.value },
|
user: { ...member.user, username: e.target.value },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
onKeyDown={(e) =>
|
onKeyDown={(e) =>
|
||||||
e.key === "Enter" &&
|
e.key === "Enter" &&
|
||||||
addMemberToCollection(
|
addMemberToCollection(
|
||||||
session.data?.user.email as string,
|
session.data?.user.username as string,
|
||||||
member.user.email,
|
member.user.username,
|
||||||
collection,
|
collection,
|
||||||
setMemberState
|
setMemberState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Email"
|
placeholder="Username"
|
||||||
className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
className="w-full rounded-md p-3 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
addMemberToCollection(
|
addMemberToCollection(
|
||||||
session.data?.user.email as string,
|
session.data?.user.username as string,
|
||||||
member.user.email,
|
member.user.username,
|
||||||
collection,
|
collection,
|
||||||
setMemberState
|
setMemberState
|
||||||
)
|
)
|
||||||
|
@ -206,7 +206,7 @@ export default function TeamManagement({
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const updatedMembers = collection.members.filter(
|
const updatedMembers = collection.members.filter(
|
||||||
(member) => {
|
(member) => {
|
||||||
return member.user.email !== e.user.email;
|
return member.user.username !== e.user.username;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
setCollection({
|
setCollection({
|
||||||
|
@ -225,7 +225,7 @@ export default function TeamManagement({
|
||||||
<p className="text-sm font-bold text-sky-500">
|
<p className="text-sm font-bold text-sky-500">
|
||||||
{e.user.name}
|
{e.user.name}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sky-900">{e.user.email}</p>
|
<p className="text-sky-900">{e.user.username}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex sm:block items-center gap-5 min-w-[10rem]">
|
<div className="flex sm:block items-center gap-5 min-w-[10rem]">
|
||||||
|
@ -269,7 +269,9 @@ export default function TeamManagement({
|
||||||
if (permissions === true) {
|
if (permissions === true) {
|
||||||
const updatedMembers = collection.members.map(
|
const updatedMembers = collection.members.map(
|
||||||
(member) => {
|
(member) => {
|
||||||
if (member.user.email === e.user.email) {
|
if (
|
||||||
|
member.user.username === e.user.username
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
...member,
|
...member,
|
||||||
canCreate: !e.canCreate,
|
canCreate: !e.canCreate,
|
||||||
|
@ -312,7 +314,9 @@ export default function TeamManagement({
|
||||||
if (permissions === true) {
|
if (permissions === true) {
|
||||||
const updatedMembers = collection.members.map(
|
const updatedMembers = collection.members.map(
|
||||||
(member) => {
|
(member) => {
|
||||||
if (member.user.email === e.user.email) {
|
if (
|
||||||
|
member.user.username === e.user.username
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
...member,
|
...member,
|
||||||
canUpdate: !e.canUpdate,
|
canUpdate: !e.canUpdate,
|
||||||
|
@ -355,7 +359,9 @@ export default function TeamManagement({
|
||||||
if (permissions === true) {
|
if (permissions === true) {
|
||||||
const updatedMembers = collection.members.map(
|
const updatedMembers = collection.members.map(
|
||||||
(member) => {
|
(member) => {
|
||||||
if (member.user.email === e.user.email) {
|
if (
|
||||||
|
member.user.username === e.user.username
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
...member,
|
...member,
|
||||||
canDelete: !e.canDelete,
|
canDelete: !e.canDelete,
|
||||||
|
|
|
@ -56,8 +56,8 @@ export default function ChangePassword({
|
||||||
|
|
||||||
setSubmitLoader(false);
|
setSubmitLoader(false);
|
||||||
|
|
||||||
if (user.email !== account.email || user.name !== account.name)
|
if (user.username !== account.username || user.name !== account.name)
|
||||||
update({ email: user.email, name: user.name });
|
update({ username: user.username, name: user.name });
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setUser({ ...user, oldPassword: undefined, newPassword: undefined });
|
setUser({ ...user, oldPassword: undefined, newPassword: undefined });
|
||||||
|
|
|
@ -64,8 +64,8 @@ export default function PrivacySettings({
|
||||||
|
|
||||||
setSubmitLoader(false);
|
setSubmitLoader(false);
|
||||||
|
|
||||||
if (user.email !== account.email || user.name !== account.name)
|
if (user.username !== account.username || user.name !== account.name)
|
||||||
update({ email: user.email, name: user.name });
|
update({ username: user.username, name: user.name });
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setUser({ ...user, oldPassword: undefined, newPassword: undefined });
|
setUser({ ...user, oldPassword: undefined, newPassword: undefined });
|
||||||
|
@ -93,7 +93,7 @@ export default function PrivacySettings({
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-sky-500 my-2">Whitelisted Users</p>
|
<p className="text-sm text-sky-500 my-2">Whitelisted Users</p>
|
||||||
<p className="text-gray-500 text-sm mb-3">
|
<p className="text-gray-500 text-sm mb-3">
|
||||||
Please provide the Email addresses of the users you wish to grant
|
Please provide the Username of the users you wish to grant
|
||||||
visibility to your profile. Separated by comma.
|
visibility to your profile. Separated by comma.
|
||||||
</p>
|
</p>
|
||||||
<textarea
|
<textarea
|
||||||
|
|
|
@ -80,8 +80,12 @@ export default function ProfileSettings({
|
||||||
|
|
||||||
setSubmitLoader(false);
|
setSubmitLoader(false);
|
||||||
|
|
||||||
if (user.email !== account.email || user.name !== account.name)
|
if (user.username !== account.username || user.name !== account.name)
|
||||||
update({ email: user.email, name: user.name });
|
update({
|
||||||
|
username: user.username,
|
||||||
|
email: user.username,
|
||||||
|
name: user.name,
|
||||||
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setUser({ ...user, oldPassword: undefined, newPassword: undefined });
|
setUser({ ...user, oldPassword: undefined, newPassword: undefined });
|
||||||
|
@ -146,11 +150,11 @@ export default function ProfileSettings({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-sky-500 mb-2">Email</p>
|
<p className="text-sm text-sky-500 mb-2">Username</p>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={user.email}
|
value={user.username}
|
||||||
onChange={(e) => setUser({ ...user, email: e.target.value })}
|
onChange={(e) => setUser({ ...user, username: e.target.value })}
|
||||||
className="w-full rounded-md p-2 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
className="w-full rounded-md p-2 border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default function useInitialData() {
|
||||||
setCollections();
|
setCollections();
|
||||||
setTags();
|
setTags();
|
||||||
// setLinks();
|
// setLinks();
|
||||||
setAccount(data.user.email as string);
|
setAccount(data.user.username as string);
|
||||||
}
|
}
|
||||||
}, [status]);
|
}, [status]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ export default function AuthRedirect({ children }: Props) {
|
||||||
}
|
}
|
||||||
}, [status]);
|
}, [status]);
|
||||||
|
|
||||||
if (status !== "loading" && !redirect) return <>{children}</>;
|
return <>{children}</>;
|
||||||
else return <></>;
|
// if (status !== "loading" && !redirect) return <>{children}</>;
|
||||||
|
// else return <></>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ export default async function getCollection(userId: number) {
|
||||||
include: {
|
include: {
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
email: true,
|
username: true,
|
||||||
name: true,
|
name: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -42,7 +42,7 @@ export default async function postCollection(
|
||||||
color: collection.color,
|
color: collection.color,
|
||||||
members: {
|
members: {
|
||||||
create: collection.members.map((e) => ({
|
create: collection.members.map((e) => ({
|
||||||
user: { connect: { email: e.user.email.toLowerCase() } },
|
user: { connect: { username: e.user.username.toLowerCase() } },
|
||||||
canCreate: e.canCreate,
|
canCreate: e.canCreate,
|
||||||
canUpdate: e.canUpdate,
|
canUpdate: e.canUpdate,
|
||||||
canDelete: e.canDelete,
|
canDelete: e.canDelete,
|
||||||
|
@ -57,7 +57,7 @@ export default async function postCollection(
|
||||||
include: {
|
include: {
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
email: true,
|
username: true,
|
||||||
name: true,
|
name: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -43,7 +43,7 @@ export default async function updateCollection(
|
||||||
isPublic: collection.isPublic,
|
isPublic: collection.isPublic,
|
||||||
members: {
|
members: {
|
||||||
create: collection.members.map((e) => ({
|
create: collection.members.map((e) => ({
|
||||||
user: { connect: { email: e.user.email.toLowerCase() } },
|
user: { connect: { username: e.user.username.toLowerCase() } },
|
||||||
canCreate: e.canCreate,
|
canCreate: e.canCreate,
|
||||||
canUpdate: e.canUpdate,
|
canUpdate: e.canUpdate,
|
||||||
canDelete: e.canDelete,
|
canDelete: e.canDelete,
|
||||||
|
@ -58,7 +58,7 @@ export default async function updateCollection(
|
||||||
include: {
|
include: {
|
||||||
user: {
|
user: {
|
||||||
select: {
|
select: {
|
||||||
email: true,
|
username: true,
|
||||||
name: true,
|
name: true,
|
||||||
id: true,
|
id: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { prisma } from "@/lib/api/db";
|
import { prisma } from "@/lib/api/db";
|
||||||
|
|
||||||
export default async function getUser(
|
export default async function getUser(
|
||||||
lookupEmail: string,
|
lookupUsername: string,
|
||||||
isSelf: boolean,
|
isSelf: boolean,
|
||||||
userEmail: string
|
username: string
|
||||||
) {
|
) {
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
where: {
|
where: {
|
||||||
email: lookupEmail.toLowerCase(),
|
username: lookupUsername.toLowerCase(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ export default async function getUser(
|
||||||
if (
|
if (
|
||||||
!isSelf &&
|
!isSelf &&
|
||||||
user?.isPrivate &&
|
user?.isPrivate &&
|
||||||
!user.whitelistedUsers.includes(userEmail.toLowerCase())
|
!user.whitelistedUsers.includes(username.toLowerCase())
|
||||||
) {
|
) {
|
||||||
return { response: "This profile is private.", status: 401 };
|
return { response: "This profile is private.", status: 401 };
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ export default async function getUser(
|
||||||
// If user is requesting someone elses data
|
// If user is requesting someone elses data
|
||||||
id: unsensitiveInfo.id,
|
id: unsensitiveInfo.id,
|
||||||
name: unsensitiveInfo.name,
|
name: unsensitiveInfo.name,
|
||||||
email: unsensitiveInfo.email,
|
username: unsensitiveInfo.username,
|
||||||
};
|
};
|
||||||
|
|
||||||
return { response: data || null, status: 200 };
|
return { response: data || null, status: 200 };
|
||||||
|
|
|
@ -72,7 +72,7 @@ export default async function updateUser(
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
name: user.name,
|
name: user.name,
|
||||||
email: user.email.toLowerCase(),
|
username: user.username.toLowerCase(),
|
||||||
isPrivate: user.isPrivate,
|
isPrivate: user.isPrivate,
|
||||||
whitelistedUsers: user.whitelistedUsers,
|
whitelistedUsers: user.whitelistedUsers,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
import { CollectionIncludingMembersAndLinkCount, Member } from "@/types/global";
|
import { CollectionIncludingMembersAndLinkCount, Member } from "@/types/global";
|
||||||
import getPublicUserDataByEmail from "./getPublicUserDataByEmail";
|
import getPublicUserDataByUsername from "./getPublicUserDataByUsername";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
|
|
||||||
const addMemberToCollection = async (
|
const addMemberToCollection = async (
|
||||||
ownerEmail: string,
|
ownerUsername: string,
|
||||||
memberEmail: string,
|
memberUsername: string,
|
||||||
collection: CollectionIncludingMembersAndLinkCount,
|
collection: CollectionIncludingMembersAndLinkCount,
|
||||||
setMember: (newMember: Member) => null | undefined
|
setMember: (newMember: Member) => null | undefined
|
||||||
) => {
|
) => {
|
||||||
const checkIfMemberAlreadyExists = collection.members.find((e) => {
|
const checkIfMemberAlreadyExists = collection.members.find((e) => {
|
||||||
const email = e.user.email.toLowerCase();
|
const username = e.user.username.toLowerCase();
|
||||||
return email === memberEmail.toLowerCase();
|
return username === memberUsername.toLowerCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
// no duplicate members
|
// no duplicate members
|
||||||
!checkIfMemberAlreadyExists &&
|
!checkIfMemberAlreadyExists &&
|
||||||
// member can't be empty
|
// member can't be empty
|
||||||
memberEmail.trim() !== "" &&
|
memberUsername.trim() !== "" &&
|
||||||
// member can't be the owner
|
// member can't be the owner
|
||||||
memberEmail.trim() !== ownerEmail
|
memberUsername.trim() !== ownerUsername
|
||||||
) {
|
) {
|
||||||
// Lookup, get data/err, list ...
|
// Lookup, get data/err, list ...
|
||||||
const user = await getPublicUserDataByEmail(
|
const user = await getPublicUserDataByUsername(
|
||||||
memberEmail.trim().toLowerCase()
|
memberUsername.trim().toLowerCase()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (user.email) {
|
if (user.username) {
|
||||||
setMember({
|
setMember({
|
||||||
collectionId: collection.id,
|
collectionId: collection.id,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
|
@ -35,12 +35,12 @@ const addMemberToCollection = async (
|
||||||
canDelete: false,
|
canDelete: false,
|
||||||
user: {
|
user: {
|
||||||
name: user.name,
|
name: user.name,
|
||||||
email: user.email,
|
username: user.username,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (checkIfMemberAlreadyExists) toast.error("User already exists.");
|
} else if (checkIfMemberAlreadyExists) toast.error("User already exists.");
|
||||||
else if (memberEmail.trim() === ownerEmail)
|
else if (memberUsername.trim() === ownerUsername)
|
||||||
toast.error("You are already the collection owner.");
|
toast.error("You are already the collection owner.");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
|
|
||||||
export default async function getPublicUserDataByEmail(email: string) {
|
export default async function getPublicUserDataByEmail(username: string) {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`/api/routes/users?email=${email.toLowerCase()}`
|
`/api/routes/users?username=${username.toLowerCase()}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
|
@ -13,6 +13,7 @@
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@auth/prisma-adapter": "^1.0.0",
|
||||||
"@aws-sdk/client-s3": "^3.363.0",
|
"@aws-sdk/client-s3": "^3.363.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.3.0",
|
"@fortawesome/free-regular-svg-icons": "^6.3.0",
|
||||||
|
|
|
@ -5,8 +5,14 @@ import type { AppProps } from "next/app";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import AuthRedirect from "@/layouts/AuthRedirect";
|
import AuthRedirect from "@/layouts/AuthRedirect";
|
||||||
import { Toaster } from "react-hot-toast";
|
import { Toaster } from "react-hot-toast";
|
||||||
|
import { Session } from "next-auth";
|
||||||
|
|
||||||
export default function App({ Component, pageProps }: AppProps) {
|
export default function App({
|
||||||
|
Component,
|
||||||
|
pageProps,
|
||||||
|
}: AppProps<{
|
||||||
|
session: Session;
|
||||||
|
}>) {
|
||||||
return (
|
return (
|
||||||
<SessionProvider session={pageProps.session}>
|
<SessionProvider session={pageProps.session}>
|
||||||
<Head>
|
<Head>
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
|
||||||
const session = await getServerSession(req, res, authOptions);
|
const session = await getServerSession(req, res, authOptions);
|
||||||
|
|
||||||
if (!session?.user?.email)
|
if (!session?.user?.username)
|
||||||
return res.status(401).json({ response: "You must be logged in." });
|
return res.status(401).json({ response: "You must be logged in." });
|
||||||
|
|
||||||
const collectionIsAccessible = await getPermission(
|
const collectionIsAccessible = await getPermission(
|
||||||
|
|
|
@ -3,39 +3,66 @@ import NextAuth from "next-auth/next";
|
||||||
import CredentialsProvider from "next-auth/providers/credentials";
|
import CredentialsProvider from "next-auth/providers/credentials";
|
||||||
import { AuthOptions } from "next-auth";
|
import { AuthOptions } from "next-auth";
|
||||||
import bcrypt from "bcrypt";
|
import bcrypt from "bcrypt";
|
||||||
|
import EmailProvider from "next-auth/providers/email";
|
||||||
|
|
||||||
export const authOptions: AuthOptions = {
|
export const authOptions: AuthOptions = {
|
||||||
session: {
|
session: {
|
||||||
strategy: "jwt",
|
strategy: "jwt",
|
||||||
},
|
},
|
||||||
providers: [
|
providers: [
|
||||||
|
// EmailProvider({
|
||||||
|
// server: process.env.EMAIL_SERVER,
|
||||||
|
// from: process.env.EMAIL_FROM,
|
||||||
|
// }),
|
||||||
CredentialsProvider({
|
CredentialsProvider({
|
||||||
type: "credentials",
|
type: "credentials",
|
||||||
credentials: {},
|
credentials: {
|
||||||
|
username: {
|
||||||
|
label: "Username",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
label: "Password",
|
||||||
|
type: "password",
|
||||||
|
},
|
||||||
|
},
|
||||||
async authorize(credentials, req) {
|
async authorize(credentials, req) {
|
||||||
const { email, password } = credentials as {
|
if (!credentials) return null;
|
||||||
id: number;
|
|
||||||
email: string;
|
// const { username, password } = credentials as {
|
||||||
password: string;
|
// id: number;
|
||||||
};
|
// username: string;
|
||||||
|
// password: string;
|
||||||
|
// };
|
||||||
|
|
||||||
|
console.log(credentials);
|
||||||
|
|
||||||
const findUser = await prisma.user.findFirst({
|
const findUser = await prisma.user.findFirst({
|
||||||
where: {
|
where: {
|
||||||
email: email.toLowerCase(),
|
username: credentials.username.toLowerCase(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let passwordMatches: boolean = false;
|
let passwordMatches: boolean = false;
|
||||||
|
|
||||||
if (findUser?.password) {
|
if (findUser?.password) {
|
||||||
passwordMatches = bcrypt.compareSync(password, findUser.password);
|
passwordMatches = bcrypt.compareSync(
|
||||||
|
credentials.password,
|
||||||
|
findUser.password
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
id: findUser?.id,
|
||||||
|
name: findUser?.name,
|
||||||
|
username: findUser?.username.toLowerCase(),
|
||||||
|
});
|
||||||
|
|
||||||
if (passwordMatches) {
|
if (passwordMatches) {
|
||||||
return {
|
return {
|
||||||
id: findUser?.id,
|
id: findUser?.id,
|
||||||
name: findUser?.name,
|
name: findUser?.name,
|
||||||
email: findUser?.email.toLowerCase(),
|
email: findUser?.username.toLowerCase(),
|
||||||
};
|
};
|
||||||
} else return null as any;
|
} else return null as any;
|
||||||
},
|
},
|
||||||
|
@ -46,15 +73,19 @@ export const authOptions: AuthOptions = {
|
||||||
},
|
},
|
||||||
callbacks: {
|
callbacks: {
|
||||||
session: async ({ session, token }) => {
|
session: async ({ session, token }) => {
|
||||||
|
console.log("TOKEN:", token);
|
||||||
session.user.id = parseInt(token?.sub as any);
|
session.user.id = parseInt(token?.sub as any);
|
||||||
|
session.user.username = session.user.email;
|
||||||
|
console.log("SESSION:", session);
|
||||||
|
|
||||||
return session;
|
return session;
|
||||||
},
|
},
|
||||||
// Using the `...rest` parameter to be able to narrow down the type based on `trigger`
|
// Using the `...rest` parameter to be able to narrow down the type based on `trigger`
|
||||||
jwt({ token, trigger, session }) {
|
jwt({ token, trigger, session }) {
|
||||||
if (trigger === "update" && session?.name && session?.email) {
|
if (trigger === "update" && session?.name && session?.username) {
|
||||||
// Note, that `session` can be any arbitrary object, remember to validate it!
|
// Note, that `session` can be any arbitrary object, remember to validate it!
|
||||||
token.name = session.name;
|
token.name = session.name;
|
||||||
|
token.username = session.username.toLowerCase();
|
||||||
token.email = session.email.toLowerCase();
|
token.email = session.email.toLowerCase();
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
|
|
|
@ -8,7 +8,7 @@ interface Data {
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,14 +18,14 @@ export default async function Index(
|
||||||
) {
|
) {
|
||||||
const body: User = req.body;
|
const body: User = req.body;
|
||||||
|
|
||||||
if (!body.email || !body.password || !body.name)
|
if (!body.username || !body.password || !body.name)
|
||||||
return res
|
return res
|
||||||
.status(400)
|
.status(400)
|
||||||
.json({ response: "Please fill out all the fields." });
|
.json({ response: "Please fill out all the fields." });
|
||||||
|
|
||||||
const checkIfUserExists = await prisma.user.findFirst({
|
const checkIfUserExists = await prisma.user.findFirst({
|
||||||
where: {
|
where: {
|
||||||
email: body.email.toLowerCase(),
|
username: body.username.toLowerCase(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export default async function Index(
|
||||||
await prisma.user.create({
|
await prisma.user.create({
|
||||||
data: {
|
data: {
|
||||||
name: body.name,
|
name: body.name,
|
||||||
email: body.email.toLowerCase(),
|
username: body.username.toLowerCase(),
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
|
||||||
const session = await getServerSession(req, res, authOptions);
|
const session = await getServerSession(req, res, authOptions);
|
||||||
|
|
||||||
const userId = session?.user.id;
|
const userId = session?.user.id;
|
||||||
const userEmail = session?.user.email?.toLowerCase();
|
const userName = session?.user.username?.toLowerCase();
|
||||||
const queryId = Number(req.query.id);
|
const queryId = Number(req.query.id);
|
||||||
|
|
||||||
if (!queryId)
|
if (!queryId)
|
||||||
|
@ -17,7 +17,7 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
|
||||||
.status(401)
|
.status(401)
|
||||||
.send("Invalid parameters.");
|
.send("Invalid parameters.");
|
||||||
|
|
||||||
if (!userId || !userEmail)
|
if (!userId || !userName)
|
||||||
return res
|
return res
|
||||||
.setHeader("Content-Type", "text/plain")
|
.setHeader("Content-Type", "text/plain")
|
||||||
.status(401)
|
.status(401)
|
||||||
|
@ -32,7 +32,7 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
targetUser?.isPrivate &&
|
targetUser?.isPrivate &&
|
||||||
!targetUser.whitelistedUsers.includes(userEmail)
|
!targetUser.whitelistedUsers.includes(userName)
|
||||||
) {
|
) {
|
||||||
return res
|
return res
|
||||||
.setHeader("Content-Type", "text/plain")
|
.setHeader("Content-Type", "text/plain")
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default async function collections(
|
||||||
) {
|
) {
|
||||||
const session = await getServerSession(req, res, authOptions);
|
const session = await getServerSession(req, res, authOptions);
|
||||||
|
|
||||||
if (!session?.user?.email) {
|
if (!session?.user?.username) {
|
||||||
return res.status(401).json({ response: "You must be logged in." });
|
return res.status(401).json({ response: "You must be logged in." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import updateLink from "@/lib/api/controllers/links/updateLink";
|
||||||
export default async function links(req: NextApiRequest, res: NextApiResponse) {
|
export default async function links(req: NextApiRequest, res: NextApiResponse) {
|
||||||
const session = await getServerSession(req, res, authOptions);
|
const session = await getServerSession(req, res, authOptions);
|
||||||
|
|
||||||
if (!session?.user?.email) {
|
if (!session?.user?.username) {
|
||||||
return res.status(401).json({ response: "You must be logged in." });
|
return res.status(401).json({ response: "You must be logged in." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import getTags from "@/lib/api/controllers/tags/getTags";
|
||||||
export default async function tags(req: NextApiRequest, res: NextApiResponse) {
|
export default async function tags(req: NextApiRequest, res: NextApiResponse) {
|
||||||
const session = await getServerSession(req, res, authOptions);
|
const session = await getServerSession(req, res, authOptions);
|
||||||
|
|
||||||
if (!session?.user?.email) {
|
if (!session?.user?.username) {
|
||||||
return res.status(401).json({ response: "You must be logged in." });
|
return res.status(401).json({ response: "You must be logged in." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,15 @@ import updateUser from "@/lib/api/controllers/users/updateUser";
|
||||||
export default async function users(req: NextApiRequest, res: NextApiResponse) {
|
export default async function users(req: NextApiRequest, res: NextApiResponse) {
|
||||||
const session = await getServerSession(req, res, authOptions);
|
const session = await getServerSession(req, res, authOptions);
|
||||||
|
|
||||||
if (!session?.user?.email) {
|
if (!session?.user.username) {
|
||||||
return res.status(401).json({ response: "You must be logged in." });
|
return res.status(401).json({ response: "You must be logged in." });
|
||||||
}
|
}
|
||||||
|
|
||||||
const lookupEmail = req.query.email as string;
|
const lookupUsername = req.query.username as string;
|
||||||
const isSelf = session.user.email === lookupEmail ? true : false;
|
const isSelf = session.user.username === lookupUsername ? true : false;
|
||||||
|
|
||||||
if (req.method === "GET") {
|
if (req.method === "GET") {
|
||||||
const users = await getUsers(lookupEmail, isSelf, session.user.email);
|
const users = await getUsers(lookupUsername, isSelf, session.user.username);
|
||||||
return res.status(users.status).json({ response: users.response });
|
return res.status(users.status).json({ response: users.response });
|
||||||
} else if (req.method === "PUT" && !req.body.password) {
|
} else if (req.method === "PUT" && !req.body.password) {
|
||||||
const updated = await updateUser(req.body, session.user.id);
|
const updated = await updateUser(req.body, session.user.id);
|
||||||
|
|
|
@ -22,18 +22,23 @@ export default function Dashboard() {
|
||||||
const [numberOfLinks, setNumberOfLinks] = useState(0);
|
const [numberOfLinks, setNumberOfLinks] = useState(0);
|
||||||
|
|
||||||
const [tagPinDisclosure, setTagPinDisclosure] = useState<boolean>(() => {
|
const [tagPinDisclosure, setTagPinDisclosure] = useState<boolean>(() => {
|
||||||
const storedValue = localStorage.getItem("tagPinDisclosure");
|
const storedValue =
|
||||||
|
typeof window !== "undefined" && localStorage.getItem("tagPinDisclosure");
|
||||||
return storedValue ? storedValue === "true" : true;
|
return storedValue ? storedValue === "true" : true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const [collectionPinDisclosure, setCollectionPinDisclosure] =
|
const [collectionPinDisclosure, setCollectionPinDisclosure] =
|
||||||
useState<boolean>(() => {
|
useState<boolean>(() => {
|
||||||
const storedValue = localStorage.getItem("collectionPinDisclosure");
|
const storedValue =
|
||||||
|
typeof window !== "undefined" &&
|
||||||
|
localStorage.getItem("collectionPinDisclosure");
|
||||||
return storedValue ? storedValue === "true" : true;
|
return storedValue ? storedValue === "true" : true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const [linkPinDisclosure, setLinkPinDisclosure] = useState<boolean>(() => {
|
const [linkPinDisclosure, setLinkPinDisclosure] = useState<boolean>(() => {
|
||||||
const storedValue = localStorage.getItem("linkPinDisclosure");
|
const storedValue =
|
||||||
|
typeof window !== "undefined" &&
|
||||||
|
localStorage.getItem("linkPinDisclosure");
|
||||||
return storedValue ? storedValue === "true" : true;
|
return storedValue ? storedValue === "true" : true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { useState } from "react";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
|
|
||||||
interface FormData {
|
interface FormData {
|
||||||
email: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,18 +13,18 @@ export default function Login() {
|
||||||
const [submitLoader, setSubmitLoader] = useState(false);
|
const [submitLoader, setSubmitLoader] = useState(false);
|
||||||
|
|
||||||
const [form, setForm] = useState<FormData>({
|
const [form, setForm] = useState<FormData>({
|
||||||
email: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loginUser() {
|
async function loginUser() {
|
||||||
if (form.email !== "" && form.password !== "") {
|
if (form.username !== "" && form.password !== "") {
|
||||||
setSubmitLoader(true);
|
setSubmitLoader(true);
|
||||||
|
|
||||||
const load = toast.loading("Authenticating...");
|
const load = toast.loading("Authenticating...");
|
||||||
|
|
||||||
const res = await signIn("credentials", {
|
const res = await signIn("credentials", {
|
||||||
email: form.email,
|
username: form.username,
|
||||||
password: form.password,
|
password: form.password,
|
||||||
redirect: false,
|
redirect: false,
|
||||||
});
|
});
|
||||||
|
@ -54,13 +54,13 @@ export default function Login() {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-sm text-sky-500 w-fit font-semibold">Email</p>
|
<p className="text-sm text-sky-500 w-fit font-semibold">Username</p>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="johnny@example.com"
|
placeholder="johnny@example.com"
|
||||||
value={form.email}
|
value={form.username}
|
||||||
onChange={(e) => setForm({ ...form, email: e.target.value })}
|
onChange={(e) => setForm({ ...form, username: e.target.value })}
|
||||||
className="w-full rounded-md p-3 mx-auto border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
className="w-full rounded-md p-3 mx-auto border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import SubmitButton from "@/components/SubmitButton";
|
||||||
|
|
||||||
interface FormData {
|
interface FormData {
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
passwordConfirmation: string;
|
passwordConfirmation: string;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ export default function Register() {
|
||||||
|
|
||||||
const [form, setForm] = useState<FormData>({
|
const [form, setForm] = useState<FormData>({
|
||||||
name: "",
|
name: "",
|
||||||
email: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
passwordConfirmation: "",
|
passwordConfirmation: "",
|
||||||
});
|
});
|
||||||
|
@ -26,7 +26,7 @@ export default function Register() {
|
||||||
async function registerUser() {
|
async function registerUser() {
|
||||||
if (
|
if (
|
||||||
form.name !== "" &&
|
form.name !== "" &&
|
||||||
form.email !== "" &&
|
form.username !== "" &&
|
||||||
form.password !== "" &&
|
form.password !== "" &&
|
||||||
form.passwordConfirmation !== ""
|
form.passwordConfirmation !== ""
|
||||||
) {
|
) {
|
||||||
|
@ -54,7 +54,7 @@ export default function Register() {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setForm({
|
setForm({
|
||||||
name: "",
|
name: "",
|
||||||
email: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
passwordConfirmation: "",
|
passwordConfirmation: "",
|
||||||
});
|
});
|
||||||
|
@ -96,13 +96,13 @@ export default function Register() {
|
||||||
className="w-full rounded-md p-3 mx-auto border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
className="w-full rounded-md p-3 mx-auto border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<p className="text-sm text-sky-500 w-fit font-semibold">Email</p>
|
<p className="text-sm text-sky-500 w-fit font-semibold">Username</p>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="johnny@example.com"
|
placeholder="johnny@example.com"
|
||||||
value={form.email}
|
value={form.username}
|
||||||
onChange={(e) => setForm({ ...form, email: e.target.value })}
|
onChange={(e) => setForm({ ...form, username: e.target.value })}
|
||||||
className="w-full rounded-md p-3 mx-auto border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
className="w-full rounded-md p-3 mx-auto border-sky-100 border-solid border outline-none focus:border-sky-500 duration-100"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `email` on the `User` table. All the data in the column will be lost.
|
||||||
|
- A unique constraint covering the columns `[username]` on the table `User` will be added. If there are existing duplicate values, this will fail.
|
||||||
|
- Added the required column `username` to the `User` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- DropIndex
|
||||||
|
DROP INDEX "User_email_key";
|
||||||
|
|
||||||
|
ALTER TABLE "User" RENAME COLUMN "email" TO "username";
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "User" ADD COLUMN "emailVerified" TIMESTAMP(3),
|
||||||
|
ADD COLUMN "image" TEXT;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "VerificationToken" (
|
||||||
|
"identifier" TEXT NOT NULL,
|
||||||
|
"token" TEXT NOT NULL,
|
||||||
|
"expires" TIMESTAMP(3) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"("token");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "VerificationToken"("identifier", "token");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
|
@ -7,22 +7,69 @@ datasource db {
|
||||||
url = env("DATABASE_URL")
|
url = env("DATABASE_URL")
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
// model Account {
|
||||||
id Int @id @default(autoincrement())
|
// id String @id @default(cuid())
|
||||||
name String
|
// userId Int
|
||||||
email String @unique
|
// type String
|
||||||
password String
|
// provider String
|
||||||
collections Collection[]
|
// providerAccountId String
|
||||||
tags Tag[]
|
// refresh_token String? @db.Text
|
||||||
|
// access_token String? @db.Text
|
||||||
|
// expires_at Int?
|
||||||
|
// token_type String?
|
||||||
|
// scope String?
|
||||||
|
// id_token String? @db.Text
|
||||||
|
// session_state String?
|
||||||
|
|
||||||
pinnedLinks Link[]
|
// user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
// @@unique([provider, providerAccountId])
|
||||||
|
// }
|
||||||
|
|
||||||
|
// model Session {
|
||||||
|
// id String @id @default(cuid())
|
||||||
|
// sessionToken String @unique
|
||||||
|
// userId Int
|
||||||
|
// expires DateTime
|
||||||
|
// user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
|
// }
|
||||||
|
|
||||||
|
model User {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
name String
|
||||||
|
|
||||||
|
username String @unique
|
||||||
|
|
||||||
|
// email String? @unique
|
||||||
|
emailVerified DateTime?
|
||||||
|
image String?
|
||||||
|
|
||||||
|
// accounts Account[]
|
||||||
|
// sessions Session[]
|
||||||
|
|
||||||
collectionsJoined UsersAndCollections[]
|
password String
|
||||||
isPrivate Boolean @default(false)
|
collections Collection[]
|
||||||
whitelistedUsers String[] @default([])
|
|
||||||
createdAt DateTime @default(now())
|
tags Tag[]
|
||||||
|
|
||||||
|
pinnedLinks Link[]
|
||||||
|
|
||||||
|
collectionsJoined UsersAndCollections[]
|
||||||
|
isPrivate Boolean @default(false)
|
||||||
|
whitelistedUsers String[] @default([])
|
||||||
|
createdAt DateTime @default(now())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
model VerificationToken {
|
||||||
|
identifier String
|
||||||
|
token String @unique
|
||||||
|
expires DateTime
|
||||||
|
|
||||||
|
@@unique([identifier, token])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
model Collection {
|
model Collection {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
name String
|
name String
|
||||||
|
|
|
@ -8,14 +8,14 @@ type ResponseObject = {
|
||||||
|
|
||||||
type AccountStore = {
|
type AccountStore = {
|
||||||
account: AccountSettings;
|
account: AccountSettings;
|
||||||
setAccount: (email: string) => void;
|
setAccount: (username: string) => void;
|
||||||
updateAccount: (user: AccountSettings) => Promise<ResponseObject>;
|
updateAccount: (user: AccountSettings) => Promise<ResponseObject>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useAccountStore = create<AccountStore>()((set) => ({
|
const useAccountStore = create<AccountStore>()((set) => ({
|
||||||
account: {} as AccountSettings,
|
account: {} as AccountSettings,
|
||||||
setAccount: async (email) => {
|
setAccount: async (username) => {
|
||||||
const response = await fetch(`/api/routes/users?email=${email}`);
|
const response = await fetch(`/api/routes/users?username=${username}`);
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export interface Member {
|
||||||
canCreate: boolean;
|
canCreate: boolean;
|
||||||
canUpdate: boolean;
|
canUpdate: boolean;
|
||||||
canDelete: boolean;
|
canDelete: boolean;
|
||||||
user: OptionalExcluding<User, "email" | "name">;
|
user: OptionalExcluding<User, "username" | "name">;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CollectionIncludingMembersAndLinkCount
|
export interface CollectionIncludingMembersAndLinkCount
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import NextAuth, { DefaultSession } from "next-auth";
|
import NextAuth from "next-auth";
|
||||||
|
|
||||||
declare module "next-auth" {
|
declare module "next-auth" {
|
||||||
interface Session {
|
interface Session {
|
||||||
user: {
|
user: {
|
||||||
id: number;
|
id: number;
|
||||||
} & DefaultSession["user"];
|
username: string;
|
||||||
|
email: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
39
yarn.lock
39
yarn.lock
|
@ -12,6 +12,25 @@
|
||||||
resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
|
resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
|
||||||
integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
|
integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
|
||||||
|
|
||||||
|
"@auth/core@0.8.1":
|
||||||
|
version "0.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@auth/core/-/core-0.8.1.tgz#8fbfb7b11ed3e4b346857b033e454efb7c16df26"
|
||||||
|
integrity sha512-WudBmZudZ/cvykxHV5hIwrYsd7AlETQ535O7w3sSiiumT28+U9GvBb8oSRtfzxpW9rym3lAdfeTJqGA8U4FecQ==
|
||||||
|
dependencies:
|
||||||
|
"@panva/hkdf" "^1.0.4"
|
||||||
|
cookie "0.5.0"
|
||||||
|
jose "^4.11.1"
|
||||||
|
oauth4webapi "^2.0.6"
|
||||||
|
preact "10.11.3"
|
||||||
|
preact-render-to-string "5.2.3"
|
||||||
|
|
||||||
|
"@auth/prisma-adapter@^1.0.0":
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@auth/prisma-adapter/-/prisma-adapter-1.0.0.tgz#9107498921997b6174e0189553f29d0eb49ba2a0"
|
||||||
|
integrity sha512-+x+s5dgpNmqrcQC2ZRAXZIM6yhkWP/EXjIUgqUyMepLiX1OHi2AXIUAAbXsW4oG9OpYr/rvPIzPBpuGt6sPFwQ==
|
||||||
|
dependencies:
|
||||||
|
"@auth/core" "0.8.1"
|
||||||
|
|
||||||
"@aws-crypto/crc32@3.0.0":
|
"@aws-crypto/crc32@3.0.0":
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa"
|
resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa"
|
||||||
|
@ -1023,7 +1042,7 @@
|
||||||
"@nodelib/fs.scandir" "2.1.5"
|
"@nodelib/fs.scandir" "2.1.5"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
"@panva/hkdf@^1.0.2":
|
"@panva/hkdf@^1.0.2", "@panva/hkdf@^1.0.4":
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.1.1.tgz#ab9cd8755d1976e72fc77a00f7655a64efe6cd5d"
|
resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.1.1.tgz#ab9cd8755d1976e72fc77a00f7655a64efe6cd5d"
|
||||||
integrity sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==
|
integrity sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==
|
||||||
|
@ -2022,7 +2041,7 @@ convert-source-map@^1.5.0:
|
||||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
|
||||||
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
|
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
|
||||||
|
|
||||||
cookie@^0.5.0:
|
cookie@0.5.0, cookie@^0.5.0:
|
||||||
version "0.5.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
|
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
|
||||||
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
|
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
|
||||||
|
@ -3270,7 +3289,7 @@ jiti@^1.18.2:
|
||||||
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd"
|
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd"
|
||||||
integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==
|
integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==
|
||||||
|
|
||||||
jose@^4.11.4, jose@^4.14.1:
|
jose@^4.11.1, jose@^4.11.4, jose@^4.14.1:
|
||||||
version "4.14.4"
|
version "4.14.4"
|
||||||
resolved "https://registry.yarnpkg.com/jose/-/jose-4.14.4.tgz#59e09204e2670c3164ee24cbfe7115c6f8bff9ca"
|
resolved "https://registry.yarnpkg.com/jose/-/jose-4.14.4.tgz#59e09204e2670c3164ee24cbfe7115c6f8bff9ca"
|
||||||
integrity sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==
|
integrity sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==
|
||||||
|
@ -3663,6 +3682,11 @@ oauth-sign@~0.9.0:
|
||||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||||
|
|
||||||
|
oauth4webapi@^2.0.6:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/oauth4webapi/-/oauth4webapi-2.3.0.tgz#d01aeb83b60dbe3ff9ef1c6ec4a39e29c7be7ff6"
|
||||||
|
integrity sha512-JGkb5doGrwzVDuHwgrR4nHJayzN4h59VCed6EW8Tql6iHDfZIabCJvg6wtbn5q6pyB2hZruI3b77Nudvq7NmvA==
|
||||||
|
|
||||||
oauth@^0.9.15:
|
oauth@^0.9.15:
|
||||||
version "0.9.15"
|
version "0.9.15"
|
||||||
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
|
||||||
|
@ -3961,6 +3985,13 @@ postcss@^8.4.23, postcss@^8.4.24:
|
||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
|
preact-render-to-string@5.2.3:
|
||||||
|
version "5.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz#23d17376182af720b1060d5a4099843c7fe92fe4"
|
||||||
|
integrity sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==
|
||||||
|
dependencies:
|
||||||
|
pretty-format "^3.8.0"
|
||||||
|
|
||||||
preact-render-to-string@^5.1.19:
|
preact-render-to-string@^5.1.19:
|
||||||
version "5.2.6"
|
version "5.2.6"
|
||||||
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz#0ff0c86cd118d30affb825193f18e92bd59d0604"
|
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz#0ff0c86cd118d30affb825193f18e92bd59d0604"
|
||||||
|
@ -3968,7 +3999,7 @@ preact-render-to-string@^5.1.19:
|
||||||
dependencies:
|
dependencies:
|
||||||
pretty-format "^3.8.0"
|
pretty-format "^3.8.0"
|
||||||
|
|
||||||
preact@^10.6.3:
|
preact@10.11.3, preact@^10.6.3:
|
||||||
version "10.11.3"
|
version "10.11.3"
|
||||||
resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.3.tgz#8a7e4ba19d3992c488b0785afcc0f8aa13c78d19"
|
resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.3.tgz#8a7e4ba19d3992c488b0785afcc0f8aa13c78d19"
|
||||||
integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==
|
integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==
|
||||||
|
|
Ŝarĝante…
Reference in New Issue