commit
8ba0d87e97
|
@ -7,3 +7,5 @@
|
||||||
.dockerignore
|
.dockerignore
|
||||||
Dockerfile
|
Dockerfile
|
||||||
docker-compose.yaml
|
docker-compose.yaml
|
||||||
|
/node_modules/
|
||||||
|
/npm-debug.log/
|
|
@ -1,28 +1,20 @@
|
||||||
FROM node:9.3.0-alpine
|
FROM node:8
|
||||||
|
|
||||||
# install static server
|
# Create app directory
|
||||||
RUN npm install -g serve
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
# create a 'tmp' folder for the build and make it the current working directory
|
# Install app dependencies
|
||||||
WORKDIR /app/tmp
|
# A wildcard is used to ensure both package.json AND package-lock.json are copied
|
||||||
|
# where available (npm@5+)
|
||||||
|
COPY ./client/package*.json ./
|
||||||
|
|
||||||
# copy only the package.json to take advantage of cached Docker layers
|
|
||||||
COPY package.json .
|
|
||||||
|
|
||||||
# install project dependencies
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
# If you are building your code for production
|
||||||
|
# RUN npm install --only=production
|
||||||
|
|
||||||
# copy project files and folders to the working directory
|
# Bundle app source
|
||||||
COPY . .
|
COPY ./client .
|
||||||
|
|
||||||
# build for production with minification
|
EXPOSE 3000
|
||||||
RUN npm run build
|
RUN npm run build:dev
|
||||||
|
CMD ["node", "dist/index.js"]
|
||||||
# make the 'app' folder the current working directory
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# clean up (i.e. extract 'dist' folder and remove everything else)
|
|
||||||
RUN mv tmp/dist dist && rm -fr tmp
|
|
||||||
|
|
||||||
EXPOSE 5000
|
|
||||||
CMD [ "serve", "--single", "--port", "3000", "dist" ]
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,22 +5,23 @@
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"build:prod": "webpack --config webpack.config.prod.js",
|
|
||||||
"build:dev": "webpack --config webpack.config.js",
|
"build:dev": "webpack --config webpack.config.js",
|
||||||
"watch": "webpack-watch-server --config webpack.config.js"
|
"dev": "tsc-watch src/index.ts --outDir ./dist --onSuccess 'node ./dist/index.js' --onFailure 'echo Beep! Compilation Failed'"
|
||||||
},
|
},
|
||||||
"author": "Dr. Patrick Bartsch",
|
"author": "Dr. Patrick Bartsch",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"tsc-watch": "^1.0.26",
|
||||||
"uglifyjs-webpack-plugin": "^1.1.6",
|
"uglifyjs-webpack-plugin": "^1.1.6",
|
||||||
"webpack": "^3.10.0"
|
"webpack": "^3.10.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/express": "^4.11.0",
|
"@types/express": "^4.11.0",
|
||||||
|
"bootstrap": "^4.0.0-alpha.6",
|
||||||
"express": "^4.16.2",
|
"express": "^4.16.2",
|
||||||
|
"jquery": "^3.3.1",
|
||||||
"ts-loader": "^3.2.0",
|
"ts-loader": "^3.2.0",
|
||||||
"twig": "^1.12.0",
|
"twig": "^1.12.0",
|
||||||
"typescript": "^2.6.2",
|
"typescript": "^2.6.2"
|
||||||
"webpack-watch-server": "^1.2.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
let $ = require("jquery");
|
||||||
|
//let bs = require("bootstrap");
|
||||||
|
|
||||||
|
let connected = false;
|
||||||
|
const api_url = 'http://localhost:8000';
|
||||||
|
|
||||||
|
$(".close").on('click', () => {
|
||||||
|
$(".close").alert('close');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (localStorage.getItem('sessionToken') !== null) {
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
$('.menu').html('<li class="nav-item">\n' +
|
||||||
|
' <a class="nav-link" id="logout-link" href="/logout">Log out</a>\n' +
|
||||||
|
' </li>');
|
||||||
|
|
||||||
|
$('#logout-link').click((e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
sendRequest('POST', '/logout', null, function (res) {
|
||||||
|
localStorage.removeItem('sessionToken');
|
||||||
|
window.location.pathname = '/';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendRequest(method, url, data, callback) {
|
||||||
|
let request = new XMLHttpRequest();
|
||||||
|
request.open(method, api_url + url);
|
||||||
|
request.setRequestHeader("Content-Type", "application/json");
|
||||||
|
request.setRequestHeader('Accept', 'application/json');
|
||||||
|
if (localStorage.getItem('sessionToken') !== undefined) {
|
||||||
|
request.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('sessionToken'));
|
||||||
|
}
|
||||||
|
request.responseType = 'json';
|
||||||
|
request.onload = function () {
|
||||||
|
if (callback) callback(request.response);
|
||||||
|
};
|
||||||
|
request.send(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAdvert(message) {
|
||||||
|
$('#advert').html('<div class="alert alert-primary alert-dismissible fade show" role="alert">\n' +
|
||||||
|
' ' + message +
|
||||||
|
' <button type="button" class="close" data-dismiss="alert" aria-label="Close">\n' +
|
||||||
|
' <span aria-hidden="true">×</span>\n' +
|
||||||
|
' </button>\n' +
|
||||||
|
' </div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshTaskList() {
|
||||||
|
sendRequest('GET', '/tasks', null, function (response) {
|
||||||
|
$('.task-list').html('');
|
||||||
|
|
||||||
|
response.data.forEach(function (task) {
|
||||||
|
let status = 'Open';
|
||||||
|
|
||||||
|
if (task.status === "0") {
|
||||||
|
status = 'Closed';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.task-list').append('<div class="media text-muted pt-3">\n' +
|
||||||
|
' <div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">\n' +
|
||||||
|
' <div class="d-flex justify-content-between align-items-center w-100">\n' +
|
||||||
|
' <a href="/task/' + task.id + '"><strong class="text-gray-dark">' + task.title + '</strong></a>\n' +
|
||||||
|
' <span class="badge badge-pill badge-primary">' + status + '</span>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' <spadatan class="d-block">' + task.description + '</spadatan>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' </div>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connected) {
|
||||||
|
$('#createTaskForm').html('<div class="my-3 p-3 bg-white rounded box-shadow">\n' +
|
||||||
|
' <form>\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="title">Title</label>\n' +
|
||||||
|
' <input type="text" name="title" id="title" class="form-control">\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
' <div class="form-group">\n' +
|
||||||
|
' <label for="description">Description</label>\n' +
|
||||||
|
' <textarea name="description" id="description" class="form-control"></textarea>\n' +
|
||||||
|
' </div>\n' +
|
||||||
|
'\n' +
|
||||||
|
' <button type="submit" id="createTask" class="btn btn-success">Create task</button>\n' +
|
||||||
|
' </form>\n' +
|
||||||
|
' </div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#createTask').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
sendRequest('POST', '/tasks', {
|
||||||
|
title: $("#title")[0].value,
|
||||||
|
description: $("#description")[0].value
|
||||||
|
}, function (data) {
|
||||||
|
setAdvert(data.message);
|
||||||
|
refreshTaskList();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshTaskList();
|
||||||
|
|
||||||
|
$('#signin').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
sendRequest('POST', '/auth', {
|
||||||
|
username: $('#username')[0].value,
|
||||||
|
password: $('#password')[0].value
|
||||||
|
}, function (res) {
|
||||||
|
if (res.data.token !== undefined) {
|
||||||
|
localStorage.setItem('sessionToken', res.data.token);
|
||||||
|
window.location.pathname = '/';
|
||||||
|
} else {
|
||||||
|
setAdvert(res.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#register').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
sendRequest('POST', '/signup', {
|
||||||
|
username: $('#username')[0].value,
|
||||||
|
password: $('#password')[0].value,
|
||||||
|
email: $('#email')[0].value
|
||||||
|
}, function (res) {
|
||||||
|
setAdvert(res.message);
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,11 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
//import * as bodyParser from "body-parser";
|
//import * as bodyParser from "body-parser";
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
const http = require("http");
|
const http = require("http");
|
||||||
|
let path = require("path");
|
||||||
let app = express();
|
let app = express();
|
||||||
app.set('view engine', 'twig');
|
app.set('view engine', 'twig');
|
||||||
app.set('views', __dirname + '/views');
|
app.set('views', __dirname + '/views');
|
||||||
|
app.use(express.static(path.resolve(__dirname) + '/../dist/public/'));
|
||||||
app.get('/', (req, res) => {
|
app.get('/', (req, res) => {
|
||||||
res.render('index', { title: 'Hey', message: 'Hello there!' });
|
res.render('index');
|
||||||
|
});
|
||||||
|
app.get('/login', (req, res) => {
|
||||||
|
res.render('login');
|
||||||
|
});
|
||||||
|
app.get('/register', (req, res) => {
|
||||||
|
res.render('register');
|
||||||
});
|
});
|
||||||
app.get('/task/{id}', (req, res) => {
|
app.get('/task/{id}', (req, res) => {
|
||||||
//res.render('index', {title: 'Hey', message: 'Hello there!'});
|
//res.render('index', {title: 'Hey', message: 'Hello there!'});
|
||||||
|
|
|
@ -3,13 +3,24 @@ import * as express from "express";
|
||||||
import {Request, Response} from "express";
|
import {Request, Response} from "express";
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
|
|
||||||
|
let path = require("path");
|
||||||
|
|
||||||
let app: express.Application = express();
|
let app: express.Application = express();
|
||||||
|
|
||||||
app.set('view engine', 'twig');
|
app.set('view engine', 'twig');
|
||||||
app.set('views', __dirname + '/views');
|
app.set('views', __dirname + '/views');
|
||||||
|
app.use(express.static(path.resolve(__dirname)+'/../dist/public/'));
|
||||||
|
|
||||||
app.get('/', (req: Request, res: Response) => {
|
app.get('/', (req: Request, res: Response) => {
|
||||||
res.render('index', {title: 'Hey', message: 'Hello there!'});
|
res.render('index');
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/login', (req: Request, res: Response) => {
|
||||||
|
res.render('login');
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/register', (req: Request, res: Response) => {
|
||||||
|
res.render('register');
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/task/{id}', (req: Request, res: Response) => {
|
app.get('/task/{id}', (req: Request, res: Response) => {
|
||||||
|
|
|
@ -1,123 +1,20 @@
|
||||||
<!doctype html>
|
{% extends 'layout.twig' %}
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
<link rel="icon" href="/favicon.ico">
|
|
||||||
|
|
||||||
<title>Project manager</title>
|
{% block body %}
|
||||||
|
<main role="main" class="container">
|
||||||
<!-- Bootstrap core CSS -->
|
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-info rounded box-shadow">
|
||||||
<link href="https://getbootstrap.com/docs/4.1/dist/css/bootstrap.min.css" rel="stylesheet">
|
<img class="mr-3" src="https://image.flaticon.com/icons/svg/138/138839.svg" alt="" width="48" height="48">
|
||||||
|
<div class="lh-100">
|
||||||
<!-- Custom styles for this template -->
|
<h6 class="mb-0 text-white lh-100">Task manager</h6>
|
||||||
<link href="https://getbootstrap.com/docs/4.1/examples/offcanvas/offcanvas.css" rel="stylesheet">
|
<small>https://github.com/Sundowndev/interview-v1</small>
|
||||||
</head>
|
|
||||||
|
|
||||||
<body class="bg-light">
|
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
|
||||||
<a class="navbar-brand mr-auto mr-lg-0" href="#">Project manager</a>
|
|
||||||
<button class="navbar-toggler p-0 border-0" type="button" data-toggle="offcanvas">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="navbar-collapse offcanvas-collapse" id="navbarsExampleDefault">
|
|
||||||
<ul class="navbar-nav mr-auto">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="#">Sign in</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="#">Register</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="nav-scroller bg-white box-shadow">
|
|
||||||
<nav class="nav nav-underline">
|
|
||||||
<a class="nav-link" href="#">Tasks</a>
|
|
||||||
<a class="nav-link" href="#">Users</a>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-warning alert-dismissible fade show" role="alert">
|
|
||||||
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
|
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<main role="main" class="container">
|
|
||||||
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-info rounded box-shadow">
|
|
||||||
<img class="mr-3" src="https://image.flaticon.com/icons/svg/138/138839.svg" alt="" width="48" height="48">
|
|
||||||
<div class="lh-100">
|
|
||||||
<h6 class="mb-0 text-white lh-100">Task manager</h6>
|
|
||||||
<small>https://github.com/Sundowndev/interview-v1</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="my-3 p-3 bg-white rounded box-shadow">
|
|
||||||
<form action="#">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="title">Title</label>
|
|
||||||
<input type="text" name="title" id="title" class="form-control">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="description">Description</label>
|
|
||||||
<textarea name="description" id="description" class="form-control"></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-success">Create task</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="my-3 p-3 bg-white rounded box-shadow">
|
|
||||||
<h6 class="border-bottom border-gray pb-2 mb-0">All tasks</h6>
|
|
||||||
<div class="media text-muted pt-3">
|
|
||||||
<img src="https://dummyimage.com/32x32/54bf22/fff.jpg&text=+" alt="" class="mr-2 rounded">
|
|
||||||
<div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
|
|
||||||
<div class="d-flex justify-content-between align-items-center w-100">
|
|
||||||
<a href=""><strong class="text-gray-dark">Faire rapport de stage</strong></a>
|
|
||||||
<span class="badge badge-pill badge-primary">Open</span>
|
|
||||||
</div>
|
|
||||||
<span class="d-block">Je dois faire ça lààààà</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="media text-muted pt-3">
|
|
||||||
<img src="https://dummyimage.com/32x32/54bf22/fff.jpg&text=+" alt="" class="mr-2 rounded">
|
|
||||||
<div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
|
|
||||||
<div class="d-flex justify-content-between align-items-center w-100">
|
|
||||||
<a href=""><strong class="text-gray-dark">Faire rapport de stage</strong></a>
|
|
||||||
<span class="badge badge-pill badge-primary">Open</span>
|
|
||||||
</div>
|
|
||||||
<span class="d-block">Je dois faire ça lààààà</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="media text-muted pt-3">
|
|
||||||
<img src="https://dummyimage.com/32x32/54bf22/fff.jpg&text=+" alt="" class="mr-2 rounded">
|
|
||||||
<div class="media-body pb-3 mb-0 small lh-125 border-bottom border-gray">
|
|
||||||
<div class="d-flex justify-content-between align-items-center w-100">
|
|
||||||
<a href=""><strong class="text-gray-dark">Faire rapport de stage</strong></a>
|
|
||||||
<span class="badge badge-pill badge-primary">Open</span>
|
|
||||||
</div>
|
|
||||||
<span class="d-block">Je dois faire ça lààààà</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript
|
<div id="createTaskForm"></div>
|
||||||
================================================== -->
|
|
||||||
<!-- Placed at the end of the document so the pages load faster -->
|
<div class="my-3 p-3 bg-white rounded box-shadow">
|
||||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
<h6 class="border-bottom border-gray pb-2 mb-0">All tasks</h6>
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js" integrity="sha384-o+RDsa0aLu++PJvFqy8fFScvbHFLtbvScb8AjopnFD+iEQ7wo/CG0xlczd+2O/em" crossorigin="anonymous"></script>
|
<div class="task-list"></div>
|
||||||
<script>
|
</div>
|
||||||
$(".close").on('click', () => {
|
</main>
|
||||||
$(".close").alert('close');
|
{% endblock %}
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<link rel="icon" href="/favicon.ico">
|
||||||
|
|
||||||
|
<title>{% block title %}Project manager{% endblock %}</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="https://getbootstrap.com/docs/4.1/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="https://getbootstrap.com/docs/4.1/examples/offcanvas/offcanvas.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="bg-light">
|
||||||
|
{% block header %}
|
||||||
|
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
||||||
|
<a class="navbar-brand mr-auto mr-lg-0" href="/">Project manager</a>
|
||||||
|
<button class="navbar-toggler p-0 border-0" type="button" data-toggle="offcanvas">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="navbar-collapse offcanvas-collapse" id="navbarsExampleDefault">
|
||||||
|
<ul class="navbar-nav mr-auto menu">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/login">Sign in</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/register">Register</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!--<div class="nav-scroller bg-white box-shadow">
|
||||||
|
<nav class="nav nav-underline">
|
||||||
|
<a class="nav-link" href="#">Tasks</a>
|
||||||
|
<a class="nav-link" href="#">Users</a>
|
||||||
|
</nav>
|
||||||
|
</div>-->
|
||||||
|
|
||||||
|
<div id="advert"></div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<main role="main" class="container">
|
||||||
|
<div class="d-flex align-items-center p-3 my-3 text-white-50 bg-info rounded box-shadow">
|
||||||
|
<img class="mr-3" src="https://image.flaticon.com/icons/svg/138/138839.svg" alt="" width="48" height="48">
|
||||||
|
<div class="lh-100">
|
||||||
|
<h6 class="mb-0 text-white lh-100">Task manager</h6>
|
||||||
|
<small>https://github.com/Sundowndev/interview-v1</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
<script src="/app.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,20 @@
|
||||||
|
{% extends 'layout.twig' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<main role="main" class="container">
|
||||||
|
<div class="my-3 p-3 bg-white rounded box-shadow">
|
||||||
|
<form action="#">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input type="text" name="username" id="username" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input type="password" name="password" id="password" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" id="signin" class="btn btn-success">Sign in</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,26 @@
|
||||||
|
{% extends 'layout.twig' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<main role="main" class="container">
|
||||||
|
<div class="my-3 p-3 bg-white rounded box-shadow">
|
||||||
|
<form action="#">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input type="text" name="username" id="username" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email</label>
|
||||||
|
<input type="text" name="email" id="email" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input type="password" name="password" id="password" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" id="register" class="btn btn-success">Register</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{% endblock %}
|
|
@ -1,8 +1,8 @@
|
||||||
var webpack = require('webpack');
|
let webpack = require('webpack');
|
||||||
var path = require('path');
|
let path = require('path');
|
||||||
var fs = require('fs');
|
let fs = require('fs');
|
||||||
|
|
||||||
var nodeModules = {};
|
let nodeModules = {};
|
||||||
fs.readdirSync('node_modules')
|
fs.readdirSync('node_modules')
|
||||||
.filter(function (x) {
|
.filter(function (x) {
|
||||||
return ['.bin'].indexOf(x) === -1;
|
return ['.bin'].indexOf(x) === -1;
|
||||||
|
@ -11,11 +11,26 @@ fs.readdirSync('node_modules')
|
||||||
nodeModules[mod] = 'commonjs ' + mod;
|
nodeModules[mod] = 'commonjs ' + mod;
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = {
|
const scriptConfig = {
|
||||||
entry: './src/index.ts',
|
name: 'app',
|
||||||
|
entry: {
|
||||||
|
app: './src/assets/app.js'
|
||||||
|
},
|
||||||
|
target: 'web',
|
||||||
|
output: {
|
||||||
|
filename: 'app.js',
|
||||||
|
path: path.resolve(__dirname, 'dist/public')
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const appConfig = {
|
||||||
|
name: 'index',
|
||||||
|
entry: {
|
||||||
|
index: './src/index.ts',
|
||||||
|
},
|
||||||
target: 'node',
|
target: 'node',
|
||||||
output: {
|
output: {
|
||||||
filename: 'index.js',
|
filename: '[name].js',
|
||||||
path: path.resolve(__dirname, 'dist')
|
path: path.resolve(__dirname, 'dist')
|
||||||
},
|
},
|
||||||
devtool: 'source-map',
|
devtool: 'source-map',
|
||||||
|
@ -35,3 +50,5 @@ module.exports = {
|
||||||
__dirname: true
|
__dirname: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = [scriptConfig, appConfig];
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
var webpack = require('webpack');
|
|
||||||
var path = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
|
||||||
|
|
||||||
var nodeModules = {};
|
|
||||||
fs.readdirSync('node_modules')
|
|
||||||
.filter(function (x) {
|
|
||||||
return ['.bin'].indexOf(x) === -1;
|
|
||||||
})
|
|
||||||
.forEach(function (mod) {
|
|
||||||
nodeModules[mod] = 'commonjs ' + mod;
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
entry: './src/index.ts',
|
|
||||||
target: 'node',
|
|
||||||
output: {
|
|
||||||
filename: 'index.js',
|
|
||||||
path: path.resolve(__dirname, 'dist')
|
|
||||||
},
|
|
||||||
devtool: 'source-map',
|
|
||||||
plugins: [
|
|
||||||
new UglifyJsPlugin({
|
|
||||||
test: /\.js($|\?)/i
|
|
||||||
})
|
|
||||||
],
|
|
||||||
resolve: {
|
|
||||||
// Add `.ts` and `.tsx` as a resolvable extension.
|
|
||||||
extensions: ['.ts', '.tsx', '.js']
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
|
|
||||||
{ test: /\.tsx?$/, loader: 'ts-loader' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
externals: nodeModules
|
|
||||||
};
|
|
|
@ -43,9 +43,18 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- '443:443'
|
- '443:443'
|
||||||
|
|
||||||
|
client:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./Dockerfile.client
|
||||||
|
volumes:
|
||||||
|
# Comment out the next line in production
|
||||||
|
- ./client:/usr/src/app:rw
|
||||||
|
ports:
|
||||||
|
- 3000:3000
|
||||||
|
|
||||||
# For development purposes
|
# For development purposes
|
||||||
adminer:
|
adminer:
|
||||||
image: adminer
|
image: adminer
|
||||||
restart: always
|
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 8080:8080
|
|
@ -5,5 +5,5 @@ MYSQL_HOST=db
|
||||||
MYSQL_PORT=3306
|
MYSQL_PORT=3306
|
||||||
MYSQL_DBNAME=app1
|
MYSQL_DBNAME=app1
|
||||||
### Allow origin for the API ###
|
### Allow origin for the API ###
|
||||||
ALLOW_ORIGIN=^https?://localhost:?[0-9]*$
|
ALLOW_ORIGIN=http://localhost:3000
|
||||||
APP_SECRET=04980744f74f4ec36ad5a9d5fec8876f
|
APP_SECRET=04980744f74f4ec36ad5a9d5fec8876f
|
|
@ -6,6 +6,8 @@ use App\Service\JsonResponse;
|
||||||
$router->setNamespace('\App\Controller');
|
$router->setNamespace('\App\Controller');
|
||||||
|
|
||||||
$router->before('GET|POST|PUT|DELETE', '/.*', function () use ($router) {
|
$router->before('GET|POST|PUT|DELETE', '/.*', function () use ($router) {
|
||||||
|
date_default_timezone_set('Europe/Paris');
|
||||||
|
|
||||||
# This will be always executed
|
# This will be always executed
|
||||||
$dotEnvParser = new DotEnvParser();
|
$dotEnvParser = new DotEnvParser();
|
||||||
$dotEnvParser->run();
|
$dotEnvParser->run();
|
||||||
|
@ -15,19 +17,12 @@ $router->before('GET|POST|PUT|DELETE', '/.*', function () use ($router) {
|
||||||
if ($_SERVER['HTTP_ACCEPT'] !== 'application/json') {
|
if ($_SERVER['HTTP_ACCEPT'] !== 'application/json') {
|
||||||
$code = 400;
|
$code = 400;
|
||||||
$message = 'Accept header is not set to "application/json".';
|
$message = 'Accept header is not set to "application/json".';
|
||||||
print $jsonResponse->create($code, $message, []);
|
return $jsonResponse->create($code, $message, []);
|
||||||
exit();
|
|
||||||
} elseif ($_SERVER['REQUEST_METHOD'] != 'GET' && $_SERVER['CONTENT_TYPE'] !== 'application/json') {
|
} elseif ($_SERVER['REQUEST_METHOD'] != 'GET' && $_SERVER['CONTENT_TYPE'] !== 'application/json') {
|
||||||
$code = 400;
|
$code = 400;
|
||||||
$message = 'Content-type header is not set to "application/json".';
|
$message = 'Content-type header is not set to "application/json".';
|
||||||
print $jsonResponse->create($code, $message, []);
|
return $jsonResponse->create($code, $message, []);
|
||||||
exit();
|
}
|
||||||
}/* elseif ($_SERVER['HTTP_ORIGIN'] !== getenv('ALLOW_ORIGIN')) {
|
|
||||||
$code = 403;
|
|
||||||
$message = 'Unallowed origin.';
|
|
||||||
print $jsonResponse->create($code, $message, []);
|
|
||||||
exit();
|
|
||||||
}*/
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,3 +73,6 @@ $router->mount('/users', function () use ($router) {
|
||||||
// Get one task's tasks
|
// Get one task's tasks
|
||||||
$router->get('/(\d+)/tasks', 'UserController@getTasks');
|
$router->get('/(\d+)/tasks', 'UserController@getTasks');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Quickfix for Chrome prelight request on OPTIONS method
|
||||||
|
$router->options('(.*)', 'DefaultController@index');
|
|
@ -4,6 +4,7 @@
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"license": "WTFPL",
|
"license": "WTFPL",
|
||||||
"require": {
|
"require": {
|
||||||
|
"php": "7.*",
|
||||||
"bramus/router": "~1.3",
|
"bramus/router": "~1.3",
|
||||||
"codervio/envmanager": "^1.7"
|
"codervio/envmanager": "^1.7"
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "4ac0df3751e41700bc67b558c17957c9",
|
"content-hash": "a1c9c0daaa465c088d4d51534487d4a9",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bramus/router",
|
"name": "bramus/router",
|
||||||
|
@ -118,6 +118,8 @@
|
||||||
"stability-flags": [],
|
"stability-flags": [],
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": {
|
||||||
|
"php": "7.*"
|
||||||
|
},
|
||||||
"platform-dev": []
|
"platform-dev": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Service\Database;
|
||||||
|
use App\Service\JsonResponse;
|
||||||
|
use App\Service\Request;
|
||||||
|
use App\Service\Session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Controller
|
||||||
|
* @package App\Controller
|
||||||
|
*/
|
||||||
|
class Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Database
|
||||||
|
*/
|
||||||
|
protected $db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var JsonResponse
|
||||||
|
*/
|
||||||
|
protected $jsonResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Request
|
||||||
|
*/
|
||||||
|
protected $request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Session
|
||||||
|
*/
|
||||||
|
protected $session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \App\Service\Security
|
||||||
|
*/
|
||||||
|
protected $security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->db = new Database();
|
||||||
|
$this->request = new Request();
|
||||||
|
$this->jsonResponse = new JsonResponse();
|
||||||
|
$this->session = new Session($this->db, $this->jsonResponse);
|
||||||
|
$this->security = $this->session->security;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,23 +2,14 @@
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Service\JsonResponse;
|
class DefaultController extends Controller
|
||||||
|
|
||||||
class DefaultController
|
|
||||||
{
|
{
|
||||||
private $jsonResponse;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->jsonResponse = new JsonResponse();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API homepage
|
* API homepage
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
print $this->jsonResponse->create(200, 'Hello! :)');
|
return $this->jsonResponse->create(200, 'Hello! :)');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +17,6 @@ class DefaultController
|
||||||
*/
|
*/
|
||||||
public function error()
|
public function error()
|
||||||
{
|
{
|
||||||
print $this->jsonResponse->create(404, 'Resource not found.');
|
return $this->jsonResponse->create(404, 'Resource not found.');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,30 +4,18 @@ namespace App\Controller;
|
||||||
|
|
||||||
use App\Repository\SessionRepository;
|
use App\Repository\SessionRepository;
|
||||||
use App\Repository\UserRepository;
|
use App\Repository\UserRepository;
|
||||||
use App\Service\Database;
|
|
||||||
use App\Service\JsonResponse;
|
|
||||||
use App\Service\Request;
|
|
||||||
use App\Service\Session;
|
|
||||||
|
|
||||||
class SessionController
|
class SessionController extends Controller
|
||||||
{
|
{
|
||||||
private $db;
|
|
||||||
private $jsonResponse;
|
|
||||||
private $sessionRepository;
|
|
||||||
private $request;
|
|
||||||
private $session;
|
|
||||||
private $security;
|
|
||||||
private $userRepository;
|
private $userRepository;
|
||||||
|
private $sessionRepository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->db = new Database();
|
parent::__construct();
|
||||||
$this->request = new Request();
|
|
||||||
$this->jsonResponse = new JsonResponse();
|
|
||||||
$this->session = new Session($this->db, $this->jsonResponse);
|
|
||||||
$this->security = $this->session->security;
|
|
||||||
$this->sessionRepository = new SessionRepository($this->db, $this->security);
|
|
||||||
$this->userRepository = new UserRepository($this->db);
|
$this->userRepository = new UserRepository($this->db);
|
||||||
|
$this->sessionRepository = new SessionRepository($this->db, $this->security);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,15 +26,13 @@ class SessionController
|
||||||
$body = $this->request->getContent()->jsonToArray();
|
$body = $this->request->getContent()->jsonToArray();
|
||||||
|
|
||||||
if (empty($body['username']) || empty($body['password'])) {
|
if (empty($body['username']) || empty($body['password'])) {
|
||||||
print $this->jsonResponse->create(400, 'Please provide an username and password.');
|
return $this->jsonResponse->create(400, 'Please provide an username and password.');
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->userRepository->findOneByUsername($body['username']);
|
$user = $this->userRepository->findOneByUsername($body['username']);
|
||||||
|
|
||||||
if (is_null($user) || !$this->security->passwordVerify($body['password'], $user['password'])) {
|
if (is_null($user) || !$this->security->passwordVerify($body['password'], $user['password'])) {
|
||||||
print $this->jsonResponse->create(403, 'Bad credentials.');
|
return $this->jsonResponse->create(403, 'Bad credentials.');
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = $this->security->generateToken($user['id']);
|
$token = $this->security->generateToken($user['id']);
|
||||||
|
@ -56,7 +42,7 @@ class SessionController
|
||||||
|
|
||||||
$this->sessionRepository->create($user['id'], $token, $expire_at->format('Y-m-d H:i:s'), $_SERVER['REMOTE_ADDR']);
|
$this->sessionRepository->create($user['id'], $token, $expire_at->format('Y-m-d H:i:s'), $_SERVER['REMOTE_ADDR']);
|
||||||
|
|
||||||
print $this->jsonResponse->create(200, 'Welcome ' . $user['name'], [
|
return $this->jsonResponse->create(200, 'Welcome ' . $user['name'], [
|
||||||
'token' => $token,
|
'token' => $token,
|
||||||
'expire_at' => $expire_at,
|
'expire_at' => $expire_at,
|
||||||
]);
|
]);
|
||||||
|
@ -70,8 +56,7 @@ class SessionController
|
||||||
$body = $this->request->getContent()->jsonToArray();
|
$body = $this->request->getContent()->jsonToArray();
|
||||||
|
|
||||||
if (empty($body['username']) || empty($body['email']) || empty($body['password'])) {
|
if (empty($body['username']) || empty($body['email']) || empty($body['password'])) {
|
||||||
print $this->jsonResponse->create(400, 'Please provide an username, email and password.');
|
return $this->jsonResponse->create(400, 'Please provide an username, email and password.');
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = [
|
$user = [
|
||||||
|
@ -81,13 +66,12 @@ class SessionController
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!is_null($this->userRepository->findOneByEmail($user['email']))) {
|
if (!is_null($this->userRepository->findOneByEmail($user['email']))) {
|
||||||
print $this->jsonResponse->create(403, 'Email already registered!');
|
return $this->jsonResponse->create(403, 'Email already registered!');
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->userRepository->create($user['username'], $user['email'], $user['password']);
|
$this->userRepository->create($user['username'], $user['email'], $user['password']);
|
||||||
|
|
||||||
print $this->jsonResponse->create(200, 'Success. Now send your credentials to /auth to sign in.', [
|
return $this->jsonResponse->create(200, 'Success. Now send your credentials to /auth to sign in.', [
|
||||||
'username' => $user['username'],
|
'username' => $user['username'],
|
||||||
'email' => $user['email'],
|
'email' => $user['email'],
|
||||||
]);
|
]);
|
||||||
|
@ -99,13 +83,12 @@ class SessionController
|
||||||
public function signout()
|
public function signout()
|
||||||
{
|
{
|
||||||
if (!$this->security->isLogged()) {
|
if (!$this->security->isLogged()) {
|
||||||
print $this->security->NotAllowedRequest();
|
return $this->security->NotAllowedRequest();
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->sessionRepository->deleteByToken($this->security->getBearerToken());
|
$this->sessionRepository->deleteByToken($this->security->getBearerToken());
|
||||||
|
|
||||||
print $this->jsonResponse->create(200, 'Good bye.', []);
|
return $this->jsonResponse->create(200, 'Good bye.', []);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,10 +97,9 @@ class SessionController
|
||||||
public function me()
|
public function me()
|
||||||
{
|
{
|
||||||
if (!$this->security->isLogged()) {
|
if (!$this->security->isLogged()) {
|
||||||
print $this->security->NotAllowedRequest();
|
return $this->security->NotAllowedRequest();
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print $this->jsonResponse->create(200, 'hello!', $this->session->getUser());
|
return $this->jsonResponse->create(200, 'hello!', $this->session->getUser());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,33 +2,21 @@
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Service\JsonResponse;
|
|
||||||
use App\Service\Database;
|
|
||||||
use App\Repository\TaskRepository;
|
use App\Repository\TaskRepository;
|
||||||
use App\Service\Request;
|
|
||||||
use App\Service\Session;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TaskController
|
* Class TaskController
|
||||||
* @package App\Controller
|
* @package App\Controller
|
||||||
*/
|
*/
|
||||||
class TaskController
|
class TaskController extends Controller
|
||||||
{
|
{
|
||||||
private $db;
|
|
||||||
private $request;
|
|
||||||
private $jsonResponse;
|
|
||||||
private $session;
|
|
||||||
private $security;
|
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->db = new Database();
|
parent::__construct();
|
||||||
$this->request = new Request();
|
|
||||||
$this->jsonResponse = new JsonResponse();
|
|
||||||
$this->repository = new TaskRepository($this->db);
|
$this->repository = new TaskRepository($this->db);
|
||||||
$this->session = new Session($this->db, $this->jsonResponse);
|
|
||||||
$this->security = $this->session->security;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +31,7 @@ class TaskController
|
||||||
$message = "Here are the tasks!";
|
$message = "Here are the tasks!";
|
||||||
$data = $this->repository->findAll();
|
$data = $this->repository->findAll();
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
return $this->jsonResponse->create($code, $message, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +46,7 @@ class TaskController
|
||||||
$code = ($data != null) ? 200 : 404;
|
$code = ($data != null) ? 200 : 404;
|
||||||
$message = ($data != null) ? "Task found." : "Task not found.";
|
$message = ($data != null) ? "Task found." : "Task not found.";
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
return $this->jsonResponse->create($code, $message, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,8 +58,7 @@ class TaskController
|
||||||
public function post()
|
public function post()
|
||||||
{
|
{
|
||||||
if (!$this->security->isLogged()) {
|
if (!$this->security->isLogged()) {
|
||||||
print $this->security->NotAllowedRequest();
|
return $this->security->NotAllowedRequest();
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$body = $this->request->getContent()->jsonToArray();
|
$body = $this->request->getContent()->jsonToArray();
|
||||||
|
@ -80,8 +67,7 @@ class TaskController
|
||||||
$code = 400;
|
$code = 400;
|
||||||
$message = 'Bad parameters.';
|
$message = 'Bad parameters.';
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message);
|
return $this->jsonResponse->create($code, $message);
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->session->getUser();
|
$user = $this->session->getUser();
|
||||||
|
@ -97,7 +83,7 @@ class TaskController
|
||||||
$message = 'Success!';
|
$message = 'Success!';
|
||||||
$data = $task;
|
$data = $task;
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
return $this->jsonResponse->create($code, $message, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,16 +95,14 @@ class TaskController
|
||||||
public function put($id)
|
public function put($id)
|
||||||
{
|
{
|
||||||
if (!$this->security->isLogged()) {
|
if (!$this->security->isLogged()) {
|
||||||
print $this->security->NotAllowedRequest();
|
return $this->security->NotAllowedRequest();
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$task = $this->repository->findOneById($id);
|
$task = $this->repository->findOneById($id);
|
||||||
$user = $this->session->getUser();
|
$user = $this->session->getUser();
|
||||||
|
|
||||||
if ($task['user_id'] !== $user['id']) {
|
if ($task['user_id'] !== $user['id']) {
|
||||||
print $this->security->NotAllowedRequest();
|
return $this->security->NotAllowedRequest();
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$body = $this->request->getContent()->jsonToArray();
|
$body = $this->request->getContent()->jsonToArray();
|
||||||
|
@ -133,7 +117,7 @@ class TaskController
|
||||||
$message = "Task edited.";
|
$message = "Task edited.";
|
||||||
$data = $task;
|
$data = $task;
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
return $this->jsonResponse->create($code, $message, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,16 +129,14 @@ class TaskController
|
||||||
public function delete($id)
|
public function delete($id)
|
||||||
{
|
{
|
||||||
if (!$this->security->isLogged()) {
|
if (!$this->security->isLogged()) {
|
||||||
print $this->security->NotAllowedRequest();
|
return $this->security->NotAllowedRequest();
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$task = $this->repository->findOneById($id);
|
$task = $this->repository->findOneById($id);
|
||||||
$user = $this->session->getUser();
|
$user = $this->session->getUser();
|
||||||
|
|
||||||
if ($task['user_id'] !== $user['id']) {
|
if ($task['user_id'] !== $user['id']) {
|
||||||
print $this->security->NotAllowedRequest();
|
return $this->security->NotAllowedRequest();
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->repository->deleteById($id);
|
$this->repository->deleteById($id);
|
||||||
|
@ -163,6 +145,6 @@ class TaskController
|
||||||
$message = "Task deleted.";
|
$message = "Task deleted.";
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, $data);
|
return $this->jsonResponse->create($code, $message, $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,21 +3,17 @@
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Repository\TaskRepository;
|
use App\Repository\TaskRepository;
|
||||||
use App\Service\Database;
|
|
||||||
use App\Service\JsonResponse;
|
|
||||||
use App\Repository\UserRepository;
|
use App\Repository\UserRepository;
|
||||||
|
|
||||||
class UserController
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
private $db;
|
|
||||||
private $jsonResponse;
|
|
||||||
private $repository;
|
private $repository;
|
||||||
private $taskRepository;
|
private $taskRepository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->db = new Database();
|
parent::__construct();
|
||||||
$this->jsonResponse = new JsonResponse();
|
|
||||||
$this->repository = new UserRepository($this->db);
|
$this->repository = new UserRepository($this->db);
|
||||||
$this->taskRepository = new TaskRepository($this->db);
|
$this->taskRepository = new TaskRepository($this->db);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +30,7 @@ class UserController
|
||||||
$code = ($user != null) ? 200 : 404;
|
$code = ($user != null) ? 200 : 404;
|
||||||
$message = ($user != null) ? "User found." : "User not found.";
|
$message = ($user != null) ? "User found." : "User not found.";
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, [
|
return $this->jsonResponse->create($code, $message, [
|
||||||
'id' => $user['id'],
|
'id' => $user['id'],
|
||||||
'username' => $user['name'],
|
'username' => $user['name'],
|
||||||
'email' => $user['email'],
|
'email' => $user['email'],
|
||||||
|
@ -49,12 +45,11 @@ class UserController
|
||||||
$code = ($data != null) ? 200 : 404;
|
$code = ($data != null) ? 200 : 404;
|
||||||
$message = ($data != null) ? "User found." : "User not found.";
|
$message = ($data != null) ? "User found." : "User not found.";
|
||||||
|
|
||||||
print $this->jsonResponse->create($code, $message, []);
|
return $this->jsonResponse->create($code, $message, []);
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$tasks = $this->taskRepository->findByUserId($id);
|
$tasks = $this->taskRepository->findByUserId($id);
|
||||||
|
|
||||||
print $this->jsonResponse->create(200, 'Here are the tasks.', $tasks);
|
return $this->jsonResponse->create(200, 'Here are the tasks.', $tasks);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,7 +30,7 @@ class SessionRepository
|
||||||
* TaskRepository constructor.
|
* TaskRepository constructor.
|
||||||
* @param $db
|
* @param $db
|
||||||
*/
|
*/
|
||||||
public function __construct($db, Security $security)
|
public function __construct(Database $db, Security $security)
|
||||||
{
|
{
|
||||||
$this->db = $db;
|
$this->db = $db;
|
||||||
$this->security = $security;
|
$this->security = $security;
|
||||||
|
|
|
@ -64,7 +64,7 @@ class UserRepository
|
||||||
public function findOneByUsername($username)
|
public function findOneByUsername($username)
|
||||||
{
|
{
|
||||||
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE name = :username');
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE name = :username');
|
||||||
$stmt->bindParam(':username', $username, \PDO::PARAM_INT);
|
$stmt->bindParam(':username', $username, \PDO::PARAM_STR);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
$user = $stmt->fetch(\PDO::FETCH_ASSOC);
|
$user = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
@ -83,7 +83,7 @@ class UserRepository
|
||||||
public function findOneByEmail($email)
|
public function findOneByEmail($email)
|
||||||
{
|
{
|
||||||
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE email = :email');
|
$stmt = $this->db->getConnection()->prepare('SELECT * FROM ' . $this->tableName . ' WHERE email = :email');
|
||||||
$stmt->bindParam(':email', $email, \PDO::PARAM_INT);
|
$stmt->bindParam(':email', $email, \PDO::PARAM_STR);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
|
|
||||||
$user = $stmt->fetch(\PDO::FETCH_ASSOC);
|
$user = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||||
|
@ -103,9 +103,9 @@ class UserRepository
|
||||||
public function create($username, $email, $password)
|
public function create($username, $email, $password)
|
||||||
{
|
{
|
||||||
$stmt = $this->db->getConnection()->prepare('INSERT INTO ' . $this->tableName . ' (`name`, `email`, `password`) VALUES(:name, :email, :password)');
|
$stmt = $this->db->getConnection()->prepare('INSERT INTO ' . $this->tableName . ' (`name`, `email`, `password`) VALUES(:name, :email, :password)');
|
||||||
$stmt->bindParam(':name', $username);
|
$stmt->bindParam(':name', $username, \PDO::PARAM_STR);
|
||||||
$stmt->bindParam(':email', $email);
|
$stmt->bindParam(':email', $email, \PDO::PARAM_STR);
|
||||||
$stmt->bindParam(':password', $password);
|
$stmt->bindParam(':password', $password, \PDO::PARAM_STR);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@ namespace App\Service;
|
||||||
*/
|
*/
|
||||||
class JsonResponse
|
class JsonResponse
|
||||||
{
|
{
|
||||||
public function create(int $code, string $message = null, array $data = [])
|
public function create(int $code, string $message = null, array $data = []): ?string
|
||||||
{
|
{
|
||||||
$response = [
|
$response = [
|
||||||
'code' => $code,
|
'code' => $code,
|
||||||
|
@ -16,11 +16,16 @@ class JsonResponse
|
||||||
'data' => $data
|
'data' => $data
|
||||||
];
|
];
|
||||||
|
|
||||||
header('Access-Control-Allow-Origin: ' . getenv('ALLOW_ORIGIN'));
|
//header('Access-Control-Allow-Origin: ' . getenv('ALLOW_ORIGIN'));
|
||||||
|
header("Access-Control-Allow-Origin: http://localhost:3000");
|
||||||
|
header("Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token, Authorization");
|
||||||
|
header("Access-Control-Allow-Credentials: true");
|
||||||
|
header('Access-Control-Max-Age: 1');
|
||||||
header('Accept: application/json');
|
header('Accept: application/json');
|
||||||
header('Content-Type: application/json');
|
header('Content-Type: application/json');
|
||||||
http_response_code($code);
|
http_response_code($code);
|
||||||
|
|
||||||
return json_encode($response);
|
print json_encode($response);
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue