passphera-core 0.9.1__tar.gz → 0.11.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (21) hide show
  1. {passphera-core-0.9.1 → passphera_core-0.11.0}/PKG-INFO +12 -3
  2. passphera_core-0.11.0/passphera_core/application/generator.py +57 -0
  3. passphera_core-0.11.0/passphera_core/application/password.py +86 -0
  4. {passphera-core-0.9.1 → passphera_core-0.11.0}/passphera_core/entities.py +15 -42
  5. passphera_core-0.11.0/passphera_core/exceptions.py +19 -0
  6. passphera_core-0.11.0/passphera_core/interfaces.py +44 -0
  7. {passphera-core-0.9.1 → passphera_core-0.11.0}/passphera_core.egg-info/PKG-INFO +12 -3
  8. {passphera-core-0.9.1 → passphera_core-0.11.0}/passphera_core.egg-info/SOURCES.txt +1 -2
  9. {passphera-core-0.9.1 → passphera_core-0.11.0}/setup.py +2 -2
  10. passphera-core-0.9.1/passphera_core/application/generator.py +0 -78
  11. passphera-core-0.9.1/passphera_core/application/password.py +0 -118
  12. passphera-core-0.9.1/passphera_core/application/user.py +0 -56
  13. passphera-core-0.9.1/passphera_core/exceptions.py +0 -49
  14. passphera-core-0.9.1/passphera_core/interfaces.py +0 -92
  15. {passphera-core-0.9.1 → passphera_core-0.11.0}/README.md +0 -0
  16. {passphera-core-0.9.1 → passphera_core-0.11.0}/passphera_core/__init__.py +0 -0
  17. {passphera-core-0.9.1 → passphera_core-0.11.0}/passphera_core/application/__init__.py +0 -0
  18. {passphera-core-0.9.1 → passphera_core-0.11.0}/passphera_core.egg-info/dependency_links.txt +0 -0
  19. {passphera-core-0.9.1 → passphera_core-0.11.0}/passphera_core.egg-info/requires.txt +0 -0
  20. {passphera-core-0.9.1 → passphera_core-0.11.0}/passphera_core.egg-info/top_level.txt +0 -0
  21. {passphera-core-0.9.1 → passphera_core-0.11.0}/setup.cfg +0 -0
@@ -1,11 +1,11 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: passphera-core
3
- Version: 0.9.1
3
+ Version: 0.11.0
4
4
  Summary: The core system of passphera project
5
5
  Home-page: https://github.com/passphera/core
6
6
  Author: Fathi Abdelmalek
7
7
  Author-email: abdelmalek.fathi.2001@gmail.com
8
- Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Development Status :: 4 - Beta
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Programming Language :: Python
@@ -15,6 +15,15 @@ Classifier: Topic :: Security :: Cryptography
15
15
  Requires-Python: >=3
16
16
  Description-Content-Type: text/markdown
17
17
  Requires-Dist: cipherspy
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
18
27
 
19
28
  # passphera-core
20
29
 
@@ -0,0 +1,57 @@
1
+ from datetime import datetime, timezone
2
+ from uuid import UUID
3
+
4
+ from passphera_core.entities import Generator
5
+ from passphera_core.interfaces import GeneratorRepository
6
+
7
+
8
+ class GetGeneratorUseCase:
9
+ def __init__(self, generator_repository: GeneratorRepository):
10
+ self.generator_repository: GeneratorRepository = generator_repository
11
+
12
+ def execute(self, generator_id: UUID) -> Generator:
13
+ return self.generator_repository.get(generator_id)
14
+
15
+
16
+ class GetGeneratorPropertyUseCase:
17
+ def __init__(self, generator_repository: GeneratorRepository):
18
+ self.generator_repository: GeneratorRepository = generator_repository
19
+
20
+ def execute(self, generator_id: UUID, field: str) -> str:
21
+ generator_entity: Generator = self.generator_repository.get(generator_id)
22
+ return getattr(generator_entity, field)
23
+
24
+
25
+ class UpdateGeneratorPropertyUseCase:
26
+ def __init__(self, generator_repository: GeneratorRepository):
27
+ self.generator_repository: GeneratorRepository = generator_repository
28
+
29
+ def execute(self, generator_id: UUID, field: str, value: str) -> None:
30
+ generator_entity: Generator = self.generator_repository.get(generator_id)
31
+ setattr(generator_entity, field, value)
32
+ if field == 'algorithm':
33
+ generator_entity.get_algorithm()
34
+ generator_entity.updated_at = datetime.now(timezone.utc)
35
+ self.generator_repository.update(generator_entity)
36
+
37
+
38
+ class AddCharacterReplacementUseCase:
39
+ def __init__(self, generator_repository: GeneratorRepository):
40
+ self.generator_repository: GeneratorRepository = generator_repository
41
+
42
+ def execute(self, generator_id: UUID, character: str, replacement: str) -> None:
43
+ generator_entity: Generator = self.generator_repository.get(generator_id)
44
+ generator_entity.replace_character(character, replacement)
45
+ generator_entity.updated_at = datetime.now(timezone.utc)
46
+ self.generator_repository.update(generator_entity)
47
+
48
+
49
+ class ResetCharacterReplacementUseCase:
50
+ def __init__(self, generator_repository: GeneratorRepository,):
51
+ self.generator_repository: GeneratorRepository = generator_repository
52
+
53
+ def execute(self, generator_id: UUID, character: str) -> None:
54
+ generator_entity: Generator = self.generator_repository.get(generator_id)
55
+ generator_entity.reset_character(character)
56
+ generator_entity.updated_at = datetime.now(timezone.utc)
57
+ self.generator_repository.update(generator_entity)
@@ -0,0 +1,86 @@
1
+ from uuid import UUID
2
+
3
+ from passphera_core.entities import Password, Generator
4
+ from passphera_core.exceptions import DuplicatePasswordException, PasswordNotFoundException
5
+ from passphera_core.interfaces import PasswordRepository, GeneratorRepository
6
+
7
+
8
+ class GeneratePasswordUseCase:
9
+ def __init__(
10
+ self,
11
+ password_repository: PasswordRepository,
12
+ generator_repository: GeneratorRepository,
13
+ ):
14
+ self.password_repository: PasswordRepository = password_repository
15
+ self.generator_repository: GeneratorRepository = generator_repository
16
+
17
+ def execute(self, generator_id: UUID, context: str, text: str) -> Password:
18
+ password_entity: Password = self.password_repository.get_by_context(context)
19
+ if password_entity:
20
+ raise DuplicatePasswordException(password_entity)
21
+ generator_entity: Generator = self.generator_repository.get(generator_id)
22
+ password: str = generator_entity.generate_password(text)
23
+ password_entity: Password = Password(context=context, text=text, password=password)
24
+ password_entity.encrypt()
25
+ self.password_repository.save(password_entity)
26
+ return password_entity
27
+
28
+
29
+ class GetPasswordByContextUseCase:
30
+ def __init__(self, password_repository: PasswordRepository):
31
+ self.password_repository: PasswordRepository = password_repository
32
+
33
+ def execute(self, context: str) -> Password:
34
+ password_entity: Password = self.password_repository.get_by_context(context)
35
+ if not password_entity:
36
+ raise PasswordNotFoundException()
37
+ return password_entity
38
+
39
+
40
+ class UpdatePasswordUseCase:
41
+ def __init__(
42
+ self,
43
+ password_repository: PasswordRepository,
44
+ generator_repository: GeneratorRepository,
45
+ ):
46
+ self.password_repository: PasswordRepository = password_repository
47
+ self.generator_repository: GeneratorRepository = generator_repository
48
+
49
+ def execute(self, generator_id: UUID, context: str, text: str) -> Password:
50
+ password_entity: Password = self.password_repository.get_by_context(context)
51
+ if not password_entity:
52
+ raise PasswordNotFoundException()
53
+ generator_entity: Generator = self.generator_repository.get(generator_id)
54
+ password: str = generator_entity.generate_password(text)
55
+ password_entity.text = text
56
+ password_entity.password = password
57
+ password_entity.encrypt()
58
+ self.password_repository.update(password_entity)
59
+ return password_entity
60
+
61
+
62
+ class DeletePasswordUseCase:
63
+ def __init__(self, password_repository: PasswordRepository):
64
+ self.password_repository: PasswordRepository = password_repository
65
+
66
+ def execute(self, context: str) -> None:
67
+ password_entity: Password = self.password_repository.get_by_context(context)
68
+ if not password_entity:
69
+ raise PasswordNotFoundException()
70
+ self.password_repository.delete(password_entity)
71
+
72
+
73
+ class GetAllPasswordsUseCase:
74
+ def __init__(self, password_repository: PasswordRepository):
75
+ self.password_repository: PasswordRepository = password_repository
76
+
77
+ def execute(self) -> list[Password]:
78
+ return self.password_repository.list()
79
+
80
+
81
+ class DeleteAllPasswordsUseCase:
82
+ def __init__(self, password_repository: PasswordRepository):
83
+ self.password_repository: PasswordRepository = password_repository
84
+
85
+ def execute(self) -> None:
86
+ self.password_repository.flush()
@@ -5,22 +5,19 @@ from uuid import UUID, uuid4
5
5
  from cryptography.fernet import Fernet
6
6
 
7
7
  from cipherspy.cipher import *
8
- from cipherspy.cipher.base_cipher import BaseCipherAlgorithm
8
+ from cipherspy.exceptions import InvalidAlgorithmException
9
9
  from cipherspy.utilities import generate_salt, derive_key
10
10
 
11
- from passphera_core import exceptions
12
-
13
11
 
14
12
  @dataclass
15
13
  class Password:
16
14
  id: UUID = field(default_factory=uuid4)
17
- user_id: UUID = field(default_factory=uuid4)
18
- created_at: datetime = field(default=datetime.now(timezone.utc))
19
- updated_at: datetime = field(default=datetime.now(timezone.utc))
15
+ created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
16
+ updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
20
17
  context: str = field(default_factory=str)
21
18
  text: str = field(default_factory=str)
22
19
  password: str = field(default_factory=str)
23
- salt: bytes = field(default_factory=bytes)
20
+ salt: bytes = field(default_factory=lambda: bytes)
24
21
 
25
22
  def encrypt(self) -> None:
26
23
  self.salt = generate_salt()
@@ -33,9 +30,10 @@ class Password:
33
30
 
34
31
 
35
32
  @dataclass
36
- class GeneratorConfig:
33
+ class Generator:
37
34
  id: UUID = field(default_factory=uuid4)
38
- generator_id: UUID = field(default_factory=uuid4)
35
+ created_at: datetime = field(default_factory=datetime.now)
36
+ updated_at: datetime = field(default_factory=datetime.now)
39
37
  shift: int = field(default=3)
40
38
  multiplier: int = field(default=3)
41
39
  key: str = field(default="hill")
@@ -56,7 +54,7 @@ class GeneratorConfig:
56
54
  :return: BaseCipherAlgorithm: The primary algorithm used for the cipher
57
55
  """
58
56
  if self.algorithm.lower() not in self._cipher_registry:
59
- raise exceptions.InvalidAlgorithmException(self.algorithm)
57
+ raise InvalidAlgorithmException(self.algorithm)
60
58
  return self._cipher_registry[self.algorithm.lower()]
61
59
 
62
60
  def replace_character(self, char: str, replacement: str) -> None:
@@ -77,49 +75,24 @@ class GeneratorConfig:
77
75
  """
78
76
  self.characters_replacements.pop(char, None)
79
77
 
80
-
81
- @dataclass
82
- class Generator:
83
- id: UUID = field(default_factory=uuid4)
84
- user_id: UUID = field(default_factory=uuid4)
85
- created_at: datetime = field(default_factory=datetime.now)
86
- updated_at: datetime = field(default_factory=datetime.now)
87
- config: GeneratorConfig = field(default_factory=GeneratorConfig)
88
-
89
78
  def apply_replacements(self, password: str) -> str:
90
79
  """
91
80
  Replace character from the ciphered password with character replacements from the generator configurations
81
+ :param password: The password to perform the action on it
92
82
  :return: str: The new ciphered password after character replacements
93
83
  """
94
- translation_table = str.maketrans(self.config.characters_replacements)
84
+ translation_table: dict[int, str] = str.maketrans(self.characters_replacements)
95
85
  return password.translate(translation_table)
96
86
 
97
87
  def generate_password(self, text: str) -> str:
98
88
  """
99
89
  Generate a strong password string using the raw password (add another layer of encryption to it)
90
+ :param text: The text to generate password from it
100
91
  :return: str: The generated ciphered password
101
92
  """
102
- affine = AffineCipherAlgorithm(self.config.shift, self.config.multiplier)
103
- intermediate = affine.encrypt(f"{self.config.prefix}{text}{self.config.postfix}")
104
- main_algorithm = self.config.get_algorithm()
105
- password = main_algorithm.encrypt(intermediate)
93
+ main_algorithm: BaseCipherAlgorithm = self.get_algorithm()
94
+ secondary_algorithm: AffineCipherAlgorithm = AffineCipherAlgorithm(self.shift, self.multiplier)
95
+ intermediate: str = secondary_algorithm.encrypt(f"{self.prefix}{text}{self.postfix}")
96
+ password: str = main_algorithm.encrypt(intermediate)
106
97
  password = self.apply_replacements(password)
107
98
  return ''.join(c.upper() if c in text else c for c in password)
108
-
109
-
110
- @dataclass
111
- class User:
112
- id: UUID = field(default_factory=uuid4)
113
- created_at: datetime = field(default_factory=datetime.now)
114
- updated_at: datetime = field(default_factory=datetime.now)
115
- username: str = field(default_factory=str)
116
- email: str = field(default_factory=str)
117
- password: str = field(default_factory=str)
118
- generator: UUID = field(default_factory=UUID)
119
- passwords: list[UUID] = field(default_factory=list[UUID])
120
-
121
- def add_password(self, password_id: UUID) -> None:
122
- self.passwords.append(password_id)
123
-
124
- def delete_password(self, password_id: UUID) -> None:
125
- self.passwords.remove(password_id)
@@ -0,0 +1,19 @@
1
+ from passphera_core.entities import Password
2
+
3
+
4
+ class PasswordNotFoundException(Exception):
5
+ def __init__(self) -> None:
6
+ super().__init__("Password not found")
7
+
8
+
9
+ class DuplicatePasswordException(Exception):
10
+ def __init__(self, password: Password) -> None:
11
+ self.password = password
12
+ message = self._build_message(password)
13
+ super().__init__(message)
14
+
15
+ @staticmethod
16
+ def _build_message(password: Password) -> str:
17
+ if hasattr(password, 'context') and password.context:
18
+ return f"Password for context '{password.context}' already exists"
19
+ return "Duplicate password detected"
@@ -0,0 +1,44 @@
1
+ from abc import ABC, abstractmethod
2
+ from uuid import UUID
3
+
4
+ from passphera_core.entities import Password, Generator
5
+
6
+
7
+ class PasswordRepository(ABC):
8
+ @abstractmethod
9
+ def save(self, password: Password) -> None:
10
+ pass
11
+
12
+ @abstractmethod
13
+ def get_by_context(self, context: str) -> Password:
14
+ pass
15
+
16
+ @abstractmethod
17
+ def update(self, password: Password) -> None:
18
+ pass
19
+
20
+ @abstractmethod
21
+ def delete(self, password: Password) -> None:
22
+ pass
23
+
24
+ @abstractmethod
25
+ def list(self) -> list[Password]:
26
+ pass
27
+
28
+ @abstractmethod
29
+ def flush(self) -> None:
30
+ pass
31
+
32
+
33
+ class GeneratorRepository(ABC):
34
+ @abstractmethod
35
+ def save(self, generator: Generator) -> None:
36
+ pass
37
+
38
+ @abstractmethod
39
+ def get(self, generator_id: UUID) -> Generator:
40
+ pass
41
+
42
+ @abstractmethod
43
+ def update(self, generator: Generator) -> None:
44
+ pass
@@ -1,11 +1,11 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: passphera-core
3
- Version: 0.9.1
3
+ Version: 0.11.0
4
4
  Summary: The core system of passphera project
5
5
  Home-page: https://github.com/passphera/core
6
6
  Author: Fathi Abdelmalek
7
7
  Author-email: abdelmalek.fathi.2001@gmail.com
8
- Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Development Status :: 4 - Beta
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Programming Language :: Python
@@ -15,6 +15,15 @@ Classifier: Topic :: Security :: Cryptography
15
15
  Requires-Python: >=3
16
16
  Description-Content-Type: text/markdown
17
17
  Requires-Dist: cipherspy
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
18
27
 
19
28
  # passphera-core
20
29
 
@@ -11,5 +11,4 @@ passphera_core.egg-info/requires.txt
11
11
  passphera_core.egg-info/top_level.txt
12
12
  passphera_core/application/__init__.py
13
13
  passphera_core/application/generator.py
14
- passphera_core/application/password.py
15
- passphera_core/application/user.py
14
+ passphera_core/application/password.py
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name='passphera-core',
8
- version='0.9.1',
8
+ version='0.11.0',
9
9
  author='Fathi Abdelmalek',
10
10
  author_email='abdelmalek.fathi.2001@gmail.com',
11
11
  url='https://github.com/passphera/core',
@@ -16,7 +16,7 @@ setup(
16
16
  python_requires='>=3',
17
17
  install_requires=['cipherspy'],
18
18
  classifiers=[
19
- "Development Status :: 3 - Alpha",
19
+ "Development Status :: 4 - Beta",
20
20
  "License :: OSI Approved :: MIT License",
21
21
  "Operating System :: OS Independent",
22
22
  "Programming Language :: Python",
@@ -1,78 +0,0 @@
1
- from datetime import datetime, timezone
2
- from uuid import UUID
3
-
4
- from passphera_core.entities import Generator, GeneratorConfig
5
- from passphera_core.interfaces import GeneratorRepository, GeneratorConfigRepository
6
-
7
-
8
- class GetGeneratorUseCase:
9
- def __init__(self, generator_repository: GeneratorRepository):
10
- self.generator_repository: GeneratorRepository = generator_repository
11
-
12
- def execute(self, user_id: UUID) -> Generator:
13
- return self.generator_repository.find_by_user_id(user_id)
14
-
15
-
16
- class GetGeneratorConfigPropertyUseCase:
17
- def __init__(self, generator_repository: GeneratorRepository, generator_config_repository: GeneratorConfigRepository):
18
- self.generator_repository: GeneratorRepository = generator_repository
19
- self.generator_config_repository: GeneratorConfigRepository = generator_config_repository
20
-
21
- def execute(self, user_id: UUID, field: str) -> str:
22
- generator_entity: Generator = self.generator_repository.find_by_user_id(user_id)
23
- generator_config_entity: GeneratorConfig = self.generator_config_repository.find_by_generator_id(generator_entity.id)
24
- return getattr(generator_config_entity, field)
25
-
26
-
27
- class UpdateGeneratorConfigUseCase:
28
- def __init__(
29
- self,
30
- generator_repository: GeneratorRepository,
31
- generator_config_repository: GeneratorConfigRepository,
32
- ):
33
- self.generator_repository: GeneratorRepository = generator_repository
34
- self.generator_config_repository: GeneratorConfigRepository = generator_config_repository
35
-
36
- def execute(self, user_id: UUID, field: str, value: str) -> None:
37
- generator_entity: Generator = self.generator_repository.find_by_user_id(user_id)
38
- generator_config_entity: GeneratorConfig = self.generator_config_repository.find_by_generator_id(generator_entity.id)
39
- setattr(generator_config_entity, field, value)
40
- if field == 'algorithm':
41
- generator_config_entity.get_algorithm()
42
- generator_config_entity.updated_at = datetime.now(timezone.utc)
43
- self.generator_config_repository.update(generator_config_entity)
44
-
45
-
46
-
47
- class AddCharacterReplacementUseCase:
48
- def __init__(
49
- self,
50
- generator_repository: GeneratorRepository,
51
- generator_config_repository: GeneratorConfigRepository,
52
- ):
53
- self.generator_repository: GeneratorRepository = generator_repository
54
- self.generator_config_repository: GeneratorConfigRepository = generator_config_repository
55
-
56
- def execute(self, user_id: UUID, character: str, replacement: str) -> None:
57
- generator_entity: Generator = self.generator_repository.find_by_user_id(user_id)
58
- generator_config_entity: GeneratorConfig = self.generator_config_repository.find_by_generator_id(generator_entity.id)
59
- generator_config_entity.replace_character(character, replacement)
60
- generator_config_entity.updated_at = datetime.now(timezone.utc)
61
- self.generator_config_repository.update(generator_config_entity)
62
-
63
-
64
- class ResetCharacterReplacementUseCase:
65
- def __init__(
66
- self,
67
- generator_repository: GeneratorRepository,
68
- generator_config_repository: GeneratorConfigRepository,
69
- ):
70
- self.generator_repository: GeneratorRepository = generator_repository
71
- self.generator_config_repository: GeneratorConfigRepository = generator_config_repository
72
-
73
- def execute(self, user_id: UUID, character: str) -> None:
74
- generator_entity: Generator = self.generator_repository.find_by_user_id(user_id)
75
- generator_config_entity: GeneratorConfig = self.generator_config_repository.find_by_generator_id(generator_entity.id)
76
- generator_config_entity.reset_character(character)
77
- generator_config_entity.updated_at = datetime.now(timezone.utc)
78
- self.generator_config_repository.update(generator_config_entity)
@@ -1,118 +0,0 @@
1
- from datetime import datetime, timezone
2
- from uuid import UUID
3
-
4
- from passphera_core.entities import Password, Generator, User
5
- from passphera_core.exceptions import EntityNotFoundException
6
- from passphera_core.interfaces import PasswordRepository, GeneratorRepository, UserRepository
7
-
8
-
9
- class GeneratePasswordUseCase:
10
- def __init__(
11
- self,
12
- password_repository: PasswordRepository,
13
- generator_repository: GeneratorRepository,
14
- user_repository: UserRepository
15
- ):
16
- self.password_repository: PasswordRepository = password_repository
17
- self.generator_repository: GeneratorRepository = generator_repository
18
- self.user_repository: UserRepository = user_repository
19
-
20
- def execute(self, user_id: UUID, context: str, text: str) -> Password:
21
- user_entity: User = self.user_repository.find_by_id(user_id)
22
- generator_entity: Generator = self.generator_repository.find_by_id(user_entity.generator)
23
- password: str = generator_entity.generate_password(text)
24
- password_entity: Password = Password(user_id=user_id, context=context, text=text, password=password)
25
- password_entity.encrypt()
26
- self.password_repository.save(password_entity)
27
- user_entity.add_password(password_entity.id)
28
- self.user_repository.update(user_entity)
29
- return password_entity
30
-
31
-
32
- class GetPasswordByIdUseCase:
33
- def __init__(self, password_repository: PasswordRepository):
34
- self.password_repository: PasswordRepository = password_repository
35
-
36
- def execute(self, password_id: UUID) -> Password:
37
- password_entity: Password = self.password_repository.find_by_id(password_id)
38
- if not password_entity:
39
- raise EntityNotFoundException(password_entity)
40
- return password_entity
41
-
42
-
43
- class GetPasswordByContextUseCase:
44
- def __init__(self, password_repository: PasswordRepository, user_repository: UserRepository):
45
- self.password_repository: PasswordRepository = password_repository
46
- self.user_repository: UserRepository = user_repository
47
-
48
- def execute(self, user_id: UUID, context: str) -> Password:
49
- user_entity: User = self.user_repository.find_by_id(user_id)
50
- for password_id in user_entity.passwords:
51
- password_entity: Password = self.password_repository.find_by_id(password_id)
52
- if password_entity.context == context:
53
- return password_entity
54
- raise EntityNotFoundException(Password())
55
-
56
-
57
- class UpdatePasswordUseCase:
58
- def __init__(
59
- self,
60
- password_repository: PasswordRepository,
61
- generator_repository: GeneratorRepository,
62
- user_repository: UserRepository
63
- ):
64
- self.password_repository: PasswordRepository = password_repository
65
- self.generator_repository: GeneratorRepository = generator_repository
66
- self.user_repository: UserRepository = user_repository
67
-
68
- def execute(self, user_id: UUID, context: str, text: str) -> Password:
69
- user_entity: User = self.user_repository.find_by_id(user_id)
70
- generator_entity: Generator = self.generator_repository.find_by_id(user_entity.generator)
71
- for password_id in user_entity.passwords:
72
- password_entity: Password = self.password_repository.find_by_id(password_id)
73
- if password_entity.context == context:
74
- password_entity.password = generator_entity.generate_password(text)
75
- password_entity.encrypt()
76
- password_entity.updated_at = datetime.now(timezone.utc)
77
- self.password_repository.update(password_entity)
78
- return password_entity
79
- raise EntityNotFoundException(Password())
80
-
81
-
82
- class DeletePasswordUseCase:
83
- def __init__(self, password_repository: PasswordRepository, user_repository: UserRepository):
84
- self.password_repository: PasswordRepository = password_repository
85
- self.user_repository: UserRepository = user_repository
86
-
87
- def execute(self, user_id: UUID, password_id: UUID) -> None:
88
- self.password_repository.delete(password_id)
89
- user_entity: User = self.user_repository.find_by_id(user_id)
90
- user_entity.delete_password(password_id)
91
- self.user_repository.update(user_entity)
92
-
93
-
94
- class GetAllUserPasswordsUseCase:
95
- def __init__(self, password_repository: PasswordRepository, user_repository: UserRepository):
96
- self.password_repository: PasswordRepository = password_repository
97
- self.user_repository: UserRepository = user_repository
98
-
99
- def execute(self, user_id: UUID) -> list[Password]:
100
- user_entity: User = self.user_repository.find_by_id(user_id)
101
- passwords: list[Password] = []
102
- for password_id in user_entity.passwords:
103
- password_entity: Password = self.password_repository.find_by_id(password_id)
104
- passwords.append(password_entity)
105
- return passwords
106
-
107
-
108
- class DeleteAllUserPasswordsUseCase:
109
- def __init__(self, password_repository: PasswordRepository, user_repository: UserRepository):
110
- self.password_repository: PasswordRepository = password_repository
111
- self.user_repository: UserRepository = user_repository
112
-
113
- def execute(self, user_id: UUID) -> None:
114
- user_entity: User = self.user_repository.find_by_id(user_id)
115
- for password_id in user_entity.passwords:
116
- self.password_repository.delete(password_id)
117
- user_entity.delete_password(password_id)
118
- self.user_repository.update(user_entity)
@@ -1,56 +0,0 @@
1
- from uuid import UUID
2
-
3
- from passphera_core.entities import User, Generator
4
- from passphera_core.exceptions import DuplicateEntityException
5
- from passphera_core.interfaces import UserRepository, GeneratorRepository
6
-
7
-
8
- class RegisterUserUseCase:
9
- def __init__(self, user_repository: UserRepository, generator_repository: GeneratorRepository):
10
- self.user_repository: UserRepository = user_repository
11
- self.generator_repository: GeneratorRepository = generator_repository
12
-
13
- def execute(self, user: User) -> User:
14
- if self.user_repository.find_by_email(user.email):
15
- raise DuplicateEntityException(user, 'email')
16
- if self.user_repository.find_by_username(user.username):
17
- raise DuplicateEntityException(user, 'username')
18
- user_entity: User = User(**user.__dict__)
19
- generator_entity: Generator = Generator(user_id=user_entity.id)
20
- self.generator_repository.save(generator_entity)
21
- user_entity.generator = generator_entity.id
22
- self.user_repository.save(user_entity)
23
- return user_entity
24
-
25
-
26
- class GetUserByIdUseCase:
27
- def __init__(self, user_repository: UserRepository):
28
- self.user_repository: UserRepository = user_repository
29
-
30
- def execute(self, id: UUID) -> User:
31
- user = self.user_repository.find_by_id(id)
32
- if not user:
33
- raise ValueError(f'User not found')
34
- return user
35
-
36
-
37
- class GetUserByUsernameUseCase:
38
- def __init__(self, user_repository: UserRepository):
39
- self.user_repository = user_repository
40
-
41
- def execute(self, username: str) -> User:
42
- user = self.user_repository.find_by_username(username)
43
- if not user:
44
- raise ValueError(f'User not found')
45
- return user
46
-
47
-
48
- class GetUserByEmailUseCase:
49
- def __init__(self, user_repository: UserRepository):
50
- self.user_repository = user_repository
51
-
52
- def execute(self, email: str) -> User:
53
- user = self.user_repository.find_by_email(email)
54
- if not user:
55
- raise ValueError(f'User not found')
56
- return user
@@ -1,49 +0,0 @@
1
- from typing import Union, Literal
2
-
3
- from passphera_core.entities import Password, Generator, User
4
-
5
-
6
- class InvalidAlgorithmException(Exception):
7
- def __init__(self, algorithm: str) -> None:
8
- self.algorithm = algorithm
9
- super().__init__(f"Invalid algorithm: '{algorithm}'")
10
-
11
-
12
- class EntityNotFoundException(Exception):
13
- def __init__(self, entity: Union[Password, Generator, User]) -> None:
14
- self.entity = entity
15
- entity_type = entity.__class__.__name__
16
- super().__init__(f"{entity_type} not found")
17
-
18
-
19
- class DuplicateEntityException(Exception):
20
- def __init__(
21
- self,
22
- entity: Union[Password, User],
23
- duplicate_field: Literal['context', 'email', 'username'] = None
24
- ) -> None:
25
- self.entity = entity
26
- self.duplicate_field = duplicate_field
27
- message = self._build_message(entity, duplicate_field)
28
- super().__init__(message)
29
-
30
- def _build_message(self, entity: Union[Password, User], duplicate_field: str | None) -> str:
31
- if isinstance(entity, Password):
32
- return self._build_password_message(entity)
33
- elif isinstance(entity, User):
34
- return self._build_user_message(entity, duplicate_field)
35
- return "Duplicate entity detected"
36
-
37
- @staticmethod
38
- def _build_password_message(password: Password) -> str:
39
- if hasattr(password, 'context') and password.context:
40
- return f"Password for context '{password.context}' already exists"
41
- return "Duplicate password detected"
42
-
43
- @staticmethod
44
- def _build_user_message(user: User, duplicate_field: str) -> str:
45
- if duplicate_field == 'email':
46
- return f"User with email '{user.email}' already exists"
47
- elif duplicate_field == 'username':
48
- return f"User with username '{user.username}' already exists"
49
- return "Duplicate user detected"
@@ -1,92 +0,0 @@
1
- from abc import ABC, abstractmethod
2
- from uuid import UUID
3
-
4
- from passphera_core.entities import Password, Generator, GeneratorConfig, User
5
-
6
-
7
- class PasswordRepository(ABC):
8
- @abstractmethod
9
- def save(self, password: Password) -> None:
10
- pass
11
-
12
- @abstractmethod
13
- def update(self, password: Password) -> None:
14
- pass
15
-
16
- @abstractmethod
17
- def delete(self, password_id: UUID) -> None:
18
- pass
19
-
20
- @abstractmethod
21
- def find_by_id(self, password_id: UUID) -> Password:
22
- pass
23
-
24
-
25
- class GeneratorRepository(ABC):
26
- @abstractmethod
27
- def save(self, generator: Generator) -> None:
28
- pass
29
-
30
- @abstractmethod
31
- def update(self, generator: Generator) -> None:
32
- pass
33
-
34
- @abstractmethod
35
- def delete(self, generator_id: UUID) -> None:
36
- pass
37
-
38
- @abstractmethod
39
- def find_by_id(self, generator_id: UUID) -> Generator:
40
- pass
41
-
42
- @abstractmethod
43
- def find_by_user_id(self, user_id: UUID) -> Generator:
44
- pass
45
-
46
-
47
- class GeneratorConfigRepository(ABC):
48
- @abstractmethod
49
- def save(self, generator_config: GeneratorConfig) -> None:
50
- pass
51
-
52
- @abstractmethod
53
- def update(self, generator_config: GeneratorConfig) -> None:
54
- pass
55
-
56
- @abstractmethod
57
- def delete(self, generator_config_id: UUID) -> None:
58
- pass
59
-
60
- @abstractmethod
61
- def find_by_id(self, generator_config_id: UUID) -> GeneratorConfig:
62
- pass
63
-
64
- @abstractmethod
65
- def find_by_generator_id(self, generator_id: UUID) -> GeneratorConfig:
66
- pass
67
-
68
-
69
- class UserRepository(ABC):
70
- @abstractmethod
71
- def save(self, user: User) -> None:
72
- pass
73
-
74
- @abstractmethod
75
- def update(self, user: User) -> None:
76
- pass
77
-
78
- @abstractmethod
79
- def delete(self, user_id: UUID) -> None:
80
- pass
81
-
82
- @abstractmethod
83
- def find_by_id(self, user_id: UUID) -> User:
84
- pass
85
-
86
- @abstractmethod
87
- def find_by_username(self, username: str) -> User:
88
- pass
89
-
90
- @abstractmethod
91
- def find_by_email(self, email: str) -> User:
92
- pass