Add user registration/login, persistent likes, category hiding, and contact email
- User auth: register (nickname + password + email), login, logout with PHP sessions - Persistent likes: logged-in users' likes saved to users.json, anonymous via session - "Tykkäämäni" filter button next to search — filter liked posts, combinable with search - Hide empty/sparse categories from filter buttons until posts exist - Replace broken contact form with simple mailto link (info@tykkaa.fi) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
134
api.php
134
api.php
@@ -52,6 +52,19 @@ function isAdmin(): bool {
|
||||
return !empty($_SESSION['tykkaafi_admin']);
|
||||
}
|
||||
|
||||
function isLoggedIn(): bool {
|
||||
return !empty($_SESSION['tykkaafi_user_id']);
|
||||
}
|
||||
|
||||
function getLoggedInUser(): ?array {
|
||||
if (!isLoggedIn()) return null;
|
||||
$users = readData('users.json', []);
|
||||
foreach ($users as $u) {
|
||||
if ($u['id'] === $_SESSION['tykkaafi_user_id']) return $u;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ─── Oletusdata ────────────────────────────────────────────────
|
||||
// Kategoriat jotka on poistettu — poistetaan automaattisesti live-serveriltä
|
||||
const REMOVED_CATEGORIES = ['knitting', 'kasvit', 'matkustus', 'tips'];
|
||||
@@ -691,26 +704,55 @@ switch ($action) {
|
||||
ok(['categories' => getOrInitCategories()]);
|
||||
|
||||
case 'likes':
|
||||
$likes = readData('likes.json', new stdClass());
|
||||
$userLikes = $_SESSION['user_likes'] ?? [];
|
||||
$likes = readData('likes.json', new stdClass());
|
||||
$user = getLoggedInUser();
|
||||
if ($user) {
|
||||
$userLikes = $user['likes'] ?? [];
|
||||
} else {
|
||||
$userLikes = $_SESSION['user_likes'] ?? [];
|
||||
}
|
||||
ok(['likes' => $likes, 'userLikes' => $userLikes]);
|
||||
|
||||
case 'toggle_like':
|
||||
$postId = $body['postId'] ?? '';
|
||||
if (!$postId) err('Missing postId');
|
||||
$likes = readData('likes.json', []);
|
||||
$userLikes = $_SESSION['user_likes'] ?? [];
|
||||
$idx = array_search($postId, $userLikes, true);
|
||||
if ($idx === false) {
|
||||
$likes[$postId] = ($likes[$postId] ?? 0) + 1;
|
||||
$userLikes[] = $postId;
|
||||
$liked = true;
|
||||
$likes = readData('likes.json', []);
|
||||
$user = getLoggedInUser();
|
||||
|
||||
if ($user) {
|
||||
$users = readData('users.json', []);
|
||||
$userLikes = $user['likes'] ?? [];
|
||||
$idx = array_search($postId, $userLikes, true);
|
||||
if ($idx === false) {
|
||||
$likes[$postId] = ($likes[$postId] ?? 0) + 1;
|
||||
$userLikes[] = $postId;
|
||||
$liked = true;
|
||||
} else {
|
||||
$likes[$postId] = max(0, ($likes[$postId] ?? 1) - 1);
|
||||
array_splice($userLikes, $idx, 1);
|
||||
$liked = false;
|
||||
}
|
||||
foreach ($users as &$u) {
|
||||
if ($u['id'] === $user['id']) { $u['likes'] = array_values($userLikes); break; }
|
||||
}
|
||||
unset($u);
|
||||
writeData('users.json', $users);
|
||||
$_SESSION['user_likes'] = array_values($userLikes);
|
||||
} else {
|
||||
$likes[$postId] = max(0, ($likes[$postId] ?? 1) - 1);
|
||||
array_splice($userLikes, $idx, 1);
|
||||
$liked = false;
|
||||
$userLikes = $_SESSION['user_likes'] ?? [];
|
||||
$idx = array_search($postId, $userLikes, true);
|
||||
if ($idx === false) {
|
||||
$likes[$postId] = ($likes[$postId] ?? 0) + 1;
|
||||
$userLikes[] = $postId;
|
||||
$liked = true;
|
||||
} else {
|
||||
$likes[$postId] = max(0, ($likes[$postId] ?? 1) - 1);
|
||||
array_splice($userLikes, $idx, 1);
|
||||
$liked = false;
|
||||
}
|
||||
$_SESSION['user_likes'] = array_values($userLikes);
|
||||
}
|
||||
$_SESSION['user_likes'] = array_values($userLikes);
|
||||
|
||||
writeData('likes.json', $likes);
|
||||
ok(['liked' => $liked, 'count' => $likes[$postId] ?? 0]);
|
||||
|
||||
@@ -801,6 +843,72 @@ switch ($action) {
|
||||
case 'admin_check':
|
||||
ok(['loggedIn' => isAdmin()]);
|
||||
|
||||
// ─── Käyttäjätunnukset ─────────────────────────────────────
|
||||
case 'user_register':
|
||||
$nickname = trim($body['nickname'] ?? '');
|
||||
$email = trim($body['email'] ?? '');
|
||||
$password = $body['password'] ?? '';
|
||||
|
||||
if (!$nickname || !$password) err('Nimimerkki ja salasana vaaditaan.');
|
||||
if (mb_strlen($nickname) < 2 || mb_strlen($nickname) > 30) err('Nimimerkin tulee olla 2–30 merkkiä.');
|
||||
if (mb_strlen($password) < 6) err('Salasanan tulee olla vähintään 6 merkkiä.');
|
||||
if ($email && !filter_var($email, FILTER_VALIDATE_EMAIL)) err('Sähköpostiosoite ei kelpaa.');
|
||||
|
||||
$users = readData('users.json', []);
|
||||
foreach ($users as $u) {
|
||||
if (mb_strtolower($u['nickname']) === mb_strtolower($nickname)) {
|
||||
err('Nimimerkki on jo käytössä.');
|
||||
}
|
||||
}
|
||||
|
||||
$user = [
|
||||
'id' => 'user_' . time() . '_' . random_int(1000, 9999),
|
||||
'nickname' => htmlspecialchars($nickname, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
||||
'email' => htmlspecialchars($email, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
||||
'password' => password_hash($password, PASSWORD_DEFAULT),
|
||||
'likes' => $_SESSION['user_likes'] ?? [],
|
||||
'created' => date('Y-m-d'),
|
||||
];
|
||||
|
||||
$users[] = $user;
|
||||
writeData('users.json', $users);
|
||||
$_SESSION['tykkaafi_user_id'] = $user['id'];
|
||||
|
||||
ok(['user' => ['id' => $user['id'], 'nickname' => $user['nickname'], 'likes' => $user['likes']]]);
|
||||
|
||||
case 'user_login':
|
||||
$nickname = trim($body['nickname'] ?? '');
|
||||
$password = $body['password'] ?? '';
|
||||
if (!$nickname || !$password) err('Nimimerkki ja salasana vaaditaan.');
|
||||
|
||||
$users = readData('users.json', []);
|
||||
foreach ($users as $u) {
|
||||
if (mb_strtolower($u['nickname']) === mb_strtolower($nickname)) {
|
||||
if (password_verify($password, $u['password'])) {
|
||||
$_SESSION['tykkaafi_user_id'] = $u['id'];
|
||||
$_SESSION['user_likes'] = $u['likes'] ?? [];
|
||||
ok(['user' => ['id' => $u['id'], 'nickname' => $u['nickname'], 'likes' => $u['likes'] ?? []]]);
|
||||
}
|
||||
err('Väärä salasana.');
|
||||
}
|
||||
}
|
||||
err('Nimimerkkiä ei löydy.');
|
||||
|
||||
case 'user_logout':
|
||||
unset($_SESSION['tykkaafi_user_id']);
|
||||
ok();
|
||||
|
||||
case 'user_check':
|
||||
$user = getLoggedInUser();
|
||||
if ($user) {
|
||||
ok(['loggedIn' => true, 'user' => [
|
||||
'id' => $user['id'],
|
||||
'nickname' => $user['nickname'],
|
||||
'likes' => $user['likes'] ?? [],
|
||||
]]);
|
||||
}
|
||||
ok(['loggedIn' => false]);
|
||||
|
||||
default:
|
||||
err('Unknown action');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user