mirror of
https://git.cant.at/Madeorsk/PollVerlaine
synced 2024-11-25 08:04:33 +01:00
Merge remote-tracking branch 'origin/tagada'
This commit is contained in:
commit
f738330baf
67
API.md
Normal file
67
API.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# VerlainePoll's API
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
### Create a poll
|
||||||
|
```
|
||||||
|
POST /polls
|
||||||
|
```
|
||||||
|
|
||||||
|
| Field | Description | Optional |
|
||||||
|
| -------------- | ------------------------------------ | ---------- |
|
||||||
|
| `title` | The question. | no |
|
||||||
|
| `options` | All the options. Array of strings. | no |
|
||||||
|
| `settings` | A Settings object. | yes |
|
||||||
|
|
||||||
|
Return a Poll.
|
||||||
|
|
||||||
|
### Retrieve a poll
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /polls/:id
|
||||||
|
```
|
||||||
|
|
||||||
|
Return a Poll.
|
||||||
|
|
||||||
|
### Vote
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /polls/:id/vote
|
||||||
|
```
|
||||||
|
| Field | Description | Optional |
|
||||||
|
| -------------- | -------------------------------------------- | ---------- |
|
||||||
|
| `options` | Options you want to vote for. Array of ids. | no |
|
||||||
|
|
||||||
|
Return a Poll.
|
||||||
|
|
||||||
|
### Delete a poll
|
||||||
|
|
||||||
|
```
|
||||||
|
DELETE /polls/:id
|
||||||
|
```
|
||||||
|
|
||||||
|
Return a Poll.
|
||||||
|
|
||||||
|
## Entities
|
||||||
|
|
||||||
|
### Poll
|
||||||
|
|
||||||
|
| Attribute | Description | Nullable |
|
||||||
|
| --------------- | ------------------------------------ | ---------- |
|
||||||
|
| `id` | | no |
|
||||||
|
| `title` | The question. | no |
|
||||||
|
| `options` | All the options. Array of Options. | no |
|
||||||
|
| `settings` | A Settings object. | no |
|
||||||
|
| `creation_date` | Creation date. | no |
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Attribute | Description | Nullable |
|
||||||
|
| --------------- | ------------------------------------ | ---------- |
|
||||||
|
| `label` | The option. | no |
|
||||||
|
|
||||||
|
### Settings
|
||||||
|
|
||||||
|
| Attribute | Description | Nullable |
|
||||||
|
| --------------- | ------------------------------------ | ---------- |
|
||||||
|
| `unique_ip` | One vote per IP address. Boolean. | yes |
|
@ -9,7 +9,7 @@ Clone the repository :
|
|||||||
mkdir db && touch db/polls.db && composer install
|
mkdir db && touch db/polls.db && composer install
|
||||||
```
|
```
|
||||||
|
|
||||||
Uncomment the dba extention in `php.ini` :
|
Uncomment the `dba` extention in `php.ini` :
|
||||||
```
|
```
|
||||||
extension=dba
|
extension=dba
|
||||||
```
|
```
|
||||||
@ -25,3 +25,5 @@ location /
|
|||||||
```
|
```
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
|
See [API.md](API.md).
|
40
index.php
40
index.php
@ -3,14 +3,19 @@ require __DIR__ . "/vendor/autoload.php";
|
|||||||
require __DIR__ . "/models/Poll.php";
|
require __DIR__ . "/models/Poll.php";
|
||||||
require __DIR__ . "/config/app.php";
|
require __DIR__ . "/config/app.php";
|
||||||
|
|
||||||
function format_poll($poll)
|
function format_poll($poll, $with_delete_token = false)
|
||||||
{
|
{
|
||||||
return [
|
$array = [
|
||||||
"id" => $poll->id,
|
"id" => $poll->id,
|
||||||
"title" => $poll->title,
|
"title" => $poll->title,
|
||||||
"creation_date" => $poll->creation_date,
|
"creation_date" => $poll->creation_date,
|
||||||
"options" => $poll->options,
|
"options" => $poll->options,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if ($with_delete_token === true)
|
||||||
|
$array['delete_token'] = $poll->delete_token;
|
||||||
|
|
||||||
|
return $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
Flight::route("POST /polls", function () {
|
Flight::route("POST /polls", function () {
|
||||||
@ -20,7 +25,7 @@ Flight::route("POST /polls", function () {
|
|||||||
$request_json = $request->data;
|
$request_json = $request->data;
|
||||||
$poll = Poll::create_poll($request_json);
|
$poll = Poll::create_poll($request_json);
|
||||||
if ($poll)
|
if ($poll)
|
||||||
Flight::json(format_poll($poll), 201);
|
Flight::json(format_poll($poll, true), 201);
|
||||||
else
|
else
|
||||||
Flight::halt(403, "<h1>403 Forbidden</h1><h3>Invalid data.</h3>");
|
Flight::halt(403, "<h1>403 Forbidden</h1><h3>Invalid data.</h3>");
|
||||||
}
|
}
|
||||||
@ -103,6 +108,35 @@ Flight::route("GET /polls/@id:[a-fA-F0-9]+/results", function ($id) {
|
|||||||
Flight::notFound();
|
Flight::notFound();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Flight::route("GET|DELETE /polls/@id:[a-fA-F0-9]+/@token:[a-fA-F0-9]+", function ($id, $token) {
|
||||||
|
$poll = Poll::load_poll($id);
|
||||||
|
if ($poll)
|
||||||
|
{
|
||||||
|
if (Flight::request()->type === "application/json")
|
||||||
|
{
|
||||||
|
if ($poll->delete_token === $token)
|
||||||
|
{
|
||||||
|
$poll->delete();
|
||||||
|
Flight::json(format_poll($poll), 204);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Flight::halt(401, "<h1>401 Unauthorized</h1><h3>Invalid token.</h3>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($poll->delete_token === $token)
|
||||||
|
{
|
||||||
|
$poll->delete();
|
||||||
|
Flight::redirect('/', 204);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Flight::redirect('/', 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Flight::notFound();
|
||||||
|
});
|
||||||
|
|
||||||
Flight::route("/", function () {
|
Flight::route("/", function () {
|
||||||
global $VERLAINE;
|
global $VERLAINE;
|
||||||
Flight::render("home", ["app_url" => $VERLAINE["app_url"]], "body_content");
|
Flight::render("home", ["app_url" => $VERLAINE["app_url"]], "body_content");
|
||||||
|
@ -22,6 +22,7 @@ class Poll
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
$poll->gen_new_id();
|
$poll->gen_new_id();
|
||||||
|
$poll->delete_token = bin2hex(openssl_random_pseudo_bytes(16));
|
||||||
$poll->save();
|
$poll->save();
|
||||||
return $poll;
|
return $poll;
|
||||||
}
|
}
|
||||||
@ -46,6 +47,7 @@ class Poll
|
|||||||
$poll->title = $saved_poll_data->title;
|
$poll->title = $saved_poll_data->title;
|
||||||
$poll->creation_date = $saved_poll_data->creation_date;
|
$poll->creation_date = $saved_poll_data->creation_date;
|
||||||
$poll->options = $saved_poll_data->options;
|
$poll->options = $saved_poll_data->options;
|
||||||
|
$poll->delete_token = $saved_poll_data->delete_token;
|
||||||
|
|
||||||
dba_close($db);
|
dba_close($db);
|
||||||
return $poll;
|
return $poll;
|
||||||
@ -61,8 +63,9 @@ class Poll
|
|||||||
public $title;
|
public $title;
|
||||||
public $creation_date;
|
public $creation_date;
|
||||||
public $options = [];
|
public $options = [];
|
||||||
|
public $delete_token;
|
||||||
|
|
||||||
public function gen_new_id()
|
private function gen_new_id()
|
||||||
{
|
{
|
||||||
$db = dba_open(SAVE_PATH . "/polls.db", "rd");
|
$db = dba_open(SAVE_PATH . "/polls.db", "rd");
|
||||||
|
|
||||||
@ -97,7 +100,15 @@ class Poll
|
|||||||
"title" => $this->title,
|
"title" => $this->title,
|
||||||
"creation_date" => $this->creation_date,
|
"creation_date" => $this->creation_date,
|
||||||
"options" => $this->options,
|
"options" => $this->options,
|
||||||
|
"delete_token" => $this->delete_token
|
||||||
]), $db);
|
]), $db);
|
||||||
dba_close($db);
|
dba_close($db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function delete()
|
||||||
|
{
|
||||||
|
$db = dba_open(SAVE_PATH . "/polls.db", "wd");
|
||||||
|
dba_delete($this->id, $db);
|
||||||
|
dba_close($db);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
let result_el = document.getElementById("result");
|
let result_el = document.getElementById("result");
|
||||||
result_el.innerHTML = result_el.innerHTML.replace(/:poll_title/g, json.title);
|
result_el.innerHTML = result_el.innerHTML.replace(/:poll_title/g, json.title);
|
||||||
result_el.innerHTML = result_el.innerHTML.replace(/:poll_url/g, `/polls/${json.id}`);
|
result_el.innerHTML = result_el.innerHTML.replace(/:poll_url/g, `/polls/${json.id}`);
|
||||||
|
result_el.innerHTML = result_el.innerHTML.replace(/:delete_url/g, `/polls/${json.id}/${json.delete_token}`);
|
||||||
result_el.removeAttribute("hidden");
|
result_el.removeAttribute("hidden");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
<div id="result" hidden>
|
<div id="result" hidden>
|
||||||
<p>Your poll <strong>:poll_title</strong> is ready!</p>
|
<p>Your poll <strong>:poll_title</strong> is ready!</p>
|
||||||
<input type="text" name="pollurl" value="<?= $app_url ?>:poll_url" />
|
<input type="text" name="pollurl" value="<?= $app_url ?>:poll_url" />
|
||||||
|
<input type="text" name="deleteurl" value="<?= $app_url ?>:delete_url" />
|
||||||
<a class="button" href=":poll_url">See the poll!</a>
|
<a class="button" href=":poll_url">See the poll!</a>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
@ -10,5 +10,5 @@
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<input type="submit" value="Vote" />
|
<input type="submit" value="Vote" />
|
||||||
</form>
|
</form>
|
||||||
<a class="button margin">Jump to results</a>
|
<a class="button margin" href="/polls/<?= $poll->id ?>/results">Jump to results</a>
|
||||||
</main>
|
</main>
|
Loading…
Reference in New Issue
Block a user