Kotchasan Framework Documentation

Kotchasan Framework Documentation

Login Class - Authentication System

EN 05 Feb 2026 02:15

Login Class - Authentication System

The Login class handles user authentication, session management, and permission-based access control.

Namespace

Kotchasan\Login

Overview

The Login class provides:

  • User login/logout functionality
  • Session management
  • Permission checking
  • Role-based access control (super admin, admin, member)
  • Status verification
  • Password recovery support

Public Properties

public static $from_submit    // Whether login form was submitted
public static $login_input     // Input field to focus ('username' / 'password')
public static $login_message   // Login message/error
public static $login_params    // Submitted login parameters

Public Methods (11 methods)

create()

Create instance and handle login process

public static function create(Request $request): static

Parameters:

  • $request - HTTP request object

Returns: Login instance

Example:

use Kotchasan\Login;
use Kotchasan\Http\Request;

$request = new Request();
$login = Login::create($request);

logout()

Log out user (clear session)

public function logout(Request $request): void

Example:

$login = Login::create($request);
$login->logout($request);
// User is logged out

forgot()

Initiate password recovery process

public function forgot(Request $request): void

Note: This is a stub method - must be implemented in subclass

Example:

// Override in subclass
class MyLogin extends Login
{
    public function forgot(Request $request)
    {
        $email = $request->post('email')->toString();
        // Send reset email
    }
}

login()

Perform login

public function login(Request $request, array $loginParams): void

Parameters:

  • $request - HTTP request
  • $loginParams - Login data ['username' => '', 'password' => '']

Example:

$login->login($request, [
    'username' => 'admin',
    'password' => '1234'
]);

checkLogin()

Validate username/password (should be overridden)

public function checkLogin(array $loginParams): string|array

Parameters:

  • $loginParams - ['username' => '', 'password' => '']

Returns:

  • string - Error message if login fails
  • array - User data if login succeeds

Example:

class MyLogin extends Login
{
    public function checkLogin($loginParams)
    {
        $user = \Kotchasan\Model::create()
            ->from('user')
            ->where(['username', $loginParams['username']])
            ->first();

        if (!$user) {
            return 'User not found';
        }

        if (!password_verify($loginParams['password'], $user->password)) {
            return 'Incorrect password';
        }

        return (object)[
            'id' => $user->id,
            'username' => $user->username,
            'status' => $user->status,
            'permission' => json_decode($user->permission, true)
        ];
    }
}

hasPermission()

Check user permission

public static function hasPermission(
    string|array $permission,
    ?object $login = null,
    bool $checkAdmin = true
): ?object

Parameters:

  • $permission - Permission(s) to check
  • $login - Login data (defaults to isMember())
  • $checkAdmin - If true, admin has all permissions

Returns: Login object if has permission, null otherwise

Example:

$login = Login::isMember();

// Check single permission
if (Login::hasPermission('can_edit', $login)) {
    // Has edit permission
}

// Check multiple permissions (any match)
if (Login::hasPermission(['can_edit', 'can_delete'], $login)) {
    // Has at least one permission
}

isSuperAdmin()

Check if user is super admin (id === 1)

public static function isSuperAdmin(?object $login = null): ?object

Returns: Login object if super admin, null otherwise

Example:

if ($user = Login::isSuperAdmin()) {
    // Is super admin (id = 1)
    echo "Super Admin: " . $user->username;
}

isAdmin()

Check if user is admin (status === 1)

public static function isAdmin(?object $login = null): ?object

Returns: Login object if admin, null otherwise

Example:

if ($user = Login::isAdmin()) {
    // Is admin
    echo "Admin: " . $user->username;
}

isMember()

Check if user is logged in

public static function isMember(): ?object

Returns: Login object if logged in, null otherwise

Example:

if ($user = Login::isMember()) {
    echo "Logged in as: " . $user->username;
} else {
    // Not logged in - redirect to login page
    header('Location: /login');
}

checkStatus()

Check user status

public static function checkStatus(
    object $login,
    mixed $statuses
): ?object

Parameters:

  • $login - Login data
  • $statuses - Allowed status(es) (int or array)

Returns: Login object if status matches, null otherwise

Example:

$login = Login::isMember();

// Check single status
if (Login::checkStatus($login, 2)) {
    // status = 2 (e.g., active member)
}

// Check multiple statuses
if (Login::checkStatus($login, [2, 3])) {
    // status = 2 or 3
}

sessionKey()

Get session key for storing login data

public static function sessionKey(): string

Returns: Session key (from config or default 'login')

Example:

$key = Login::sessionKey();  // 'login' or value from config
$userData = $_SESSION[$key];

Complete Usage Examples

1. Basic Login System

use Kotchasan\Login;
use Kotchasan\Http\Request;

class AuthController
{
    public function showLoginPage()
    {
        $request = new Request();
        $login = Login::create($request);

        // Get data for display
        $data = [
            'message' => Login::$login_message,
            'username' => Login::$login_params['username'] ?? '',
            'focus' => Login::$login_input
        ];

        // Check if logged in
        if ($user = Login::isMember()) {
            // Login successful - redirect
            header('Location: /dashboard');
            exit;
        }

        // Show login page
        return view('login', $data);
    }
}

2. Custom Database Login

use Kotchasan\Login;
use Kotchasan\Model;

class AppLogin extends Login
{
    public function checkLogin($loginParams)
    {
        $username = $loginParams['username'] ?? '';
        $password = $loginParams['password'] ?? '';

        // Find user in database
        $user = Model::create()
            ->from('users')
            ->where(['username', $username])
            ->first();

        if (!$user) {
            self::$login_input = 'username';
            return 'Username not found';
        }

        if ($user->status == 0) {
            return 'Account is inactive';
        }

        // Verify password
        if (!password_verify($password, $user->password)) {
            self::$login_input = 'password';
            return 'Incorrect password';
        }

        // Update last login
        Model::create()
            ->update('users')
            ->set(['last_login' => time()])
            ->where(['id', $user->id])
            ->execute();

        // Return user data
        return (object)[
            'id' => $user->id,
            'username' => $user->username,
            'name' => $user->name,
            'email' => $user->email,
            'status' => $user->status,
            'permission' => json_decode($user->permission, true) ?? []
        ];
    }
}

3. Permission-Based Access Control

use Kotchasan\Login;

class ArticleController
{
    public function edit($id)
    {
        $login = Login::isMember();

        if (!$login) {
            return redirect('/login');
        }

        // Check edit permission
        if (!Login::hasPermission('can_edit_article', $login)) {
            return error('You don\'t have permission to edit articles');
        }

        // Has permission - proceed
        $article = $this->getArticle($id);
        return view('article/edit', ['article' => $article]);
    }

    public function delete($id)
    {
        $login = Login::isMember();

        // Check if admin or has delete permission
        if (!Login::isAdmin($login) &&
            !Login::hasPermission('can_delete_article', $login, false)) {
            return error('Permission denied');
        }

        // Delete article
        $this->deleteArticle($id);
        return success('Article deleted');
    }
}

4. Role-Based Dashboard

use Kotchasan\Login;

class DashboardController
{
    public function index()
    {
        $login = Login::isMember();

        if (!$login) {
            return redirect('/login');
        }

        // Super Admin Dashboard
        if (Login::isSuperAdmin($login)) {
            return $this->superAdminDashboard($login);
        }

        // Admin Dashboard
        if (Login::isAdmin($login)) {
            return $this->adminDashboard($login);
        }

        // Member Dashboard
        return $this->memberDashboard($login);
    }

    private function superAdminDashboard($login)
    {
        return view('dashboard/super', [
            'users' => $this->getAllUsers(),
            'settings' => $this->getSystemSettings()
        ]);
    }

    private function adminDashboard($login)
    {
        return view('dashboard/admin', [
            'stats' => $this->getStatistics(),
            'recent' => $this->getRecentActivities()
        ]);
    }

    private function memberDashboard($login)
    {
        return view('dashboard/member', [
            'profile' => $login,
            'tasks' => $this->getUserTasks($login->id)
        ]);
    }
}

5. Status-Based Content Access

use Kotchasan\Login;

class ContentController
{
    public function show($id)
    {
        $login = Login::isMember();
        $content = $this->getContent($id);

        // Public content
        if ($content->is_public) {
            return $this->renderContent($content);
        }

        // Login required
        if (!$login) {
            return redirect('/login');
        }

        // Check allowed status
        if (!Login::checkStatus($login, [1, 2, 3])) {
            return error('Your account status does not allow access to this content');
        }

        // Render content
        return $this->renderContent($content);
    }
}

6. Password Recovery

use Kotchasan\Login;
use Kotchasan\Email;
use Kotchasan\Model;

class AppLogin extends Login
{
    public function forgot(Request $request)
    {
        $email = $request->post('email')->toString();

        // Find user
        $user = Model::create()
            ->from('users')
            ->where(['email', $email])
            ->first();

        if (!$user) {
            self::$login_message = 'Email not found';
            return;
        }

        // Generate reset token
        $token = bin2hex(random_bytes(32));
        $expire = time() + 3600; // 1 hour

        // Save token
        Model::create()
            ->update('users')
            ->set([
                'reset_token' => $token,
                'reset_expire' => $expire
            ])
            ->where(['id', $user->id])
            ->execute();

        // Send email
        $resetLink = "https://example.com/reset?token=$token";
        Email::send($email, 'Password Reset',
            "Click to reset: $resetLink");

        self::$login_message = 'Reset link sent to your email';
    }
}

7. Authentication Middleware

use Kotchasan\Login;

class AuthMiddleware
{
    public static function requireLogin()
    {
        if (!Login::isMember()) {
            header('Location: /login');
            exit;
        }
    }

    public static function requireAdmin()
    {
        $login = Login::isMember();

        if (!Login::isAdmin($login)) {
            http_response_code(403);
            die('Access forbidden');
        }
    }

    public static function requirePermission($permission)
    {
        $login = Login::isMember();

        if (!Login::hasPermission($permission, $login)) {
            http_response_code(403);
            die('Permission denied');
        }
    }
}

// Usage
AuthMiddleware::requireLogin();
AuthMiddleware::requireAdmin();
AuthMiddleware::requirePermission('can_manage_users');

Best Practices

1. Always Extend for Production

// ✅ Good: Extend and override checkLogin
class MyLogin extends Login
{
    public function checkLogin($loginParams)
    {
        // Check against real database
    }
}

// ❌ Bad: Use default in production
$login = Login::create($request);  // Uses config username/password

2. Use sessionKey()

// ✅ Good: Use sessionKey() for flexibility
$key = Login::sessionKey();
$userData = $_SESSION[$key];

// ❌ Bad: Hardcode session key
$userData = $_SESSION['login'];  // Won't work if config changes

3. Check Permissions

// ✅ Good: Check before action
if (Login::hasPermission('can_delete', $login)) {
    $this->deleteItem($id);
}

// ❌ Bad: Assume permission
$this->deleteItem($id);  // Unsafe!

4. Handle Error Messages

// ✅ Good: Use Login::$login_message and Login::$login_input
if (Login::$login_message) {
    echo "<div class='error'>" . Login::$login_message . "</div>";
}
if (Login::$login_input) {
    echo "<script>document.getElementById('" . Login::$login_input . "').focus();</script>";
}

Summary

The Login class provides comprehensive authentication:

  • ✅ Login/logout management
  • ✅ Permission checking
  • ✅ Role-based access (super admin, admin, member)
  • ✅ Status verification
  • 🔒 Must extend for production use
  • 📝 Password recovery support

Suitable for:

  • Membership systems
  • Admin panels
  • CMS platforms
  • Web applications
  • API authentication (with sessions)

File Size: 304 lines
Public Methods: 11 methods
Pattern: Extends KBase