Skip to content

Commit 8570418

Browse files
authored
fix-code (#11)
* fix-code:add-endpoint * fix-code:review1
1 parent c59ac74 commit 8570418

15 files changed

Lines changed: 186 additions & 32 deletions
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Request, Response } from 'express';
2+
import { successResponse, errorResponse } from '../utils/response';
3+
import UserRepository from '../repositories/user-repository';
4+
import { generateApiKey } from '../utils/auth';
5+
import Users from '../models/user';
6+
import { InferAttributes } from 'sequelize';
7+
8+
type UserType = InferAttributes<Users>;
9+
10+
interface AuthRequest extends Request {
11+
user?: UserType;
12+
}
13+
14+
export const getApiKey = async (req: AuthRequest, res: Response) => {
15+
try {
16+
if (!req.user) {
17+
return errorResponse(res, 'Unauthorized', 401);
18+
}
19+
20+
return successResponse(
21+
res,
22+
{ apikey: req.user.apikey },
23+
'User details retrieved',
24+
);
25+
} catch (error) {
26+
console.error(error);
27+
return errorResponse(res, 'Unauthorized', 401);
28+
}
29+
};
30+
31+
export const regenerateApiKey = async (req: AuthRequest, res: Response) => {
32+
try {
33+
if (!req.user) {
34+
return errorResponse(res, 'Unauthorized', 401);
35+
}
36+
37+
const newApiKey = await generateApiKey();
38+
await UserRepository.update({ id: req.user.id }, { apikey: newApiKey });
39+
40+
return successResponse(
41+
res,
42+
{ apikey: newApiKey },
43+
'User details retrieved',
44+
);
45+
} catch (error) {
46+
console.error(error);
47+
return errorResponse(res, 'Unauthorized', 401);
48+
}
49+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Request, Response } from 'express';
2+
import { sequelize } from '../config/database';
3+
import { QueryTypes } from 'sequelize';
4+
import { errorResponse, successResponse } from '../utils/response';
5+
6+
export const executeQuery = async (req: Request, res: Response) => {
7+
try {
8+
const { query } = req.body;
9+
10+
if (!query || typeof query !== 'string') {
11+
return errorResponse(res, 'Query is required and must be a string', 400);
12+
}
13+
14+
const forbiddenPatterns = [
15+
/DROP\s+TABLE/i,
16+
/ALTER\s+/i,
17+
/DELETE\s+FROM\s+[^\s]+(\s*;|$)/i,
18+
];
19+
if (forbiddenPatterns.some((pattern) => pattern.test(query))) {
20+
return errorResponse(res, 'Query contains forbidden operations', 403);
21+
}
22+
23+
const result = await sequelize.query(query, { type: QueryTypes.RAW });
24+
return successResponse(res, result, 'Query executed successfully');
25+
} catch (error) {
26+
console.error(error);
27+
return errorResponse(res, 'Failed to execute query', 500);
28+
}
29+
};
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { Request, Response } from 'express';
22
import SchemaRepository from '../repositories/schema-repository';
3+
import { errorResponse, successResponse } from '../utils/response';
34

45
export const schema = async (req: Request, res: Response) => {
56
try {
67
const tables = await SchemaRepository.getSchemas();
78

8-
return res.json({ success: true, tables });
9+
return successResponse(res, tables);
910
} catch (error) {
1011
const errorMessage =
1112
error instanceof Error ? error.message : 'Unknown error';
12-
res.status(500).json({ error: errorMessage });
13+
return errorResponse(res, errorMessage, 500);
1314
}
1415
};

src/controllers/user-controller.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ import { ENV } from '../config/env';
55
import { hashPassword, generateApiKey } from '../utils/auth';
66
import { successResponse, errorResponse } from '../utils/response';
77
import UserRepository from '../repositories/user-repository';
8+
import Users from '../models/user';
9+
import { InferAttributes } from 'sequelize';
10+
11+
type UserType = InferAttributes<Users>;
12+
13+
interface AuthRequest extends Request {
14+
user?: UserType;
15+
}
816

917
export const registerUser = async (req: Request, res: Response) => {
1018
try {
@@ -71,21 +79,9 @@ export const loginUser = async (req: Request, res: Response) => {
7179
}
7280
};
7381

74-
export const getUserDetails = async (req: Request, res: Response) => {
82+
export const getUserDetails = async (req: AuthRequest, res: Response) => {
7583
try {
76-
const token = req.headers.authorization?.split(' ')[1];
77-
if (!token) {
78-
return errorResponse(res, 'Unauthorized', 401);
79-
}
80-
81-
const decoded: any = jwt.verify(token, ENV.JWT_SECRET);
82-
const user = await UserRepository.findOne({ id: decoded.userId });
83-
84-
if (!user) {
85-
return errorResponse(res, 'Unauthorized', 401);
86-
}
87-
88-
return successResponse(res, user, 'User details retrieved');
84+
return successResponse(res, req.user, 'User details retrieved');
8985
} catch (error) {
9086
console.error(error);
9187
return errorResponse(res, 'Unauthorized', 401);

src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import ddlRoutes from './routes/ddl-routes';
66
import { sequelize } from './config/database';
77
import schemaRoutes from './routes/schema-routes';
88
import dmlRoutes from './routes/dml-routes';
9+
import queryRoutes from './routes/query-routes';
10+
import apikeyRoutes from './routes/apikey-routes';
911

1012
sequelize
1113
.sync({ alter: true })
@@ -30,6 +32,8 @@ apiRouter.use('/users', userRoutes);
3032
apiRouter.use('/migrate', ddlRoutes);
3133
apiRouter.use('/schemas', schemaRoutes);
3234
apiRouter.use('/execute', dmlRoutes);
35+
apiRouter.use('/query', queryRoutes);
36+
apiRouter.use('/apikey', apikeyRoutes);
3337

3438
app.use('/api', apiRouter);
3539

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Request, Response, NextFunction } from 'express';
2+
import { errorResponse } from '../utils/response';
3+
import UserRepository from '../repositories/user-repository';
4+
5+
export const apiKeyMiddleware = async (
6+
req: Request,
7+
res: Response,
8+
next: NextFunction,
9+
) => {
10+
try {
11+
const apiKey = req.headers['x-api-key'] as string;
12+
13+
if (!apiKey) {
14+
return errorResponse(res, 'Unauthorized', 401);
15+
}
16+
17+
const user = await UserRepository.findOne(
18+
{ apikey: apiKey },
19+
{ attributes: { exclude: ['password'] } },
20+
);
21+
if (!user) {
22+
return errorResponse(res, 'Unauthorized', 401);
23+
}
24+
25+
(req as any).user = user;
26+
next();
27+
} catch (error) {
28+
console.error('Error:', error);
29+
return errorResponse(res, 'Unauthorized', 401);
30+
}
31+
};

src/middlewares/auth-middleware.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,18 @@ import { Request, Response, NextFunction } from 'express';
22
import jwt from 'jsonwebtoken';
33
import { errorResponse } from '../utils/response';
44
import { ENV } from '../config/env';
5+
import UserRepository from '../repositories/user-repository';
6+
import Users from '../models/user';
7+
import { InferAttributes } from 'sequelize';
58

6-
export const authMiddleware = (
7-
req: Request,
9+
type UserType = InferAttributes<Users>;
10+
11+
interface AuthRequest extends Request {
12+
user?: UserType;
13+
}
14+
15+
export const authMiddleware = async (
16+
req: AuthRequest,
817
res: Response,
918
next: NextFunction,
1019
) => {
@@ -14,8 +23,17 @@ export const authMiddleware = (
1423
return errorResponse(res, 'Unauthorized', 401);
1524
}
1625

17-
const decoded = jwt.verify(token, ENV.JWT_SECRET);
18-
(req as any).user = decoded;
26+
const decoded: any = jwt.verify(token, ENV.JWT_SECRET);
27+
const user = await UserRepository.findOne(
28+
{ id: decoded.userId },
29+
{ attributes: { exclude: ['password'] } },
30+
);
31+
32+
if (!user) {
33+
return errorResponse(res, 'Unauthorized', 401);
34+
}
35+
36+
req.user = user;
1937
next();
2038
} catch (error) {
2139
console.error('Error:', error);
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import Users from '../models/user';
2-
import { WhereOptions } from 'sequelize';
2+
import { FindOptions, WhereOptions } from 'sequelize';
33

44
class UserRepository {
5-
static async findOne(condition: WhereOptions) {
6-
return await Users.findOne({ where: condition });
5+
static async findOne(condition: WhereOptions, options: FindOptions = {}) {
6+
return await Users.findOne({ where: condition, ...options });
77
}
88

99
static async insert(data: {
@@ -14,6 +14,10 @@ class UserRepository {
1414
}) {
1515
return await Users.create(data);
1616
}
17+
18+
static async update(condition: WhereOptions, data: Partial<Users>) {
19+
return await Users.update(data, { where: condition });
20+
}
1721
}
1822

1923
export default UserRepository;

src/routes/apikey-routes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Router } from 'express';
2+
import { authMiddleware } from '../middlewares/auth-middleware';
3+
import { getApiKey, regenerateApiKey } from '../controllers/apikey-controller';
4+
5+
const router = Router();
6+
7+
router.get('/', authMiddleware, getApiKey);
8+
router.put('/', authMiddleware, regenerateApiKey);
9+
10+
export default router;

src/routes/auth-routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Router } from 'express';
2-
const { registerUser, loginUser } = require('../controllers/user-controller');
2+
import { registerUser, loginUser } from '../controllers/user-controller';
33

44
const router = Router();
55

0 commit comments

Comments
 (0)