Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor and prettify all files #56

Merged
merged 1 commit into from
Apr 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .prettierrc
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"
}
118 changes: 54 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand All @@ -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'.

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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"
}
```

Expand All @@ -194,7 +188,7 @@ If successfull you will receive a json object as below:

```json
{
"deleted": true
"deleted": true
}
```

Expand All @@ -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

Expand Down
16 changes: 9 additions & 7 deletions db/build.js
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;
7 changes: 2 additions & 5 deletions db/connection.js
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;
35 changes: 18 additions & 17 deletions db/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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;
71 changes: 71 additions & 0 deletions handlers/examples-handlers.js
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
};
Loading