summaryrefslogtreecommitdiff
path: root/src/Controllers/LoginController.php
blob: 1ff234cdf79b776603b4e6000e25d9b273ae149c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?php

namespace App\Controllers;

use App\Database;
use App\Errors\AppException;
use App\Errors\ErrorCode;
use App\Errors\UnknownError;
use App\Models\Device;
use App\Models\User;
use App\Types\LoginFlow;
use App\Types\LoginType;
use App\Types\UserRegistrationKind;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;

class LoginController
{
  /**
   * GET /_matrix/client/r0/login
   */
  public function supportedLoginTypes(): Response
  {
    return new JsonResponse([
      "flows" => [
        (new LoginFlow(LoginType::PASSWORD))->toArray(),
      ],
    ]);
  }

  /**
   * POST /_matrix/client/v3/login
   */
  public function login(): Response
  {
    $request = Request::createFromGlobals();
    $body = json_decode($request->getContent(), true);

    // validate login type
    $loginType = null;
    try {
      $loginType = LoginType::from($body["type"]);
    } catch (\ValueError $error) {
      throw new UnknownError("Bad login type.", Response::HTTP_BAD_REQUEST);
    }

    // get user id
    $userId = $body["identifier"]["user"];

    #if ($loginType == LoginType::PASSWORD) {}

    $user = User::fetchWithPassword($userId, $body["password"]);

    if (! $user) {
      throw new AppException(ErrorCode::FORBIDDEN, "Invalid credentials.", Response::HTTP_FORBIDDEN);
    }

    $deviceId = $body["device_id"] ?? "";
    $device = $user->fetchDevice($deviceId);

    if (! $device) {
      $device = Device::new(
        $user->getId(),
        initialDisplayName: $body["initial_device_display_name"] ?? "",
      );
    }

    return new JsonResponse([
      "access_token" => $device->getAccessToken(),
      "device_id" => $device->getId(),
      "expires_in_ms" => 60000,
      "refresh_token" => $device->getRefreshToken(),
      "user_id" => $user->getId(),
      #"well_known" => [],
    ]);
  }

  /**
   * POST /_matrix/client/v3/register
   */
  public function register(): Response
  {
    $request = Request::createFromGlobals();
    $body = json_decode($request->getContent(), true);

    $kind = UserRegistrationKind::from($request->query->get("kind") ?? "user");

    $username = $body["username"];
    $userId = "@$username:$_ENV[DOMAIN]";

    Database::getInstance()->query("insert into users (id, password) values (:id, :password)", [
      "id" => $userId,
      "password" => $body["password"],
    ]);

    $device_id = $body["device_id"] ?? "";
    $initialDeviceDisplayName = $body["initialDeviceDisplayName"] ?? "";

    $device = Device::new($userId, $device_id, $initialDeviceDisplayName);
    $device->insert();

    return new JsonResponse([
      "access_token" => $device->getAccessToken(),
      "device_id" => $device->getId(),
      "expires_in_ms" => 60000,
      "refresh_token" => $device->getRefreshToken(),
      "user_id" => $userId,
    ]);
  }
}