Merge branch 'develop' into stable

This commit is contained in:
Jay Trees 2022-01-18 13:43:49 +01:00
commit aa7e0d6eab
19 changed files with 366 additions and 32 deletions

View file

@ -15,6 +15,10 @@ Use at your own risk.
![Create a wishlist](/includes/assets/img/wishlist-create.png "Create a wishlist") ![Create a wishlist](/includes/assets/img/wishlist-create.png "Create a wishlist")
![Add a product](/includes/assets/img/wishlist-product-add.png "Add a product") ![Add a product](/includes/assets/img/wishlist-product-add.png "Add a product")
## Installation
1. Download the latest [release](https://github.com/grandeljay/wishthis/releases) and upload all files to your server
1. Follow the instructions of the installer
## Contributing ## Contributing
Install dependencies Install dependencies
``` ```

View file

@ -12,3 +12,10 @@
.ui.modal > .actions { .ui.modal > .actions {
text-align: inherit; text-align: inherit;
} }
/**
* Progress
*/
.ui.progress.nolabel:last-child {
margin: 0;
}

View file

@ -1,9 +1,4 @@
$(function() { $(function() {
/**
* URL Parameter
*/
const urlParams = new URLSearchParams(window.location.search);
/** /**
* Fomantic UI * Fomantic UI
*/ */
@ -20,6 +15,11 @@ $(function() {
}); });
function wishlistRefresh() { function wishlistRefresh() {
/**
* URL Parameter
*/
const urlParams = new URLSearchParams(window.location.search);
$('.ui.dropdown.wishlists').api({ $('.ui.dropdown.wishlists').api({
action: 'get wishlists', action: 'get wishlists',
method: 'GET', method: 'GET',

View file

@ -9,9 +9,11 @@ $(function() {
if (wishlistValue) { if (wishlistValue) {
$('.wishlist-view').removeClass('disabled'); $('.wishlist-view').removeClass('disabled');
$('.wishlist-share').removeClass('disabled');
$('.wishlist-delete button').removeClass('disabled'); $('.wishlist-delete button').removeClass('disabled');
} else { } else {
$('.wishlist-view').addClass('disabled'); $('.wishlist-view').addClass('disabled');
$('.wishlist-share').addClass('disabled');
$('.wishlist-delete button').addClass('disabled'); $('.wishlist-delete button').addClass('disabled');
} }
}); });

View file

@ -26,7 +26,7 @@ class Database
$this->pdo = new \PDO($dsn, $this->user, $this->password, $options); $this->pdo = new \PDO($dsn, $this->user, $this->password, $options);
} }
public function query(string $query) public function query(string $query): mixed
{ {
return $this->pdo->query( return $this->pdo->query(
$query, $query,

View file

@ -40,4 +40,18 @@ class Options
return $value; return $value;
} }
public function setOption(string $key, string $value): void
{
try {
$option = $this->database->query('UPDATE `options`
SET `value`
WHERE `key` = ' . $key . '
;');
$value = $option['value'] ?? '';
} catch (\Throwable $th) {
//throw $th;
}
}
} }

View file

@ -10,7 +10,7 @@ use wishthis\User;
class Page class Page
{ {
private string $language = 'en'; public string $language = 'en';
/** /**
* __construct * __construct
@ -18,13 +18,15 @@ class Page
* @param string $filepath The filepath (__FILE__) of the page. * @param string $filepath The filepath (__FILE__) of the page.
* @param string $title The HTML title of the page. * @param string $title The HTML title of the page.
*/ */
public function __construct(string $filepath, public string $title = 'wishthis') public function __construct(string $filepath, public string $title = 'wishthis', public int $power = 0)
{ {
$this->name = pathinfo($filepath, PATHINFO_FILENAME); $this->name = pathinfo($filepath, PATHINFO_FILENAME);
/** /**
* Session * Session
*/ */
global $user;
$disableRedirect = array( $disableRedirect = array(
'home', 'home',
'login', 'login',
@ -35,6 +37,14 @@ class Page
header('Location: /?page=login'); header('Location: /?page=login');
die(); die();
} }
/**
* Power
*/
if ($user->power < $this->power) {
header('Location: /?page=power&required=' . $this->power);
die();
}
} }
public function header(): void public function header(): void
@ -162,7 +172,7 @@ class Page
</div> </div>
</div> </div>
<?php global $options; ?> <?php global $options; ?>
<?php if ($options->updateAvailable && $user && $user->isLoggedIn()) { ?> <?php if ($options->updateAvailable && $user && 100 === $user->power) { ?>
<a class="item" href="/?page=update"> <a class="item" href="/?page=update">
<i class="upload icon"></i> Update <i class="upload icon"></i> Update
</a> </a>
@ -195,7 +205,9 @@ class Page
</div> </div>
<div class="ui inverted link list"> <div class="ui inverted link list">
<a class="item" href="https://github.com/grandeljay/wishthis" target="_blank"><i class="big github icon"></i></a> <a class="item" href="https://github.com/grandeljay/wishthis" target="_blank">
<i class="big github icon"></i>
</a>
</div> </div>
</div> </div>
</div> </div>

View file

@ -13,14 +13,29 @@ namespace wishthis;
class User class User
{ {
public int $id; public int $id;
public int $power = 0;
public function __construct(int $id = -1) public function __construct(int $id = -1)
{ {
if (-1 === $id) { if (-1 === $id) {
$this->id = $_SESSION['user']['id']; if (isset($_SESSION['user']['id'])) {
$this->id = $_SESSION['user']['id'];
}
} else { } else {
$this->id = $id; $this->id = $id;
} }
if (!isset($this->id)) {
return;
}
global $database;
$user = $database->query('SELECT * FROM `users`
WHERE `id` = ' . $this->id . ';')
->fetch();
$this->power = $user['power'];
} }
/** /**

View file

@ -101,7 +101,7 @@ switch ($step) {
$database->query('CREATE TABLE `users` ( $database->query('CREATE TABLE `users` (
`id` int PRIMARY KEY AUTO_INCREMENT, `id` int PRIMARY KEY AUTO_INCREMENT,
`email` varchar(64) NOT NULL UNIQUE, `email` varchar(64) NOT NULL UNIQUE,
`password` varchar(128) NOT NULL `password` varchar(128) NOT NULL INDEX
);'); );');
/** /**
@ -122,7 +122,7 @@ switch ($step) {
$database->query('CREATE TABLE `products` ( $database->query('CREATE TABLE `products` (
`id` int NOT NULL PRIMARY KEY AUTO_INCREMENT, `id` int NOT NULL PRIMARY KEY AUTO_INCREMENT,
`wishlist` int NOT NULL, `wishlist` int NOT NULL,
`url` VARCHAR(255) NOT NULL, `hash` VARCHAR(255) NOT NULL INDEX,
FOREIGN KEY (`wishlist`) FOREIGN KEY (`wishlist`)
REFERENCES `wishlists` (`id`) REFERENCES `wishlists` (`id`)
ON DELETE CASCADE ON DELETE CASCADE

View file

@ -11,13 +11,25 @@ use wishthis\Page;
$page = new page(__FILE__, 'Login'); $page = new page(__FILE__, 'Login');
if (isset($_POST['email'], $_POST['password'])) { if (isset($_POST['email'], $_POST['password'])) {
$email = $_POST['email'];
$password = sha1($_POST['password']);
$database->query('UPDATE `users`
SET `last_login` = NOW()
WHERE `email` = "' . $email . '"
AND `password` = "' . $password . '"
;');
$user = $database->query( $user = $database->query(
'SELECT * FROM `users` 'SELECT * FROM `users`
WHERE `email` = "' . $_POST['email'] . '" WHERE `email` = "' . $email . '"
AND `password` = "' . sha1($_POST['password']) . '";' AND `password` = "' . $password . '";'
)->fetch(); )->fetch();
$_SESSION['user'] = $user; if (false === $user) {
# code...
} else {
$_SESSION['user'] = $user;
}
} }
if (isset($_SESSION['user'])) { if (isset($_SESSION['user'])) {

View file

@ -10,7 +10,12 @@ use wishthis\Page;
$page = new page(__FILE__, 'Logout'); $page = new page(__FILE__, 'Logout');
session_destroy(); if (PHP_SESSION_ACTIVE === session_status()) {
session_destroy();
header('Location: /?page=logout');
die();
}
$page->header(); $page->header();
$page->navigation(); $page->navigation();

32
includes/pages/power.php Normal file
View file

@ -0,0 +1,32 @@
<?php
/**
* power.php
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
use wishthis\Page;
$page = new page(__FILE__, 'Insufficient power');
$page->header();
$page->navigation();
?>
<main>
<div class="ui container">
<h1 class="ui header"><?= $page->title ?></h1>
<div class="ui segment">
<h2 class="ui header">Restricted access</h2>
<p>
You do not have enough power to view this page.
You need <strong><?= $_GET['required'] ?></strong> to see this page, but only have <strong><?= $user->power ?></strong>.
</p>
</div>
</div>
</main>
<?php
$page->footer();
?>

View file

@ -11,10 +11,19 @@ use wishthis\Page;
$page = new page(__FILE__, 'Register'); $page = new page(__FILE__, 'Register');
if (isset($_POST['email'], $_POST['password'])) { if (isset($_POST['email'], $_POST['password'])) {
$database->query('INSERT INTO `users` $users = $database->query('SELECT * FROM `users`;')->fetchAll();
(`email`, `password`) VALUES
("' . $_POST['email'] . '", "' . sha1($_POST['password']) . '") if (0 === count($users)) {
;'); $database->query('INSERT INTO `users`
(`email`, `password`, `power`) VALUES
("' . $_POST['email'] . '", "' . sha1($_POST['password']) . '", 100)
;');
} else {
$database->query('INSERT INTO `users`
(`email`, `password`) VALUES
("' . $_POST['email'] . '", "' . sha1($_POST['password']) . '")
;');
}
header('Location: /?page=login'); header('Location: /?page=login');
die(); die();

76
includes/pages/update.php Normal file
View file

@ -0,0 +1,76 @@
<?php
/**
* home.php
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
use wishthis\{Page, User};
$page = new page(__FILE__, 'Update', 100);
$page->header();
$page->navigation();
/**
* Update
*/
if ('POST' === $_SERVER['REQUEST_METHOD']) {
/** Current version is below 0.2.0 */
if (-1 === version_compare($options->version, '0.2.0')) {
$database->query('ALTER TABLE `users`
ADD `last_login` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `password`,
ADD `power` BOOLEAN NOT NULL DEFAULT 0 AFTER `last_login`
;');
$database->query('UPDATE `users`
SET `power` = 100
WHERE `id` = ' . $user->id .
';');
$database->query('ALTER TABLE `users` ADD INDEX(`password`);');
$database->query('ALTER TABLE `wishlists`
ADD `hash` VARCHAR(128) NOT NULL AFTER `name`
;');
$database->query('ALTER TABLE `wishlists` ADD INDEX(`hash`);');
$database->query('INSERT INTO `options` (`key`, `value`) VALUES ("version", "' . VERSION . '");');
// Use this for future versions since it didn't existsin 0.1.0
// $options->setOption('version', VERSION);
}
header('Location: /?page=home');
die();
}
?>
<main>
<div class="ui container">
<h1 class="ui header"><?= $page->title ?></h1>
<div class="ui segment">
<h2 class="ui header">New version detected</h2>
<p>Thank you for updating to <strong>v<?= VERSION ?></strong>!</p>
<p>There have been some changes in the database, please run the updater.</p>
<div class="ui icon warning message">
<i class="exclamation triangle icon"></i>
<div class="content">
<div class="header">
Use at own risk
</div>
<p>Be sure to make backups before proceeding.</p>
</div>
</div>
<form class="ui form" method="post">
<button class="ui orange button" type="submit">
<i class="upload icon"></i>
Run the updater
</button>
</form>
</div>
</div>
</main>
<?php
$page->footer();
?>

View file

@ -12,8 +12,15 @@ $page = new page(__FILE__, 'Create a wishlist');
if (isset($_POST['name'])) { if (isset($_POST['name'])) {
$database->query('INSERT INTO `wishlists` $database->query('INSERT INTO `wishlists`
(`user`, `name`) VALUES (
(' . $_SESSION['user']['id'] . ', "' . $_POST['name'] . '") `user`,
`name`,
`hash`
) VALUES (
' . $_SESSION['user']['id'] . ',
"' . $_POST['name'] . '",
"' . time() . $_SESSION['user']['id'] . $_POST['name'] . '"
)
;'); ;');
header('Location: /?page=wishlist-product-add'); header('Location: /?page=wishlist-product-add');

View file

@ -18,7 +18,6 @@ if (isset($_POST['url'], $_POST['wishlist'])) {
$page = new page(__FILE__, 'Add a product'); $page = new page(__FILE__, 'Add a product');
$page->header(); $page->header();
$page->navigation(); $page->navigation();
$user = new User();
?> ?>
<main> <main>
<div class="ui container"> <div class="ui container">

View file

@ -19,9 +19,10 @@ $products = array();
* Get wishlist products * Get wishlist products
*/ */
if (isset($_GET['wishlist'])) { if (isset($_GET['wishlist'])) {
$user = new User(); $wishlist = $database->query('SELECT * FROM `wishlists`
$wishlist = $_GET['wishlist']; WHERE `id` = "' . $_GET['wishlist'] . '"')
$products = $user->getProducts($wishlist); ->fetch();
$products = $user->getProducts($_GET['wishlist']);
} }
/** /**
@ -59,10 +60,10 @@ if (isset($_POST['wishlist_delete_id'])) {
<h2 class="ui header">Options</h1> <h2 class="ui header">Options</h1>
<p>Wishlist related options.</p> <p>Wishlist related options.</p>
<button class="ui small labeled icon button disabled"> <a class="ui small labeled icon button wishlist-share disabled" href="/?wishlist=<?= $wishlist['hash'] ?? '' ?>" target="_blank">
<i class="share icon"></i> <i class="share icon"></i>
Share Share
</button> </a>
<form class="ui form wishlist-delete" method="post" style="display: inline-block;"> <form class="ui form wishlist-delete" method="post" style="display: inline-block;">
<input type="hidden" name="wishlist_delete_id" /> <input type="hidden" name="wishlist_delete_id" />

126
includes/pages/wishlist.php Normal file
View file

@ -0,0 +1,126 @@
<?php
/**
* wishlist.php
*
* @author Jay Trees <github.jay@grandel.anonaddy.me>
*/
use wishthis\{Page, User};
use Embed\Embed;
$page = new page(__FILE__, 'Wishlist');
$page->header();
$page->navigation();
$wishlist = $database->query('SELECT * FROM `wishlists`
WHERE `hash` = "' . $_GET['wishlist'] . '"')
->fetch();
$products = $user->getProducts($wishlist['id']);
?>
<main>
<div class="ui container">
<h1 class="ui header"><?= $page->title ?></h1>
<div class="ui segment">
<h2 class="ui header"><?= $wishlist['name'] ?></h2>
</div>
<?php if (!empty($products)) { ?>
<div class="ui three column grid">
<?php foreach ($products as $product) { ?>
<?php
/**
* @link https://github.com/oscarotero/Embed
*/
$embed = new Embed();
$info = $embed->get($product['url']);
?>
<div class="column">
<div class="ui fluid card">
<?php if ($info->image) { ?>
<div class="image">
<img src="<?= $info->image ?>" />
</div>
<?php } ?>
<div class="content">
<?php if ($info->title) { ?>
<div class="header">
<?php if ($info->url) { ?>
<a href="<?= $info->url ?>" target="_blank"><?= $info->title ?></a>
<?php } else { ?>
<?= $info->title ?>
<?php } ?>
</div>
<?php } ?>
<?php if ($info->keywords) { ?>
<div class="meta">
<?= $info->keywords ?>
</div>
<?php } ?>
<?php if ($info->description) { ?>
<div class="description">
<?= $info->description ?>
</div>
<?php } ?>
</div>
<div class="extra content">
<?php if ($info->publishedTime) { ?>
<span class="right floated">
<?= $info->publishedTime ?>
</span>
<?php } ?>
<?php if ($info->favicon) { ?>
<?php if ($info->providerName) { ?>
<img src="<?= $info->favicon ?>"
title="<?= $info->providerName ?>"
alt="<?= $info->providerName ?>"
/>
<?php } else { ?>
<img src="<?= $info->favicon ?>" />
<?php } ?>
<?php } ?>
</div>
</div>
</div>
<?php } ?>
</div>
<?php } else { ?>
<?php if (isset($_GET['wishlist'])) { ?>
<div class="ui icon message">
<i class="info circle icon"></i>
<div class="content">
<div class="header">
Empty
</div>
<p>The selected wishlist seems to be empty.</p>
<a class="ui mini button" href="/?page=wishlist-product-add">Add a product</a>
</div>
</div>
<?php } else { ?>
<div class="ui icon message">
<i class="info circle icon"></i>
<div class="content">
<div class="header">
No wishlist selected
</div>
<p>Select a wishlist to see it's products.</p>
</div>
</div>
<?php } ?>
<?php } ?>
</div>
</main>
<?php
$page->footer();
?>

View file

@ -6,8 +6,6 @@
* @author Jay Trees <github.jay@grandel.anonaddy.me> * @author Jay Trees <github.jay@grandel.anonaddy.me>
*/ */
$version_new = '0.1.0';
/** /**
* Include * Include
*/ */
@ -55,6 +53,11 @@ if (
*/ */
session_start(); session_start();
/**
* User
*/
$user = new wishthis\User();
/** /**
* API * API
*/ */
@ -72,12 +75,21 @@ if (!$options) {
/** /**
* Update * Update
*/ */
define('VERSION', '0.2.0');
if ($options) { if ($options) {
if (-1 === version_compare($options->version, $version_new)) { if (-1 === version_compare($options->version, VERSION)) {
$options->updateAvailable = true; $options->updateAvailable = true;
} }
} }
/**
* Wishlist
*/
if (!isset($_GET['page']) && isset($_GET['wishlist'])) {
$page = 'wishlist';
}
/** /**
* Page * Page
*/ */
@ -94,5 +106,6 @@ if (file_exists($pagePath)) {
<h1>Not found</h1> <h1>Not found</h1>
<p>The requested URL was not found on this server.</p> <p>The requested URL was not found on this server.</p>
<?php <?php
echo $pagePath;
die(); die();
} }