mirror of
https://github.com/pawelmalak/snippet-box.git
synced 2025-12-21 13:23:05 +01:00
Check snippet read permissions in controllers
This commit is contained in:
34
src/controllers/auth/getProfile.ts
Normal file
34
src/controllers/auth/getProfile.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Response, NextFunction } from 'express';
|
||||
import { asyncWrapper } from '../../middleware';
|
||||
import { UserInstance, UserModel } from '../../models';
|
||||
import { UserInfoRequest } from '../../typescript/interfaces';
|
||||
|
||||
interface RequestBody {}
|
||||
|
||||
interface ResponseBody {
|
||||
data: Omit<UserInstance, 'password'>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get user profile by token
|
||||
* @route /api/auth/me
|
||||
* @request POST
|
||||
* @access Public
|
||||
*/
|
||||
export const getProfile = asyncWrapper(
|
||||
async (
|
||||
req: UserInfoRequest<RequestBody>,
|
||||
res: Response<ResponseBody>,
|
||||
next: NextFunction
|
||||
): Promise<void> => {
|
||||
const user = (await UserModel.findOne({
|
||||
where: { id: req.user.id },
|
||||
attributes: { exclude: ['password'] },
|
||||
raw: true
|
||||
})) as UserInstance;
|
||||
|
||||
res.status(200).json({
|
||||
data: user
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -2,6 +2,7 @@ import { Response, NextFunction } from 'express';
|
||||
import { QueryTypes } from 'sequelize';
|
||||
import { sequelize } from '../../db';
|
||||
import { asyncWrapper } from '../../middleware';
|
||||
import { UserInfoRequest } from '../../typescript/interfaces';
|
||||
|
||||
/**
|
||||
* @description Count tags
|
||||
@@ -10,13 +11,23 @@ import { asyncWrapper } from '../../middleware';
|
||||
* @access Private
|
||||
*/
|
||||
export const countTags = asyncWrapper(
|
||||
async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||
async (
|
||||
req: UserInfoRequest,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<void> => {
|
||||
let where = !req.user.isAdmin
|
||||
? `WHERE snippets.createdBy = ${req.user.id}`
|
||||
: '';
|
||||
|
||||
const result = await sequelize.query(
|
||||
`SELECT
|
||||
COUNT(tags.name) as count,
|
||||
tags.name
|
||||
FROM snippets_tags
|
||||
INNER JOIN tags ON snippets_tags.tag_id = tags.id
|
||||
INNER JOIN snippets ON snippets_tags.snippet_id = snippets.id
|
||||
${where}
|
||||
GROUP BY tags.name
|
||||
ORDER BY name ASC`,
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Response, NextFunction } from 'express';
|
||||
import { asyncWrapper } from '../../middleware';
|
||||
import { SnippetModel, Snippet_TagModel } from '../../models';
|
||||
import { Snippet, UserInfoRequest } from '../../typescript/interfaces';
|
||||
import { tagParser, createTags, ErrorResponse } from '../../utils';
|
||||
import { UserInfoRequest } from '../../typescript/interfaces';
|
||||
import { ErrorResponse } from '../../utils';
|
||||
|
||||
interface Params {
|
||||
id: number;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { Response, NextFunction } from 'express';
|
||||
import { asyncWrapper } from '../../middleware';
|
||||
import { SnippetModel, TagModel } from '../../models';
|
||||
import { UserInfoRequest } from '../../typescript/interfaces';
|
||||
|
||||
/**
|
||||
* @description Get all snippets
|
||||
@@ -8,7 +9,13 @@ import { SnippetModel, TagModel } from '../../models';
|
||||
* @request GET
|
||||
*/
|
||||
export const getAllSnippets = asyncWrapper(
|
||||
async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||
async (
|
||||
req: UserInfoRequest,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<void> => {
|
||||
let where = req.user.isAdmin ? {} : { createdBy: req.user.id };
|
||||
|
||||
const snippets = await SnippetModel.findAll({
|
||||
include: {
|
||||
model: TagModel,
|
||||
@@ -17,7 +24,8 @@ export const getAllSnippets = asyncWrapper(
|
||||
through: {
|
||||
attributes: []
|
||||
}
|
||||
}
|
||||
},
|
||||
where
|
||||
});
|
||||
|
||||
const populatedSnippets = snippets.map(snippet => {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { Response, NextFunction } from 'express';
|
||||
import { asyncWrapper } from '../../middleware';
|
||||
import { SnippetModel, TagModel } from '../../models';
|
||||
import { Op } from 'sequelize';
|
||||
import { UserInfoRequest } from '../../typescript/interfaces';
|
||||
|
||||
interface Body {
|
||||
query: string;
|
||||
@@ -17,7 +18,7 @@ interface Body {
|
||||
*/
|
||||
export const searchSnippets = asyncWrapper(
|
||||
async (
|
||||
req: Request<{}, {}, Body>,
|
||||
req: UserInfoRequest<Body>,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<void> => {
|
||||
@@ -49,6 +50,9 @@ export const searchSnippets = asyncWrapper(
|
||||
},
|
||||
{
|
||||
language: languageFilter
|
||||
},
|
||||
{
|
||||
createdBy: req.user.id
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
2
src/environment.d.ts
vendored
2
src/environment.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
PORT: number;
|
||||
PORT: string;
|
||||
NODE_ENV: string;
|
||||
JWT_SECRET: string;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import { NextFunction, Response } from 'express';
|
||||
import { asyncWrapper } from '.';
|
||||
import { ErrorResponse } from '../utils';
|
||||
import { verify } from 'jsonwebtoken';
|
||||
import { Token, UserInfoRequest } from '../typescript/interfaces';
|
||||
import { UserModel } from '../models';
|
||||
|
||||
interface Query {
|
||||
token?: string;
|
||||
}
|
||||
|
||||
export const authenticate = asyncWrapper(
|
||||
async (req: UserInfoRequest, res: Response, next: NextFunction) => {
|
||||
async (
|
||||
req: UserInfoRequest<{}, {}, Query>,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) => {
|
||||
let token: string | null = null;
|
||||
|
||||
// Check if token was provided
|
||||
@@ -14,6 +22,8 @@ export const authenticate = asyncWrapper(
|
||||
if (req.headers.authorization.startsWith('Bearer ')) {
|
||||
token = req.headers.authorization.split(' ')[1];
|
||||
}
|
||||
} else if (req.query.token) {
|
||||
token = req.query.token;
|
||||
}
|
||||
|
||||
if (token) {
|
||||
|
||||
@@ -21,7 +21,7 @@ snippetRouter
|
||||
requireBody('title', 'language', 'code', 'tags'),
|
||||
createSnippet
|
||||
)
|
||||
.get(getAllSnippets);
|
||||
.get(authenticate, getAllSnippets);
|
||||
|
||||
snippetRouter
|
||||
.route('/:id')
|
||||
@@ -29,6 +29,6 @@ snippetRouter
|
||||
.put(authenticate, updateSnippet)
|
||||
.delete(authenticate, deleteSnippet);
|
||||
|
||||
snippetRouter.route('/statistics/count').get(countTags);
|
||||
snippetRouter.route('/raw/:id').get(getRawCode);
|
||||
snippetRouter.route('/search').post(searchSnippets);
|
||||
snippetRouter.route('/statistics/count').get(authenticate, countTags);
|
||||
snippetRouter.route('/raw/:id').get(authenticate, getRawCode);
|
||||
snippetRouter.route('/search').post(authenticate, searchSnippets);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Request } from 'express';
|
||||
|
||||
export interface UserInfoRequest<body = {}, params = {}>
|
||||
extends Request<params, {}, body> {
|
||||
export interface UserInfoRequest<body = {}, params = {}, query = {}>
|
||||
extends Request<params, {}, body, query> {
|
||||
user: {
|
||||
id: number;
|
||||
email: string;
|
||||
|
||||
Reference in New Issue
Block a user