Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔧 Corrigindo bugs, Codcov 100% #11

Merged
merged 1 commit into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions encryptdef/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Modulo que é o ponto de entrada do programa"""

from encryptdef.cli import main
from encryptdef.cli import main # pragma: no cover

if __name__ == "__main__": # pragma: no cover

if __name__ == "__main__":
# Passando um contexto vazio
main(ctx=None)
2 changes: 1 addition & 1 deletion encryptdef/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def main(ctx: Optional[click.Context] = None) -> None:
correta, não será possível desencriptar os dados ou arquivos.**
"""
if ctx is None:
ctx = click.Context(main)
ctx = click.Context(main) # pragma: no cover

if ctx.invoked_subcommand is None:
core.interactive_mode()
Expand Down
44 changes: 23 additions & 21 deletions encryptdef/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
TEMPLATE_DECRYPTED,
TEMPLATE_DECRYPTED_FILE,
TEMPLATE_DECRYPTED_MESSAGE,
TEMPLATE_EMPTY_FILE_ERROR,
TEMPLATE_ENCRYPT_FILE,
TEMPLATE_ENCRYPT_KEY,
TEMPLATE_ENCRYPT_MESSAGE,
Expand Down Expand Up @@ -56,6 +57,10 @@ class InvalidKey(Exception):
"""Formato de string criptografada inválido"""


class EmptyFileError(Exception):
"""Formato de string criptografada inválido"""


def encrypt(message: str, password: str) -> str:
"""
Criptografa uma mensagem usando AES GCM com uma chave derivada por Scrypt.
Expand Down Expand Up @@ -227,7 +232,7 @@ def process_lines(


def process_file_content(
file: str,
file_path: str,
key: str,
new_file_path: str,
process_line_func: Callable[[str, str], Union[str, bool]],
Expand All @@ -236,7 +241,7 @@ def process_file_content(
Processa o conteúdo de um arquivo e salva o resultado em um novo arquivo.

Args:
file (str): Caminho do arquivo original.
file_path (str): Caminho do arquivo original.
key (str): Chave para criptografar ou descriptografar.
new_file_path (str): Caminho do novo arquivo.
process_line_func (Callable[[str, str], Union[str, bool]]): Função para
Expand All @@ -245,13 +250,13 @@ def process_file_content(
Returns:
bool: True se o processamento for bem-sucedido, False caso contrário.
"""
lines = read_file(file)
lines = read_file(file_path)
if not lines:
raise EmptyFileError(TEMPLATE_EMPTY_FILE_ERROR % file_path)

max_workers = print_get_max_workers(lines)
processed_lines = process_lines(lines, key, process_line_func, max_workers)

if not processed_lines:
return False

write_file(new_file_path, processed_lines)
print_and_record_log(
(
Expand Down Expand Up @@ -281,24 +286,25 @@ def process_file(
Returns:
bool: True se o processamento for bem-sucedido, False caso contrário.
"""
file, key, new_file = data_list

try:
new_file_path = get_new_file_path(file, new_file, CURRENT_DIR)
file_path, key, new_file = data_list
new_file_path = get_new_file_path(file_path, new_file, CURRENT_DIR)
return process_file_content(
file, key, new_file_path, process_line_func
file_path, key, new_file_path, process_line_func
)

except FileNotFoundError:
print_and_record_log(TEMPLATE_FILE_NOT_FOUND % file, "error")
print_and_record_log(TEMPLATE_FILE_NOT_FOUND % file_path, "error")
console.print(TEMPLATE_INFO_FILE)
return False

except (
TypeError,
IsADirectoryError,
ValueError,
InvalidEncryptedFormat,
InvalidKey,
EmptyFileError,
) as e:
print_and_record_log(str(e), "error")
return False
Expand All @@ -307,7 +313,7 @@ def process_file(
def process_keyfile_and_args(
keyfile: Optional[str],
message: Optional[str],
file: Optional[str],
file_: Optional[str],
template_key: str,
) -> str:
"""
Expand All @@ -321,7 +327,7 @@ def process_keyfile_and_args(
a chave será solicitada.
message (Optional[str]): Dados para criptografar ou descriptografar.
Usado se 'file' não for fornecido.
file (Optional[str]): Caminho do arquivo a ser criptografado ou
file_ (Optional[str]): Caminho do arquivo a ser criptografado ou
descriptografado. Usado se 'message' não for fornecido.
template_key (str): Template para solicitar a chave ao usuário,
se necessário.
Expand All @@ -335,12 +341,12 @@ def process_keyfile_and_args(
SystemExit: Se o arquivo de chave não for encontrado, ou se a chave
fornecida for inválida.
"""
if message and file:
if message and file_:
raise click.UsageError(
"Você deve fornecer apenas um dos argumentos: --message ou --file,"
"não ambos."
" não ambos."
)
if not message and not file:
if not message and not file_:
raise click.UsageError(
"Você deve fornecer um dos argumentos: --message ou --file."
)
Expand All @@ -355,13 +361,9 @@ def process_keyfile_and_args(
else:
while not key or key.isspace():
key = console.input(template_key, password=True).strip()
if key.isspace():
if not key:
print_and_record_log(TEMPLATE_ERROR_EMPTY_FIELD, "error")

if key is None:
print_and_record_log(TEMPLATE_ERROR_EMPTY_FIELD, "error")
sys.exit(1)

return key


Expand Down
13 changes: 7 additions & 6 deletions encryptdef/interactive_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ def validate_and_get_input(prompts: List[str]) -> List[str]:
inputs = [
get_user_input(prompt, "🔑" in prompt) for prompt in prompts
]

if any(not input for input in inputs):
raise ValueError(TEMPLATE_ERROR_EMPTY_FIELD)
return inputs
Expand Down Expand Up @@ -174,15 +173,17 @@ def print_get_max_workers(lines: List[str]) -> int:
max_workers = 1

if len(lines) > 500:
use_more_cores = int(
console.input(TEMPLATE_GET_MAX_WORKERS % max_workers)
)
user_input = console.input(
TEMPLATE_GET_MAX_WORKERS % max_workers
).strip()
console.print("\n", end="")

if not use_more_cores or use_more_cores > max_workers:
if not user_input.isdigit() or not (
0 < int(user_input) <= max_workers
):
raise ValueError(TEMPLATE_ERROR_INVALID_CHOICE)

return use_more_cores
return int(user_input)

return 1

Expand Down
8 changes: 4 additions & 4 deletions encryptdef/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


def configure_logger(
logfile: Optional[Union[str, os.PathLike[str]]] = None
log_level: str, logfile: Optional[Union[str, os.PathLike[str]]] = None
) -> None:
"""Configura o logger com um handler de arquivo rotativo."""
if logfile is None:
Expand All @@ -32,10 +32,10 @@ def configure_logger(
fh = handlers.RotatingFileHandler(
logfile, maxBytes=10**6, backupCount=10
)
fh.setLevel(LOG_LEVEL)
fh.setLevel(log_level)
fh.setFormatter(fmt)
log_instance.addHandler(fh)
log_instance.setLevel(LOG_LEVEL)
log_instance.setLevel(log_level)


def get_logger() -> logging.Logger:
Expand All @@ -44,7 +44,7 @@ def get_logger() -> logging.Logger:


# Configure o logger ao importar o módulo
configure_logger()
configure_logger(LOG_LEVEL)

log = get_logger()

Expand Down
5 changes: 4 additions & 1 deletion encryptdef/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@
⚠ ERRO - FORMATO DE STRING CRIPTOGRAFADA INVÁLIDO!"""

TEMPLATE_TYPE_ERROR = """
⚠ ERRO - ESPERADO UMA STRING, OBTIDO '%s'"""
⚠ ERRO - ESPERADO UMA STRING, OBTIDO '%s'."""

TEMPLATE_IS_DIRECTORY = """
⚠ ERRO - '%s' É UM DIRETÓRIO, NÃO UM ARQUIVO."""

TEMPLATE_EMPTY_FILE_ERROR = """
⚠ ERRO - ARQUIVO '%s' ESTÁ VAZIO."""
10 changes: 2 additions & 8 deletions encryptdef/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@
import re
from typing import List

from colorama import init

from encryptdef.template import TEMPLATE_IS_DIRECTORY

# Inicializa colorama para garantir o funcionamento em sistemas Windows
init()


def get_new_file_path(file: str, new_file: str, current_dir: str) -> str:
"""
Expand Down Expand Up @@ -93,10 +88,9 @@ def write_file(new_file_path: str, processed_lines: List[str]) -> None:


def clear_console():
"""Limpa o console de forma segura."""
"""Limpa o console de forma segura.
Utilizando sequências de escape ANSI"""
if os.name == "posix":
print("\033[H\033[J", end="")
elif os.name == "nt":
# Inicializa o colorama, que é seguro e portátil
init()
print("\033c", end="")
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ local_scheme = "no-local-version" # determina a parte local (como dev1+g7aff1b9.
minversion = "6.0"
addopts = "-ra -q -vv"
testpaths = "tests"
filterwarnings = "ignore::DeprecationWarning:rich_click"

[tool.flake8]
exclude = [".venv", "build", ".vscodelocal", "migrations", "template.py"]
Expand Down
1 change: 1 addition & 0 deletions requirements.test.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#teste
pytest
pytest-mock

# coverage
coverage
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pycryptodomex >=3.20.0
rich-click >=1.8.2
colorama >=0.4.6
8 changes: 0 additions & 8 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@

import pytest

MARKER = """\
unit: Mark unit tests
integration: Mark integration tests
high: High Priority
medium: Medium Priority
low: Low Priority
"""


@pytest.fixture(autouse=True)
def go_to_tmpdir(request): # injeção de dependencias
Expand Down
4 changes: 2 additions & 2 deletions tests/test_assigning_a_name_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


def test_assigning_a_name_file_absolute():
"""Test function assigning_a_name_file"""
"""Testando a função assigning_a_name_file"""
file = "/tmp/test/file-test-123.txt"
name = "encrypt-"
expected_result = "/tmp/test/encrypt-file-test-123.txt"
Expand All @@ -14,7 +14,7 @@ def test_assigning_a_name_file_absolute():


def test_assigning_a_name_file_relative():
"""Test function assigning_a_name_file"""
"""Testando a função assigning_a_name_file"""
file = "-123-file-test.txt"
name = "decrypt-"
expected_result = "decrypt--123-file-test.txt"
Expand Down
74 changes: 74 additions & 0 deletions tests/test_decrypt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Modulo para testar a função decrypt em core.py"""

from base64 import b64decode, b64encode

import pytest

from encryptdef.core import (
InvalidEncryptedFormat,
InvalidKey,
decrypt,
encrypt,
)
from encryptdef.template import (
TEMPLATE_ERROR_INVALID_ENCRYPTED_FORMAT,
TEMPLATE_INVALID_KEY,
)


def test_decrypt_correct_message():
"""Testa a função decrypt"""
message1 = "Message one: djas;kl/d<j@!#@'>$!@&()&&¨|#!@&*%#312312adasd"
password1 = "strongpassword123"

message2 = "Message two: 1~[]31'2>~[]dADd12<asS&(*¨*&¨#%@!#!@/HDJKA@!#"
password2 = "djas;kl/d<j@!#@'>$!@&()&&¨|#!@&*%#312312adasd"

encrypted_message1 = encrypt(message1, password1)
decrypted_message1 = decrypt(encrypted_message1, password1)

encrypted_message2 = encrypt(message2, password2)
decrypted_message2 = decrypt(encrypted_message2, password2)

assert decrypted_message1 == message1
assert decrypted_message2 == message2


def test_decrypt_with_wrong_password():
"""Testa a função decrypt"""
message = "This is a test message."
password = "strongpassword123"
wrong_password = "wrongpassword456"

encrypted_message = encrypt(message, password)

with pytest.raises(InvalidKey) as excinfo:
decrypt(encrypted_message, wrong_password)
assert str(excinfo.value) == TEMPLATE_INVALID_KEY


def test_decrypt_invalid_format():
"""Testa a função decrypt"""
invalid_encrypted_message = "invalid*encrypted*message-format"
password = "strongpassword123"

with pytest.raises(InvalidEncryptedFormat) as excinfo:
decrypt(invalid_encrypted_message, password)

assert str(excinfo.value) == TEMPLATE_ERROR_INVALID_ENCRYPTED_FORMAT


def test_decrypt_with_modified_message():
"""Testa a função decrypt"""
message = "This is a test message."
password = "strongpassword123"

encrypted_message = encrypt(message, password)
parts = encrypted_message.split("*")
modified_cipher_text = b64encode(b"modified" + b64decode(parts[0])).decode(
"utf-8"
)
modified_encrypted_message = "*".join([modified_cipher_text] + parts[1:])

with pytest.raises(InvalidKey):
decrypt(modified_encrypted_message, password)
Loading
Loading