summaryrefslogtreecommitdiff
path: root/src/Models
diff options
context:
space:
mode:
Diffstat (limited to 'src/Models')
-rw-r--r--src/Models/RoomEvent.php74
-rw-r--r--src/Models/Tokens.php29
-rw-r--r--src/Models/User.php67
3 files changed, 160 insertions, 10 deletions
diff --git a/src/Models/RoomEvent.php b/src/Models/RoomEvent.php
new file mode 100644
index 0000000..11d74b0
--- /dev/null
+++ b/src/Models/RoomEvent.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Models;
+
+use App\Database;
+use Matrix\Data\UnsignedData;
+use Matrix\Enums\EventType;
+use Matrix\Events\ClientEvent;
+use Matrix\Events\StateEvent;
+
+class RoomEvent
+{
+ public function __construct(
+ private ClientEvent $event,
+ )
+ {}
+
+ /**
+ * @param array<string, mixed> $row
+ */
+ public static function transformEvent(array $row): ClientEvent
+ {
+ $rowUnsigned = json_decode($row["unsigned"], true);
+ $unsigned = new UnsignedData(
+ age: $row["age"] ?? ((time() - new \DateTime($row["origin_server_timestamp"])->getTimestamp()) * 1000),
+ membership: $row["membership"] ?? null,
+ previousContent: $row["previous_content"] ?? null,
+ redactedBecause: $row["redacted_because"] ?? null,
+ transactionId: $row["transaction_id"] ?? null,
+ );
+
+ return new ClientEvent(
+ content: json_decode($row["content"], true),
+ eventId: $row["id"],
+ originServerTimestamp: new \DateTime($row["origin_server_timestamp"])->getTimestamp(),
+ roomId: $row["room_id"],
+ sender: $row["sender"],
+ type: EventType::from($row["type"]),
+ unsigned: $unsigned,
+ );
+ }
+
+ public function insert(): bool
+ {
+ if ($this->event instanceof StateEvent) {
+ return !! Database::getInstance()->query(<<<SQL
+ insert into room_events (id, content, type, sender, origin_server_timestamp, room_id, unsigned, state_key)
+ values (:id, :content, :type, :sender, to_timestamp(:origin_server_timestamp), :room_id, :unsigned, :state_key)
+ SQL, [
+ "id" => $this->event->getId(),
+ "content" => json_encode($this->event->getContent()),
+ "type" => $this->event->getType()->value,
+ "sender" => $this->event->getSender(),
+ "origin_server_timestamp" => \DateTime::createFromTimestamp($this->event->getOriginServerTimestamp())->format("U.v"),
+ "room_id" => $this->event->getRoomId(),
+ "unsigned" => json_encode($this->event->getUnsigned()),
+ "state_key" => $this->event->getStateKey(),
+ ]);
+ }
+
+ return !! Database::getInstance()->query(<<<SQL
+ insert into room_events (id, content, type, sender, origin_server_timestamp, room_id, unsigned)
+ values (:id, :content, :type, :sender, to_timestamp(:origin_server_timestamp), :room_id, :unsigned)
+ SQL, [
+ "id" => $this->event->getId(),
+ "content" => json_encode($this->event->getContent()),
+ "type" => $this->event->getType()->value,
+ "sender" => $this->event->getSender(),
+ "origin_server_timestamp" => \DateTime::createFromTimestamp($this->event->getOriginServerTimestamp())->format("U.v"),
+ "room_id" => $this->event->getRoomId(),
+ "unsigned" => json_encode($this->event->getUnsigned()),
+ ]);
+ }
+}
diff --git a/src/Models/Tokens.php b/src/Models/Tokens.php
index 4ad8e1d..ee912fb 100644
--- a/src/Models/Tokens.php
+++ b/src/Models/Tokens.php
@@ -37,9 +37,9 @@ class Tokens implements ConnectsToDatabase
$isExpiredSql = "";
if ($isExpired) {
- $isExpiredSql = "and expires_at <= current_timestamp";
+ #$isExpiredSql = "and expires_at <= current_timestamp";
} else {
- $isExpiredSql = "and expires_at > current_timestamp";
+ #$isExpiredSql = "and expires_at > current_timestamp";
}
$row = [];
@@ -78,6 +78,26 @@ class Tokens implements ConnectsToDatabase
public static function fetchAll(): array
{}
+ public static function fetchWithAccessToken(string $accessToken): ?self
+ {
+ $row = Database::getInstance()->query(
+ <<<SQL
+ select * from tokens
+ where access_token=:access_token
+ order by created_at desc
+ SQL,
+ [
+ "access_token" => $accessToken,
+ ]
+ )->fetch();
+
+ if (empty($row)) {
+ return null;
+ }
+
+ return self::fromDatabase($row);
+ }
+
public static function fetchWithRefreshToken(string $refreshToken): ?self
{
$row = Database::getInstance()->query(
@@ -140,6 +160,11 @@ class Tokens implements ConnectsToDatabase
);
}
+ public function isExpired(): bool
+ {
+ return $this->expiresAt->format("U.v") <= time();
+ }
+
public function getAccessToken(): string
{
return $this->accessToken;
diff --git a/src/Models/User.php b/src/Models/User.php
index c0c73f8..a30bee0 100644
--- a/src/Models/User.php
+++ b/src/Models/User.php
@@ -3,19 +3,28 @@
namespace App\Models;
use App\Database;
+use App\Errors\AppException;
use App\Errors\UnauthorizedError;
use App\Support\ConnectsToDatabase;
+use Matrix\Enums\ErrorCode;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
class User implements ConnectsToDatabase
{
- public function __construct(private string $id)
+ private string $deviceId;
+
+ public function __construct(
+ private string $id,
+ private string $name,
+ )
{}
public static function fromDatabase(array $row): self
{
return new self(
$row["id"],
+ $row["name"],
);
}
@@ -55,7 +64,7 @@ class User implements ConnectsToDatabase
public static function fetchWithAccessToken(string $accessToken): ?self
{
$row = Database::getInstance()->query(<<<SQL
- select users.* from users left join tokens on tokens.user_id = users.id where tokens.access_token=:access_token
+ select users.*, tokens.device_id from users left join tokens on tokens.user_id = users.id where tokens.access_token=:access_token
SQL, [
"access_token" => $accessToken,
])->fetch();
@@ -64,23 +73,42 @@ class User implements ConnectsToDatabase
return null;
}
- return self::fromDatabase($row);
+ $user = self::fromDatabase($row);
+ $user->setDeviceId($row["device_id"]);
+
+ return $user;
}
- public static function new(string $id): self
+ public static function new(string $id, string $name): self
{
- return new self($id);
+ return new self($id, $name);
}
public static function authenticateWithRequest(Request $request): self
{
$accessToken = str_replace("Bearer ", "", $request->headers->get("authorization") ?: "");
+
+ if (empty($accessToken)) {
+ throw new AppException(ErrorCode::UNAUTHORIZED, "Missing access token", Response::HTTP_UNAUTHORIZED);
+ }
+
$user = self::fetchWithAccessToken($accessToken);
if (empty($user)) {
throw new UnauthorizedError();
}
+ $tokens = Tokens::fetchWithAccessToken($accessToken);
+
+ if (empty($tokens) /*|| $tokens->isExpired()*/) {
+ throw new AppException(
+ ErrorCode::UNKNOWN_TOKEN,
+ "Soft logged out",
+ Response::HTTP_UNAUTHORIZED,
+ ["soft_logout" => true],
+ );
+ }
+
return $user;
}
@@ -88,11 +116,12 @@ class User implements ConnectsToDatabase
{
return !! Database::getInstance()->query(
<<<SQL
- insert into users (id)
- values (:id)
+ insert into users (id, name)
+ values (:id, :name)
SQL,
[
"id" => $this->id,
+ "name" => $this->name,
]
);
}
@@ -108,10 +137,32 @@ class User implements ConnectsToDatabase
return $this->id;
}
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+ public function setDeviceId(string $id): void
+ {
+ $this->deviceId = $id;
+ }
+
+ public function getDeviceId(): string
+ {
+ return $this->deviceId;
+ }
+
public function fetchDevice(string $id): ?Device
{
- return Device::fetch($id, $this->id);
+ $device = Device::fetch($id, $this->id);
+
+ if ($device) {
+ $this->setDeviceId($device->getId());
+ }
+
+ return $device;
}
+
/**
* @return Device[]
*/