Secure user endponts with session, dont require calling endpoints from nextauth, call models instead so we can completely secure the endpoints

This commit is contained in:
austinkelsay 2024-10-02 16:58:36 -05:00
parent 0eecb9a23b
commit a0e124d9ef
10 changed files with 88 additions and 14 deletions

View File

@ -2,20 +2,16 @@ import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials"; import CredentialsProvider from "next-auth/providers/credentials";
import EmailProvider from "next-auth/providers/email"; import EmailProvider from "next-auth/providers/email";
import NDK from "@nostr-dev-kit/ndk"; import NDK from "@nostr-dev-kit/ndk";
import axios from "axios";
import { PrismaAdapter } from "@next-auth/prisma-adapter"; import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "@/db/prisma"; import prisma from "@/db/prisma";
import { findKind0Fields } from "@/utils/nostr"; import { findKind0Fields } from "@/utils/nostr";
import { generateSecretKey, getPublicKey } from 'nostr-tools/pure' import { generateSecretKey, getPublicKey } from 'nostr-tools/pure'
import { bytesToHex } from '@noble/hashes/utils' import { bytesToHex } from '@noble/hashes/utils'
import { updateUser } from "@/db/models/userModels"; import { updateUser, getUserByPubkey, createUser } from "@/db/models/userModels";
import { createRole } from "@/db/models/roleModels"; import { createRole } from "@/db/models/roleModels";
import appConfig from "@/config/appConfig"; import appConfig from "@/config/appConfig";
// todo update EMAIL_FROM to be a plebdevs email // todo update EMAIL_FROM to be a plebdevs email
const BACKEND_URL = process.env.BACKEND_URL;
const ndk = new NDK({ const ndk = new NDK({
explicitRelayUrls: appConfig.defaultRelayUrls, explicitRelayUrls: appConfig.defaultRelayUrls,
}); });
@ -28,24 +24,25 @@ const authorize = async (pubkey) => {
const profile = await user.fetchProfile(); const profile = await user.fetchProfile();
// Check if user exists, create if not // Check if user exists, create if not
const response = await axios.get(`${BACKEND_URL}/api/users/${pubkey}`); let dbUser = await getUserByPubkey(pubkey);
if (response.status === 200 && response.data) {
if (dbUser) {
const fields = await findKind0Fields(profile); const fields = await findKind0Fields(profile);
// Combine user object with kind0Fields, giving priority to kind0Fields // Combine user object with kind0Fields, giving priority to kind0Fields
const combinedUser = { ...response.data, ...fields }; const combinedUser = { ...dbUser, ...fields };
// Update the user on the backend if necessary // Update the user in the database if necessary
// await axios.put(`${BACKEND_URL}/api/users/${combinedUser.id}`, combinedUser); dbUser = await updateUser(dbUser.id, combinedUser);
return combinedUser; return dbUser;
} else if (response.status === 204) { } else {
// Create user // Create user
if (profile) { if (profile) {
const fields = await findKind0Fields(profile); const fields = await findKind0Fields(profile);
const payload = { pubkey, username: fields.username, avatar: fields.avatar }; const payload = { pubkey, username: fields.username, avatar: fields.avatar };
const createUserResponse = await axios.post(`${BACKEND_URL}/api/users`, payload); dbUser = await createUser(payload);
return createUserResponse.data; return dbUser;
} }
} }
} catch (error) { } catch (error) {

View File

@ -1,9 +1,19 @@
import { checkCourseCompletion } from "@/db/models/userCourseModels"; import { checkCourseCompletion } from "@/db/models/userCourseModels";
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
// todo somehow make it to where we can get lesson slug in this endpoint // todo somehow make it to where we can get lesson slug in this endpoint
export default async function handler(req, res) { export default async function handler(req, res) {
const { method } = req; const { method } = req;
const { slug, courseSlug } = req.query; const { slug, courseSlug } = req.query;
const session = await getServerSession(req, res, authOptions);
if (!session) {
res.status(401).json({ error: "Unauthorized" });
return;
}
switch (method) { switch (method) {
case "GET": case "GET":
try { try {

View File

@ -1,9 +1,19 @@
import { createOrUpdateUserCourse } from "@/db/models/userCourseModels"; import { createOrUpdateUserCourse } from "@/db/models/userCourseModels";
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
export default async function handler(req, res) { export default async function handler(req, res) {
const { method } = req; const { method } = req;
const { slug, courseSlug } = req.query; const { slug, courseSlug } = req.query;
const userId = slug; const userId = slug;
const session = await getServerSession(req, res, authOptions);
if (!session) {
res.status(401).json({ error: "Unauthorized" });
return;
}
switch (method) { switch (method) {
case "POST": case "POST":
try { try {

View File

@ -1,4 +1,6 @@
import { getUserById, getUserByPubkey, getUserByEmail, updateUser, deleteUser } from "@/db/models/userModels"; import { getUserById, getUserByPubkey, getUserByEmail, updateUser, deleteUser } from "@/db/models/userModels";
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
export default async function handler(req, res) { export default async function handler(req, res) {
const { slug } = req.query; const { slug } = req.query;
@ -6,6 +8,13 @@ export default async function handler(req, res) {
const isPubkey = /^[0-9a-fA-F]{64}$/.test(slug); const isPubkey = /^[0-9a-fA-F]{64}$/.test(slug);
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(slug); const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(slug);
const session = await getServerSession(req, res, authOptions);
if (!session) {
res.status(401).json({ error: "Unauthorized" });
return;
}
try { try {
let user; let user;
if (isPubkey) { if (isPubkey) {

View File

@ -1,10 +1,20 @@
import { getUserLesson, createOrUpdateUserLesson, deleteUserLesson } from "@/db/models/userLessonModels"; import { getUserLesson, createOrUpdateUserLesson, deleteUserLesson } from "@/db/models/userLessonModels";
import { getResourceById } from "@/db/models/resourceModels"; import { getResourceById } from "@/db/models/resourceModels";
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
// todo somehow make it to where we can get lesson slug in this endpoint // todo somehow make it to where we can get lesson slug in this endpoint
export default async function handler(req, res) { export default async function handler(req, res) {
const { method } = req; const { method } = req;
const { slug, resourceSlug, courseId } = req.query; const { slug, resourceSlug, courseId } = req.query;
const session = await getServerSession(req, res, authOptions);
if (!session) {
res.status(401).json({ error: "Unauthorized" });
return;
}
switch (method) { switch (method) {
case "GET": case "GET":
try { try {

View File

@ -1,11 +1,21 @@
import { getUserLessons, createOrUpdateUserLesson } from "@/db/models/userLessonModels"; import { getUserLessons, createOrUpdateUserLesson } from "@/db/models/userLessonModels";
import { getResourceById } from "@/db/models/resourceModels"; import { getResourceById } from "@/db/models/resourceModels";
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
// todo somehow make it to where we can get lesson slug in this endpoint // todo somehow make it to where we can get lesson slug in this endpoint
export default async function handler(req, res) { export default async function handler(req, res) {
const { method } = req; const { method } = req;
const { slug, courseId } = req.query; const { slug, courseId } = req.query;
const userId = slug; const userId = slug;
const session = await getServerSession(req, res, authOptions);
if (!session) {
res.status(401).json({ error: "Unauthorized" });
return;
}
switch (method) { switch (method) {
case "GET": case "GET":
try { try {

View File

@ -1,9 +1,18 @@
import { getLightningAddress, createLightningAddress, updateLightningAddress, deleteLightningAddress } from "@/db/models/lightningAddressModels" import { getLightningAddress, createLightningAddress, updateLightningAddress, deleteLightningAddress } from "@/db/models/lightningAddressModels"
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
export default async function handler(req, res) { export default async function handler(req, res) {
const { slug } = req.query; const { slug } = req.query;
const userId = slug; const userId = slug;
const session = await getServerSession(req, res, authOptions);
if (!session) {
res.status(401).json({ error: "Unauthorized" });
return;
}
switch (req.method) { switch (req.method) {
case 'GET': case 'GET':
try { try {

View File

@ -1,9 +1,18 @@
import { getNip05, createNip05, updateNip05, deleteNip05 } from '@/db/models/nip05Models'; import { getNip05, createNip05, updateNip05, deleteNip05 } from '@/db/models/nip05Models';
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
export default async function handler(req, res) { export default async function handler(req, res) {
const { slug } = req.query; const { slug } = req.query;
const userId = slug; const userId = slug;
const session = await getServerSession(req, res, authOptions);
if (!session) {
res.status(401).json({ error: "Unauthorized" });
return;
}
switch (req.method) { switch (req.method) {
case 'GET': case 'GET':
try { try {

View File

@ -2,6 +2,7 @@ import { getAllUsers, createUser } from '@/db/models/userModels';
import { getServerSession } from "next-auth/next" import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js" import { authOptions } from "@/pages/api/auth/[...nextauth].js"
// todo add recaptcha for additional security
export default async function handler(req, res) { export default async function handler(req, res) {
// const session = await getServerSession(req, res, authOptions); // const session = await getServerSession(req, res, authOptions);
if (req.method === 'POST') { if (req.method === 'POST') {

View File

@ -1,6 +1,15 @@
import { updateUserSubscription } from "@/db/models/userModels"; import { updateUserSubscription } from "@/db/models/userModels";
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/pages/api/auth/[...nextauth].js"
export default async function handler(req, res) { export default async function handler(req, res) {
const session = await getServerSession(req, res, authOptions);
if (!session) {
res.status(401).json({ error: "Unauthorized" });
return;
}
if (req.method === 'PUT') { if (req.method === 'PUT') {
try { try {
const { userId, isSubscribed, nwc } = req.body; const { userId, isSubscribed, nwc } = req.body;