aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MANUAL.md48
-rw-r--r--app/class/Controller.php27
-rw-r--r--app/class/Controllerconnect.php49
-rw-r--r--app/class/Controlleruser.php29
-rw-r--r--app/class/Modelconnect.php45
-rw-r--r--app/class/Routes.php1
-rw-r--r--app/class/Session.php6
-rw-r--r--app/class/User.php58
-rw-r--r--app/view/templates/user.php20
-rw-r--r--composer.json1
-rw-r--r--composer.lock53
11 files changed, 297 insertions, 40 deletions
diff --git a/MANUAL.md b/MANUAL.md
index 78f9dfc..c80d525 100644
--- a/MANUAL.md
+++ b/MANUAL.md
@@ -26,7 +26,7 @@ This 4 steps tutorial will introduce you to the basic __W__ moves.
The first thing you have to do before creating a page is to **choose an address** for this page. Each page have a unique address that identify it, it is the [**page id**](#page-id). You can use the address bar of your web browser to directly access, [edit](#edit) or [delete](#delete) a page.
-You can type anything in your address bar. If it is an already exisiting page_id, you will access a page. Otherwise, you will arrive to an empty space waiting to be filled.
+You can type anything in your address bar (after your W installation root). If it is an already exisiting page_id, you will access a page. Otherwise, you will arrive to an empty space waiting to be filled.
Once you've typed an address and found nothing, if you are connected, you now have the opportunity to create a page at this address.
@@ -69,7 +69,7 @@ One of the most interesting things to do when you use internet publishing, is to
All those methods will create a link pointing to the `<page_id>` you've given.
-Those kind of links are called internal links beccause they stay inside of your domain. To set a link outside of your website, simply remplace `<page_id>` by
+Those kind of links are called internal links beccause they stay inside of your domain. To set a link outside of your website, simply remplace `<page_id>` by the website adress you whant to target (ex : `https://w-cms.top`), but this won't work with the third method as it is'nt a W page.
#### Insert images
@@ -114,7 +114,7 @@ In the home menu [super editors and above](#super-editor) can :
- __File :__ Import pages as JSON file. (usefull for transfering pages from a W instance to another).
- __Edit :__ Apply changes, render, or delete multiple pages at once.
- __Filters :__ Use your [filtering options](#options) to generate a [automatic menu](#page-list) you can later include in a page.
-- __Bookmarks :__ Save your [filtering options](#options) presets here. Common and personnal storages are possible.
+- __Bookmarks :__ Create some [bookmarks](#bookmarks) to save your [filtering options](#options) as presets.
- __Display :__ Set columns to be shown (user based) and tag colors.
@@ -134,7 +134,7 @@ Just select the options you want and press "Fitler". Use the "Reset" button to c
This panel is also usefull to set up a [page list](#page-list) to include the same list of page you've filtered in any page.
-##### Pages
+##### list view
The table is composed of [meta](#meta-infos) datas and actions links that are :
@@ -142,6 +142,15 @@ __EDIT__, __READ__, __DELETE__ and __DOWNLOAD__, they are equivalent to [pages c
To edit columns you want to see, use the [menu](#home-menu)>Display submenu.
+##### map view
+
+The map give you an overview of your website, showing you links between pages.
+
+By default orphans pages are hidden, but you can ajust settings to fit your needs.
+
+- left click on a page to read it
+- right click to edit it
+
#### Edition
The edition interface is accessible when [typing `/edit`](#edit) after an existing [page_id](#page-id) in the address bar. Or from the [home](#home), by clicking on the pencil button.
@@ -177,13 +186,38 @@ When you need to use images, sound or videos in your pages, or any other type of
##### Media menu
-The media menu allow you to do more powerfull function like moving medias or delete folders.
+The media menu allow you to do more powerfull function like moving medias or delete folders it is only accessible by [super editors](#super-editor) and above.
+
+- __file :__ to import new files, create or delete directories
+- __edit :__ to edit selected items
+- __filter :__ to export filter settings as [medialist](#media-list)
+- __Bookmarks :__ Create some [bookmarks](#bookmarks) to save your [filtering options](#media-filters) as presets.
+
+
+##### Explorer
+
+The explorer allow you to navigate between differents directories. It will show you the amount of files in every folder.
+
+##### Media Filters
+
+By ajusting filters, you can
#### Admin
#### User manager
+#### Bookmarks
+
+Bookmarks can be created as shortcuts to quickly jump to a specified view.
+
+There are two kinds of bookmarks :
+- Home bookmarks
+- Media bookmars
+
+Each one is doing the same thing : saving a specific filter setting and allow you to access it in one click.
+
+After ajusting [home options](#options), or [media filters](#media-filters), select the bookmark menu (in the [home menu](#home-menu) or [media menu](#media-menu)), add a name and a symbol, this will add a new bookmark in the main top bar !
@@ -451,6 +485,10 @@ Date and Time are just a
By default, page's date and time are the same as creation date and time.
+##### Datemodif
+
+You can't edit manualy this date. It's just the last time the page has been edited.
+
##### Thumbnail
The thumbnail have two use cases :
diff --git a/app/class/Controller.php b/app/class/Controller.php
index 11a2c12..c631726 100644
--- a/app/class/Controller.php
+++ b/app/class/Controller.php
@@ -45,17 +45,30 @@ class Controller
public function setuser()
{
- if (empty($this->session->user)) {
- $this->user = new User();
- } else {
- if (!$this->user = $this->usermanager->get($this->session->user)) {
- if (!$this->user = $this->usermanager->readcookie()) {
- $this->user = new User();
+ // check session, then cookies
+ if (!empty($this->session->user)) {
+ $user = $this->usermanager->get($this->session->user);
+ } elseif (!empty($_COOKIE['authtoken'])) {
+ try {
+ $modelconnect = new Modelconnect();
+ $datas = $modelconnect->checkcookie();
+ $user = $this->usermanager->get($datas['userid']);
+ if ($user !== false && $user->checksession($datas['wsession'])) {
+ $this->session->addtosession("wsession", $datas['wsession']);
+ $this->session->addtosession("user", $datas['userid']);
} else {
- $this->session->addtosession('user', $this->user->id());
+ $user = false;
}
+ } catch (Exception $e) {
+ Model::sendflashmessage("Invalid Autentification cookie exist : $e", "warning");
}
}
+ // create visitor
+ if (empty($user)) {
+ $this->user = new User();
+ } else {
+ $this->user = $user;
+ }
}
public function initplates()
diff --git a/app/class/Controllerconnect.php b/app/class/Controllerconnect.php
index 8347a8f..4790c63 100644
--- a/app/class/Controllerconnect.php
+++ b/app/class/Controllerconnect.php
@@ -2,8 +2,12 @@
namespace Wcms;
+use RuntimeException;
+
class Controllerconnect extends Controller
{
+ /** @var Modelconnect */
+ protected $modelconnect;
public function log()
{
@@ -38,21 +42,36 @@ class Controllerconnect extends Controller
{
if (!empty($_POST['pass']) && !empty($_POST['user'])) {
$this->user = $this->usermanager->passwordcheck($_POST['user'], $_POST['pass']);
- if ($this->user != false) {
- if (
+ if (
+ $this->user != false
+ && (
$this->user->expiredate() === false
|| $this->user->level() === 10
|| $this->user->expiredate('date') > $this->now
- ) {
- $this->user->connectcounter();
- $this->usermanager->add($this->user);
- $this->session->addtosession('user', $this->user->id());
-
- if ($_POST['rememberme'] && $this->user->cookie() > 0) {
- $token = $this->createauthtoken();
- if ($token) {
- $_SESSION['user' . Config::basepath()]['authtoken'] = $token;
+ )
+ ) {
+ $this->user->connectcounter();
+ $this->usermanager->add($this->user);
+ $this->session->addtosession('user', $this->user->id());
+
+ if ($_POST['rememberme']) {
+ if ($this->user->cookie() > 0) {
+ try {
+ $this->modelconnect = new Modelconnect();
+ $wsession = $this->user->newsession();
+ $this->modelconnect->createauthcookie(
+ $this->user->id(),
+ $wsession,
+ $this->user->cookie()
+ );
+ $this->usermanager->add($this->user);
+ $this->session->addtosession('wsession', $wsession);
+ } catch (RuntimeException $e) {
+ Model::sendflashmessage("Can't create authentification cookie : $e", "warning");
}
+ } else {
+ $message = "Can't remember you beccause user cookie conservation time is set to 0 days";
+ Model::sendflashmessage($message, "warning");
}
}
}
@@ -66,11 +85,11 @@ class Controllerconnect extends Controller
public function logout($route, $id = null)
{
- $this->user = $this->usermanager->logout();
$this->session->addtosession('user', '');
- if (!empty($_SESSION['user' . Config::basepath()]['authtoken'])) {
- $this->destroyauthtoken($_SESSION['user' . Config::basepath()]['authtoken']);
- }
+ $this->user->destroysession($this->session->wsession);
+ $this->session->addtosession('wsession', '');
+ $this->usermanager->add($this->user);
+
if ($id !== null && $route !== 'home') {
$this->routedirect($route, ['page' => $id]);
} else {
diff --git a/app/class/Controlleruser.php b/app/class/Controlleruser.php
index 0345434..1e61c1a 100644
--- a/app/class/Controlleruser.php
+++ b/app/class/Controlleruser.php
@@ -40,9 +40,6 @@ class Controlleruser extends Controller
} catch (RuntimeException $th) {
Model::sendflashmessage('There was a problem when updating preference : ' . $th->getMessage(), 'error');
}
- if ($_POST['passwordhash']) {
- $user->hashpassword();
- }
$this->usermanager->add($user);
$this->routedirect('user');
} else {
@@ -50,6 +47,32 @@ class Controlleruser extends Controller
}
}
+ public function password()
+ {
+ if ($this->user->iseditor()) {
+ if (
+ !empty($_POST['password1']) &&
+ !empty($_POST['password2']) &&
+ $_POST['password1'] === $_POST['password2']
+ ) {
+ if (
+ $this->user->setpassword($_POST['password1']) &&
+ $this->user->hashpassword() &&
+ $this->usermanager->add($this->user)
+ ) {
+ Model::sendflashmessage('password updated successfully', 'success');
+ } else {
+ Model::sendflashmessage("password is not compatible or an error occured", 'error');
+ }
+ } else {
+ Model::sendflashmessage("passwords does not match", "error");
+ }
+ $this->routedirect('user');
+ } else {
+ $this->routedirect('home');
+ }
+ }
+
public function bookmark()
{
diff --git a/app/class/Modelconnect.php b/app/class/Modelconnect.php
new file mode 100644
index 0000000..1201d36
--- /dev/null
+++ b/app/class/Modelconnect.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Wcms;
+
+use Firebase\JWT\JWT;
+use RuntimeException;
+use Exception;
+
+class Modelconnect extends Model
+{
+
+ /**
+ * @param string $userid
+ * @param string $wsession
+ * @param int $conservation
+ * @throws RuntimeException if secret key is not set or cant send cookie
+ */
+ public function createauthcookie(string $userid, string $wsession, int $conservation)
+ {
+ $datas = [
+ "userid" => $userid,
+ "wsession" => $wsession
+ ];
+ if (empty(Config::secretkey())) {
+ throw new RuntimeException("Secret Key not set");
+ }
+ $jwt = JWT::encode($datas, Config::secretkey());
+ $cookie = setcookie('authtoken', $jwt, time() + $conservation * 24 * 3600, "", "", false, true);
+ if (!$cookie) {
+ throw new RuntimeException("Cant be send");
+ }
+ }
+
+ /**
+ * Check cookie using JWT
+ * @throws Exception
+ */
+ public function checkcookie()
+ {
+ if (!empty($_COOKIE['authtoken'])) {
+ $datas = JWT::decode($_COOKIE['authtoken'], Config::secretkey(), ['HS256']);
+ return get_object_vars($datas);
+ }
+ }
+}
diff --git a/app/class/Routes.php b/app/class/Routes.php
index 13bd2ac..65d8444 100644
--- a/app/class/Routes.php
+++ b/app/class/Routes.php
@@ -47,6 +47,7 @@ class Routes
['POST', '/!user/update', 'Controlleruser#update', 'userupdate'],
['POST', '/!user/bookmark', 'Controlleruser#bookmark', 'userbookmark'],
['POST', '/!user/pref', 'Controlleruser#pref', 'userpref'],
+ ['POST', '/!user/password', 'Controlleruser#password', 'userpassword'],
['POST', '/!user/token', 'Controlleruser#token', 'usertoken'],
['GET', '/!info', 'Controllerinfo#desktop', 'info'],
['GET', '/!timeline', 'Controllertimeline#desktop', 'timeline'],
diff --git a/app/class/Session.php b/app/class/Session.php
index 64b6b26..5228237 100644
--- a/app/class/Session.php
+++ b/app/class/Session.php
@@ -12,6 +12,7 @@ class Session extends Item
public $showrightpanel = false;
public $homedisplay = 'list';
public $mediadisplay = 'list';
+ public $wsession = '';
public function __construct($datas = [])
{
@@ -78,4 +79,9 @@ class Session extends Item
$this->mediadisplay = $mediadisplay;
}
}
+
+ public function setwsession($wsession)
+ {
+ $this->wsession = $wsession;
+ }
}
diff --git a/app/class/User.php b/app/class/User.php
index e78c10c..f9ea120 100644
--- a/app/class/User.php
+++ b/app/class/User.php
@@ -19,6 +19,8 @@ class User extends Item
protected $expiredate = false;
/** @var Bookmark[] Associative array as `id => Bookmark`*/
protected $bookmark = [];
+ /** @var array sessions */
+ protected $sessions = [];
protected $display = ['bookmark' => false];
public function __construct($datas = [])
@@ -103,6 +105,11 @@ class User extends Item
return $this->bookmark;
}
+ public function sessions()
+ {
+ return $this->sessions;
+ }
+
public function display()
{
return $this->display;
@@ -134,16 +141,18 @@ class User extends Item
}
}
- public function setpassword($password)
+ /**
+ * @return bool if password is compatible and set, otherwise flase
+ */
+ public function setpassword($password): bool
{
if (!empty($password) && is_string($password)) {
if (strlen($password) >= Model::PASSWORD_MIN_LENGTH && strlen($password) <= Model::PASSWORD_MAX_LENGTH) {
$this->password = $password;
return true;
- } else {
- return false;
}
}
+ return false;
}
public function setsignature(string $signature)
@@ -218,6 +227,13 @@ class User extends Item
}
}
+ public function setsessions($sessions)
+ {
+ if (is_array($sessions)) {
+ $this->sessions = $sessions;
+ }
+ }
+
public function setdisplay($display)
{
if (is_array($display)) {
@@ -268,6 +284,42 @@ class User extends Item
return false;
}
+ /**
+ * Generate new unique session ID
+ * @param string $info session info to store
+ * @return string session key
+ */
+ public function newsession(string $info = "no_info"): string
+ {
+ $exist = true;
+ while ($exist === true) {
+ $session = bin2hex(random_bytes(10));
+ $exist = key_exists($session, $this->sessions());
+ }
+ $this->sessions[$session] = $info;
+ return $session;
+ }
+
+ /**
+ * Remove Session from user
+ * @param string $session session ID to remove
+ * @return bool true if session exist and was destroyed, false if key does not exist
+ */
+ public function destroysession(string $session): bool
+ {
+ if (key_exists($session, $this->sessions)) {
+ unset($this->sessions[$session]);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public function checksession(string $session): bool
+ {
+ return key_exists($session, $this->sessions);
+ }
+
public function isvisitor()
diff --git a/app/view/templates/user.php b/app/view/templates/user.php
index faa44aa..31df074 100644
--- a/app/view/templates/user.php
+++ b/app/view/templates/user.php
@@ -40,15 +40,25 @@ $this->layout('layout', ['title' => 'user', 'stylesheets' => [$css . 'home.css']
<label for="cookie">Cookie conservation time <i>(In days)</i></label>
<p>When you tick the <em>remember-me</em> checkbox during login, you can choose how much time <strong>W</strong> will remember you.</p>
- <input type="password" name="password" id="password" minlength="<?= Wcms\Model::PASSWORD_MIN_LENGTH ?>" maxlength="<?= Wcms\Model::PASSWORD_MAX_LENGTH ?>">
- <label for="password">New password</label>
+ <input type="submit" value="update preferences">
- <input type="hidden" name="passwordhash" value="1">
+ </form>
+
+ <form action="<?= $this->url('userpassword') ?>" method="post">
+ <h3>Password</h3>
+
+ <label for="password1">Type your new password</label>
+ </br>
+ <input type="password" name="password1" id="password1" minlength="<?= Wcms\Model::PASSWORD_MIN_LENGTH ?>" required>
+ </br>
+ <label for="password2">Confirm password</label>
+ </br>
+ <input type="password" name="password2" id="password2" minlength="<?= Wcms\Model::PASSWORD_MIN_LENGTH ?>" required>
<p>Password have to be between <?= Wcms\Model::PASSWORD_MIN_LENGTH ?> and <?= Wcms\Model::PASSWORD_MAX_LENGTH ?> characters long.</p>
- <input type="submit" value="update preferences">
-
+ <input type="submit" value="update password">
+
</form>
</div>
diff --git a/composer.json b/composer.json
index 95a2d94..dccf6ab 100644
--- a/composer.json
+++ b/composer.json
@@ -4,6 +4,7 @@
"require": {
"php": ">=7.2.0",
"altorouter/altorouter": "^1.2",
+ "firebase/php-jwt": "^5.2",
"jamesmoss/flywheel": "^0.5.2",
"league/plates": "^3.3",
"michelf/php-markdown": "^1.8"
diff --git a/composer.lock b/composer.lock
index 5606478..7d41d88 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "6da5a2cb510d9953dfe07df3411f9cd9",
+ "content-hash": "271a2f7b5c32b5641b02ea8f50d55f73",
"packages": [
{
"name": "altorouter/altorouter",
@@ -62,6 +62,56 @@
"time": "2015-11-30T00:47:43+00:00"
},
{
+ "name": "firebase/php-jwt",
+ "version": "v5.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/firebase/php-jwt.git",
+ "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/feb0e820b8436873675fd3aca04f3728eb2185cb",
+ "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": ">=4.8 <=9"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Firebase\\JWT\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Neuman Vong",
+ "email": "neuman+pear@twilio.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Anant Narayanan",
+ "email": "anant@php.net",
+ "role": "Developer"
+ }
+ ],
+ "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
+ "homepage": "https://github.com/firebase/php-jwt",
+ "keywords": [
+ "jwt",
+ "php"
+ ],
+ "time": "2020-03-25T18:49:23+00:00"
+ },
+ {
"name": "jamesmoss/flywheel",
"version": "0.5.3",
"source": {
@@ -3359,7 +3409,6 @@
"psr",
"psr-7"
],
- "abandoned": "laminas/laminas-diactoros",
"time": "2019-11-13T19:16:13+00:00"
}
],