14 Commits

Author SHA1 Message Date
e49f2e00eb Made pip upgrade before copying requirements.txt in Dockerfile 2022-11-18 16:38:25 +00:00
fd002e3718 Added command to update pip setuptools and install wheel in Dockerfile 2022-11-18 11:34:04 +00:00
d68a7bb6e8 Moved check of generated password into separate function 2022-11-15 15:39:38 +03:00
d5f3708c50 Refactored utils.py
Created constants FORBIDDEN_CHARS, PUNCTUATION, PASSWORD_CHARS
Removed pipe from forbidden chars
Moved Message type alias to the top of the file
Optimized _base_check and made its parameter positional only
Changed gen_password to use said constants
2022-11-15 15:17:36 +03:00
cc13b35282 Made class Account private in utils.py 2022-11-14 16:58:34 +03:00
3802943225 Changed telebot.types.Message to Message in handlers for old functions 2022-11-14 16:58:34 +03:00
309fb2108b Removed unnessesary import from src.__init__ 2022-11-14 16:58:34 +03:00
9d5c52bebe optimized password generation function 2022-11-14 16:58:26 +03:00
a61deca6fa Removed unnecessary comments and type hints in src.__init__ 2022-11-13 19:49:21 +03:00
18abdecb74 Increased time untill deletion for /gen_password to 15 secs 2022-11-13 18:53:11 +03:00
46a1fe59b2 Documented /gen_password command 2022-11-13 18:51:23 +03:00
9ee51dc19f Added /gen_password command 2022-11-13 18:49:57 +03:00
2c07b3bed2 Added function for password generation is utils.py 2022-11-13 18:49:14 +03:00
b8113dc47b Sorted imports in utils.py 2022-11-13 18:16:03 +03:00
6 changed files with 65 additions and 22 deletions

View File

@ -15,8 +15,9 @@ RUN adduser -u 1000 --disabled-password --gecos "" appuser && chown -R appuser /
RUN apt update && apt full-upgrade -y
# Install pip requirements
RUN pip install -U pip setuptools wheel
COPY requirements.txt .
RUN python -m pip install -r requirements.txt
RUN pip install -r requirements.txt
COPY . /app

View File

@ -23,6 +23,7 @@
- /help - помощь
- /export - получить пароли в json формате
- /import - импортировать пароли из json в файле в таком же формате, как из /export
- /gen_password - создать 10 надёжных паролей
### Настройка

View File

@ -1,12 +1,10 @@
import os
from dotenv import load_dotenv
from sqlalchemy.future import Engine
from . import bot, cryptography, database
__all__ = ["bot", "cryptography", "database"]
engine: Engine
def main() -> None:
@ -16,7 +14,7 @@ def main() -> None:
user=os.getenv("DB_USER"),
passwd=os.getenv("DB_PASS"),
db=os.getenv("DB_NAME"),
) # type: ignore
)
database.prepare.prepare(engine)
bot_ = bot.create_bot(os.getenv("TG_TOKEN"), engine) # type: ignore
bot_ = bot.create_bot(os.getenv("TG_TOKEN"), engine)
bot_.infinity_polling()

View File

@ -46,4 +46,7 @@ def create_bot(token: str, engine: Engine) -> telebot.TeleBot:
bot.register_message_handler(
functools.partial(handlers.import_accounts, bot, engine), commands=["import"]
)
bot.register_message_handler(
functools.partial(handlers.gen_password, bot), commands=["gen_password"]
)
return bot

View File

@ -13,6 +13,7 @@ from .utils import (
check_account_name,
check_login,
check_passwd,
gen_passwd,
get_all_accounts,
json_to_accounts,
send_tmp_message,
@ -21,9 +22,7 @@ from .utils import (
Message = telebot.types.Message
def get_accounts(
bot: telebot.TeleBot, engine: Engine, mes: telebot.types.Message
) -> None:
def get_accounts(bot: telebot.TeleBot, engine: Engine, mes: Message) -> None:
base_handler(bot, mes)
accounts = database.get.get_accounts(engine, mes.from_user.id)
if not accounts:
@ -41,9 +40,7 @@ def get_accounts(
)
def delete_all(
bot: telebot.TeleBot, engine: Engine, mes: telebot.types.Message
) -> None:
def delete_all(bot: telebot.TeleBot, engine: Engine, mes: Message) -> None:
base_handler(bot, mes)
bot_mes = bot.send_message(
mes.chat.id,
@ -332,7 +329,7 @@ def _delete_account2(
send_tmp_message(bot, mes.chat.id, "Аккаунт удалён")
def help(bot: telebot.TeleBot, mes: telebot.types.Message) -> None:
def help(bot: telebot.TeleBot, mes: Message) -> None:
message = """Команды:
/set_master_pass - установить мастер пароль
/add_account - создать аккаунт
@ -344,7 +341,8 @@ def help(bot: telebot.TeleBot, mes: telebot.types.Message) -> None:
/cancel - отмена текущего действия
/help - помощь
/export - получить пароли в json формате
/import - импортировать пароли из json в файле в таком же формате, как из /export"""
/import - импортировать пароли из json в файле в таком же формате, как из /export
/gen_password - создать 10 надёжных паролей"""
bot.send_message(mes.chat.id, message)
@ -471,3 +469,15 @@ def _import3(
send_tmp_message(bot, mes.chat.id, mes_text, 10)
del text, mes, accounts
gc.collect()
def gen_password(bot: telebot.TeleBot, mes: Message) -> None:
# Generate 10 passwords and put 'em in the backticks
base_handler(bot, mes)
passwords = (f"`{gen_passwd()}`" for _ in range(10))
text = (
"Пароли:\n"
+ "\n".join(passwords)
+ "\nНажмите на пароль, чтобы его скопировать"
)
send_tmp_message(bot, mes.chat.id, text, 15)

View File

@ -1,15 +1,26 @@
import io
import string
import time
from random import SystemRandom
from typing import Self, Type
import pydantic
import telebot
from sqlalchemy.future import Engine
from .. import database, cryptography
from .. import cryptography, database
class Account(pydantic.BaseModel):
FORBIDDEN_CHARS = frozenset("`\n")
PUNCTUATION = frozenset(string.punctuation).difference(FORBIDDEN_CHARS)
PASSWORD_CHARS = tuple(
frozenset(string.ascii_letters + string.digits).difference(FORBIDDEN_CHARS)
| PUNCTUATION
)
Message = telebot.types.Message
class _Account(pydantic.BaseModel):
name: str
login: str
passwd: str
@ -23,11 +34,11 @@ class Account(pydantic.BaseModel):
class _Accounts(pydantic.BaseModel):
accounts: list[Account] = pydantic.Field(default_factory=list)
accounts: list[_Account] = pydantic.Field(default_factory=list)
def _accounts_list_to_json(accounts: list[tuple[str, str, str]]) -> str:
accounts = _Accounts(accounts=[Account.from_tuple(i) for i in accounts])
accounts = _Accounts(accounts=[_Account.from_tuple(i) for i in accounts])
return accounts.json()
@ -36,9 +47,6 @@ def json_to_accounts(json_: str) -> list[tuple[str, str, str]]:
return [i.as_tuple() for i in accounts.accounts]
Message = telebot.types.Message
def send_tmp_message(
bot: telebot.TeleBot, chat_id: telebot.types.Message, text: str, timeout: int = 5
) -> None:
@ -76,9 +84,9 @@ def accounts_to_json(accounts: list[tuple[str, str, str]]) -> io.StringIO:
return file
def _base_check(val: str) -> bool:
def _base_check(val: str, /) -> bool:
"Returns false if finds new lines or backtick (`)"
return not ("\n" in val or "`" in val)
return not any(i in FORBIDDEN_CHARS for i in val)
def check_account_name(name: str) -> bool:
@ -99,3 +107,25 @@ def check_passwd(passwd: str) -> bool:
def check_account(name: str, login: str, passwd: str) -> bool:
"""Runs checks for account name, login and password"""
return check_account_name(name) and check_login(login) and check_passwd(passwd)
def _check_gened_password(passwd: str, /) -> bool:
"""Retuns true if generated password is valid,
false otherwise.
Password is valid if there is at least one lowercase character,
uppercase character and one punctuation character"""
return (
any(c.islower() for c in passwd)
and any(c.isupper() for c in passwd)
and any(c.isdigit() for c in passwd)
and any(c in PUNCTUATION for c in passwd)
)
def gen_passwd() -> str:
"""Generates password of length 32"""
choices = SystemRandom().choices
while True:
passwd = "".join(choices(PASSWORD_CHARS, k=32))
if _check_gened_password(passwd):
return passwd