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

諏訪子 <suwako@076.moe>、2025-12-12 00:50
コミット 72f3f5d39bcd6fccce246e10be2b9e23c14174e3 ・親 4085b77 ・ファイルを見る

5個のファイル、+112 -6

変更 route.php
@@ -44,6 +44,7 @@
4444 $routes[] = Route::add('GET', 'register', User::class.'@register');
4545 }
4646 $routes[] = Route::add('GET', 'logout', User::class.'@logout');
47+ $routes[] = Route::add('GET', 'profile/{name}', User::class.'@profile');
4748 }
4849
4950 /* if (RSS_ENABLED) {} */
@@ -144,4 +144,37 @@
144144 throw new \Exception($e->getMessage());
145145 }
146146 }
147+
148+ public function profile(array $params): void {
149+ if (!AUTH_ENABLED) return;
150+ $name = '';
151+ if (isset($params['name'])) $name = $params['name'];
152+ if ($name === '') {
153+ header('Location: /');
154+ exit();
155+ }
156+
157+ try {
158+ $auth = new Auth;
159+ $user = $auth->getLoggedInUser();
160+ $u = $auth->getUser($name);
161+
162+ $tmpl = new Template('/');
163+ $pagetit = 'サインイン';
164+ $description = 'サイトにサインイン';
165+
166+ $tmpl->assign('pagetit', $pagetit);
167+ $tmpl->assign('curPage', 'auth');
168+ $tmpl->assign('custCss', false);
169+ $tmpl->assign('menu', $this->getMenu());
170+ $tmpl->assign('description', $description);
171+ $tmpl->assign('error', $error);
172+ $tmpl->assign('user', $user);
173+ $tmpl->assign('u', $u);
174+
175+ $tmpl->render('profile');
176+ } catch (\Exception $e) {
177+ throw new \Exception($e->getMessage());
178+ }
179+ }
147180 }
@@ -34,7 +34,27 @@
3434 return $this->pubUser;
3535 }
3636
37- public function setToken(string $username, string $password): \Result {
37+ public function getUser(string $name): \stdClass {
38+ $user = $this->getUserDataFromName($name);
39+ unset($user->password);
40+ unset($user->tokens);
41+ $myself = $this->getUserData();
42+ if ($myself->role === 1) {
43+ unset($user->email);
44+ }
45+ $user->name = namecolor($user);
46+ $user->regDate = date('Y年m月d日', $user->regDate);
47+ $user->gender = $user->gender === 0 ? '男' : ($user->gender === 1 ? '女' : '不明');
48+ $user->role = $user->role === 1 ? '管理者' : ($user->role === -1 ? 'BANされた' : 'ユーザー');
49+ $user->avatar = '/static/user/'.($user->avatar === '' ? 'noicon.png' : $user->username.'/'.$user->avatar);
50+ $user->altName = $user->displayname ?: $user->username;
51+ unset($user->username);
52+ unset($user->displayname);
53+ unset($user->namecolor);
54+ return $user;
55+ }
56+
57+ public function setToken(string $username, #[SensitiveParameter] string $password): \Result {
3858 if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
3959 $userData = $this->getUserData();
4060 if (!isset($userData->tokens) || !is_array($userData->tokens)) $userData->tokens = [];
@@ -129,7 +149,7 @@
129149 return \Result::Error("エラー:ユーザー「{$username}」は存在しません。");
130150 }
131151
132- public function mkUser(?string $username = null, ?string $password = null, ?string $passwordVerify = null, ?string $email = null): \Result {
152+ public function mkUser(?string $username = null, #[SensitiveParameter] ?string $password = null, ?string $passwordVerify = null, ?string $email = null): \Result {
133153 if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
134154 if (!AUTH_REGISTER_ENABLED) return \Result::Error('ユーザー登録は無効です。');
135155 $resUsr = $this->verifyUsername($username);
@@ -191,7 +211,7 @@
191211
192212 ////////////////////
193213
194- private function verifyLogin(string $username, string $password): \Result {
214+ private function verifyLogin(string $username, #[SensitiveParameter] string $password): \Result {
195215 if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
196216 $userData = $this->getUserData();
197217 if ($username !== $userData->username || !password_verify($password, $userData->password)) {
@@ -286,6 +306,39 @@
286306 return json_decode($lines);
287307 }
288308
309+ private function getUserDataFromName(string $name): \stdClass {
310+ if (!AUTH_ENABLED) return new \stdClass;
311+ $file = scandir($this->dataDir);
312+ $userFile = "";
313+ $matches = [];
314+
315+ foreach ($file as $f) {
316+ if ($f === '.kara' || $f === '.' || $f === '..') continue;
317+ if (preg_match('/^(.*?)\.(.*?)\.json$/', $f, $matches)) {
318+ if (isset($matches[2]) && $matches[2] === $name) {
319+ $userFile = $matches[0];
320+ break;
321+ }
322+ }
323+ }
324+ $path = $this->dataDir.$userFile;
325+ unset($file, $userFile);
326+
327+ if (!file_exists($path) || !is_readable($path)) {
328+ kys('エラー');
329+ }
330+
331+ $fp = fopen($path, 'r');
332+ assert_not_null($fp);
333+ if (!$fp) kys('ユーザーが存在しない。');
334+ $lines = "";
335+ while (($buf = fgets($fp, 4096)) !== false) $lines .= $buf.PHP_EOL;
336+ if (!feof($fp)) kys("エラー:不明なエラー");
337+ fclose($fp);
338+ unset($path);
339+ return json_decode($lines);
340+ }
341+
289342 private function isEmailExist(?string $email = null): \Result {
290343 if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
291344 $userList = scandir($this->dataDir);
@@ -342,7 +395,7 @@
342395 return \Result::Success();
343396 }
344397
345- private function verifyPassword(?string $password = null, ?string $passwordVerify = null): \Result {
398+ private function verifyPassword(#[SensitiveParameter] ?string $password = null, #[SensitiveParameter] ?string $passwordVerify = null): \Result {
346399 if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
347400 if (null === $password || '' === $password) return \Result::Error('エラー:パスワードをご入力下さい。');
348401 if ($password !== $passwordVerify) return \Result::Error('エラー:パスワードは一致していません。');
@@ -355,7 +408,7 @@
355408 return \Result::Success();
356409 }
357410
358- private function checkPasswordStandards(?string $password = null): \Result {
411+ private function checkPasswordStandards(#[SensitiveParameter] ?string $password = null): \Result {
359412 if (!AUTH_ENABLED) return \Result::Error('エラー:認証システムは無効です。');
360413 if (strlen($password) < $this->minPassLen) return \Result::Error("エラー:パスワードは{$this->minPassLen}以上をご入力下さい。");
361414
@@ -59,7 +59,7 @@
5959 {@ if (AUTH_ENABLED) @}
6060 <div>
6161 {@ if (isset($user) && isset($user->id) && $user->id > 0) @}
62- お帰りなしゃ~い、{{{ namecolor($user) }}}! (<a href="/logout">ログアウト</a>)
62+ お帰りなしゃ~い、<a style="text-decoration: none;" href="/profile/{{ $user->username }}">{{{ namecolor($user) }}}</a>! (<a href="/logout">ログアウト</a>)
6363 {@ else @}
6464 <a href="/login">ログイン</a>
6565 {@ if (AUTH_REGISTER_ENABLED) @}
@@ -0,0 +1,19 @@
1+{@ include(common/header) @}
2+ <h1 class="paragraph">{{{ $u->name }}}</h1>
3+ <p class="paragraph">
4+ <table>
5+ <tbody>
6+ <tr>
7+ <td rowspan="3"><img src="{{ $u->avatar }}" alt="{{ $u->altName }}" style="max-width: 100px; max-height: 100px; width: 100%; height: 100%;" /></td>
8+ <td>登録日:{{ $u->regDate }}</td>
9+ </tr>
10+ <tr>
11+ <td>ロール:{{ $u->role }}</td>
12+ </tr>
13+ <tr>
14+ <td>性別:{{ $u->gender }}</td>
15+ </tr>
16+ </tbody>
17+ </table>
18+ </p>
19+{@ include(common/footer) @}