diff --git a/config/sql/se/Users.sql b/config/sql/se/Users.sql index 87310a17..ab40a1d5 100644 --- a/config/sql/se/Users.sql +++ b/config/sql/se/Users.sql @@ -4,6 +4,7 @@ CREATE TABLE `Users` ( `Name` varchar(255) DEFAULT NULL, `Created` datetime NOT NULL, `Uuid` char(36) NOT NULL, + `PasswordHash` varchar(255) NULL, PRIMARY KEY (`UserId`), UNIQUE KEY `idxEmail` (`Email`) ) ENGINE=InnoDB AUTO_INCREMENT=281 DEFAULT CHARSET=utf8mb4; diff --git a/lib/Artwork.php b/lib/Artwork.php index 74b1b9da..a5855794 100644 --- a/lib/Artwork.php +++ b/lib/Artwork.php @@ -17,7 +17,7 @@ use function Safe\sprintf; * @property string $ImageUrl * @property string $ThumbUrl * @property string $Thumb2xUrl - * @property string $ImageSize + * @property string $Dimensions * @property Ebook $Ebook * @property Museum $Museum * @property ?ImageMimeType $MimeType @@ -48,7 +48,7 @@ class Artwork extends PropertiesBase{ protected $_ImageUrl = null; protected $_ThumbUrl = null; protected $_Thumb2xUrl = null; - protected $_ImageSize = null; + protected $_Dimensions = null; protected $_Ebook = null; protected $_Museum = null; protected ?ImageMimeType $_MimeType = null; @@ -157,26 +157,20 @@ class Artwork extends PropertiesBase{ return $this->_Thumb2xUrl; } - protected function GetImageSize(): string{ + protected function GetDimensions(): string{ try{ - $bytes = @filesize(WEB_ROOT . $this->ImageUrl); - $sizes = 'BKMGTP'; - $factor = intval(floor((strlen((string)$bytes) - 1) / 3)); - $sizeNumber = sprintf('%.1f', $bytes / pow(1024, $factor)); - $sizeUnit = $sizes[$factor] ?? ''; - $this->_ImageSize = $sizeNumber . $sizeUnit; list($imageWidth, $imageHeight) = getimagesize(WEB_ROOT . $this->ImageUrl); if($imageWidth && $imageHeight){ - $this->_ImageSize .= ' (' . $imageWidth . ' × ' . $imageHeight . ')'; + $this->_Dimensions .= $imageWidth . ' × ' . $imageHeight; } } catch(Exception){ // Image doesn't exist - $this->_ImageSize = ''; + $this->_Dimensions = ''; } - return $this->_ImageSize; + return $this->_Dimensions; } protected function GetEbook(): ?Ebook{ @@ -217,7 +211,7 @@ class Artwork extends PropertiesBase{ $error->Add($ex); } - if(trim($this->Exception) == ''){ + if($this->Exception !== null && trim($this->Exception) == ''){ $this->Exception = null; } @@ -517,11 +511,6 @@ class Artwork extends PropertiesBase{ return false; } - public function HasMatchingMuseum(): bool{ - - return true; - } - // *********** // ORM METHODS // *********** diff --git a/lib/Core.php b/lib/Core.php index 5557b660..e0085e21 100644 --- a/lib/Core.php +++ b/lib/Core.php @@ -38,7 +38,14 @@ if($GLOBALS['User'] === null){ $session = new Session(); try{ - $session->Create($httpBasicAuthLogin); + $password = $_SERVER['PHP_AUTH_PW'] ?? null; + if($password == ''){ + $password = null; + } + + // Most patrons have a null password, meaning they only need to log in using an email and a blank password. + // Some users with admin rights need a password to log in. + $session->Create($httpBasicAuthLogin, $password); $GLOBALS['User'] = $session->User; } catch(Exception){ diff --git a/lib/Exceptions/InvalidUserException.php b/lib/Exceptions/InvalidUserException.php index 380f433c..36818da3 100644 --- a/lib/Exceptions/InvalidUserException.php +++ b/lib/Exceptions/InvalidUserException.php @@ -2,5 +2,5 @@ namespace Exceptions; class InvalidUserException extends AppException{ - protected $message = 'We couldn’t locate you in our system.'; + protected $message = 'We couldn’t validate your login information.'; } diff --git a/lib/Exceptions/PasswordRequiredException.php b/lib/Exceptions/PasswordRequiredException.php new file mode 100644 index 00000000..daf0d8f7 --- /dev/null +++ b/lib/Exceptions/PasswordRequiredException.php @@ -0,0 +1,5 @@ + +namespace Exceptions; + +class PasswordRequiredException extends AppException{ +} diff --git a/lib/Library.php b/lib/Library.php index cb436c68..f617afa3 100644 --- a/lib/Library.php +++ b/lib/Library.php @@ -167,8 +167,8 @@ class Library{ private static function GetBrowsableArtwork(): array{ return Db::Query(' SELECT * - FROM Artworks - WHERE Status IN ("approved", "in_use")', [], 'Artwork'); + from Artworks + where Status in ("approved", "in_use")', [], 'Artwork'); } /** @@ -262,7 +262,6 @@ class Library{ } return $matches; - } /** diff --git a/lib/Session.php b/lib/Session.php index 962f969d..389a450f 100644 --- a/lib/Session.php +++ b/lib/Session.php @@ -32,8 +32,8 @@ class Session extends PropertiesBase{ // METHODS // ******* - public function Create(?string $email = null): void{ - $this->User = User::GetIfRegistered($email); + public function Create(?string $email = null, ?string $password = null): void{ + $this->User = User::GetIfRegistered($email, $password); $this->UserId = $this->User->UserId; $existingSessions = Db::Query(' @@ -59,7 +59,7 @@ class Session extends PropertiesBase{ ', [$this->UserId, $this->SessionId, $this->Created]); } - $this->SetSessionCookie($this->SessionId); + self::SetSessionCookie($this->SessionId); } public static function GetLoggedInUser(): ?User{ diff --git a/lib/User.php b/lib/User.php index cffe7959..060ba8a6 100644 --- a/lib/User.php +++ b/lib/User.php @@ -12,6 +12,7 @@ class User extends PropertiesBase{ public $Email; public $Created; public $Uuid; + public $PasswordHash; protected $_IsRegistered = null; protected $_Payments = null; protected $_Benefits = null; @@ -73,19 +74,25 @@ class User extends PropertiesBase{ // METHODS // ******* - public function Create(): void{ + public function Create(?string $password = null): void{ $uuid = Uuid::uuid4(); $this->Uuid = $uuid->toString(); $this->Created = new DateTime(); + $this->PasswordHash = null; + if($password !== null){ + $this->PasswordHash = password_hash($password, PASSWORD_DEFAULT); + } + try{ Db::Query(' - INSERT into Users (Email, Name, Uuid, Created) + INSERT into Users (Email, Name, Uuid, Created, PasswordHash) values (?, + ?, ?, ?, ?) - ', [$this->Email, $this->Name, $this->Uuid, $this->Created]); + ', [$this->Email, $this->Name, $this->Uuid, $this->Created, $this->PasswordHash]); } catch(PDOException $ex){ if(($ex->errorInfo[1] ?? 0) == 1062){ @@ -137,7 +144,7 @@ class User extends PropertiesBase{ return $result[0]; } - public static function GetIfRegistered(?string $identifier): User{ + public static function GetIfRegistered(?string $identifier, ?string $password = null): User{ // We consider a user "registered" if they have a row in the Benefits table. // Emails without that row may only be signed up for the newsletter and thus are not "registered" users // The identifier is either an email or a UUID (api key) @@ -157,6 +164,15 @@ class User extends PropertiesBase{ throw new Exceptions\InvalidUserException(); } + if($result[0]->PasswordHash !== null && $password === null){ + // Indicate that a password is required before we log in + throw new Exceptions\PasswordRequiredException(); + } + + if($result[0]->PasswordHash !== null && !password_verify($password ?? '', $result[0]->PasswordHash)){ + throw new Exceptions\InvalidUserException(); + } + return $result[0]; } } diff --git a/scripts/upsert-to-cover-art-database b/scripts/upsert-to-cover-art-database index beb85062..9a3f7b5f 100755 --- a/scripts/upsert-to-cover-art-database +++ b/scripts/upsert-to-cover-art-database @@ -112,6 +112,7 @@ if($artwork === null){ } $artwork = new Artwork(); + $artwork->Artist = new Artist(); $artwork->Artist = $artist; $artwork->Name = $artworkName; $artwork->CompletedYear = $completedYear; diff --git a/templates/ArtworkDetail.php b/templates/ArtworkDetail.php index ec0233ee..4afe4efa 100644 --- a/templates/ArtworkDetail.php +++ b/templates/ArtworkDetail.php @@ -1,5 +1,6 @@ $artwork = $artwork ?? null; +$showCopyrightNotice = $showCopyrightNotice ?? true; if($artwork === null){ return; @@ -15,31 +16,29 @@ if($artwork === null){ -= Template::ImageCopyrightNotice() ?> + if($showCopyrightNotice){ ?> + = Template::ImageCopyrightNotice() ?> + } ?>
Title | -= Formatter::ToPlainText($artwork->Name) ?> | += Formatter::ToPlainText($artwork->Name) ?> | |
Artist | - = Formatter::ToPlainText($artwork->Artist->Name) ?> if(sizeof($artwork->Artist->AlternateSpellings) > 0){ ?> (AKA | , ) } ?> if($artwork->Artist->DeathYear !== null){ ?>, d. = $artwork->Artist->DeathYear ?> } ?> + = Formatter::ToPlainText($artwork->Artist->Name) ?> if(sizeof($artwork->Artist->AlternateSpellings) > 0){ ?> (AKA , ) } ?> if($artwork->Artist->DeathYear !== null){ ?> (d. = $artwork->Artist->DeathYear ?>) } ?>||
Year completed | -if($artwork->CompletedYear === null){ ?>(unknown) }else{ ?>= $artwork->CompletedYear ?> if($artwork->CompletedYearIsCirca){ ?> (circa) } ?> } ?> | +if($artwork->CompletedYear === null){ ?>Unknown }else{ ?> if($artwork->CompletedYearIsCirca){ ?>Circa } ?>= $artwork->CompletedYear ?> } ?> | |
File size | -= $artwork->ImageSize ?> | -||
Uploaded | -= $artwork->Created->format('F j, Y g:i a') ?> | +Dimensions | += $artwork->Dimensions ?> |
Status | @@ -70,9 +69,8 @@ if($artwork === null){