Skip to content

Commit

Permalink
Add reject keys feature, view users
Browse files Browse the repository at this point in the history
Signed-off-by: Igor Sachivka <juicy.igor@gmail.com>
  • Loading branch information
isachivka committed May 26, 2023
1 parent 514f668 commit cf78fa4
Show file tree
Hide file tree
Showing 19 changed files with 248 additions and 605 deletions.
561 changes: 31 additions & 530 deletions front/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"preview": "vite preview"
},
"dependencies": {
"nanoid": "^4.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.43.9"
Expand Down
32 changes: 16 additions & 16 deletions front/src/features/keys/AddForm.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import { useForm } from "react-hook-form";
import { useToken } from "../auth/TokenStorage.tsx";
import { endPoints } from "../../helpers/endPoints.ts";
import { nanoid } from 'nanoid';
import { useForm } from 'react-hook-form';

import { endPoints } from '../../helpers/endPoints.ts';
import { useToken } from '../auth/TokenStorage.tsx';

type AddFormProps = {
appendKey: (key: { telegramId: number; token: string; id: number }) => void;
appendKey: (key: { token: string; id: number; comment: string }) => void;
};

export const AddForm = (props: AddFormProps) => {
const { register, handleSubmit, reset } = useForm<{
telegramId: number;
token: string;
comment: string;
}>();
const { storage } = useToken();
const { token } = storage;

const onSubmit = handleSubmit(async (data) => {
try {
const key = { ...data, token: nanoid(36) } as const;
const response = await fetch(endPoints.addToken, {
method: "POST",
method: 'POST',
headers: {
"Content-Type": "application/json",
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(data),
body: JSON.stringify(key),
});
const json = await response.json();
props.appendKey(json);
props.appendKey({ ...json, token: key.token });
reset();
console.log(json);
} catch (error) {
Expand All @@ -35,12 +37,10 @@ export const AddForm = (props: AddFormProps) => {

return (
<form onSubmit={onSubmit}>
<label htmlFor="telegramId">Telegram ID:</label>
<input type="number" id="telegramId" {...register("telegramId")} />

<label htmlFor="token">Token:</label>
<input type="text" id="token" {...register("token")} />

<label>
<span>Comment:</span>
<input type="text" id="comment" {...register('comment')} />
</label>
<button type="submit">Submit</button>
</form>
);
Expand Down
42 changes: 39 additions & 3 deletions front/src/features/keys/Row.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,48 @@
import { useCallback } from 'react';

import { endPoints } from '../../helpers/endPoints.ts';
import { useToken } from '../auth/TokenStorage.tsx';

type RowProps = {
telegramId: number;
id: number;
token: string;
comment: string;
users: { userId: number }[];
removeKey: (id: number) => void;
};

export const Row = (props: RowProps) => {
const { storage } = useToken();
const { token: authToken } = storage;
const { token, comment, users, id, removeKey } = props;
const onClickReject = useCallback(async () => {
try {
const response = await fetch(endPoints.rejectToken, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${authToken}`,
},
body: JSON.stringify({ id }),
});
const json = await response.json();
removeKey(id);
console.log(json);
} catch (error) {
console.error(error);
}
}, [id]);

return (
<tr>
<td>{props.telegramId}</td>
<td>{props.token}</td>
<td>
<button onClick={onClickReject}>reject</button>
</td>
<td>
<pre>{token || '********'}</pre>
</td>
<td>{comment}</td>
<td>{users.map((user) => user.userId).join(', ')}</td>
</tr>
);
};
57 changes: 42 additions & 15 deletions front/src/features/keys/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
import { useApi } from "../../helpers/useApi.ts";
import { Row } from "./Row.tsx";
import { AddForm } from "./AddForm.tsx";
import { useCallback } from "react";
import { endPoints } from "../../helpers/endPoints.ts";
import { useCallback } from 'react';

import { endPoints } from '../../helpers/endPoints.ts';
import { useApi } from '../../helpers/useApi.ts';
import { AddForm } from './AddForm.tsx';
import { Row } from './Row.tsx';

type Key = {
token: string;
id: number;
comment: string;
};

type KeyWithUser = Key & {
users: { userId: number }[];
};

export const Table = () => {
const [keys, setKeys] = useApi<
{ telegramId: number; token: string; id: number }[]
>(endPoints.keys);
const [keys, setKeys] = useApi<KeyWithUser[]>(endPoints.keys);

const appendKey = useCallback(
(key: { telegramId: number; token: string; id: number }) => {
(key: Key) => {
if (keys) {
setKeys([...keys, key]);
setKeys([{ ...key, users: [] }, ...keys]);
}
},
[keys, setKeys]
);

const removeKey = useCallback(
(id: number) => {
if (keys) {
setKeys([...keys.filter((key) => key.id !== id)]);
}
},
[keys, setKeys]
Expand All @@ -24,21 +42,30 @@ export const Table = () => {

return (
<>
<table border={1} width="100%">
<AddForm appendKey={appendKey} />
<br />
<table border={0} width="100%">
<thead>
<tr>
<td>telegramId</td>
<td></td>
<td>token</td>
<td>comment</td>
<td>users</td>
</tr>
</thead>
<tbody>
{keys.map((key) => (
<Row key={key.id} telegramId={key.telegramId} token={key.token} />
<Row
id={key.id}
key={key.id}
comment={key.comment}
users={key.users}
token={key.token}
removeKey={removeKey}
/>
))}
</tbody>
</table>
<br />
<AddForm appendKey={appendKey} />
</>
);
};
3 changes: 2 additions & 1 deletion front/src/helpers/endPoints.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const baseApi = import.meta.env.VITE_BASE_API
? import.meta.env.VITE_BASE_API
: "";
: '';

export const endPoints = {
health: `${baseApi}/api/v1/health`,
keys: `${baseApi}/api/v1/keys`,
addToken: `${baseApi}/api/v1/addToken`,
rejectToken: `${baseApi}/api/v1/rejectToken`,
};
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gpt",
"version": "1.2.0",
"version": "1.3.0",
"description": "",
"main": "index.js",
"scripts": {
Expand Down
58 changes: 44 additions & 14 deletions src/api/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,52 @@
import express from 'express';

import type { UsersStorage } from '../bot/user/usersStorage';
import db from '../db';

const routes = express.Router();
export const getHandlers = (usersStorage: UsersStorage) => {
const routes = express.Router();

routes.get('/api/v1/health', (req, res) => {
res.status(200).send({ status: 'OK' });
});
routes.get('/api/v1/health', (req, res) => {
res.status(200).send({ status: 'OK' });
});

routes.get('/api/v1/keys', async (req, res) => {
const keys = await db.Key.findAll();
res.send(keys);
});
routes.get('/api/v1/keys', async (req, res) => {
const keys = await db.Key.findAll({ include: db.User });
res.send(
keys.map((key) => ({
id: key.id,
comment: key.comment,
users: key.users,
}))
);
});

routes.post('/api/v1/addToken', async (req, res) => {
const { token, telegramId } = req.body;
const key = await db.Key.create({ token, telegramId });
res.send(key);
});
routes.post('/api/v1/addToken', async (req, res) => {
const { token, comment } = req.body;
const key = await db.Key.create({ token, comment });
res.send({
id: key.id,
comment: key.comment,
users: key.users,
});
});

export default routes;
routes.delete('/api/v1/rejectToken', async (req, res) => {
const { id } = req.body;
const key = await db.Key.findOne({ where: { id }, include: db.User });
await Promise.all(
key.users!.map((user) => {
return usersStorage.get(user.id).then((memoryUser) => {
memoryUser.unauthorize();
return user.update({ auth: false });
});
})
);
await key.destroy();
res.send({
ok: true,
});
});

return routes;
};
7 changes: 4 additions & 3 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ import cors from 'cors';
import express from 'express';
import path from 'path';

import type { UsersStorage } from '../bot/user/usersStorage';
import { authMiddleware } from './authMiddleware';
import handlers from './handlers';
import { getHandlers } from './handlers';

export const initializeApi = () => {
export const initializeApi = (usersStorage: UsersStorage) => {
const app = express();

app.use(cors());
app.use(express.json());
app.use('/', express.static(path.resolve(__dirname, '../static')));
app.use(authMiddleware);
app.use(handlers);
app.use(getHandlers(usersStorage));

app.listen(3000, () => {
console.log('Listen 3000');
Expand Down
2 changes: 1 addition & 1 deletion src/bot/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export type ModeCommands =
export type OtherCommands = typeof start | typeof stats | typeof newDialog;

/*
set_temperature_mode - Set temperature
image_mode - Image creation mode
text_mode - Chat mode
new_dialog - New dialog
set_temperature_mode - Set temperature
*/
5 changes: 2 additions & 3 deletions src/bot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { Telegraf, Telegram } from 'telegraf';

import { initializeCommands } from './commands';
import { initializeListeners } from './listeners';
import { UsersStorage } from './user/usersStorage';
import type { UsersStorage } from './user/usersStorage';

export const initializeBot = () => {
export const initializeBot = (usersStorage: UsersStorage) => {
const telegram = new Telegram(process.env.BOT_KEY);
const bot = new Telegraf(process.env.BOT_KEY);
const usersStorage = new UsersStorage();

initializeCommands(bot, usersStorage);
initializeListeners(telegram, bot, usersStorage);
Expand Down
2 changes: 1 addition & 1 deletion src/bot/processors/modes/broadcast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const broadcastHandler = async (
}

const users = await db.User.findAll();
const chatIds = users.map((user) => user.chatId || user.userId);
const chatIds = users.map((user) => user.userId);

await Promise.all(
chatIds.map((chatId) => {
Expand Down
6 changes: 5 additions & 1 deletion src/bot/user/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,17 @@ export class User {
pg.User.create({
userId: this.id,
auth: true,
chatId: this.id,
token: token,
});
bot.telegram.sendMessage(this.id, locales.en.authSuccess, {});
this.auth = true;
return false;
}

public unauthorize() {
this.auth = false;
}

public isAuthorized() {
return this.auth;
}
Expand Down
Loading

0 comments on commit cf78fa4

Please sign in to comment.