bank/
wesweb01/bank/modules/user.php1 lines
<?php
# Fil som skapar klass för användare och användardata.
require "utility.php";
date_default_timezone_set('Europe/Stockholm'); # Används för när transaktioner sparas.
# Datum skrivs ner och man vill ha det i rätt tidszon.
class User
# En klass för en användare. Innehåller funktioner för transaktioner och datalagring.
{
public static $storage = "users/%s.json"; # Sökväg till sparade användare.
# %s ersätts med namnet till användaren med hjälp av sprintf.
public $username;
public $password;
public $salt; # Salt för lösenordet, för ökad säkerhet.
public $accounts; # Lista med kontoobjekt.
public static function LoadUser($username): ?User
# Statisk funktion som försöker ladda en användare från användarnamn.
# Hämtar ett användarobjekt.
{
$file = sprintf(self::$storage, strtolower($username)); # Här används sprintf för att få filen till användaren.
if (!file_exists(($file))) # Kollar ifall användaren saknas.
return null;
$jsonData = json_decode(file_get_contents($file)); # Laddar datan från filen.
$user = new User(); # Skapar ett blankt användarobjekt
# Sedan överförs data från jsonData till user.
# Anledningen att jag gör det en för en är för att jag vill ha kontroll över vilka klasser som den lästa datan har.
# Exempelvis vill jag att accounts ska vara en lista på kontoobjekt.
# Det hade varit smidigt att definiera en struktur och ladda json-data utifrån den, som man kan i exempelvis C#
# men vad jag vet så går inte det i php.
$user->username = $jsonData->username;
$user->password = $jsonData->password;
$user->salt = $jsonData->salt;
$user->accounts = array();
foreach ($jsonData->accounts as $account) { # Här skapar vi kontoobjekt för varje konto.
array_push($user->accounts, new Account($account->name, $account->transactions, $account->mainAccount, $account->id, $account->active));
}
return $user;
}
public static function RegisterUser($username, $password): ?User
# Statisk funktion som skapar ett konto från användarnamn och lösenord.
{
if (self::UserExists($username)) # Kollar ifall användarnamnet redan är taget.
return null;
$salt = generate_uuid(); # Skapar lösenordssalt.
$user = new User(); # Här skapas ett tomt användarobjekt som senare fylls på.
$user->username = $username;
$user->password = hash_password($password, $salt);
$user->salt = $salt;
$user->accounts = array(
new Account("Bankkort", array( # Huvudbankkontot skapas och ges en välkomstbonus på 1000 kr.
new Transaction(
"Välkomstbonus",
1000
)
), true)
);
$user->saveData();
return $user;
}
public static function TryLoginUser($username, $password): ?User
# Statisk funktion som försöker logga in användare med användarnamn och lösenord.
{
if (!self::UserExists($username)) # Kontrollerar att användaren finns.
return null;
$user = self::LoadUser($username); # Laddar datan.
$hashed = hash_password($password, $user->salt); # Hashar lösenordet och kollar att de stämmer överens.
if ($user->password != $hashed)
return null;
return $user;
}
public static function UserExists($username): bool
# Statisk funktion som kollar ifall en användare finns utifrån användarnamn.
{
return file_exists(sprintf(self::$storage, strtolower($username)));
}
public function createAccount($name): Account
# Funktion som skapar ett nytt (bank)konto. Koden förklarar sig själv.
{
$account = new Account($name);
array_push($this->accounts, $account);
$this->saveData();
return $account;
}
public function getAccountFromId($id): ?Account
# Funktion som hämtar ett kontoobjekt från konto-ID.
{
foreach ($this->accounts as $account) { # Itererar genom alla och hämtar det med matchande ID.
if ($account->id == $id)
return $account;
}
return null;
}
public function getMainAccount(): ?Account
# Hämtar huvudkontot. Huvudkontot är ett konto som insättningar, uttag och mottag av externa transaktioner sker från.
# Det kan inte tas bort.
{
foreach ($this->accounts as $account) {
if ($account->mainAccount) {
return $account;
}
}
return null; # Bör aldrig inträffa
}
public function logDeposit($amount): void
# Sparar ett uttag från huvudkontot.
{
$account = $this->getMainAccount();
$account->logTransaction(new Transaction("Insättning", $amount));
$this->saveData();
}
public function logWithdrawal($amount): void
# Sparar en insättning till huvudkontot.
{
$account = $this->getMainAccount();
$account->logTransaction(new Transaction("Uttag", -$amount));
$this->saveData();
}
public function logInternalTransaction($senderAccount, $recipientAccount, $amount, $message = "Intern transaktion"): void
# Sparar en intern transkation (mellan två konton hos samma användare).
{
# Pengar tas från sändaren och ges till mottagaren.
$senderAccount->logTransaction(new Transaction($message, -$amount, $recipientAccount->id));
$recipientAccount->logTransaction(new Transaction($message, $amount, $senderAccount->id));
$this->saveData();
}
public function logExternalTransaction($senderAccount, $recipientUser, $amount): void
# Sparar en extern transkation (från en användare till en annan).
{
# Pengar tas från sändarkontot.
$senderAccount->logTransaction(new Transaction("Transaktion", -$amount, $recipientUser->username));
$this->saveData();
# Transaktionen sker till huvudkontot hos mottagaren.
$recipientAccount = $recipientUser->getMainAccount();
$recipientAccount->logTransaction(new Transaction("Transaktion", $amount, $this->username));
$recipientUser->saveData();
}
public function saveData(): void
# Sparar en användare.
{
$file = sprintf(self::$storage, strtolower($this->username));
# Eftersom hela objektet innehåller all information kan $this sparas till filen.
file_put_contents($file, json_encode($this, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
}
}
class Account
# Klass för en användares bankkonto
{
public $name;
public $id;
public $transactions; # Lista på transaktioner.
public $mainAccount; # Bool. Ska finnas exakt ett konto som är true.
public $active; # Bool. Bestämmer ifall kontot är aktivt eller inte. Konton tas aldrig bort, utan active sätts till false.
public function __construct($name, $transactions = null, $isMainAccount = false, $id = null, $active = true)
{
$this->name = $name;
$this->id = $id ?? generate_uuid();
$this->transactions = $transactions ?? array();
$this->mainAccount = $isMainAccount;
$this->active = $active;
}
public function getBalance(): int
# Hämtar saldot för kontot genom att summera alla transaktioner.
{
$balance = 0;
foreach ($this->transactions as $transaction) {
$balance += $transaction->sum;
}
return $balance;
}
public function logTransaction($transaction): void
# Sparar en transaktion till kontot.
# Transaktionen sparas inte, utan User->saveData() måste köras.
{
array_push($this->transactions, $transaction);
}
}
class Transaction
# Klass för transaktioner.
# Innehåller inte särskilt mycket funktionalitet, men fills för att hålla transaktioner i objekt-form.
{
public $name;
public $sum; # Mängden pengar som överförts. Är negativt ifall pengar har skickats från kontot.
public $otherId; # Konto-ID för andra kontot i transaktionen.
# Eftersom detta objekt ligger i en array i varje konto, vet man redan vilket ena kontot är.
public $date;
public function __construct($name, $sum, $otherId = null, $date = null)
{
$this->name = $name;
$this->sum = $sum;
$this->otherId = $otherId;
$this->date = $date ?? date("Y-m-d"); # Markerar nuvarande datumet ifall inget annat angetts.
}
}
?>