mirror of https://github.com/MaxLeiter/Drift
				
				
				
			Added celebreate validation
							parent
							
								
									c9f84fe69c
								
							
						
					
					
						commit
						7b2baad782
					
				@ -1,85 +1,104 @@
 | 
			
		||||
import { Router } from 'express'
 | 
			
		||||
import { genSalt, hash, compare } from "bcrypt"
 | 
			
		||||
import { User } from '../../lib/models/User'
 | 
			
		||||
import { sign } from 'jsonwebtoken'
 | 
			
		||||
import config from '../../lib/config'
 | 
			
		||||
import jwt from '../../lib/middleware/jwt'
 | 
			
		||||
import { Router } from "express";
 | 
			
		||||
import { genSalt, hash, compare } from "bcrypt";
 | 
			
		||||
import { User } from "../../lib/models/User";
 | 
			
		||||
import { sign } from "jsonwebtoken";
 | 
			
		||||
import config from "../../lib/config";
 | 
			
		||||
import jwt from "../../lib/middleware/jwt";
 | 
			
		||||
import { celebrate, Joi } from "celebrate";
 | 
			
		||||
 | 
			
		||||
const NO_EMPTY_SPACE_REGEX = /^\S*$/
 | 
			
		||||
const NO_EMPTY_SPACE_REGEX = /^\S*$/;
 | 
			
		||||
 | 
			
		||||
export const auth = Router()
 | 
			
		||||
export const auth = Router();
 | 
			
		||||
 | 
			
		||||
const validateAuthPayload = (username: string, password: string): void => {
 | 
			
		||||
    if (!NO_EMPTY_SPACE_REGEX.test(username) || password.length < 6) {
 | 
			
		||||
        throw new Error("Authentication data does not fulfill requirements")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auth.post('/signup', async (req, res, next) => {
 | 
			
		||||
  if (!NO_EMPTY_SPACE_REGEX.test(username) || password.length < 6) {
 | 
			
		||||
    throw new Error("Authentication data does not fulfill requirements");
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
auth.post(
 | 
			
		||||
  "/signup",
 | 
			
		||||
  celebrate({
 | 
			
		||||
    params: {
 | 
			
		||||
      username: Joi.string().required(),
 | 
			
		||||
      password: Joi.string().required(),
 | 
			
		||||
    },
 | 
			
		||||
  }),
 | 
			
		||||
  async (req, res, next) => {
 | 
			
		||||
    try {
 | 
			
		||||
        validateAuthPayload(req.body.username, req.body.password)
 | 
			
		||||
      validateAuthPayload(req.body.username, req.body.password);
 | 
			
		||||
 | 
			
		||||
        const username = req.body.username.toLowerCase();
 | 
			
		||||
      const username = req.body.username.toLowerCase();
 | 
			
		||||
 | 
			
		||||
        const existingUser = await User.findOne({ where: { username: username } })
 | 
			
		||||
        if (existingUser) {
 | 
			
		||||
            throw new Error("Username already exists")
 | 
			
		||||
        }
 | 
			
		||||
      const existingUser = await User.findOne({
 | 
			
		||||
        where: { username: username },
 | 
			
		||||
      });
 | 
			
		||||
      if (existingUser) {
 | 
			
		||||
        throw new Error("Username already exists");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        const salt = await genSalt(10)
 | 
			
		||||
        const user = {
 | 
			
		||||
            username: username as string,
 | 
			
		||||
            password: await hash(req.body.password, salt)
 | 
			
		||||
        }
 | 
			
		||||
      const salt = await genSalt(10);
 | 
			
		||||
      const user = {
 | 
			
		||||
        username: username as string,
 | 
			
		||||
        password: await hash(req.body.password, salt),
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
        const created_user = await User.create(user);
 | 
			
		||||
      const created_user = await User.create(user);
 | 
			
		||||
 | 
			
		||||
        const token = generateAccessToken(created_user.id);
 | 
			
		||||
      const token = generateAccessToken(created_user.id);
 | 
			
		||||
 | 
			
		||||
        res.status(201).json({ token: token, userId: created_user.id })
 | 
			
		||||
      res.status(201).json({ token: token, userId: created_user.id });
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        next(e);
 | 
			
		||||
      next(e);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
auth.post('/signin', async (req, res, next) => {
 | 
			
		||||
    const error = "User does not exist or password is incorrect"
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
auth.post(
 | 
			
		||||
  "/signin",
 | 
			
		||||
  celebrate({
 | 
			
		||||
    params: {
 | 
			
		||||
      username: Joi.string().required(),
 | 
			
		||||
      password: Joi.string().required(),
 | 
			
		||||
    },
 | 
			
		||||
  }),
 | 
			
		||||
  async (req, res, next) => {
 | 
			
		||||
    const error = "User does not exist or password is incorrect";
 | 
			
		||||
    const errorToThrow = new Error(error);
 | 
			
		||||
    try {
 | 
			
		||||
        if (!req.body.username || !req.body.password) {
 | 
			
		||||
            throw errorToThrow
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const username = req.body.username.toLowerCase();
 | 
			
		||||
        const user = await User.findOne({ where: { username: username } });
 | 
			
		||||
        if (!user) {
 | 
			
		||||
            throw errorToThrow
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const password_valid = await compare(req.body.password, user.password);
 | 
			
		||||
        if (password_valid) {
 | 
			
		||||
            const token = generateAccessToken(user.id);
 | 
			
		||||
            res.status(200).json({ token: token, userId: user.id });
 | 
			
		||||
        } else {
 | 
			
		||||
            throw errorToThrow
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (!req.body.username || !req.body.password) {
 | 
			
		||||
        throw errorToThrow;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const username = req.body.username.toLowerCase();
 | 
			
		||||
      const user = await User.findOne({ where: { username: username } });
 | 
			
		||||
      if (!user) {
 | 
			
		||||
        throw errorToThrow;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const password_valid = await compare(req.body.password, user.password);
 | 
			
		||||
      if (password_valid) {
 | 
			
		||||
        const token = generateAccessToken(user.id);
 | 
			
		||||
        res.status(200).json({ token: token, userId: user.id });
 | 
			
		||||
      } else {
 | 
			
		||||
        throw errorToThrow;
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        next(e);
 | 
			
		||||
      next(e);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
function generateAccessToken(id: string) {
 | 
			
		||||
    return sign({ id: id }, config.jwt_secret, { expiresIn: '2d' });
 | 
			
		||||
  return sign({ id: id }, config.jwt_secret, { expiresIn: "2d" });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auth.get("/verify-token", jwt, async (req, res, next) => {
 | 
			
		||||
    try {
 | 
			
		||||
        res.status(200).json({
 | 
			
		||||
            message: "You are authenticated"
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        next(e);
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
  try {
 | 
			
		||||
    res.status(200).json({
 | 
			
		||||
      message: "You are authenticated",
 | 
			
		||||
    });
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    next(e);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -1,29 +1,36 @@
 | 
			
		||||
import { Router } from 'express'
 | 
			
		||||
import { celebrate, Joi } from "celebrate";
 | 
			
		||||
import { Router } from "express";
 | 
			
		||||
// import { Movie } from '../models/Post'
 | 
			
		||||
import { File } from '../../lib/models/File'
 | 
			
		||||
import { File } from "../../lib/models/File";
 | 
			
		||||
 | 
			
		||||
export const files = Router()
 | 
			
		||||
export const files = Router();
 | 
			
		||||
 | 
			
		||||
files.get("/raw/:id", async (req, res, next) => {
 | 
			
		||||
files.get(
 | 
			
		||||
  "/raw/:id",
 | 
			
		||||
  celebrate({
 | 
			
		||||
    params: {
 | 
			
		||||
      id: Joi.string().required(),
 | 
			
		||||
    },
 | 
			
		||||
  }),
 | 
			
		||||
  async (req, res, next) => {
 | 
			
		||||
    try {
 | 
			
		||||
        const file = await File.findOne({
 | 
			
		||||
            where: {
 | 
			
		||||
                id: req.params.id
 | 
			
		||||
            },
 | 
			
		||||
            attributes: ["title", "content"],
 | 
			
		||||
        })
 | 
			
		||||
        // TODO: fix post inclusion
 | 
			
		||||
        // if (file?.post.visibility === 'public' || file?.post.visibility === 'unlisted') {
 | 
			
		||||
        res.setHeader("Cache-Control", "public, max-age=86400");
 | 
			
		||||
        res.json(file);
 | 
			
		||||
        // } else {
 | 
			
		||||
        // TODO: should this be `private, `?
 | 
			
		||||
        // res.setHeader("Cache-Control", "max-age=86400");
 | 
			
		||||
        // res.json(file);
 | 
			
		||||
        // }
 | 
			
		||||
      const file = await File.findOne({
 | 
			
		||||
        where: {
 | 
			
		||||
          id: req.params.id,
 | 
			
		||||
        },
 | 
			
		||||
        attributes: ["title", "content"],
 | 
			
		||||
      });
 | 
			
		||||
      // TODO: fix post inclusion
 | 
			
		||||
      // if (file?.post.visibility === 'public' || file?.post.visibility === 'unlisted') {
 | 
			
		||||
      res.setHeader("Cache-Control", "public, max-age=86400");
 | 
			
		||||
      res.json(file);
 | 
			
		||||
      // } else {
 | 
			
		||||
      // TODO: should this be `private, `?
 | 
			
		||||
      // res.setHeader("Cache-Control", "max-age=86400");
 | 
			
		||||
      // res.json(file);
 | 
			
		||||
      // }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      next(e);
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        next(e);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
export { auth } from './auth';
 | 
			
		||||
export { posts } from './posts';
 | 
			
		||||
export { users } from './users';
 | 
			
		||||
export { files } from './files';
 | 
			
		||||
export { auth } from "./auth";
 | 
			
		||||
export { posts } from "./posts";
 | 
			
		||||
export { users } from "./users";
 | 
			
		||||
export { files } from "./files";
 | 
			
		||||
 | 
			
		||||
@ -1,97 +1,116 @@
 | 
			
		||||
import { Router } from 'express'
 | 
			
		||||
import { Router } from "express";
 | 
			
		||||
// import { Movie } from '../models/Post'
 | 
			
		||||
import { File } from '../../lib/models/File'
 | 
			
		||||
import { Post } from '../../lib/models/Post';
 | 
			
		||||
import jwt, { UserJwtRequest } from '../../lib/middleware/jwt';
 | 
			
		||||
import { File } from "../../lib/models/File";
 | 
			
		||||
import { Post } from "../../lib/models/Post";
 | 
			
		||||
import jwt, { UserJwtRequest } from "../../lib/middleware/jwt";
 | 
			
		||||
import * as crypto from "crypto";
 | 
			
		||||
import { User } from '../../lib/models/User';
 | 
			
		||||
import { User } from "../../lib/models/User";
 | 
			
		||||
import { celebrate, Joi } from "celebrate";
 | 
			
		||||
 | 
			
		||||
export const posts = Router()
 | 
			
		||||
export const posts = Router();
 | 
			
		||||
 | 
			
		||||
posts.post('/create', jwt, async (req, res, next) => {
 | 
			
		||||
posts.post(
 | 
			
		||||
  "/create",
 | 
			
		||||
  jwt,
 | 
			
		||||
  celebrate({
 | 
			
		||||
    body: {
 | 
			
		||||
      title: Joi.string().required(),
 | 
			
		||||
      files: Joi.any().required(),
 | 
			
		||||
      visibility: Joi.string().required(),
 | 
			
		||||
      userId: Joi.string().required(),
 | 
			
		||||
    },
 | 
			
		||||
  }),
 | 
			
		||||
  async (req, res, next) => {
 | 
			
		||||
    console.log(req.body);
 | 
			
		||||
    try {
 | 
			
		||||
        if (!req.body.files) {
 | 
			
		||||
            throw new Error("Please provide files.")
 | 
			
		||||
        }
 | 
			
		||||
      // Create the "post" object
 | 
			
		||||
      const newPost = new Post({
 | 
			
		||||
        title: req.body.title,
 | 
			
		||||
        visibility: req.body.visibility,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
        if (!req.body.title) {
 | 
			
		||||
            throw new Error("Please provide a title.")
 | 
			
		||||
        }
 | 
			
		||||
      await newPost.save();
 | 
			
		||||
      await newPost.$add("users", req.body.userId);
 | 
			
		||||
      const newFiles = await Promise.all(
 | 
			
		||||
        req.body.files.map(async (file) => {
 | 
			
		||||
          // Establish a "file" for each file in the request
 | 
			
		||||
          const newFile = new File({
 | 
			
		||||
            title: file.title,
 | 
			
		||||
            content: file.content,
 | 
			
		||||
            sha: crypto
 | 
			
		||||
              .createHash("sha256")
 | 
			
		||||
              .update(file.content)
 | 
			
		||||
              .digest("hex")
 | 
			
		||||
              .toString(),
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
        if (!req.body.userId) {
 | 
			
		||||
            throw new Error("No user id provided.")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!req.body.visibility) {
 | 
			
		||||
            throw new Error("Please provide a visibility.")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Create the "post" object 
 | 
			
		||||
        const newPost = new Post({
 | 
			
		||||
            title: req.body.title,
 | 
			
		||||
            visibility: req.body.visibility,
 | 
			
		||||
          await newFile.$set("user", req.body.userId);
 | 
			
		||||
          await newFile.$set("post", newPost.id);
 | 
			
		||||
          await newFile.save();
 | 
			
		||||
          return newFile;
 | 
			
		||||
        })
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
        await newPost.save()
 | 
			
		||||
        await newPost.$add('users', req.body.userId);
 | 
			
		||||
        const newFiles = await Promise.all(req.body.files.map(async (file) => {
 | 
			
		||||
            // Establish a "file" for each file in the request
 | 
			
		||||
            const newFile = new File({
 | 
			
		||||
                title: file.title,
 | 
			
		||||
                content: file.content,
 | 
			
		||||
                sha: crypto.createHash('sha256').update(file.content).digest('hex').toString(),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
            await newFile.$set("user", req.body.userId);
 | 
			
		||||
            await newFile.$set("post", newPost.id);
 | 
			
		||||
            await newFile.save();
 | 
			
		||||
            return newFile;
 | 
			
		||||
        }))
 | 
			
		||||
 | 
			
		||||
        await Promise.all(newFiles.map((file) => {
 | 
			
		||||
            newPost.$add("files", file.id);
 | 
			
		||||
            newPost.save();
 | 
			
		||||
        }))
 | 
			
		||||
      await Promise.all(
 | 
			
		||||
        newFiles.map((file) => {
 | 
			
		||||
          newPost.$add("files", file.id);
 | 
			
		||||
          newPost.save();
 | 
			
		||||
        })
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
        res.json(newPost);
 | 
			
		||||
      res.json(newPost);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        next(e);
 | 
			
		||||
      next(e);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
posts.get("/:id", async (req: UserJwtRequest, res, next) => {
 | 
			
		||||
posts.get(
 | 
			
		||||
  "/:id",
 | 
			
		||||
  celebrate({
 | 
			
		||||
    params: {
 | 
			
		||||
      id: Joi.string().required(),
 | 
			
		||||
    },
 | 
			
		||||
  }),
 | 
			
		||||
  async (req: UserJwtRequest, res, next) => {
 | 
			
		||||
    try {
 | 
			
		||||
        const post = await Post.findOne({
 | 
			
		||||
            where: {
 | 
			
		||||
                id: req.params.id
 | 
			
		||||
            },
 | 
			
		||||
            include: [
 | 
			
		||||
                {
 | 
			
		||||
                    model: File,
 | 
			
		||||
                    as: "files",
 | 
			
		||||
                    attributes: ["id", "title", "content", "sha", "createdAt", "updatedAt"],
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    model: User,
 | 
			
		||||
                    as: "users",
 | 
			
		||||
                    attributes: ["id", "username"],
 | 
			
		||||
                },
 | 
			
		||||
            ]
 | 
			
		||||
        })
 | 
			
		||||
      const post = await Post.findOne({
 | 
			
		||||
        where: {
 | 
			
		||||
          id: req.params.id,
 | 
			
		||||
        },
 | 
			
		||||
        include: [
 | 
			
		||||
          {
 | 
			
		||||
            model: File,
 | 
			
		||||
            as: "files",
 | 
			
		||||
            attributes: [
 | 
			
		||||
              "id",
 | 
			
		||||
              "title",
 | 
			
		||||
              "content",
 | 
			
		||||
              "sha",
 | 
			
		||||
              "createdAt",
 | 
			
		||||
              "updatedAt",
 | 
			
		||||
            ],
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            model: User,
 | 
			
		||||
            as: "users",
 | 
			
		||||
            attributes: ["id", "username"],
 | 
			
		||||
          },
 | 
			
		||||
        ],
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
        if (post?.visibility === 'public' || post?.visibility === 'unlisted') {
 | 
			
		||||
            res.setHeader("Cache-Control", "public, max-age=86400");
 | 
			
		||||
            res.json(post);
 | 
			
		||||
        } else {
 | 
			
		||||
            // TODO: should this be `private, `?
 | 
			
		||||
            res.setHeader("Cache-Control", "max-age=86400");
 | 
			
		||||
            jwt(req, res, () => {
 | 
			
		||||
                res.json(post);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        next(e);
 | 
			
		||||
      if (post?.visibility === "public" || post?.visibility === "unlisted") {
 | 
			
		||||
        res.setHeader("Cache-Control", "public, max-age=86400");
 | 
			
		||||
        res.json(post);
 | 
			
		||||
      } else {
 | 
			
		||||
        // TODO: should this be `private, `?
 | 
			
		||||
        res.setHeader("Cache-Control", "max-age=86400");
 | 
			
		||||
        jwt(req, res, () => {
 | 
			
		||||
          res.json(post);
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      next(e);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
@ -1,46 +1,47 @@
 | 
			
		||||
import { Router } from 'express'
 | 
			
		||||
// import { Movie } from '../models/Post'
 | 
			
		||||
import { User } from '../../lib/models/User'
 | 
			
		||||
import { File } from '../../lib/models/File'
 | 
			
		||||
import jwt, { UserJwtRequest } from '../../lib/middleware/jwt'
 | 
			
		||||
import { Post } from '../../lib/models/Post'
 | 
			
		||||
import { Router } from "express";
 | 
			
		||||
import { User } from "../../lib/models/User";
 | 
			
		||||
import { File } from "../../lib/models/File";
 | 
			
		||||
import jwt, { UserJwtRequest } from "../../lib/middleware/jwt";
 | 
			
		||||
import { Post } from "../../lib/models/Post";
 | 
			
		||||
 | 
			
		||||
export const users = Router()
 | 
			
		||||
export const users = Router();
 | 
			
		||||
 | 
			
		||||
users.get('/', jwt, async (req, res, next) => {
 | 
			
		||||
    try {
 | 
			
		||||
        const allUsers = await User.findAll()
 | 
			
		||||
        res.json(allUsers)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        next(error)
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
users.get("/", jwt, async (req, res, next) => {
 | 
			
		||||
  try {
 | 
			
		||||
    const allUsers = await User.findAll();
 | 
			
		||||
    res.json(allUsers);
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    next(error);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
users.get("/mine", jwt, async (req: UserJwtRequest, res, next) => {
 | 
			
		||||
    if (!req.user) {
 | 
			
		||||
        return res.status(401).json({ error: "Unauthorized" })
 | 
			
		||||
    }
 | 
			
		||||
  if (!req.user) {
 | 
			
		||||
    return res.status(401).json({ error: "Unauthorized" });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        const user = await User.findByPk(req.user.id, {
 | 
			
		||||
            include: [
 | 
			
		||||
                {
 | 
			
		||||
                    model: Post,
 | 
			
		||||
                    as: "posts",
 | 
			
		||||
                    include: [
 | 
			
		||||
                        {
 | 
			
		||||
                            model: File,
 | 
			
		||||
                            as: "files"
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        })
 | 
			
		||||
        if (!user) {
 | 
			
		||||
            return res.status(404).json({ error: "User not found" })
 | 
			
		||||
        }
 | 
			
		||||
        return res.json(user.posts?.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()))
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        next(error)
 | 
			
		||||
  try {
 | 
			
		||||
    const user = await User.findByPk(req.user.id, {
 | 
			
		||||
      include: [
 | 
			
		||||
        {
 | 
			
		||||
          model: Post,
 | 
			
		||||
          as: "posts",
 | 
			
		||||
          include: [
 | 
			
		||||
            {
 | 
			
		||||
              model: File,
 | 
			
		||||
              as: "files",
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
    });
 | 
			
		||||
    if (!user) {
 | 
			
		||||
      return res.status(404).json({ error: "User not found" });
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
    return res.json(
 | 
			
		||||
      user.posts?.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
 | 
			
		||||
    );
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    next(error);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue