Removed local user storage.
This commit is contained in:
parent
25599ddd08
commit
36994255f7
12 changed files with 125 additions and 145 deletions
18
database/2025_01_03_190130_remove_local_users_table.php
Normal file
18
database/2025_01_03_190130_remove_local_users_table.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
use Index\Db\DbConnection;
|
||||
use Index\Db\Migration\DbMigration;
|
||||
|
||||
final class RemoveLocalUsersTable_20250103_190130 implements DbMigration {
|
||||
public function migrate(DbConnection $conn): void {
|
||||
// Remove foreign key from prm_uploads
|
||||
$conn->execute(<<<SQL
|
||||
ALTER TABLE prm_uploads
|
||||
DROP INDEX prm_uploads_user_foreign,
|
||||
ADD INDEX prm_uploads_user_index (user_id) USING BTREE,
|
||||
DROP FOREIGN KEY prm_uploads_user_foreign
|
||||
SQL);
|
||||
|
||||
// Nuke table
|
||||
$conn->execute('DROP TABLE prm_users');
|
||||
}
|
||||
}
|
|
@ -1,30 +1,9 @@
|
|||
<?php
|
||||
namespace EEPROM\Auth;
|
||||
|
||||
use EEPROM\Users\UserInfo;
|
||||
|
||||
class AuthInfo {
|
||||
public private(set) ?UserInfo $userInfo;
|
||||
|
||||
public function __construct() {
|
||||
$this->setInfo();
|
||||
}
|
||||
|
||||
public function setInfo(
|
||||
?UserInfo $userInfo = null
|
||||
): void {
|
||||
$this->userInfo = $userInfo;
|
||||
}
|
||||
|
||||
public function removeInfo(): void {
|
||||
$this->setInfo();
|
||||
}
|
||||
|
||||
public bool $loggedIn {
|
||||
get => $this->userInfo !== null;
|
||||
}
|
||||
|
||||
public ?string $userId {
|
||||
get => $this->userInfo?->id;
|
||||
}
|
||||
interface AuthInfo {
|
||||
public bool $authed { get; }
|
||||
public ?string $userId { get; }
|
||||
public bool $restricted { get; }
|
||||
public int $legacyMultiplier { get; }
|
||||
}
|
||||
|
|
26
src/Auth/AuthInfoWrapper.php
Normal file
26
src/Auth/AuthInfoWrapper.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
namespace EEPROM\Auth;
|
||||
|
||||
class AuthInfoWrapper implements AuthInfo {
|
||||
public AuthInfo $value;
|
||||
|
||||
public function __construct(?AuthInfo $authInfo = null) {
|
||||
$this->value = $authInfo ?? BlankAuthInfo::instance();
|
||||
}
|
||||
|
||||
public bool $authed {
|
||||
get => $this->value->authed;
|
||||
}
|
||||
|
||||
public ?string $userId {
|
||||
get => $this->value->userId;
|
||||
}
|
||||
|
||||
public bool $restricted {
|
||||
get => $this->value->restricted;
|
||||
}
|
||||
|
||||
public int $legacyMultiplier {
|
||||
get => $this->value->legacyMultiplier;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace EEPROM\Auth;
|
||||
|
||||
use EEPROM\Users\UsersContext;
|
||||
use EEPROM\Auth\{BlankAuthInfo,FlashiiAuthInfo};
|
||||
use Flashii\{FlashiiClient,FlashiiUrls};
|
||||
use Flashii\Credentials\{BearerCredentials,MisuzuCredentials};
|
||||
use Index\Config\Config;
|
||||
|
@ -12,8 +12,7 @@ class AuthRoutes implements RouteHandler {
|
|||
|
||||
public function __construct(
|
||||
private Config $config,
|
||||
private AuthInfo $authInfo,
|
||||
private UsersContext $usersCtx
|
||||
private AuthInfoWrapper $authInfo
|
||||
) {}
|
||||
|
||||
#[HttpMiddleware('/')]
|
||||
|
@ -39,9 +38,8 @@ class AuthRoutes implements RouteHandler {
|
|||
$this->config->getString('api', FlashiiUrls::PROD_API_URL)
|
||||
));
|
||||
|
||||
$authInfo = $flashii->v1()->me();
|
||||
if($authInfo !== null)
|
||||
$this->authInfo->setInfo($this->usersCtx->getUser($authInfo->getId()));
|
||||
$userInfo = $flashii->v1()->me();
|
||||
$this->authInfo->value = $userInfo === null ? BlankAuthInfo::instance() : new FlashiiAuthInfo($userInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
21
src/Auth/BlankAuthInfo.php
Normal file
21
src/Auth/BlankAuthInfo.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
namespace EEPROM\Auth;
|
||||
|
||||
class BlankAuthInfo implements AuthInfo {
|
||||
public private(set) bool $authed = false;
|
||||
public private(set) ?string $userId = null;
|
||||
public private(set) bool $restricted = true;
|
||||
public private(set) int $legacyMultiplier = 0;
|
||||
|
||||
private static BlankAuthInfo $instance;
|
||||
|
||||
public static function init(): void {
|
||||
self::$instance = new BlankAuthInfo;
|
||||
}
|
||||
|
||||
public static function instance(): BlankAuthInfo {
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
||||
|
||||
BlankAuthInfo::init();
|
29
src/Auth/FlashiiAuthInfo.php
Normal file
29
src/Auth/FlashiiAuthInfo.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
namespace EEPROM\Auth;
|
||||
|
||||
use Flashii\V1\Users\V1User;
|
||||
|
||||
class FlashiiAuthInfo implements AuthInfo {
|
||||
public function __construct(
|
||||
private V1User $userInfo
|
||||
) {}
|
||||
|
||||
public private(set) bool $authed = true;
|
||||
|
||||
public ?string $userId {
|
||||
get => $this->userInfo->getId();
|
||||
}
|
||||
|
||||
public bool $restricted {
|
||||
// temporary hack
|
||||
get => $this->userInfo->hasRole('x-banned');
|
||||
}
|
||||
|
||||
// replace this with an extended version of constrain_size that supports role specific size limits
|
||||
public int $legacyMultiplier {
|
||||
get => $this->userInfo->hasRole('admin')
|
||||
|| $this->userInfo->hasRole('gmod')
|
||||
|| $this->userInfo->hasRole('dev')
|
||||
|| $this->userInfo->hasRole('tenshi') ? 2 : 1;
|
||||
}
|
||||
}
|
|
@ -3,37 +3,32 @@ namespace EEPROM;
|
|||
|
||||
use Index\Config\Config;
|
||||
use Index\Db\DbConnection;
|
||||
use EEPROM\Auth\AuthInfo;
|
||||
use EEPROM\Auth\AuthInfoWrapper;
|
||||
use RPCii\HmacVerificationProvider;
|
||||
use RPCii\Server\HttpRpcServer;
|
||||
|
||||
class EEPROMContext {
|
||||
public private(set) DatabaseContext $database;
|
||||
|
||||
public private(set) SnowflakeGenerator $snowflake;
|
||||
|
||||
private AuthInfo $authInfo;
|
||||
public private(set) AuthInfoWrapper $authInfo;
|
||||
|
||||
public private(set) Denylist\DenylistContext $denylistCtx;
|
||||
public private(set) Pools\PoolsContext $poolsCtx;
|
||||
public private(set) Storage\StorageContext $storageCtx;
|
||||
public private(set) Uploads\UploadsContext $uploadsCtx;
|
||||
private Users\UsersContext $usersCtx;
|
||||
|
||||
public function __construct(
|
||||
private Config $config,
|
||||
DbConnection $dbConn
|
||||
) {
|
||||
$this->snowflake = new SnowflakeGenerator;
|
||||
$this->database = new DatabaseContext($dbConn);
|
||||
|
||||
$this->authInfo = new AuthInfo;
|
||||
$this->snowflake = new SnowflakeGenerator;
|
||||
$this->authInfo = new AuthInfoWrapper;
|
||||
|
||||
$this->denylistCtx = new Denylist\DenylistContext($dbConn);
|
||||
$this->poolsCtx = new Pools\PoolsContext($dbConn);
|
||||
$this->storageCtx = new Storage\StorageContext($config->scopeTo('storage'), $dbConn, $this->snowflake);
|
||||
$this->uploadsCtx = new Uploads\UploadsContext($config->scopeTo('domain'), $dbConn, $this->snowflake);
|
||||
$this->usersCtx = new Users\UsersContext($dbConn);
|
||||
}
|
||||
|
||||
public function createRouting(bool $isApiDomain): RoutingContext {
|
||||
|
@ -48,8 +43,7 @@ class EEPROMContext {
|
|||
|
||||
$routingCtx->register(new Auth\AuthRoutes(
|
||||
$this->config->scopeTo('apii'),
|
||||
$this->authInfo,
|
||||
$this->usersCtx
|
||||
$this->authInfo
|
||||
));
|
||||
|
||||
$routingCtx->register(new LandingRoutes($this->database));
|
||||
|
|
|
@ -8,7 +8,6 @@ use Index\Db\{DbConnection,DbStatementCache,DbTools};
|
|||
use EEPROM\SnowflakeGenerator;
|
||||
use EEPROM\Pools\PoolInfo;
|
||||
use EEPROM\Storage\StorageRecord;
|
||||
use EEPROM\Users\UserInfo;
|
||||
|
||||
class UploadsData {
|
||||
private DbStatementCache $cache;
|
||||
|
@ -64,12 +63,12 @@ class UploadsData {
|
|||
public function getUpload(
|
||||
?string $uploadId = null,
|
||||
PoolInfo|string|null $poolInfo = null,
|
||||
UserInfo|string|null $userInfo = null,
|
||||
string|null|false $userId = false,
|
||||
?string $secret = null,
|
||||
): UploadInfo {
|
||||
$hasUploadId = $uploadId !== null;
|
||||
$hasPoolInfo = $poolInfo !== null;
|
||||
$hasUserInfo = $userInfo !== null;
|
||||
$hasUserId = $userId !== false;
|
||||
$hasSecret = $secret !== null;
|
||||
|
||||
$args = 0;
|
||||
|
@ -80,8 +79,8 @@ class UploadsData {
|
|||
}
|
||||
if($hasPoolInfo)
|
||||
$query .= sprintf(' %s pool_id = ?', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasUserInfo)
|
||||
$query .= sprintf(' %s user_id = ?', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
if($hasUserId)
|
||||
$query .= sprintf(' %s user_id %s', ++$args > 1 ? 'AND' : 'WHERE', $userId === null ? 'IS NULL' : '= ?');
|
||||
if($hasSecret)
|
||||
$query .= sprintf(' %s upload_secret = ?', ++$args > 1 ? 'AND' : 'WHERE');
|
||||
|
||||
|
@ -90,8 +89,8 @@ class UploadsData {
|
|||
$stmt->nextParameter($uploadId);
|
||||
if($hasPoolInfo)
|
||||
$stmt->nextParameter($poolInfo instanceof PoolInfo ? $poolInfo->id : $poolInfo);
|
||||
if($hasUserInfo)
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
if($hasUserId && $userId !== null)
|
||||
$stmt->nextParameter($userId);
|
||||
if($hasSecret)
|
||||
$stmt->nextParameter($secret);
|
||||
$stmt->execute();
|
||||
|
@ -105,7 +104,7 @@ class UploadsData {
|
|||
|
||||
public function resolveUploadFromVariant(
|
||||
PoolInfo|string $poolInfo,
|
||||
UserInfo|string $userInfo,
|
||||
?string $userId,
|
||||
StorageRecord|string $fileInfo,
|
||||
string $variant
|
||||
): string {
|
||||
|
@ -120,7 +119,7 @@ class UploadsData {
|
|||
AND uf.upload_variant = ?
|
||||
SQL);
|
||||
$stmt->nextParameter($poolInfo instanceof PoolInfo ? $poolInfo->id : $poolInfo);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->nextParameter($userId);
|
||||
$stmt->nextParameter($fileInfo instanceof StorageRecord ? $fileInfo->id : $fileInfo);
|
||||
$stmt->nextParameter($variant);
|
||||
$stmt->execute();
|
||||
|
@ -134,7 +133,7 @@ class UploadsData {
|
|||
|
||||
public function createUpload(
|
||||
PoolInfo|string $poolInfo,
|
||||
UserInfo|string $userInfo,
|
||||
?string $userId,
|
||||
string $fileName,
|
||||
string $remoteAddr
|
||||
): UploadInfo {
|
||||
|
@ -143,7 +142,7 @@ class UploadsData {
|
|||
$stmt = $this->cache->get('INSERT INTO prm_uploads (upload_id, pool_id, user_id, upload_secret, upload_name, upload_ip) VALUES (?, ?, ?, ?, ?, INET6_ATON(?))');
|
||||
$stmt->nextParameter($uploadId);
|
||||
$stmt->nextParameter($poolInfo instanceof PoolInfo ? $poolInfo->id : $poolInfo);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->nextParameter($userId);
|
||||
$stmt->nextParameter(XString::random(4));
|
||||
$stmt->nextParameter($fileName);
|
||||
$stmt->nextParameter($remoteAddr);
|
||||
|
|
|
@ -157,11 +157,10 @@ class UploadsRoutes implements RouteHandler {
|
|||
if($request->getMethod() === 'OPTIONS')
|
||||
return 204;
|
||||
|
||||
if(!$this->authInfo->loggedIn)
|
||||
if(!$this->authInfo->authed)
|
||||
return 401;
|
||||
|
||||
$userInfo = $this->authInfo->userInfo;
|
||||
if($userInfo->restricted)
|
||||
if($this->authInfo->restricted)
|
||||
return 403;
|
||||
|
||||
if(!$request->isFormContent())
|
||||
|
@ -197,7 +196,7 @@ class UploadsRoutes implements RouteHandler {
|
|||
|
||||
$maxFileSize = $maxSizeRule->maxSize;
|
||||
if($maxSizeRule->allowLegacyMultiplier)
|
||||
$maxFileSize *= $userInfo->dataSizeMultiplier;
|
||||
$maxFileSize *= $this->authInfo->legacyMultiplier;
|
||||
|
||||
if($file->getSize() !== $fileSize || $fileSize > $maxFileSize) {
|
||||
$response->setHeader('Access-Control-Expose-Headers', 'X-EEPROM-Max-Size');
|
||||
|
@ -230,7 +229,7 @@ class UploadsRoutes implements RouteHandler {
|
|||
// TODO: Okay so we're reading from the prm_uploads_files table, then fetching the info from prm_uploads,
|
||||
// and then fetching the info again from the prm_uploads_files table... this can be done better but this will do for now
|
||||
$uploadInfo = $this->uploadsCtx->uploads->getUpload(
|
||||
uploadId: $this->uploadsCtx->uploads->resolveUploadFromVariant($poolInfo, $userInfo, $storageInfo, '')
|
||||
uploadId: $this->uploadsCtx->uploads->resolveUploadFromVariant($poolInfo, $this->authInfo->userId, $storageInfo, '')
|
||||
);
|
||||
$variantInfo = $this->uploadsCtx->uploads->getUploadVariant($uploadInfo, '');
|
||||
|
||||
|
@ -242,7 +241,7 @@ class UploadsRoutes implements RouteHandler {
|
|||
} catch(RuntimeException $ex) {
|
||||
$uploadInfo = $this->uploadsCtx->uploads->createUpload(
|
||||
$poolInfo,
|
||||
$userInfo,
|
||||
$this->authInfo->userId,
|
||||
$fileName,
|
||||
$request->getRemoteAddress()
|
||||
);
|
||||
|
@ -267,7 +266,7 @@ class UploadsRoutes implements RouteHandler {
|
|||
$response->setHeader('Access-Control-Allow-Headers', 'Authorization');
|
||||
$response->setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, DELETE');
|
||||
|
||||
if(!$this->authInfo->loggedIn)
|
||||
if(!$this->authInfo->authed)
|
||||
return 401;
|
||||
|
||||
if(strlen($uploadId) === 32) {
|
||||
|
@ -290,8 +289,7 @@ class UploadsRoutes implements RouteHandler {
|
|||
return 404;
|
||||
}
|
||||
|
||||
$userInfo = $this->authInfo->userInfo;
|
||||
if($userInfo->restricted || $userInfo->id !== $uploadInfo->userId)
|
||||
if($this->authInfo->restricted || $this->authInfo->userId !== $uploadInfo->userId)
|
||||
return 403;
|
||||
|
||||
$this->uploadsCtx->uploads->deleteUpload($uploadInfo);
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
namespace EEPROM\Users;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Index\Db\DbResult;
|
||||
|
||||
class UserInfo {
|
||||
public function __construct(
|
||||
public private(set) string $id,
|
||||
public private(set) int $createdTime,
|
||||
public private(set) ?int $restrictedTime,
|
||||
public private(set) int $dataSizeMultiplier,
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): UserInfo {
|
||||
return new UserInfo(
|
||||
id: $result->getString(0),
|
||||
createdTime: $result->getInteger(1),
|
||||
restrictedTime: $result->getIntegerOrNull(2),
|
||||
dataSizeMultiplier: $result->getInteger(3),
|
||||
);
|
||||
}
|
||||
|
||||
public CarbonImmutable $createdAt {
|
||||
get => CarbonImmutable::createFromTimestampUTC($this->createdTime);
|
||||
}
|
||||
|
||||
public bool $restricted {
|
||||
get => $this->restrictedTime !== null;
|
||||
}
|
||||
|
||||
public ?CarbonImmutable $restrictedAt {
|
||||
get => $this->restrictedTime === null ? null : CarbonImmutable::createFromTimestampUTC($this->restrictedTime);
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
namespace EEPROM\Users;
|
||||
|
||||
use Index\Db\DbConnection;
|
||||
|
||||
class UsersContext {
|
||||
public private(set) UsersData $users;
|
||||
|
||||
public function __construct(DbConnection $dbConn) {
|
||||
$this->users = new UsersData($dbConn);
|
||||
}
|
||||
|
||||
public function getUser(string $userId): UserInfo {
|
||||
$this->users->ensureUserExists($userId);
|
||||
return $this->users->getUser($userId);
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
namespace EEPROM\Users;
|
||||
|
||||
use Index\Db\{DbConnection,DbStatementCache};
|
||||
|
||||
// restrictions and permissions should be checked with misuzu or cached or something
|
||||
// size multiplier should also just be replaced with an alternate max size value for premioids, maybe based on rank?
|
||||
|
||||
class UsersData {
|
||||
private DbStatementCache $cache;
|
||||
|
||||
public function __construct(DbConnection $dbConn) {
|
||||
$this->cache = new DbStatementCache($dbConn);
|
||||
}
|
||||
|
||||
public function getUser(string $userId): ?UserInfo {
|
||||
$stmt = $this->cache->get('SELECT user_id, UNIX_TIMESTAMP(user_created), UNIX_TIMESTAMP(user_restricted), user_size_multiplier FROM prm_users WHERE user_id = ?');
|
||||
$stmt->nextParameter($userId);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
return $result->next() ? UserInfo::fromResult($result) : null;
|
||||
}
|
||||
|
||||
public function ensureUserExists(string $userId): void {
|
||||
$stmt = $this->cache->get('INSERT IGNORE INTO prm_users (user_id) VALUES (?)');
|
||||
$stmt->nextParameter($userId);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue