-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Relates #54
- Loading branch information
Showing
21 changed files
with
756 additions
and
794 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"printWidth": 100, | ||
"tabWidth": 4, | ||
"useTabs": false, | ||
"semi": true, | ||
"singleQuote": false, | ||
"trailingComma": "none", | ||
"bracketSpacing": false, | ||
"jsxBracketSameLine": false, | ||
"arrowParens": "avoid", | ||
"proseWrap": "never" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,19 +25,19 @@ Project build as a part of Founders and Coders FAC19. | |
|
||
### Stack | ||
|
||
- JavaScript | ||
- Node | ||
- Express | ||
- PostgreSQL | ||
- JavaScript | ||
- Node | ||
- Express | ||
- PostgreSQL | ||
|
||
### User Stories | ||
- As an API user, I want to: get a list of all available resources | ||
- As an API user, I want to: get all the information on a specific resource | ||
- As an API user, I want to: create a new resource | ||
- As an API user, I want to: update an existing resource | ||
- As an API user, I want to: delete an existing resource | ||
- As an API user, I want to: only be able to change an existing resource if I am authenticated to do so | ||
|
||
- As an API user, I want to: get a list of all available resources | ||
- As an API user, I want to: get all the information on a specific resource | ||
- As an API user, I want to: create a new resource | ||
- As an API user, I want to: update an existing resource | ||
- As an API user, I want to: delete an existing resource | ||
- As an API user, I want to: only be able to change an existing resource if I am authenticated to do so | ||
|
||
### Database Schema | ||
|
||
|
@@ -69,28 +69,23 @@ CREATE TABLE examples | |
1. Clone repo | ||
2. cd into folder | ||
3. Run NPM install | ||
4. If you already have an existing SUPERUSER | ||
create a local production psql data base and assign it to that user. | ||
```sql | ||
CREATE DATABASE local_production_database_name WITH OWNER your_user; | ||
``` | ||
|
||
OTHERWISE change your user to a superuser | ||
```sql ALTER USER your_user WITH SUPERUSER ``` | ||
|
||
|
||
4. If you already have an existing SUPERUSER create a local production psql data base and assign it to that user. | ||
```sql | ||
CREATE DATABASE local_production_database_name WITH OWNER your_user; | ||
``` | ||
|
||
OTHERWISE change your user to a superuser `sql ALTER USER your_user WITH SUPERUSER` | ||
|
||
5. Create a test database called localtest with the same owner/user | ||
```sql | ||
CREATE DATABASE localtest WITH OWNER your_user; | ||
``` | ||
```sql | ||
CREATE DATABASE localtest WITH OWNER your_user; | ||
``` | ||
6. Create an .env file in the project's root folder | ||
- PGDATABASE=local_production_database_name | ||
- PGUSER=your_user | ||
- PGPASSWORD=your_password | ||
- SECRET=JWTSECRET | ||
You can choose a secret of your choice. | ||
7. npm run setupdb | ||
Alternatively import db/init.sql in your preferred db admin tool | ||
- PGDATABASE=local_production_database_name | ||
- PGUSER=your_user | ||
- PGPASSWORD=your_password | ||
- SECRET=JWTSECRET You can choose a secret of your choice. | ||
7. npm run setupdb Alternatively import db/init.sql in your preferred db admin tool | ||
### Running the server | ||
|
@@ -105,11 +100,12 @@ create a local production psql data base and assign it to that user. | |
### Example users and passwords | ||
There are five default users, their email addresses are. | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] | ||
- [email protected] | ||
Their passwords are, unsurprisingly, 'password'. | ||
|
@@ -131,14 +127,13 @@ Send a post request to path above using raw json request. Example below: | |
|
||
```json | ||
{ | ||
"username": "Peter Pumpernicke;", | ||
"email": "[email protected]", | ||
"password": "password" | ||
"username": "Peter Pumpernicke;", | ||
"email": "[email protected]", | ||
"password": "password" | ||
} | ||
``` | ||
|
||
If successful, user object is returned. | ||
If user already exists, error will be returned. | ||
If successful, user object is returned. If user already exists, error will be returned. | ||
|
||
### Login as user | ||
|
||
|
@@ -148,13 +143,12 @@ Send a post request to path above using raw json request. Example below: | |
|
||
```json | ||
{ | ||
"email": "registered_email_address", | ||
"password": "your_password" | ||
"email": "registered_email_address", | ||
"password": "your_password" | ||
} | ||
``` | ||
|
||
If successful, token object is returned. YOU WILL NEED THIS TOKEN TO ADD OR DELETE EXAMPLES! | ||
If email or password are incorrect, error will be returned. | ||
If successful, token object is returned. YOU WILL NEED THIS TOKEN TO ADD OR DELETE EXAMPLES! If email or password are incorrect, error will be returned. | ||
|
||
### Get example with a specified ID | ||
|
||
|
@@ -176,9 +170,9 @@ You can use postman or similar tool. Request must be sent with AUTHORIZATION bea | |
|
||
```json | ||
{ | ||
"language": "js", | ||
"title": "enter_title_here", | ||
"example": "code_cnippet_example_here" | ||
"language": "js", | ||
"title": "enter_title_here", | ||
"example": "code_cnippet_example_here" | ||
} | ||
``` | ||
|
||
|
@@ -194,7 +188,7 @@ If successfull you will receive a json object as below: | |
|
||
```json | ||
{ | ||
"deleted": true | ||
"deleted": true | ||
} | ||
``` | ||
|
||
|
@@ -212,43 +206,39 @@ Request needs to be sent using raw json format as below: | |
|
||
```json | ||
{ | ||
"language": "value to update", | ||
"title": "value to update", | ||
"example": "value to update" | ||
"language": "value to update", | ||
"title": "value to update", | ||
"example": "value to update" | ||
} | ||
``` | ||
|
||
You only need to include the fields you want to update. Omitted fields will remain unchanged, | ||
|
||
|
||
### Search by keyword and filter by language example | ||
|
||
`GET /search/yourSearchTerm?lang=js` | ||
|
||
We sadly didn't get that far but lookout for this feature in the next version! | ||
### Project Acceptance Criteria | ||
- [x] An Express server that only returns JSON | ||
- [x] A Postgres database to store the data | ||
- [x] Endpoints for creating, reading, updating & deleting resources | ||
- [x] An Express server that only returns JSON | ||
- [x] Token-based authentication so only the owner of a resource can change it | ||
- [x] A Postgres database to store the data | ||
- [x] Correct headers and response metadata (we think) | ||
- [x] Endpoints for creating, reading, updating & deleting resources | ||
- [x] Error-handling to make it easy to use the API to build something | ||
- [x] Token-based authentication so only the owner of a resource can change it | ||
- [x] Tests for server routes and database access | ||
- [x] Correct headers and response metadata (we think) | ||
- [x] Not process user input as SQL commands | ||
- [x] Error-handling to make it easy to use the API to build something | ||
- [x] Hidden environment variables (i.e. not on GitHub) | ||
- [x] Tests for server routes and database access | ||
- [x] Not process user input as SQL commands | ||
- [x] Hidden environment variables (i.e. not on GitHub) | ||
### The end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,16 @@ | ||
const db = require('./connection'); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const db = require("./connection"); | ||
const path = require("path"); | ||
const fs = require("fs"); | ||
|
||
const initPath = path.join(__dirname, 'init.sql'); | ||
const initSql = fs.readFileSync(initPath, 'utf-8'); | ||
const initPath = path.join(__dirname, "init.sql"); | ||
const initSql = fs.readFileSync(initPath, "utf-8"); | ||
|
||
function build() { | ||
return db.query(initSql); | ||
}; | ||
} | ||
|
||
// Allows build to be ran on the command line, npm run setupdb will now run build() | ||
if (require.main === module) build(); | ||
|
||
module.exports = build; | ||
// Testing imports build but chooses when to run it | ||
module.exports = build; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,8 @@ | ||
const pg = require("pg"); | ||
const dotenv = require("dotenv"); | ||
|
||
dotenv.config(); | ||
// console.log(process.env); | ||
require("dotenv").config(); | ||
|
||
const db = new pg.Pool({ | ||
connectionString: process.env.DATABASE_URL | ||
}); | ||
|
||
module.exports = db; | ||
module.exports = db; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,24 +19,25 @@ CREATE TABLE examples | |
language VARCHAR(32), | ||
title VARCHAR(255), | ||
example TEXT NOT NULL, | ||
date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP | ||
date TIMESTAMP | ||
WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP | ||
); | ||
|
||
INSERT INTO users | ||
(username, email, user_password, adminusr) | ||
VALUES | ||
('admin', '[email protected]', '$2a$10$zH7.4s2AbH8Lz.SqsauRSOldLUacu3axD.0ZgoR2v2CJpM/pItOiy', true), | ||
('Tom', '[email protected]', '$2a$10$aHsFImUy5q1fj37Z72O6r.iUpDLL1CBH38UCaHGK25CEP5W5uyVQa', false), | ||
('Chloe', '[email protected]', '$2a$10$QFV6woSkfTa6XhaJAYYCmu8fqkLOduWm.kDzZI56crZCTIaKzaFDy', false), | ||
('Kat', '[email protected]', '$2a$10$SSahAXMX/e.3VS0juErkceVbwwR1iL8/cWYnOD5IILyf.74EMnHr6', false), | ||
('Roger', '[email protected]', '$2a$10$./Rk0decBFt/XHJcIJX2XOq3Qq0AbfsQCPNQ7Gz66TA7dFK8l5/Fm', false); | ||
INSERT INTO users | ||
(username, email, user_password, adminusr) | ||
VALUES | ||
('admin', '[email protected]', '$2a$10$zH7.4s2AbH8Lz.SqsauRSOldLUacu3axD.0ZgoR2v2CJpM/pItOiy', true), | ||
('Tom', '[email protected]', '$2a$10$aHsFImUy5q1fj37Z72O6r.iUpDLL1CBH38UCaHGK25CEP5W5uyVQa', false), | ||
('Chloe', '[email protected]', '$2a$10$QFV6woSkfTa6XhaJAYYCmu8fqkLOduWm.kDzZI56crZCTIaKzaFDy', false), | ||
('Kat', '[email protected]', '$2a$10$SSahAXMX/e.3VS0juErkceVbwwR1iL8/cWYnOD5IILyf.74EMnHr6', false), | ||
('Roger', '[email protected]', '$2a$10$./Rk0decBFt/XHJcIJX2XOq3Qq0AbfsQCPNQ7Gz66TA7dFK8l5/Fm', false); | ||
|
||
INSERT INTO examples | ||
(owner_id, language, title, example) | ||
VALUES | ||
(1, 'js', 'Test example 1', 'Example 1 code goes here.'), | ||
(2, 'sql', 'Test example 2', 'Example 2 code goes here.'), | ||
(3, 'js', 'Test example 3', 'Example 3 code goes here.'), | ||
(4, 'js', 'Test example 4', 'Example 4 code goes here.'); | ||
INSERT INTO examples | ||
(owner_id, language, title, example) | ||
VALUES | ||
(1, 'js', 'Test example 1', 'Example 1 code goes here.'), | ||
(2, 'sql', 'Test example 2', 'Example 2 code goes here.'), | ||
(3, 'js', 'Test example 3', 'Example 3 code goes here.'), | ||
(4, 'js', 'Test example 4', 'Example 4 code goes here.'); | ||
|
||
COMMIT; | ||
COMMIT; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
const modelExample = require("../model/examples-model"); | ||
|
||
function getAllExamples(req, res, next) { | ||
modelExample | ||
.getAllExamples() | ||
.then(example => res.send(example)) | ||
.catch(next); | ||
} | ||
|
||
// Inserts a new example into the examples table and returns the inserted row's id | ||
function postExample(req, res, next) { | ||
req.body.user_id = req.user.id; | ||
req.body.admin = req.user.admin; | ||
modelExample | ||
.createExample(req.body) | ||
.then(exampleId => { | ||
res.status(201).send({ | ||
exampleId: exampleId | ||
}); | ||
}) | ||
.catch(next); | ||
} | ||
|
||
function deleteExample(req, res, next) { | ||
modelExample | ||
.deleteExample(req.params.id, req.user) | ||
.then(() => { | ||
res.status(200).send({deleted: true}); | ||
}) | ||
.catch(next); | ||
} | ||
|
||
function getExample(req, res, next) { | ||
const id = req.params.id; | ||
modelExample | ||
.getExample(id) | ||
.then(result => { | ||
console.log(!result === undefined); | ||
if (!result) { | ||
res.status(204).send("Error: Resource not found"); | ||
} | ||
res.status(200).send(result); | ||
}) | ||
.catch(next); | ||
} | ||
|
||
function updateExample(req, res, next) { | ||
const id = Number(req.params.id); | ||
const userID = req.user.id; | ||
const newdata = req.body; | ||
if (id === NaN) { | ||
const err = new Error("This is not a valid ID"); | ||
err.status = 401; | ||
next(err); | ||
} | ||
|
||
modelExample | ||
.updateExamplebyID(id, newdata, userID) | ||
.then(result => { | ||
res.status(200).send(result); | ||
}) | ||
.catch(next); | ||
} | ||
|
||
module.exports = { | ||
getAllExamples, | ||
postExample, | ||
getExample, | ||
deleteExample, | ||
updateExample | ||
}; |
Oops, something went wrong.