ユーザープロフィール機能の追加

This commit is contained in:
2025-12-12 00:50:11 +09:00
parent 4085b77f6a
commit 72f3f5d39b
5 changed files with 112 additions and 6 deletions

View File

@@ -44,6 +44,7 @@ if (AUTH_ENABLED) {
$routes[] = Route::add('GET', 'register', User::class.'@register'); $routes[] = Route::add('GET', 'register', User::class.'@register');
} }
$routes[] = Route::add('GET', 'logout', User::class.'@logout'); $routes[] = Route::add('GET', 'logout', User::class.'@logout');
$routes[] = Route::add('GET', 'profile/{name}', User::class.'@profile');
} }
/* if (RSS_ENABLED) {} */ /* if (RSS_ENABLED) {} */

View File

@@ -144,4 +144,37 @@ class User {
throw new \Exception($e->getMessage()); throw new \Exception($e->getMessage());
} }
} }
public function profile(array $params): void {
if (!AUTH_ENABLED) return;
$name = '';
if (isset($params['name'])) $name = $params['name'];
if ($name === '') {
header('Location: /');
exit();
}
try {
$auth = new Auth;
$user = $auth->getLoggedInUser();
$u = $auth->getUser($name);
$tmpl = new Template('/');
$pagetit = 'サインイン';
$description = 'サイトにサインイン';
$tmpl->assign('pagetit', $pagetit);
$tmpl->assign('curPage', 'auth');
$tmpl->assign('custCss', false);
$tmpl->assign('menu', $this->getMenu());
$tmpl->assign('description', $description);
$tmpl->assign('error', $error);
$tmpl->assign('user', $user);
$tmpl->assign('u', $u);
$tmpl->render('profile');
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
} }

View File

@@ -34,7 +34,27 @@ class Auth {
return $this->pubUser; return $this->pubUser;
} }
public function setToken(string $username, string $password): \Result { public function getUser(string $name): \stdClass {
$user = $this->getUserDataFromName($name);
unset($user->password);
unset($user->tokens);
$myself = $this->getUserData();
if ($myself->role === 1) {
unset($user->email);
}
$user->name = namecolor($user);
$user->regDate = date('Y年m月d日', $user->regDate);
$user->gender = $user->gender === 0 ? '男' : ($user->gender === 1 ? '女' : '不明');
$user->role = $user->role === 1 ? '管理者' : ($user->role === -1 ? 'BANされた' : 'ユーザー');
$user->avatar = '/static/user/'.($user->avatar === '' ? 'noicon.png' : $user->username.'/'.$user->avatar);
$user->altName = $user->displayname ?: $user->username;
unset($user->username);
unset($user->displayname);
unset($user->namecolor);
return $user;
}
public function setToken(string $username, #[SensitiveParameter] string $password): \Result {
if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。'); if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
$userData = $this->getUserData(); $userData = $this->getUserData();
if (!isset($userData->tokens) || !is_array($userData->tokens)) $userData->tokens = []; if (!isset($userData->tokens) || !is_array($userData->tokens)) $userData->tokens = [];
@@ -129,7 +149,7 @@ class Auth {
return \Result::Error("エラー:ユーザー「{$username}」は存在しません。"); return \Result::Error("エラー:ユーザー「{$username}」は存在しません。");
} }
public function mkUser(?string $username = null, ?string $password = null, ?string $passwordVerify = null, ?string $email = null): \Result { public function mkUser(?string $username = null, #[SensitiveParameter] ?string $password = null, ?string $passwordVerify = null, ?string $email = null): \Result {
if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。'); if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
if (!AUTH_REGISTER_ENABLED) return \Result::Error('ユーザー登録は無効です。'); if (!AUTH_REGISTER_ENABLED) return \Result::Error('ユーザー登録は無効です。');
$resUsr = $this->verifyUsername($username); $resUsr = $this->verifyUsername($username);
@@ -191,7 +211,7 @@ class Auth {
//////////////////// ////////////////////
private function verifyLogin(string $username, string $password): \Result { private function verifyLogin(string $username, #[SensitiveParameter] string $password): \Result {
if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。'); if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
$userData = $this->getUserData(); $userData = $this->getUserData();
if ($username !== $userData->username || !password_verify($password, $userData->password)) { if ($username !== $userData->username || !password_verify($password, $userData->password)) {
@@ -286,6 +306,39 @@ class Auth {
return json_decode($lines); return json_decode($lines);
} }
private function getUserDataFromName(string $name): \stdClass {
if (!AUTH_ENABLED) return new \stdClass;
$file = scandir($this->dataDir);
$userFile = "";
$matches = [];
foreach ($file as $f) {
if ($f === '.kara' || $f === '.' || $f === '..') continue;
if (preg_match('/^(.*?)\.(.*?)\.json$/', $f, $matches)) {
if (isset($matches[2]) && $matches[2] === $name) {
$userFile = $matches[0];
break;
}
}
}
$path = $this->dataDir.$userFile;
unset($file, $userFile);
if (!file_exists($path) || !is_readable($path)) {
kys('エラー');
}
$fp = fopen($path, 'r');
assert_not_null($fp);
if (!$fp) kys('ユーザーが存在しない。');
$lines = "";
while (($buf = fgets($fp, 4096)) !== false) $lines .= $buf.PHP_EOL;
if (!feof($fp)) kys("エラー:不明なエラー");
fclose($fp);
unset($path);
return json_decode($lines);
}
private function isEmailExist(?string $email = null): \Result { private function isEmailExist(?string $email = null): \Result {
if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。'); if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
$userList = scandir($this->dataDir); $userList = scandir($this->dataDir);
@@ -342,7 +395,7 @@ class Auth {
return \Result::Success(); return \Result::Success();
} }
private function verifyPassword(?string $password = null, ?string $passwordVerify = null): \Result { private function verifyPassword(#[SensitiveParameter] ?string $password = null, #[SensitiveParameter] ?string $passwordVerify = null): \Result {
if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。'); if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
if (null === $password || '' === $password) return \Result::Error('エラー:パスワードをご入力下さい。'); if (null === $password || '' === $password) return \Result::Error('エラー:パスワードをご入力下さい。');
if ($password !== $passwordVerify) return \Result::Error('エラー:パスワードは一致していません。'); if ($password !== $passwordVerify) return \Result::Error('エラー:パスワードは一致していません。');
@@ -355,7 +408,7 @@ class Auth {
return \Result::Success(); return \Result::Success();
} }
private function checkPasswordStandards(?string $password = null): \Result { private function checkPasswordStandards(#[SensitiveParameter] ?string $password = null): \Result {
if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。'); if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
if (strlen($password) < $this->minPassLen) return \Result::Error("エラー:パスワードは{$this->minPassLen}以上をご入力下さい。"); if (strlen($password) < $this->minPassLen) return \Result::Error("エラー:パスワードは{$this->minPassLen}以上をご入力下さい。");

View File

@@ -59,7 +59,7 @@
{@ if (AUTH_ENABLED) @} {@ if (AUTH_ENABLED) @}
<div> <div>
{@ if (isset($user) && isset($user->id) && $user->id > 0) @} {@ if (isset($user) && isset($user->id) && $user->id > 0) @}
お帰りなしゃ~い、{{{ namecolor($user) }}} (<a href="/logout">ログアウト</a>) お帰りなしゃ~い、<a style="text-decoration: none;" href="/profile/{{ $user->username }}">{{{ namecolor($user) }}}</a> (<a href="/logout">ログアウト</a>)
{@ else @} {@ else @}
<a href="/login">ログイン</a> <a href="/login">ログイン</a>
{@ if (AUTH_REGISTER_ENABLED) @} {@ if (AUTH_REGISTER_ENABLED) @}

19
view/profile.maron Normal file
View File

@@ -0,0 +1,19 @@
{@ include(common/header) @}
<h1 class="paragraph">{{{ $u->name }}}</h1>
<p class="paragraph">
<table>
<tbody>
<tr>
<td rowspan="3"><img src="{{ $u->avatar }}" alt="{{ $u->altName }}" style="max-width: 100px; max-height: 100px; width: 100%; height: 100%;" /></td>
<td>登録日:{{ $u->regDate }}</td>
</tr>
<tr>
<td>ロール:{{ $u->role }}</td>
</tr>
<tr>
<td>性別:{{ $u->gender }}</td>
</tr>
</tbody>
</table>
</p>
{@ include(common/footer) @}