Skip to content
Permalink
Browse files
initial commit
  • Loading branch information
aa7401 committed Nov 22, 2020
0 parents commit bc7296098b192cef5f1be1244ee2b069ba05013c
Show file tree
Hide file tree
Showing 19 changed files with 608 additions and 0 deletions.
6 .codio
@@ -0,0 +1,6 @@

{
"preview": {
"Live Server": "https://{{domain8080}}/{{index}}"
}
}
@@ -0,0 +1,3 @@

node_modules/
package-lock.json
@@ -0,0 +1,17 @@
{
"name": "REST Web API Template",
"children": [
{
"title": "REST API Template",
"id": "2b8086f5-6a80-02fa-d21e-8c6737a7adb1",
"pageId": "2b8086f5-6a80-02fa-d21e-8c6737a7adb1",
"type": "page"
},
{
"title": "Page 2",
"id": "4eb52e58-2c43-e3c6-72b5-f0c2865ebe14",
"pageId": "4eb52e58-2c43-e3c6-72b5-f0c2865ebe14",
"type": "page"
}
]
}
@@ -0,0 +1 @@
# Sample content Page 2
@@ -0,0 +1,16 @@
You are running the REST API template which provides a running codebase on which you can build your own API.

The MySQL database is installed with a database called `api`.

The following accounts have been configured:

- The `root` account.
- There is an `apiuser`. This has CREATE, UPDATE, INSERT and DELETE permissions on all tables in the `api` database.

> Note: both accounts have a default password of `CHANGEME` make sure you change the passwords on both accounts at the earliest opportunity!
# Updating Project Settings

To allow you to access the API you need to change the project settings.

Go to Project > Settings and turn off **PROTECT DYNAMIC PORTS**.
@@ -0,0 +1,40 @@
{
"sections": [
{
"id": "2b8086f5-6a80-02fa-d21e-8c6737a7adb1",
"title": "REST API Template",
"files": [],
"path": [],
"type": "markdown",
"content-file": ".guides/content/REST-API-Template-2b80.md",
"chapter": false,
"reset": [],
"teacherOnly": false,
"learningObjectives": ""
},
{
"id": "4eb52e58-2c43-e3c6-72b5-f0c2865ebe14",
"title": "Page 2",
"files": [],
"path": [],
"type": "markdown",
"content-file": ".guides/content/Page-2-4eb5.md",
"chapter": false,
"reset": [],
"teacherOnly": false,
"learningObjectives": ""
}
],
"theme": "light",
"scripts": [],
"lexikonTopic": "",
"suppressPageNumbering": false,
"useSubmitButtons": true,
"useMarkAsComplete": true,
"hideMenu": false,
"allowGuideClose": false,
"collapsedOnStart": false,
"hideSectionsToggle": false,
"hideBackToDashboard": false,
"protectLayout": false
}
@@ -0,0 +1,67 @@
[editor]
tab_size = 2
; enter your editor preferences here...

[ide]
; enter your ide preferences here...

[code-beautifier]
; enter your code-beautifier preferences here...

[codio-filetree]
; enter your codio-filetree preferences here...

[view-javascript-code]
; enter your view-javascript-code preferences here...

[codio-lsp]
; enter your codio-lsp preferences here...

[junit]
; enter your junit preferences here...

[git]
; enter your git preferences here...

[terminal]
; enter your terminal preferences here...

[preview]
; enter your preview preferences here...

[emmet]
; enter your emmet preferences here...

[search]
; enter your search preferences here...

[guides]
; enter your guides preferences here...

[settings]
; enter your settings preferences here...

[account]
; enter your account preferences here...

[project]
; enter your project preferences here...

[install-software]
; enter your install-software preferences here...

[deployment]
; enter your deployment preferences here...

[container]
; enter your container preferences here...

[sync-structure]
; enter your sync-structure preferences here...

[education]
; enter your education preferences here...

[Codio Lexikon]
; enter your Codio Lexikon preferences here...

@@ -0,0 +1,13 @@
# REST Web API Template

This code provides a working template for the development of modern REST APIs connecting to a MySQL database.

It only runs on Codio boxes.

To install, run the following command from inside the Codio box:

```shell
$
```

> Note this will delete ALL the existing content from your Codio Box.
@@ -0,0 +1,6 @@

{
"preview": {
"Live Server": "https://{{domain8080}}/{{index}}"
}
}
@@ -0,0 +1,16 @@

/* index.js */

import Koa from 'koa'

import router from './routes/routes.js'

const app = new Koa()
app.keys = ['darkSecret']

const defaultPort = 8080
const port = process.env.PORT || defaultPort
app.use(router.routes())
app.use(router.allowedMethods())

app.listen(port, async() => console.log(`listening on port ${port}`))
@@ -0,0 +1,106 @@
#!/bin/bash

# SETUP RESTful API TEMPLATE

red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`

echo
echo "======= CHECKING WE ARE ON A CODIO BOX ======="
if [ -v CODIO_HOSTNAME ]
then
echo "Codio box detected"
echo "continuing setup"
else
echo "no Codio box detected"
echo "exiting setup"
exit 1
fi
sudo chown -R codio:codio .

# destructive section start

echo
echo "============== ${green}DELETING${reset} OLD FILES ==================="
rm -rf *
rm -rf .*
rm -rf .guides
echo
echo "============== CLONING ${green}REPOSITORY${reset} ==================="
git clone https://github.coventry.ac.uk/web/Codio-API-Template.git .
git remote rm origin
rm -rf install.sh # delete this script so it can't be run from inside the project!
rm .codio
mv codio.json .codio
echo
echo "============= DELETING ${green}TEMPORARY FILES${reset} =============="
rm -rf *.db # delete any old database files
rm -rf package-lock.json
rm -rf .settings
rm -rf .sqlite_history
rm -rf .bash_history
rm -rf .git # delete the repository we have cloned (if any)

# end of distructive section

echo
echo "========= CONFIGURING MYSQL ACCOUNT =========="
sudo debconf-set-selections <<< 'mysql-server mysql-server/root_password password CHANGEME'
sudo debconf-set-selections <<< 'mysql-server mysql-server/root_password_again password CHANGEME'

echo
echo "============ INSTALLING PACKAGES ============"

sudo add-apt-repository -y ppa:git-core/ppa
sudo apt update -y
sudo apt upgrade -y

sudo apt install -y psmisc lsof tree build-essential gcc g++ make jq curl git
sudo apt -y install mysql-server mysql-client
sudo apt autoremove -y

echo
echo "========= INSTALLING NODE USING ${green}NODESOURCE${reset} ========="
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt install -y nodejs
echo
echo "=============== INSTALLING ${green}API-TEST${reset} ================"
curl -LJO https://raw.githubusercontent.com/subeshb1/api-test/master/api-test.sh
chmod +x api-test.sh
sudo mv api-test.sh /usr/local/bin/api-test
api-test --version
echo
echo "=========== INSTALLING THE ${green}NODE PACKAGES${reset} ==========="
echo
# rm -rf node_modules
# rm -rf package-lock.json
# npm install
# npm install --save-dev eslint ava # we WILL ensure these are installed!
# npm audit fix

echo
echo "========= CUSTOMISING SHELL PROMPT =========="
if grep PS1 ~/.profile
then
echo "correct prompt found"
else
echo "prompt needs updating"
echo "PS1='$ '" >> ~/.profile
fi

if grep restart ~/.profile
then
echo "database restart command found"
else
echo "database restart command needs adding"
echo "sudo /etc/init.d/mysql restart" >> ~/.profile
fi

echo
echo "=========== CREATING DATABASE =============="
mysql -u root -pp455w0rd < install.sql

source ~/.profile


@@ -0,0 +1,14 @@

-- onetime setup for the api database
CREATE USER IF NOT EXISTS apiuser IDENTIFIED BY 'CHANGEME';
DROP DATABASE IF EXISTS api;
CREATE DATABASE IF NOT EXISTS api;
USE api;
GRANT INSERT, SELECT, UPDATE, DELETE ON api.* TO apiuser;

CREATE TABLE IF NOT EXISTS accounts (
id SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(25) NOT NULL,
password VARCHAR(60) NOT NULL,
email VARCHAR(25) NOT NULL
);
@@ -0,0 +1,77 @@

/** @module Accounts */

import bcrypt from 'bcrypt-promise'

import { extractCredentials } from '../modules/common.js'
import { get, all, run } from '../modules/mysql.js'

const saltRounds = 10

/**
* Accounts
* ES6 module that handles registering accounts and logging in.
*/
class Accounts {
/**
* Create an account object
*/
constructor() {
return (async() => {
return this
})()
}

/**
* registers a new user
* @param {String} user the chosen username
* @param {String} pass the chosen password
* @param {String} email the chosen email
* @returns {Boolean} returns true if the new user has been added
*/
async register(user, pass, email) {
try {
Array.from(arguments).forEach( val => {
if(val.length === 0) throw new Error('missing field')
})
let sql = `SELECT COUNT(id) as records FROM accounts WHERE username="${user}";`
const data = await get(sql)
console.log('data: ', data)
if(data.records !== 0) throw new Error(`username "${user}" already in use`)
sql = `SELECT COUNT(id) as records FROM accounts WHERE email="${email}";`
const emails = await get(sql)
console.log('emails: ', emails)
if(emails.records !== 0) throw new Error(`email address "${email}" is already in use`)
pass = await bcrypt.hash(pass, saltRounds)
console.log(`password length: ${pass.length}`)
sql = `INSERT INTO accounts(username, password, email) VALUES("${user}", "${pass}", "${email}")`
await run(sql)
return true
} catch(err) {
console.log('module error')
console.log(err)
throw err
}
}

/**
* checks to see if a set of login credentials are valid
* @param {String} token the basic auth token
* @returns {String} returns the username if credentials are valid
*/
async checkToken(token) {
const login = extractCredentials(token)
let sql = `SELECT count(id) AS count FROM accounts WHERE username="${login.user}";`
const records = await get(sql)
if(!records.count) throw new Error(`username "${login.user}" not found`)
sql = `SELECT password FROM accounts WHERE username = "${login.user}";`
const record = await get(sql)
const valid = await bcrypt.compare(login.pass, record.password)
if(valid === false) throw new Error(`invalid password for account "${login.user}"`)
return login.user
}

}

export default Accounts

0 comments on commit bc72960

Please sign in to comment.