From a43d78ad5eb696e0d7c88be31a78815b6a939467 Mon Sep 17 00:00:00 2001
From: Kekoa Kaaikala <kekoa.kaaikala@gmail.com>
Date: Fri, 31 Mar 2023 19:49:08 +0000
Subject: [PATCH 01/10] Island: Add a class to generate OTPs

---
 .../authentication_service/otp/__init__.py    |  1 +
 .../otp/otp_generator.py                      | 32 +++++++++++++++++++
 .../otp/test_otp_generator.py                 | 25 +++++++++++++++
 3 files changed, 58 insertions(+)
 create mode 100644 monkey/monkey_island/cc/services/authentication_service/otp/__init__.py
 create mode 100644 monkey/monkey_island/cc/services/authentication_service/otp/otp_generator.py
 create mode 100644 monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/otp/test_otp_generator.py

diff --git a/monkey/monkey_island/cc/services/authentication_service/otp/__init__.py b/monkey/monkey_island/cc/services/authentication_service/otp/__init__.py
new file mode 100644
index 00000000000..4824fb6d111
--- /dev/null
+++ b/monkey/monkey_island/cc/services/authentication_service/otp/__init__.py
@@ -0,0 +1 @@
+from .otp_generator import OTPGenerator, OTP_EXPIRATION_TIME
diff --git a/monkey/monkey_island/cc/services/authentication_service/otp/otp_generator.py b/monkey/monkey_island/cc/services/authentication_service/otp/otp_generator.py
new file mode 100644
index 00000000000..01e35d8ac15
--- /dev/null
+++ b/monkey/monkey_island/cc/services/authentication_service/otp/otp_generator.py
@@ -0,0 +1,32 @@
+import string
+import time
+
+from common.utils.code_utils import secure_generate_random_string
+from monkey_island.cc.services.authentication_service.i_otp_repository import IOTPRepository
+
+OTP_EXPIRATION_TIME = 2 * 60
+
+
+class OTPGenerator:
+    """
+    Generates OTPs
+    """
+
+    def __init__(self, otp_repository: IOTPRepository):
+        self._otp_repository = otp_repository
+
+    def generate_otp(self) -> str:
+        """
+        Generates a new OTP
+
+        The generated OTP is saved to the `IOTPRepository`
+        :return: The generated OTP
+        """
+        otp_value = self._generate_otp()
+        expiration_time = time.monotonic() + OTP_EXPIRATION_TIME
+        self._otp_repository.insert_otp(otp_value, expiration_time)
+
+        return otp_value
+
+    def _generate_otp(self) -> str:
+        return secure_generate_random_string(32, string.ascii_letters + string.digits + "._-")
diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/otp/test_otp_generator.py b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/otp/test_otp_generator.py
new file mode 100644
index 00000000000..f731681c9be
--- /dev/null
+++ b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/otp/test_otp_generator.py
@@ -0,0 +1,25 @@
+import time
+from unittest.mock import MagicMock
+
+from monkey_island.cc.services.authentication_service.i_otp_repository import IOTPRepository
+from monkey_island.cc.services.authentication_service.otp import OTP_EXPIRATION_TIME, OTPGenerator
+
+
+def test_otp_generator__saves_otp():
+    mock_otp_repository = MagicMock(spec=IOTPRepository)
+
+    otp_generator = OTPGenerator(mock_otp_repository)
+    otp = otp_generator.generate_otp()
+
+    assert mock_otp_repository.insert_otp.called_once_with(otp)
+
+
+def test_otp_generator__uses_expected_expiration_time(freezer):
+    mock_otp_repository = MagicMock(spec=IOTPRepository)
+    otp_generator = OTPGenerator(mock_otp_repository)
+
+    otp_generator.generate_otp()
+
+    expiration_time = mock_otp_repository.insert_otp.call_args[0][1]
+    expected_expiration_time = time.monotonic() + OTP_EXPIRATION_TIME
+    assert expiration_time == expected_expiration_time

From 708b18e764d4e6f04e944d9e57555309f4f937d6 Mon Sep 17 00:00:00 2001
From: Kekoa Kaaikala <kekoa.kaaikala@gmail.com>
Date: Fri, 31 Mar 2023 19:51:57 +0000
Subject: [PATCH 02/10] Project: Add vulture entry for OTPGenerator

---
 vulture_allowlist.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/vulture_allowlist.py b/vulture_allowlist.py
index ada5d09ec1e..53c31131e31 100644
--- a/vulture_allowlist.py
+++ b/vulture_allowlist.py
@@ -24,6 +24,7 @@
     MongoAgentEventRepository,
     MongoOTPRepository,
 )
+from monkey_island.cc.services.authentication_service.otp import OTPGenerator
 from monkey_island.cc.services.authentication_service.token import TokenValidator
 from monkey_island.cc.services.authentication_service.user import User
 from monkey_island.cc.services.reporting.exploitations.monkey_exploitation import MonkeyExploitation
@@ -160,3 +161,4 @@
 IOTPRepository.get_expiration
 IOTPRepository.reset
 MongoOTPRepository
+OTPGenerator.generate_otp

From d99e5955f1672fb4c8de11f7061b24572017a87e Mon Sep 17 00:00:00 2001
From: Kekoa Kaaikala <kekoa.kaaikala@gmail.com>
Date: Mon, 3 Apr 2023 20:18:36 +0000
Subject: [PATCH 03/10] Island: Move OTPGenerator into authentication_service

---
 .../cc/services/authentication_service/otp/__init__.py       | 1 -
 .../authentication_service/{otp => }/otp_generator.py        | 0
 .../authentication_service/{otp => }/test_otp_generator.py   | 5 ++++-
 3 files changed, 4 insertions(+), 2 deletions(-)
 delete mode 100644 monkey/monkey_island/cc/services/authentication_service/otp/__init__.py
 rename monkey/monkey_island/cc/services/authentication_service/{otp => }/otp_generator.py (100%)
 rename monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/{otp => }/test_otp_generator.py (86%)

diff --git a/monkey/monkey_island/cc/services/authentication_service/otp/__init__.py b/monkey/monkey_island/cc/services/authentication_service/otp/__init__.py
deleted file mode 100644
index 4824fb6d111..00000000000
--- a/monkey/monkey_island/cc/services/authentication_service/otp/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .otp_generator import OTPGenerator, OTP_EXPIRATION_TIME
diff --git a/monkey/monkey_island/cc/services/authentication_service/otp/otp_generator.py b/monkey/monkey_island/cc/services/authentication_service/otp_generator.py
similarity index 100%
rename from monkey/monkey_island/cc/services/authentication_service/otp/otp_generator.py
rename to monkey/monkey_island/cc/services/authentication_service/otp_generator.py
diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/otp/test_otp_generator.py b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py
similarity index 86%
rename from monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/otp/test_otp_generator.py
rename to monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py
index f731681c9be..00bfebe627c 100644
--- a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/otp/test_otp_generator.py
+++ b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py
@@ -2,7 +2,10 @@
 from unittest.mock import MagicMock
 
 from monkey_island.cc.services.authentication_service.i_otp_repository import IOTPRepository
-from monkey_island.cc.services.authentication_service.otp import OTP_EXPIRATION_TIME, OTPGenerator
+from monkey_island.cc.services.authentication_service.otp_generator import (
+    OTP_EXPIRATION_TIME,
+    OTPGenerator,
+)
 
 
 def test_otp_generator__saves_otp():

From 98916c63fdc385ee1bcac83bba0b33058dcba4f0 Mon Sep 17 00:00:00 2001
From: Kekoa Kaaikala <kekoa.kaaikala@gmail.com>
Date: Mon, 3 Apr 2023 20:39:50 +0000
Subject: [PATCH 04/10] Island: Move generate_otp to AuthenticationFacade

---
 .../authentication_facade.py                  | 24 ++++++++++++++++
 .../authentication_service/otp_generator.py   | 24 +++-------------
 .../test_authentication_service.py            | 28 +++++++++++++++++++
 .../test_otp_generator.py                     | 27 +++++-------------
 4 files changed, 63 insertions(+), 40 deletions(-)

diff --git a/monkey/monkey_island/cc/services/authentication_service/authentication_facade.py b/monkey/monkey_island/cc/services/authentication_service/authentication_facade.py
index 78abc37d3f7..a3f453b103a 100644
--- a/monkey/monkey_island/cc/services/authentication_service/authentication_facade.py
+++ b/monkey/monkey_island/cc/services/authentication_service/authentication_facade.py
@@ -1,17 +1,23 @@
+import string
+import time
 from typing import Tuple
 
 from flask_security import UserDatastore
 
+from common.utils.code_utils import secure_generate_random_string
 from monkey_island.cc.event_queue import IIslandEventQueue, IslandEventTopic
 from monkey_island.cc.models import IslandMode
 from monkey_island.cc.server_utils.encryption import ILockableEncryptor
 from monkey_island.cc.services.authentication_service.token_generator import TokenGenerator
 
 from . import AccountRole
+from .i_otp_repository import IOTPRepository
 from .token_parser import ParsedToken, TokenParser
 from .types import Token
 from .user import User
 
+OTP_EXPIRATION_TIME = 2 * 60  # 2 minutes
+
 
 class AuthenticationFacade:
     """
@@ -25,12 +31,14 @@ def __init__(
         user_datastore: UserDatastore,
         token_generator: TokenGenerator,
         token_parser: TokenParser,
+        otp_repository: IOTPRepository,
     ):
         self._repository_encryptor = repository_encryptor
         self._island_event_queue = island_event_queue
         self._datastore = user_datastore
         self._token_generator = token_generator
         self._token_parser = token_parser
+        self._otp_repository = otp_repository
 
     def needs_registration(self) -> bool:
         """
@@ -71,6 +79,22 @@ def _get_refresh_token_owner(self, refresh_token: ParsedToken) -> User:
             raise Exception("Invalid refresh token")
         return user
 
+    def generate_otp(self) -> str:
+        """
+        Generates a new OTP
+
+        The generated OTP is saved to the `IOTPRepository`
+        :return: The generated OTP
+        """
+        otp_value = self._generate_otp()
+        expiration_time = time.monotonic() + OTP_EXPIRATION_TIME
+        self._otp_repository.insert_otp(otp_value, expiration_time)
+
+        return otp_value
+
+    def _generate_otp(self) -> str:
+        return secure_generate_random_string(32, string.ascii_letters + string.digits + "._-")
+
     def generate_refresh_token(self, user: User) -> Token:
         """
         Generates a refresh token for a specific user
diff --git a/monkey/monkey_island/cc/services/authentication_service/otp_generator.py b/monkey/monkey_island/cc/services/authentication_service/otp_generator.py
index 01e35d8ac15..64cf4b4fa5a 100644
--- a/monkey/monkey_island/cc/services/authentication_service/otp_generator.py
+++ b/monkey/monkey_island/cc/services/authentication_service/otp_generator.py
@@ -1,10 +1,4 @@
-import string
-import time
-
-from common.utils.code_utils import secure_generate_random_string
-from monkey_island.cc.services.authentication_service.i_otp_repository import IOTPRepository
-
-OTP_EXPIRATION_TIME = 2 * 60
+from .authentication_facade import AuthenticationFacade
 
 
 class OTPGenerator:
@@ -12,21 +6,11 @@ class OTPGenerator:
     Generates OTPs
     """
 
-    def __init__(self, otp_repository: IOTPRepository):
-        self._otp_repository = otp_repository
+    def __init__(self, authentication_facade: AuthenticationFacade):
+        self._authentication_facade = authentication_facade
 
     def generate_otp(self) -> str:
         """
         Generates a new OTP
-
-        The generated OTP is saved to the `IOTPRepository`
-        :return: The generated OTP
         """
-        otp_value = self._generate_otp()
-        expiration_time = time.monotonic() + OTP_EXPIRATION_TIME
-        self._otp_repository.insert_otp(otp_value, expiration_time)
-
-        return otp_value
-
-    def _generate_otp(self) -> str:
-        return secure_generate_random_string(32, string.ascii_letters + string.digits + "._-")
+        return self._authentication_facade.generate_otp()
diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_service.py b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_service.py
index d70d901f78d..5a25d706d10 100644
--- a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_service.py
+++ b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_service.py
@@ -1,3 +1,4 @@
+import time
 from unittest.mock import MagicMock, call
 
 import pytest
@@ -8,8 +9,10 @@
 from monkey_island.cc.models import IslandMode
 from monkey_island.cc.server_utils.encryption import ILockableEncryptor
 from monkey_island.cc.services.authentication_service.authentication_facade import (
+    OTP_EXPIRATION_TIME,
     AuthenticationFacade,
 )
+from monkey_island.cc.services.authentication_service.i_otp_repository import IOTPRepository
 from monkey_island.cc.services.authentication_service.setup import setup_authentication
 from monkey_island.cc.services.authentication_service.token_generator import TokenGenerator
 from monkey_island.cc.services.authentication_service.token_parser import (
@@ -58,6 +61,11 @@ def mock_token_parser() -> TokenParser:
     return MagicMock(spec=TokenParser)
 
 
+@pytest.fixture
+def mock_otp_repository() -> IOTPRepository:
+    return MagicMock(spec=IOTPRepository)
+
+
 @pytest.fixture
 def authentication_facade(
     mock_flask_app,
@@ -66,6 +74,7 @@ def authentication_facade(
     mock_user_datastore: UserDatastore,
     mock_token_generator: TokenGenerator,
     mock_token_parser: TokenParser,
+    mock_otp_repository: IOTPRepository,
 ) -> AuthenticationFacade:
     return AuthenticationFacade(
         mock_repository_encryptor,
@@ -73,6 +82,7 @@ def authentication_facade(
         mock_user_datastore,
         mock_token_generator,
         mock_token_parser,
+        mock_otp_repository,
     )
 
 
@@ -178,6 +188,24 @@ def test_revoke_all_tokens_for_all_users(
     [mock_user_datastore.set_uniquifier.assert_any_call(user) for user in USERS]
 
 
+def test_generate_otp__saves_otp(
+    authentication_facade: AuthenticationFacade, mock_otp_repository: IOTPRepository
+):
+    otp = authentication_facade.generate_otp()
+
+    assert mock_otp_repository.insert_otp.called_once_with(otp)
+
+
+def test_generate_otp__uses_expected_expiration_time(
+    freezer, authentication_facade: AuthenticationFacade, mock_otp_repository: IOTPRepository
+):
+    authentication_facade.generate_otp()
+
+    expiration_time = mock_otp_repository.insert_otp.call_args[0][1]
+    expected_expiration_time = time.monotonic() + OTP_EXPIRATION_TIME
+    assert expiration_time == expected_expiration_time
+
+
 def test_setup_authentication__revokes_tokens(
     mock_island_event_queue: IIslandEventQueue,
     mock_repository_encryptor: ILockableEncryptor,
diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py
index 00bfebe627c..ec7bd648b3c 100644
--- a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py
+++ b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py
@@ -1,28 +1,15 @@
-import time
 from unittest.mock import MagicMock
 
-from monkey_island.cc.services.authentication_service.i_otp_repository import IOTPRepository
-from monkey_island.cc.services.authentication_service.otp_generator import (
-    OTP_EXPIRATION_TIME,
-    OTPGenerator,
+from monkey_island.cc.services.authentication_service.authentication_facade import (
+    AuthenticationFacade,
 )
+from monkey_island.cc.services.authentication_service.otp_generator import OTPGenerator
 
 
-def test_otp_generator__saves_otp():
-    mock_otp_repository = MagicMock(spec=IOTPRepository)
-
-    otp_generator = OTPGenerator(mock_otp_repository)
-    otp = otp_generator.generate_otp()
-
-    assert mock_otp_repository.insert_otp.called_once_with(otp)
-
-
-def test_otp_generator__uses_expected_expiration_time(freezer):
-    mock_otp_repository = MagicMock(spec=IOTPRepository)
-    otp_generator = OTPGenerator(mock_otp_repository)
+def test_otp_generator__generates_otp():
+    mock_authentication_facade = MagicMock(spec=AuthenticationFacade)
 
+    otp_generator = OTPGenerator(mock_authentication_facade)
     otp_generator.generate_otp()
 
-    expiration_time = mock_otp_repository.insert_otp.call_args[0][1]
-    expected_expiration_time = time.monotonic() + OTP_EXPIRATION_TIME
-    assert expiration_time == expected_expiration_time
+    assert mock_authentication_facade.generate_otp.called_once

From 92be83ede858b55694a3c27a6b2e5805f6ba96e0 Mon Sep 17 00:00:00 2001
From: Ilija Lazoroski <ilija.la@live.com>
Date: Tue, 4 Apr 2023 12:19:52 +0200
Subject: [PATCH 05/10] Island: Add IOTPGenerator to authentication serivce

---
 .../authentication_service/i_otp_generator.py       | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 monkey/monkey_island/cc/services/authentication_service/i_otp_generator.py

diff --git a/monkey/monkey_island/cc/services/authentication_service/i_otp_generator.py b/monkey/monkey_island/cc/services/authentication_service/i_otp_generator.py
new file mode 100644
index 00000000000..caa1b93ade9
--- /dev/null
+++ b/monkey/monkey_island/cc/services/authentication_service/i_otp_generator.py
@@ -0,0 +1,13 @@
+from abc import ABC, abstractmethod
+
+from .types import OTP
+
+
+class IOTPGenerator(ABC):
+    """Generator for OTPs"""
+
+    @abstractmethod
+    def generate_otp(self) -> OTP:
+        """
+        Generates a new OTP
+        """

From aba7bbe900156f94f7f68ccd234c187e6f4fa4c4 Mon Sep 17 00:00:00 2001
From: Ilija Lazoroski <ilija.la@live.com>
Date: Tue, 4 Apr 2023 12:24:21 +0200
Subject: [PATCH 06/10] Island: Implement IOTPGenerator under concrete
 AuthenticationOTPGenerator

---
 .../{otp_generator.py => authentication_otp_generator.py}   | 6 ++++--
 ...tp_generator.py => test_authentication_otp_generator.py} | 6 +++---
 2 files changed, 7 insertions(+), 5 deletions(-)
 rename monkey/monkey_island/cc/services/authentication_service/{otp_generator.py => authentication_otp_generator.py} (69%)
 rename monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/{test_otp_generator.py => test_authentication_otp_generator.py} (59%)

diff --git a/monkey/monkey_island/cc/services/authentication_service/otp_generator.py b/monkey/monkey_island/cc/services/authentication_service/authentication_otp_generator.py
similarity index 69%
rename from monkey/monkey_island/cc/services/authentication_service/otp_generator.py
rename to monkey/monkey_island/cc/services/authentication_service/authentication_otp_generator.py
index 64cf4b4fa5a..df9eff14a3b 100644
--- a/monkey/monkey_island/cc/services/authentication_service/otp_generator.py
+++ b/monkey/monkey_island/cc/services/authentication_service/authentication_otp_generator.py
@@ -1,7 +1,9 @@
 from .authentication_facade import AuthenticationFacade
+from .i_otp_generator import IOTPGenerator
+from .types import OTP
 
 
-class OTPGenerator:
+class AuthenticationOTPGenerator(IOTPGenerator):
     """
     Generates OTPs
     """
@@ -9,7 +11,7 @@ class OTPGenerator:
     def __init__(self, authentication_facade: AuthenticationFacade):
         self._authentication_facade = authentication_facade
 
-    def generate_otp(self) -> str:
+    def generate_otp(self) -> OTP:
         """
         Generates a new OTP
         """
diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_otp_generator.py
similarity index 59%
rename from monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py
rename to monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_otp_generator.py
index ec7bd648b3c..4f8cfdc1d31 100644
--- a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_otp_generator.py
+++ b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_otp_generator.py
@@ -1,15 +1,15 @@
 from unittest.mock import MagicMock
 
+from monkey_island.cc.services.authentication_service import AuthenticationOTPGenerator
 from monkey_island.cc.services.authentication_service.authentication_facade import (
     AuthenticationFacade,
 )
-from monkey_island.cc.services.authentication_service.otp_generator import OTPGenerator
 
 
-def test_otp_generator__generates_otp():
+def test_authentication_otp_generator__generates_otp():
     mock_authentication_facade = MagicMock(spec=AuthenticationFacade)
 
-    otp_generator = OTPGenerator(mock_authentication_facade)
+    otp_generator = AuthenticationOTPGenerator(mock_authentication_facade)
     otp_generator.generate_otp()
 
     assert mock_authentication_facade.generate_otp.called_once

From c731db307160960943d363e0c40eceab206c921d Mon Sep 17 00:00:00 2001
From: Ilija Lazoroski <ilija.la@live.com>
Date: Tue, 4 Apr 2023 12:38:47 +0200
Subject: [PATCH 07/10] Island: Export IOTPGenerator and
 AuthenticationOTPGenerator from __init__

---
 .../cc/services/authentication_service/__init__.py             | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/monkey/monkey_island/cc/services/authentication_service/__init__.py b/monkey/monkey_island/cc/services/authentication_service/__init__.py
index 586049312fd..f654b6db01c 100644
--- a/monkey/monkey_island/cc/services/authentication_service/__init__.py
+++ b/monkey/monkey_island/cc/services/authentication_service/__init__.py
@@ -2,3 +2,6 @@
 from .flask_resources import register_resources
 
 from .setup import setup_authentication
+
+from .i_otp_generator import IOTPGenerator
+from .authentication_otp_generator import AuthenticationOTPGenerator

From 711153cbfa3589f288bbf03549b8ccffc0889981 Mon Sep 17 00:00:00 2001
From: Ilija Lazoroski <ilija.la@live.com>
Date: Tue, 4 Apr 2023 12:39:23 +0200
Subject: [PATCH 08/10] Island: Merge AuthenticationFacade._generate_otp into
 the public method

---
 .../authentication_facade.py                       | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/monkey/monkey_island/cc/services/authentication_service/authentication_facade.py b/monkey/monkey_island/cc/services/authentication_service/authentication_facade.py
index a3f453b103a..8164ba09534 100644
--- a/monkey/monkey_island/cc/services/authentication_service/authentication_facade.py
+++ b/monkey/monkey_island/cc/services/authentication_service/authentication_facade.py
@@ -13,7 +13,7 @@
 from . import AccountRole
 from .i_otp_repository import IOTPRepository
 from .token_parser import ParsedToken, TokenParser
-from .types import Token
+from .types import OTP, Token
 from .user import User
 
 OTP_EXPIRATION_TIME = 2 * 60  # 2 minutes
@@ -79,21 +79,17 @@ def _get_refresh_token_owner(self, refresh_token: ParsedToken) -> User:
             raise Exception("Invalid refresh token")
         return user
 
-    def generate_otp(self) -> str:
+    def generate_otp(self) -> OTP:
         """
         Generates a new OTP
 
         The generated OTP is saved to the `IOTPRepository`
-        :return: The generated OTP
         """
-        otp_value = self._generate_otp()
+        otp = secure_generate_random_string(32, string.ascii_letters + string.digits + "._-")
         expiration_time = time.monotonic() + OTP_EXPIRATION_TIME
-        self._otp_repository.insert_otp(otp_value, expiration_time)
+        self._otp_repository.insert_otp(otp, expiration_time)
 
-        return otp_value
-
-    def _generate_otp(self) -> str:
-        return secure_generate_random_string(32, string.ascii_letters + string.digits + "._-")
+        return otp
 
     def generate_refresh_token(self, user: User) -> Token:
         """

From 2abdf2420b323cf3aba42f3f35b7efa8e97baa6f Mon Sep 17 00:00:00 2001
From: Ilija Lazoroski <ilija.la@live.com>
Date: Tue, 4 Apr 2023 12:59:00 +0200
Subject: [PATCH 09/10] Project: Add AuthenticationOTPGenerator to
 vulture_allowlist

---
 vulture_allowlist.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/vulture_allowlist.py b/vulture_allowlist.py
index 53c31131e31..a76545af8fd 100644
--- a/vulture_allowlist.py
+++ b/vulture_allowlist.py
@@ -24,7 +24,7 @@
     MongoAgentEventRepository,
     MongoOTPRepository,
 )
-from monkey_island.cc.services.authentication_service.otp import OTPGenerator
+from monkey_island.cc.services.authentication_service import AuthenticationOTPGenerator
 from monkey_island.cc.services.authentication_service.token import TokenValidator
 from monkey_island.cc.services.authentication_service.user import User
 from monkey_island.cc.services.reporting.exploitations.monkey_exploitation import MonkeyExploitation
@@ -161,4 +161,4 @@
 IOTPRepository.get_expiration
 IOTPRepository.reset
 MongoOTPRepository
-OTPGenerator.generate_otp
+AuthenticationOTPGenerator.generate_otp

From 445e3dcb93e49bc31b8071b176c5aa3000b90fe3 Mon Sep 17 00:00:00 2001
From: Ilija Lazoroski <ilija.la@live.com>
Date: Tue, 4 Apr 2023 13:19:13 +0200
Subject: [PATCH 10/10] Island: Rename AuthenticationOTPGenerator to
 AuthenticationServiceOTPGenerator

---
 .../cc/services/authentication_service/__init__.py          | 2 +-
 ...generator.py => authentication_service_otp_generator.py} | 2 +-
 ...ator.py => test_authentication_service_otp_generator.py} | 6 +++---
 vulture_allowlist.py                                        | 4 ++--
 4 files changed, 7 insertions(+), 7 deletions(-)
 rename monkey/monkey_island/cc/services/authentication_service/{authentication_otp_generator.py => authentication_service_otp_generator.py} (88%)
 rename monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/{test_authentication_otp_generator.py => test_authentication_service_otp_generator.py} (68%)

diff --git a/monkey/monkey_island/cc/services/authentication_service/__init__.py b/monkey/monkey_island/cc/services/authentication_service/__init__.py
index f654b6db01c..e43a94bf8dc 100644
--- a/monkey/monkey_island/cc/services/authentication_service/__init__.py
+++ b/monkey/monkey_island/cc/services/authentication_service/__init__.py
@@ -4,4 +4,4 @@
 from .setup import setup_authentication
 
 from .i_otp_generator import IOTPGenerator
-from .authentication_otp_generator import AuthenticationOTPGenerator
+from .authentication_service_otp_generator import AuthenticationServiceOTPGenerator
diff --git a/monkey/monkey_island/cc/services/authentication_service/authentication_otp_generator.py b/monkey/monkey_island/cc/services/authentication_service/authentication_service_otp_generator.py
similarity index 88%
rename from monkey/monkey_island/cc/services/authentication_service/authentication_otp_generator.py
rename to monkey/monkey_island/cc/services/authentication_service/authentication_service_otp_generator.py
index df9eff14a3b..438c3f2e187 100644
--- a/monkey/monkey_island/cc/services/authentication_service/authentication_otp_generator.py
+++ b/monkey/monkey_island/cc/services/authentication_service/authentication_service_otp_generator.py
@@ -3,7 +3,7 @@
 from .types import OTP
 
 
-class AuthenticationOTPGenerator(IOTPGenerator):
+class AuthenticationServiceOTPGenerator(IOTPGenerator):
     """
     Generates OTPs
     """
diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_otp_generator.py b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_service_otp_generator.py
similarity index 68%
rename from monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_otp_generator.py
rename to monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_service_otp_generator.py
index 4f8cfdc1d31..48d2117bef3 100644
--- a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_otp_generator.py
+++ b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/test_authentication_service_otp_generator.py
@@ -1,15 +1,15 @@
 from unittest.mock import MagicMock
 
-from monkey_island.cc.services.authentication_service import AuthenticationOTPGenerator
+from monkey_island.cc.services.authentication_service import AuthenticationServiceOTPGenerator
 from monkey_island.cc.services.authentication_service.authentication_facade import (
     AuthenticationFacade,
 )
 
 
-def test_authentication_otp_generator__generates_otp():
+def test_authentication_service_otp_generator__generates_otp():
     mock_authentication_facade = MagicMock(spec=AuthenticationFacade)
 
-    otp_generator = AuthenticationOTPGenerator(mock_authentication_facade)
+    otp_generator = AuthenticationServiceOTPGenerator(mock_authentication_facade)
     otp_generator.generate_otp()
 
     assert mock_authentication_facade.generate_otp.called_once
diff --git a/vulture_allowlist.py b/vulture_allowlist.py
index a76545af8fd..12eaa59d463 100644
--- a/vulture_allowlist.py
+++ b/vulture_allowlist.py
@@ -24,7 +24,7 @@
     MongoAgentEventRepository,
     MongoOTPRepository,
 )
-from monkey_island.cc.services.authentication_service import AuthenticationOTPGenerator
+from monkey_island.cc.services.authentication_service import AuthenticationServiceOTPGenerator
 from monkey_island.cc.services.authentication_service.token import TokenValidator
 from monkey_island.cc.services.authentication_service.user import User
 from monkey_island.cc.services.reporting.exploitations.monkey_exploitation import MonkeyExploitation
@@ -161,4 +161,4 @@
 IOTPRepository.get_expiration
 IOTPRepository.reset
 MongoOTPRepository
-AuthenticationOTPGenerator.generate_otp
+AuthenticationServiceOTPGenerator.generate_otp