Compare commits

...

2 commits

Author SHA1 Message Date
d95d78f5a2
add Discord Me cache 2023-08-27 21:53:01 +08:00
0393ab8b89
refactor change self:: to static:: 2023-08-27 15:27:42 +08:00
7 changed files with 96 additions and 22 deletions

16
.idea/php.xml generated
View file

@ -1,5 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/composer" />
@ -17,9 +27,15 @@
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" />
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" />
</phpunit_settings>
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

View file

@ -21,14 +21,14 @@ class App
public static function getTemplate(): Engine
{
static $templates = new Engine(__DIR__ . '/../templates');
$me = self::me();
$isLogin = self::checkU();
$me = static::me();
$isLogin = static::checkU();
$templates->addData([
'me' => $me,
'whoami' => "$me->username#$me->userDiscriminator",
'noStatus' => false,
'isLogin' => $isLogin,
'isAllowed' => $isLogin && $me !== null && self::isAllowed($me->userId),
'isAllowed' => $isLogin && $me !== null && static::isAllowed($me->userId),
]);
return $templates;
}
@ -40,10 +40,10 @@ class App
public static function checkU(): bool
{
$token = self::getU();
$token = static::getU();
if ($token === null) return false;
if ($token->timestamp + $token->expires_in < time()) return false;
return self::me() !== null;
return static::me() !== null;
}
public static function setU(Token $token): void
@ -80,7 +80,7 @@ class App
public static function requireAuth(): void
{
if (!self::checkU()) {
if (!static::checkU()) {
header('location: /login.php');
http_response_code(302);
exit;
@ -89,7 +89,7 @@ class App
public static function requireNonAuth(): void
{
if (self::checkU()) {
if (static::checkU()) {
header('location: /');
http_response_code(302);
exit;
@ -98,10 +98,10 @@ class App
public static function requireAllowed(): void
{
self::requireAuth();
$me = self::me();
if ($me === null || !self::isAllowed($me->userId)) {
self::template([
static::requireAuth();
$me = static::me();
if ($me === null || !static::isAllowed($me->userId)) {
static::template([
'title' => '您無權限使用本系統',
'body' => <<<HTML
<div class="mt-5">
@ -117,7 +117,7 @@ HTML,
{
try {
$token = Auth::getTokenByCode($code);
if ($token !== null) self::setU($token);
if ($token !== null) static::setU($token);
} catch (Exception) {
error_log('Failed to getTokenByCode.');
}
@ -126,9 +126,11 @@ HTML,
public static function me(): ?Me
{
try {
$u = self::getU();
$u = static::getU();
if ($u === null) return null;
return Auth::getMe($u);
$cachedMe = Redis::getCachedMe($_COOKIE['u']);
if ($cachedMe === null) return Redis::cacheMe($_COOKIE['u'], Auth::getMe($u));
return $cachedMe;
} catch (Exception) {
error_log('Failed to getMe.');
return null;
@ -139,8 +141,8 @@ HTML,
public static function template(array $params): void
{
$status = '';
if (self::checkU() && !$params['no_status']) {
$me = self::me();
if (static::checkU() && !$params['no_status']) {
$me = static::me();
$status = <<<HTML
<div>您已使用 <code>$me->username#$me->userDiscriminator</code> 登入,點選此處以<a href="/logout.php">登出系統</a>。</div>
HTML;
@ -181,13 +183,13 @@ HTML;
public static function isAllowed(string $userId): bool
{
return in_array($userId, self::allowedUsers);
return in_array($userId, static::allowedUsers);
}
#[NoReturn]
public static function render(string $name, array $data = []): void
{
$html = self::getTemplate()->render($name, $data);
$html = static::getTemplate()->render($name, $data);
header('Content-Type: text/html; charset=utf-8');
header('Content-Length: ' . strlen($html));

View file

@ -42,7 +42,7 @@ class Auth
{
$query_string = http_build_query([
'client_id' => $_ENV['DISCORD_CLIENT_ID'],
'redirect_uri' => self::DISCORD_REDIRECT_URI,
'redirect_uri' => static::DISCORD_REDIRECT_URI,
'response_type' => 'code',
'scope' => 'identify',
]);
@ -60,7 +60,7 @@ class Auth
'client_secret' => $_ENV['DISCORD_CLIENT_SECRET'],
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => self::DISCORD_REDIRECT_URI,
'redirect_uri' => static::DISCORD_REDIRECT_URI,
]),
],
])));

View file

@ -29,7 +29,7 @@ abstract class FileViewer
$directory = static::directory();
$filename = "$directory/$file";
if (!in_array($file, self::list()) || !file_exists($filename) || !is_file($filename)) return null;
if (!in_array($file, static::list()) || !file_exists($filename) || !is_file($filename)) return null;
$extension = pathinfo($filename, PATHINFO_EXTENSION);
$content = file_get_contents($filename);

54
app/Redis.php Normal file
View file

@ -0,0 +1,54 @@
<?php
namespace MingTsay\Akanyan;
use MingTsay\Akanyan\Discord\Me;
require_once __DIR__ . '/../env.php';
class Redis
{
public const PREFIX = 'akanyan:discord:me:';
public const TTL = 600; // 10 minutes
protected static ?\Redis $redis = null;
/**
* @throws \RedisException
*/
protected static function connect(): \Redis
{
if (static::$redis === null) {
static::$redis = new \Redis();
static::$redis->connect('127.0.0.1');
}
return static::$redis;
}
protected static function getKey(string $u): string
{
return static::PREFIX . md5($u);
}
public static function getCachedMe(string $u): ?Me
{
try {
$redis = static::connect();
return unserialize($redis->get(static::getKey($u))) ?: null;
} catch (\RedisException $e) {
trigger_error($e->getMessage());
return null;
}
}
public static function cacheMe(string $u, ?Me $me): ?Me
{
try {
$redis = static::connect();
$redis->setEx(static::getKey($u), static::TTL, serialize($me));
return $me;
} catch (\RedisException $e) {
trigger_error($e->getMessage());
return null;
}
}
}

View file

@ -11,6 +11,7 @@
],
"require": {
"ext-iconv": "*",
"ext-redis": "*",
"ext-sodium": "*",
"ext-zlib": "*",
"components/font-awesome": "^6.1",

3
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "528c716c3d44b77191eaef0461fe108d",
"content-hash": "94e36763cae319a07395535f9c2373eb",
"packages": [
{
"name": "components/font-awesome",
@ -734,6 +734,7 @@
"prefer-lowest": false,
"platform": {
"ext-iconv": "*",
"ext-redis": "*",
"ext-sodium": "*",
"ext-zlib": "*"
},