diff --git a/resources/views/admin/events/index.php b/resources/views/admin/events/index.php
index d4ad667..0cde247 100644
--- a/resources/views/admin/events/index.php
+++ b/resources/views/admin/events/index.php
@@ -4,16 +4,16 @@
Create New Event
-
+
- = htmlspecialchars($success) ?>
+ = htmlspecialchars($Success) ?>
-
+
- = htmlspecialchars($error) ?>
+ = htmlspecialchars($Error) ?>
diff --git a/resources/views/auth/login/login.php b/resources/views/auth/login/login.php
index add6fd9..c67aeeb 100644
--- a/resources/views/auth/login/login.php
+++ b/resources/views/auth/login/login.php
@@ -3,13 +3,13 @@
-
+
diff --git a/src/Cms/Controllers/Admin/EventCategories.php b/src/Cms/Controllers/Admin/EventCategories.php
index 78507f5..d7086d2 100644
--- a/src/Cms/Controllers/Admin/EventCategories.php
+++ b/src/Cms/Controllers/Admin/EventCategories.php
@@ -72,8 +72,8 @@ public function index( Request $request ): string
->withCsrfToken()
->with([
'categories' => $this->_repository->all(),
- FlashMessageType::SUCCESS->value => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
- FlashMessageType::ERROR->value => $sessionManager->getFlash( FlashMessageType::ERROR->value )
+ FlashMessageType::SUCCESS->viewKey() => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
+ FlashMessageType::ERROR->viewKey() => $sessionManager->getFlash( FlashMessageType::ERROR->value )
])
->render( 'index', 'admin' );
}
diff --git a/src/Cms/Controllers/Admin/Events.php b/src/Cms/Controllers/Admin/Events.php
index 5fdb93d..e6234c8 100644
--- a/src/Cms/Controllers/Admin/Events.php
+++ b/src/Cms/Controllers/Admin/Events.php
@@ -88,8 +88,8 @@ public function index( Request $request ): string
->withCsrfToken()
->with([
'events' => $events,
- FlashMessageType::SUCCESS->value => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
- FlashMessageType::ERROR->value => $sessionManager->getFlash( FlashMessageType::ERROR->value )
+ FlashMessageType::SUCCESS->viewKey() => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
+ FlashMessageType::ERROR->viewKey() => $sessionManager->getFlash( FlashMessageType::ERROR->value )
])
->render( 'index', 'admin' );
}
diff --git a/src/Cms/Controllers/Admin/Media.php b/src/Cms/Controllers/Admin/Media.php
index c1f241c..b708d9d 100644
--- a/src/Cms/Controllers/Admin/Media.php
+++ b/src/Cms/Controllers/Admin/Media.php
@@ -114,8 +114,8 @@ public function index( Request $request ): string
'resources' => $result['resources'],
'nextCursor' => $result['next_cursor'],
'totalCount' => $result['total_count'],
- FlashMessageType::SUCCESS->value => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
- FlashMessageType::ERROR->value => $sessionManager->getFlash( FlashMessageType::ERROR->value )
+ FlashMessageType::SUCCESS->viewKey() => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
+ FlashMessageType::ERROR->viewKey() => $sessionManager->getFlash( FlashMessageType::ERROR->value )
])
->render( 'index', 'admin' );
}
@@ -135,8 +135,8 @@ public function index( Request $request ): string
'resources' => [],
'nextCursor' => null,
'totalCount' => 0,
- FlashMessageType::SUCCESS->value => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
- FlashMessageType::ERROR->value => 'Failed to load media library. Please try again.'
+ FlashMessageType::SUCCESS->viewKey() => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
+ FlashMessageType::ERROR->viewKey() => 'Failed to load media library. Please try again.'
])
->render( 'index', 'admin' );
}
diff --git a/src/Cms/Controllers/Admin/Pages.php b/src/Cms/Controllers/Admin/Pages.php
index fb08a76..16b2f2a 100644
--- a/src/Cms/Controllers/Admin/Pages.php
+++ b/src/Cms/Controllers/Admin/Pages.php
@@ -88,8 +88,8 @@ public function index( Request $request ): string
->withCsrfToken()
->with([
'pages' => $pages,
- FlashMessageType::SUCCESS->value => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
- FlashMessageType::ERROR->value => $sessionManager->getFlash( FlashMessageType::ERROR->value )
+ FlashMessageType::SUCCESS->viewKey() => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
+ FlashMessageType::ERROR->viewKey() => $sessionManager->getFlash( FlashMessageType::ERROR->value )
])
->render( 'index', 'admin' );
}
diff --git a/src/Cms/Controllers/Admin/Posts.php b/src/Cms/Controllers/Admin/Posts.php
index c5c44cf..c3256c0 100644
--- a/src/Cms/Controllers/Admin/Posts.php
+++ b/src/Cms/Controllers/Admin/Posts.php
@@ -102,8 +102,8 @@ public function index( Request $request ): string
->withCsrfToken()
->with([
'posts' => $posts,
- FlashMessageType::SUCCESS->value => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
- FlashMessageType::ERROR->value => $sessionManager->getFlash( FlashMessageType::ERROR->value )
+ FlashMessageType::SUCCESS->viewKey() => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
+ FlashMessageType::ERROR->viewKey() => $sessionManager->getFlash( FlashMessageType::ERROR->value )
])
->render( 'index', 'admin' );
}
diff --git a/src/Cms/Controllers/Admin/Profile.php b/src/Cms/Controllers/Admin/Profile.php
index 65c8a54..8205717 100644
--- a/src/Cms/Controllers/Admin/Profile.php
+++ b/src/Cms/Controllers/Admin/Profile.php
@@ -82,8 +82,8 @@ public function edit( Request $request ): string
->withCsrfToken()
->with([
'groupedTimezones' => $groupedTimezones,
- FlashMessageType::SUCCESS->value => $this->getSessionManager()->getFlash( FlashMessageType::SUCCESS->value ),
- FlashMessageType::ERROR->value => $this->getSessionManager()->getFlash( FlashMessageType::ERROR->value )
+ FlashMessageType::SUCCESS->viewKey() => $this->getSessionManager()->getFlash( FlashMessageType::SUCCESS->value ),
+ FlashMessageType::ERROR->viewKey() => $this->getSessionManager()->getFlash( FlashMessageType::ERROR->value )
])
->render( 'edit', 'admin' );
}
diff --git a/src/Cms/Controllers/Admin/Users.php b/src/Cms/Controllers/Admin/Users.php
index bed5ac7..74b01d5 100644
--- a/src/Cms/Controllers/Admin/Users.php
+++ b/src/Cms/Controllers/Admin/Users.php
@@ -79,8 +79,8 @@ public function index( Request $request ): string
->withCsrfToken()
->with([
'users' => $this->_repository->all(),
- FlashMessageType::SUCCESS->value => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
- FlashMessageType::ERROR->value => $sessionManager->getFlash( FlashMessageType::ERROR->value )
+ FlashMessageType::SUCCESS->viewKey() => $sessionManager->getFlash( FlashMessageType::SUCCESS->value ),
+ FlashMessageType::ERROR->viewKey() => $sessionManager->getFlash( FlashMessageType::ERROR->value )
])
->render( 'index', 'admin' );
}
diff --git a/src/Cms/Controllers/Auth/Login.php b/src/Cms/Controllers/Auth/Login.php
index 949e931..97dc4e8 100644
--- a/src/Cms/Controllers/Auth/Login.php
+++ b/src/Cms/Controllers/Auth/Login.php
@@ -75,8 +75,8 @@ public function showLoginForm( Request $request ): string
->title( 'Login' )
->description( 'Login to ' . $this->getName() )
->withCsrfToken()
- ->with( FlashMessageType::ERROR->value, $this->getSessionManager()->getFlash( 'error' ) )
- ->with( FlashMessageType::SUCCESS->value, $this->getSessionManager()->getFlash( 'success' ) )
+ ->with( FlashMessageType::ERROR->viewKey(), $this->getSessionManager()->getFlash( FlashMessageType::ERROR->value ) )
+ ->with( FlashMessageType::SUCCESS->viewKey(), $this->getSessionManager()->getFlash( FlashMessageType::SUCCESS->value ) )
->with( 'RedirectUrl', $redirectUrl )
->render( 'login', 'auth' );
}
diff --git a/src/Cms/Enums/FlashMessageType.php b/src/Cms/Enums/FlashMessageType.php
index 0107512..a9aa169 100644
--- a/src/Cms/Enums/FlashMessageType.php
+++ b/src/Cms/Enums/FlashMessageType.php
@@ -5,6 +5,8 @@
/**
* Flash message types used throughout the CMS
*
+ * Provides consistent keys for both session storage and view variables.
+ *
* @package Neuron\Cms\Enums
*/
enum FlashMessageType: string
@@ -13,4 +15,17 @@ enum FlashMessageType: string
case ERROR = 'error';
case WARNING = 'warning';
case INFO = 'info';
+
+ /**
+ * Get the view variable name for this flash message type
+ *
+ * Views expect capitalized variable names (e.g., $Success, $Error)
+ * while session storage uses lowercase keys (e.g., 'success', 'error')
+ *
+ * @return string The capitalized view variable name
+ */
+ public function viewKey(): string
+ {
+ return ucfirst( $this->value );
+ }
}
diff --git a/src/Cms/Services/Auth/Authentication.php b/src/Cms/Services/Auth/Authentication.php
index cb72eb1..87a911f 100644
--- a/src/Cms/Services/Auth/Authentication.php
+++ b/src/Cms/Services/Auth/Authentication.php
@@ -38,10 +38,24 @@ public function __construct(
/**
* Attempt to authenticate a user
+ *
+ * Accepts either username or email address for login.
+ * Automatically detects if the input is an email and searches accordingly.
*/
public function attempt( string $username, string $password, bool $remember = false ): bool
{
- $user = $this->_userRepository->findByUsername( $username );
+ // Detect if input is an email address
+ $isEmail = filter_var( $username, FILTER_VALIDATE_EMAIL );
+
+ // Try to find user by email or username
+ if( $isEmail )
+ {
+ $user = $this->_userRepository->findByEmail( $username );
+ }
+ else
+ {
+ $user = $this->_userRepository->findByUsername( $username );
+ }
if( !$user )
{
diff --git a/tests/Unit/Cms/Enums/FlashMessageTypeTest.php b/tests/Unit/Cms/Enums/FlashMessageTypeTest.php
new file mode 100644
index 0000000..a31e934
--- /dev/null
+++ b/tests/Unit/Cms/Enums/FlashMessageTypeTest.php
@@ -0,0 +1,59 @@
+assertEquals( 'Success', FlashMessageType::SUCCESS->viewKey() );
+ $this->assertEquals( 'Error', FlashMessageType::ERROR->viewKey() );
+ $this->assertEquals( 'Warning', FlashMessageType::WARNING->viewKey() );
+ $this->assertEquals( 'Info', FlashMessageType::INFO->viewKey() );
+ }
+
+ /**
+ * Test that enum values remain lowercase for session storage
+ *
+ * The value property should remain lowercase for consistency
+ * with session flash key storage.
+ */
+ public function testEnumValuesAreLowercase(): void
+ {
+ $this->assertEquals( 'success', FlashMessageType::SUCCESS->value );
+ $this->assertEquals( 'error', FlashMessageType::ERROR->value );
+ $this->assertEquals( 'warning', FlashMessageType::WARNING->value );
+ $this->assertEquals( 'info', FlashMessageType::INFO->value );
+ }
+
+ /**
+ * Test that all enum cases exist
+ *
+ * Ensures all expected flash message types are defined.
+ */
+ public function testAllCasesExist(): void
+ {
+ $cases = FlashMessageType::cases();
+ $this->assertCount( 4, $cases );
+
+ $values = array_map( fn( $case ) => $case->value, $cases );
+ $this->assertContains( 'success', $values );
+ $this->assertContains( 'error', $values );
+ $this->assertContains( 'warning', $values );
+ $this->assertContains( 'info', $values );
+ }
+}
diff --git a/tests/Unit/Cms/Services/AuthenticationTest.php b/tests/Unit/Cms/Services/AuthenticationTest.php
index 81383ef..f6c9977 100644
--- a/tests/Unit/Cms/Services/AuthenticationTest.php
+++ b/tests/Unit/Cms/Services/AuthenticationTest.php
@@ -608,4 +608,58 @@ public function testValidateCredentialsWithInvalidPassword(): void
$this->assertFalse($result);
}
+
+ /**
+ * Test attempt() with email address instead of username
+ */
+ public function testAttemptWithEmailAddress(): void
+ {
+ $user = $this->createTestUser('emailuser', 'TestPass123');
+
+ // Attempt login using email instead of username
+ $result = $this->_authentication->attempt($user->getEmail(), 'TestPass123');
+
+ $this->assertTrue($result);
+ $this->assertTrue($this->_authentication->check());
+ $this->assertEquals('emailuser', $this->_authentication->user()->getUsername());
+ }
+
+ /**
+ * Test attempt() with username still works
+ */
+ public function testAttemptWithUsernameStillWorks(): void
+ {
+ $this->createTestUser('usernametest', 'TestPass123');
+
+ // Attempt login using username (traditional method)
+ $result = $this->_authentication->attempt('usernametest', 'TestPass123');
+
+ $this->assertTrue($result);
+ $this->assertTrue($this->_authentication->check());
+ $this->assertEquals('usernametest', $this->_authentication->user()->getUsername());
+ }
+
+ /**
+ * Test attempt() with nonexistent email returns false
+ */
+ public function testAttemptWithNonexistentEmail(): void
+ {
+ $result = $this->_authentication->attempt('nobody@example.com', 'TestPass123');
+
+ $this->assertFalse($result);
+ $this->assertFalse($this->_authentication->check());
+ }
+
+ /**
+ * Test attempt() with incorrect password using email
+ */
+ public function testAttemptWithEmailAndIncorrectPassword(): void
+ {
+ $user = $this->createTestUser('emailpasstest', 'TestPass123');
+
+ $result = $this->_authentication->attempt($user->getEmail(), 'WrongPassword');
+
+ $this->assertFalse($result);
+ $this->assertFalse($this->_authentication->check());
+ }
}