Add usage of SECRET_KEY to secure API routes
This commit is contained in:
parent
90fa28ad65
commit
d30c34deec
8 changed files with 58 additions and 64 deletions
|
@ -5,9 +5,11 @@ const getRawFile = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
const file = await fetch(`${process.env.API_URL}/files/raw/${id}`, {
|
const file = await fetch(`${process.env.API_URL}/files/raw/${id}`, {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'text/plain',
|
'Accept': 'text/plain',
|
||||||
'x-secret-key': process.env.SECRET_KEY || ''
|
'x-secret-key': process.env.SECRET_KEY || '',
|
||||||
|
'Authorization': `Bearer ${req.cookies['drift-token']}`,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
res.setHeader("Content-Type", "text/plain")
|
res.setHeader("Content-Type", "text/plain")
|
||||||
res.setHeader('Cache-Control', 's-maxage=86400');
|
res.setHeader('Cache-Control', 's-maxage=86400');
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
import { NextApiRequest, NextApiResponse } from "next"
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
if (req.headers['x-secret-key'] !== process.env.SECRET_KEY) {
|
|
||||||
return res.status(401).send('Unauthorized')
|
|
||||||
}
|
|
||||||
|
|
||||||
const { path } = req.query
|
|
||||||
|
|
||||||
if (!path || typeof path !== 'string') {
|
|
||||||
return res.status(400).json({
|
|
||||||
error: "Missing path"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await res.unstable_revalidate(path)
|
|
||||||
return res.json({ revalidated: true })
|
|
||||||
} catch (err) {
|
|
||||||
// If there was an error, Next.js will continue
|
|
||||||
// to show the last successfully generated page
|
|
||||||
return res.status(500).send('Error revalidating')
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -31,14 +31,24 @@ export const getServerSideProps: GetServerSideProps = async ({ req }) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const posts = await fetch('http://localhost:3000/server-api/users/mine', {
|
const posts = await fetch(process.env.API_URL + `/posts/mine`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"Authorization": `Bearer ${driftToken}`
|
"Authorization": `Bearer ${driftToken}`,
|
||||||
|
"x-secret-key": process.env.SECRET_KEY || ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!posts.ok || posts.status !== 200) {
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
destination: '/',
|
||||||
|
permanent: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
posts: await posts.json(),
|
posts: await posts.json(),
|
||||||
|
|
|
@ -92,7 +92,8 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"Authorization": `Bearer ${driftToken}`
|
"Authorization": `Bearer ${driftToken}`,
|
||||||
|
"x-secret-key": process.env.SECRET_KEY || "",
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ export class Post extends Model {
|
||||||
@BelongsToMany(() => User, () => PostAuthor)
|
@BelongsToMany(() => User, () => PostAuthor)
|
||||||
users?: User[];
|
users?: User[];
|
||||||
|
|
||||||
@HasMany(() => File)
|
@HasMany(() => File, { constraints: false })
|
||||||
files?: File[];
|
files?: File[];
|
||||||
|
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
import secretKey from '../lib/middleware/secret-key';
|
import secretKey from '../lib/middleware/secret-key';
|
||||||
// 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()
|
||||||
|
@ -13,7 +12,16 @@ files.get("/raw/:id", secretKey, async (req, res, next) => {
|
||||||
},
|
},
|
||||||
attributes: ["title", "content"],
|
attributes: ["title", "content"],
|
||||||
})
|
})
|
||||||
res.json(file);
|
|
||||||
|
// TODO: JWT-checkraw files
|
||||||
|
if (file?.post?.visibility === "private") {
|
||||||
|
// jwt(req as UserJwtRequest, res, () => {
|
||||||
|
// res.json(file);
|
||||||
|
// })
|
||||||
|
res.json(file);
|
||||||
|
} else {
|
||||||
|
res.json(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
next(e);
|
next(e);
|
||||||
|
|
|
@ -69,6 +69,35 @@ posts.get("/", secretKey, async (req, res, next) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
posts.get("/mine", jwt, secretKey, async (req: UserJwtRequest, res, next) => {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
posts.get("/:id", secretKey, async (req, res, next) => {
|
posts.get("/:id", secretKey, async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const post = await Post.findOne({
|
const post = await Post.findOne({
|
||||||
|
@ -95,7 +124,6 @@ posts.get("/:id", secretKey, async (req, res, next) => {
|
||||||
if (post.visibility === 'public' || post?.visibility === 'unlisted') {
|
if (post.visibility === 'public' || post?.visibility === 'unlisted') {
|
||||||
res.json(post);
|
res.json(post);
|
||||||
} else if (post.visibility === 'private') {
|
} else if (post.visibility === 'private') {
|
||||||
console.log("here")
|
|
||||||
jwt(req as UserJwtRequest, res, () => {
|
jwt(req as UserJwtRequest, res, () => {
|
||||||
res.json(post);
|
res.json(post);
|
||||||
})
|
})
|
||||||
|
@ -107,4 +135,3 @@ posts.get("/:id", secretKey, async (req, res, next) => {
|
||||||
next(e);
|
next(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
// import { Movie } from '../models/Post'
|
// import { Movie } from '../models/Post'
|
||||||
import { User } from '../lib/models/User'
|
import { User } from '../lib/models/User'
|
||||||
import { File } from '../lib/models/File'
|
import jwt from '../lib/middleware/jwt'
|
||||||
import jwt, { UserJwtRequest } from '../lib/middleware/jwt'
|
|
||||||
import { Post } from '../lib/models/Post'
|
|
||||||
|
|
||||||
export const users = Router()
|
export const users = Router()
|
||||||
|
|
||||||
|
@ -16,31 +14,3 @@ users.get('/', jwt, async (req, res, next) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
users.get("/mine", jwt, async (req: UserJwtRequest, res, next) => {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
Loading…
Reference in a new issue