Skip to content

Commit

Permalink
Add antimalware check
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Kudinov committed Sep 26, 2024
1 parent 7b03648 commit 029f96e
Show file tree
Hide file tree
Showing 14 changed files with 118 additions and 3 deletions.
Binary file added backend/.DS_Store
Binary file not shown.
21 changes: 21 additions & 0 deletions backend/app/bot/rpc/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
build_file_meta_text,
build_static_image_url,
build_user_from_search_text,
build_example_file_meta,
)
from app.services.botx_user_search import (
UserIsBotError,
Expand Down Expand Up @@ -220,3 +221,23 @@ async def echo_static_file(smartapp: SmartApp) -> RPCResultResponse[str]:
)

return RPCResultResponse(await build_static_image_url(async_file, smartapp))


class GetExampleFileArgs(RPCArgsBaseModel):
file_type: str

@rpc.feature("get_example_file", name="Example file", ui_elements=[ui_elements.file_type])
async def get_example_file(
smartapp: SmartApp, rpc_arguments: GetExampleFileArgs
) -> RPCResultResponse[str]:
try:
async_file = await build_example_file_meta(rpc_arguments.file_type, smartapp)
except IndexError:
raise RPCErrorExc(
RPCError(
reason="File type required",
id="ASYNC_FILES_REQUIRED",
)
)

return RPCResultResponse("ok", files=[async_file])
1 change: 1 addition & 0 deletions backend/app/resources/example_files/eicar.com
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
Binary file added backend/app/resources/example_files/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions backend/app/services/answers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Any, Dict

from aiofiles.tempfile import SpooledTemporaryFile
from aiofiles.threadpool import open as aioopen
from pybotx import File, Image, UserFromSearch
from pybotx_smartapp_rpc import SmartApp

Expand Down Expand Up @@ -67,3 +68,17 @@ async def build_static_image_url(image_file: Image, smartapp: SmartApp) -> str:
)

return link


async def build_example_file_meta(file_type: str, smartapp: SmartApp) -> str:
filename = "./app/resources/example_files/eicar.com" if file_type == "infected" else "./app/resources/example_files/logo.png"

async with aioopen(filename, mode="rb") as file:
file = await smartapp.bot.upload_file(
bot_id=smartapp.bot_id,
chat_id=smartapp.chat_id,
async_buffer=file,
filename=filename,
)

return file
1 change: 1 addition & 0 deletions backend/app/services/ui_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
file_picker = UIElement(id="file", type=UIElementTypes.FILE_PICKER, label="File")
files_picker = UIElement(id="files", type=UIElementTypes.FILE_PICKER, label="Files")
huids_input = UIElement(id="huids", type=UIElementTypes.ARRAY_UUID, label="Huids")
file_type = UIElement(id="file_type", type=UIElementTypes.INPUT_TEXT, label="File type")
33 changes: 33 additions & 0 deletions frontend/app/modules/antimalware/AntimalwarePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { FC } from 'react'
import { observer } from 'mobx-react'
import styled from 'styled-components'
import { useStore } from '../../hooks/useStore'
import FeatureHeader from '../../components/FeatureHeader'
import Button from '../../components/Button'
import FeaturePage from '../../components/FeaturePage'

const Buttons = styled.div`
display: flex;
justify-content: space-between;
`

const AntimalwarePage: FC = () => {
const { antimalwareStore: store } = useStore()

const handleOpenRegularFile = () => store.openFile(false)

const handleOpenInfectedFile = () => store.openFile(true)

return (
<FeaturePage>
<FeatureHeader name="Антивирусная проверка файлов" />
Открыть файл
<Buttons>
<Button onClick={handleOpenRegularFile} id="submit" title="Обычный" icon="image" />
<Button onClick={handleOpenInfectedFile} id="submit" title="Зараженный" icon="bug_report" />
</Buttons>
</FeaturePage>
)
}

export default observer(AntimalwarePage)
35 changes: 35 additions & 0 deletions frontend/app/modules/antimalware/antimalware.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as SDK from '@expressms/smartapp-sdk'
import { RootStore } from '../../store/rootStore'
import { File, STATUS, StatusResponse } from '@expressms/smartapp-sdk/build/main/types'
import { makeAutoObservable } from 'mobx'

export class AntimalwareStore {
rootStore: RootStore

constructor(rootStore: RootStore) {
makeAutoObservable(this)

this.rootStore = rootStore
}

async openFile(infected: boolean): Promise<void> {
try {
const response = (await SDK.Bridge?.sendBotEvent({
method: 'get_example_file',
params: {
fileType: infected ? 'infected' : 'regular',
},
})) as StatusResponse

if (response.payload.status === STATUS.ERROR) {
this.rootStore.toastStore.showToast(`Ошибка получения файла ${JSON.stringify(response.payload)}`)
return
}

const [file] = response.files as File[]
await SDK.openFile(file)
} catch (e) {
this.rootStore.toastStore.showToast(`Ошибка получения файла ${e?.message}`)
}
}
}
4 changes: 4 additions & 0 deletions frontend/app/modules/features-list/ClientFeatures.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ const ClientFeatures: FC = () => {
<span className="material-icons">folder_off</span>
Очистка кеша статики
</StyledLink>
<StyledLink to="antimalware">
<span className="material-icons">bug_report</span>
Антивирусная проверка файлов
</StyledLink>
</>
)
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/app/modules/features-list/FeaturesListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import MaxFileSizePage from '../max-file-size/MaxFileSizePage'
import SendBotCommandPage from '../send-bot-command/SendBotCommandPage'
import HideLogsPage from '../hide-logs/HideLogsPage'
import CleanCachePage from '../clean-cache/CleanCachePage'
import AntimalwarePage from '../antimalware/AntimalwarePage'

const Wrapper = styled.div`
margin-bottom: 30px;
Expand Down Expand Up @@ -106,6 +107,7 @@ const FeaturesListPage = () => {
<Route path="/send-bot-command" element={<SendBotCommandPage />} />
<Route path="/hide-log-data" element={<HideLogsPage />} />
<Route path="/clean-cache" element={<CleanCachePage />} />
<Route path="/antimalware" element={<AntimalwarePage />} />
</Routes>
</Wrapper>
{store.showMainLoader && <MainLoader />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const SendBotCommandPage: FC = () => {
<Input onChange={handleBodyChange} value={body} id="body" />
Данные
<Input onChange={handleDataChange} value={data} id="data" />
<Button onClick={handleSubmit} id="submit" title="Отправить" />
<Button onClick={handleSubmit} id="submit" title="Отправить" disabled={!userHuid || !body} />
<br />
<br />
{store.response && <JsonViewer data={store.response} id="response" />}
Expand Down
3 changes: 3 additions & 0 deletions frontend/app/store/rootStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { MaxFileSizeStore } from '../modules/max-file-size/max-file-size.store'
import { SendBotCommandStore } from '../modules/send-bot-command/send-bot-command.store'
import { HideLogsStore } from '../modules/hide-logs/hide-logs.store'
import { CleanCacheStore } from '../modules/clean-cache/clean-cache.store'
import { AntimalwareStore } from '../modules/antimalware/antimalware.store'

export class RootStore {
appStore: AppStore
Expand Down Expand Up @@ -68,6 +69,7 @@ export class RootStore {
sendBotCommandStore: SendBotCommandStore
hideLogsStore: HideLogsStore
cleanCacheStore: CleanCacheStore
antimalwareStore: AntimalwareStore

constructor() {
this.appStore = new AppStore(this)
Expand Down Expand Up @@ -104,5 +106,6 @@ export class RootStore {
this.sendBotCommandStore = new SendBotCommandStore(this)
this.hideLogsStore = new HideLogsStore(this)
this.cleanCacheStore = new CleanCacheStore(this)
this.antimalwareStore = new AntimalwareStore(this)
}
}
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next-feature-smartapp",
"version": "2.4.5",
"version": "2.5.0",
"description": "SmartApp with all features",
"main": "index.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion frontend/smartapp-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"manifestVersion": "1.0.0",
"smartAppVersion": "",
"bundlePath": "",
"changeLog": "Блокировка кнопки отправки для AT"
"changeLog": "Антивирусная проверкуа файлов"
}

0 comments on commit 029f96e

Please sign in to comment.