Show sourcecode
The following files exists in this folder. Click to view.
webbserverprogrammering/submissions/projekt-matkort-handler/classes/
CardBalance.php
FoodLog.php
Restaurant.php
User.php
User.php
191 lines UTF-8 Windows (CRLF)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
<?php
class User {
private $conn; // Database connection
private $id;
private $name;
private $email;
private $created_at;
function __construct($conn){
$this->conn = $conn;
}
static function register($pdo, $name, $email, $password) {
try {
$stmt = $pdo->prepare("SELECT * FROM students WHERE email = ?");
$stmt->execute([$email]);
$user_found = $stmt->fetch();
if ($user_found) { throw new Exception("Ett konto har redan skapats med denna mejl"); }
} catch (Exception $e) {
throw $e;
}
// Generate Verification Token (64 char hex) + Expiration (15 mins)
$token = bin2hex(random_bytes(32));
$expires = date('Y-m-d H:i:s', strtotime('+15 minutes'));
try {
$stmt = $pdo->prepare("INSERT INTO students (name, email, password, is_verified, verification_token, token_expires_at) VALUES (?, ?, ?, 0, ?, ?)");
$success = $stmt->execute([$name, $email, password_hash($password, PASSWORD_DEFAULT), $token, $expires]);
if (!$success) throw new Exception("Konto kunde inte skapas");
return $token; // Return token so we can send it in the email
} catch (Exception $e) {
throw new Exception("Konto kunde inte skapas");
}
}
static function login($pdo, $email, $password) {
try {
$stmt = $pdo->prepare("SELECT * FROM students WHERE email = :email");
$stmt->execute([':email' => $email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($password, $user['password'])) {
// 1. Is user verified?
if ($user['is_verified'] == 0) {
throw new Exception("vänligen verifiera din e-post innan du loggar in.");
}
$stmt = $pdo->prepare("UPDATE students SET last_login = NOW() WHERE id = :id");
$stmt->execute([':id' => $user['id']]);
session_regenerate_id(true);
$_SESSION['user_id'] = $user['id'];
$_SESSION['name'] = $user['name'];
$_SESSION['email'] = $user['email'];
$_SESSION['is_admin'] = isset($user['is_admin']) && $user['is_admin'] == 1 ? true : false;
$_SESSION['logged_in'] = true;
} else {
throw new Exception("Felaktigt användarnamn eller lösenord");
}
} catch (Exception $e) {
throw $e; // Pass literal exception up
}
}
static function verifyEmail($pdo, $token) {
try {
$stmt = $pdo->prepare("SELECT id, token_expires_at FROM students WHERE verification_token = ? AND is_verified = 0");
$stmt->execute([$token]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) throw new Exception("Ogiltig eller redan använd länk.");
if (strtotime($user['token_expires_at']) < time()) throw new Exception("Din verifieringslänk har gått ut (15 minuter gräns).");
// Success! Verify and wipe the token
$stmt = $pdo->prepare("UPDATE students SET is_verified = 1, verification_token = NULL, token_expires_at = NULL WHERE id = ?");
$stmt->execute([$user['id']]);
return $user['id'];
} catch (PDOException $e) {
throw new Exception("Databasfel vid verifiering: " . $e->getMessage());
}
}
static function generateResetToken($pdo, $email) {
try {
$stmt = $pdo->prepare("SELECT id, is_verified FROM students WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// Don't leak if email exists or not for security, just silently return false
if (!$user || $user['is_verified'] == 0) return false;
$token = bin2hex(random_bytes(32));
$expires = date('Y-m-d H:i:s', strtotime('+15 minutes'));
$stmt = $pdo->prepare("UPDATE students SET reset_token = ?, reset_token_expires_at = ? WHERE id = ?");
$stmt->execute([$token, $expires, $user['id']]);
return $token;
} catch (PDOException $e) {
throw new Exception("Databasfel: " . $e->getMessage());
}
}
static function resetPassword($pdo, $token, $new_password) {
try {
$stmt = $pdo->prepare("SELECT id, reset_token_expires_at FROM students WHERE reset_token = ?");
$stmt->execute([$token]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) throw new Exception("Ogiltig återställningslänk.");
if (strtotime($user['reset_token_expires_at']) < time()) throw new Exception("Länken har gått ut (15 minuter gräns).");
// Valid: Update password and wipe tokens
$stmt = $pdo->prepare("UPDATE students SET password = ?, reset_token = NULL, reset_token_expires_at = NULL WHERE id = ?");
$stmt->execute([password_hash($new_password, PASSWORD_DEFAULT), $user['id']]);
return true;
} catch (PDOException $e) {
throw new Exception("Databasfel vid återställning: " . $e->getMessage());
}
}
function delete() {
}
// Admin funktion
static function getAll($pdo) {
try {
$stmt = $pdo->prepare("SELECT id, name, email, is_admin, created_at FROM students");
$success = $stmt->execute();
if(!$success){
throw new Exception;
} else {
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
} catch (Exception $e) {
throw new Exception("Kunde inte hämta all användardata");
}
}
static function getAdminUserStats($pdo) {
try {
$sql = "
SELECT
s.id,
s.name,
s.email,
MAX(coalesce(cb.amount, 0)) as current_balance,
COUNT(fl.id) as total_logs,
COALESCE(SUM(fl.money_spent), 0) as total_spent,
AVG(fl.happy_rating) as avg_happy,
AVG(fl.healthy_rating) as avg_healthy,
(
SELECT r.restaurant_name
FROM food_logs fl2
JOIN restaurants r ON fl2.restaurant_id = r.id
WHERE fl2.user_id = s.id
GROUP BY r.id, r.restaurant_name
ORDER BY COUNT(fl2.id) DESC, r.restaurant_name ASC
LIMIT 1
) as most_visited_restaurant
FROM students s
LEFT JOIN food_logs fl ON s.id = fl.user_id
LEFT JOIN card_balance cb ON s.id = cb.user_id
WHERE s.is_admin = 0 OR s.is_admin IS NULL
GROUP BY s.id
ORDER BY s.created_at DESC
";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
throw new Exception("Kunde inte hämta användarstatistik: " . $e->getMessage());
}
}
static function deleteUser($pdo, $id) {
try {
$stmt = $pdo->prepare("DELETE FROM students WHERE id = ?");
return $stmt->execute([$id]);
} catch (PDOException $e) {
throw new Exception("Kunde inte ta bort användare: " . $e->getMessage());
}
}
}