Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f9a5910
file tree setup, small changes made to backend server.js
andrewbloom37 Jan 24, 2018
c24c81e
basic auth implemented on frontend
andrewbloom37 Jan 24, 2018
6085587
updated readme and reformated some JSX
andrewbloom37 Jan 24, 2018
dec0179
Merge pull request #1 from ALB37/scramblevox-frontend
andrewbloom37 Jan 24, 2018
b98ca6b
adding signup validation
andrewbloom37 Jan 24, 2018
34348be
adding logic to display error messages with signup
andrewbloom37 Jan 24, 2018
256dbed
refactored back end to reflect one-many relationship between models
andrewbloom37 Jan 24, 2018
cbb610d
persistence via cookies implemented
andrewbloom37 Jan 25, 2018
83502d6
debugging application, async issues
andrewbloom37 Jan 25, 2018
f008a19
fixed problem by moving async get request to a component further down
andrewbloom37 Jan 25, 2018
db2fcda
redirecting on refresh to prevent fatal application crash, app works,…
andrewbloom37 Jan 25, 2018
4490bd1
Merge pull request #2 from ALB37/frontend-cookies
andrewbloom37 Jan 25, 2018
6780f00
adding tests for reducer
andrewbloom37 Jan 25, 2018
63fc196
updated readme
andrewbloom37 Jan 25, 2018
79153fb
Merge pull request #3 from ALB37/frontend-cookies
andrewbloom37 Jan 25, 2018
0f96029
updated wave-router to include a fetch all route
andrewbloom37 Jan 28, 2018
98105c5
fixed accidental line addition to server file
andrewbloom37 Jan 28, 2018
ffcd191
set up action and reducer for client-wave
andrewbloom37 Jan 29, 2018
60f462b
added upload form and successfuly post to server/aws
andrewbloom37 Jan 29, 2018
687c366
transforms implemented on post form, delete works on dashboard
andrewbloom37 Jan 29, 2018
8e144b4
updated tests
andrewbloom37 Jan 29, 2018
6eb11ab
improving text description of user actions in interface
andrewbloom37 Jan 29, 2018
f4bf9f0
updated readme
andrewbloom37 Jan 29, 2018
e37dd9e
Merge pull request #4 from ALB37/many-model
andrewbloom37 Jan 29, 2018
d2f41af
refactoring redirects to history.push, cleaning up code
andrewbloom37 Jan 29, 2018
5ef626a
Merge pull request #5 from ALB37/many-model
andrewbloom37 Jan 29, 2018
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
5 changes: 5 additions & 0 deletions lab-andrew/backend/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**/node_modules/*
**/vendor/*
**/*.min.js
**/coverage/*
**/build/*
27 changes: 27 additions & 0 deletions lab-andrew/backend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"env": {
"browser": true,
"node": true,
"commonjs": true,
"jest": true,
"es6": true
},
"globals": {
"err": true,
"req": true,
"res": true,
"next": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"no-console": "off",
"indent": [ "error", 2, { "SwitchCase": 1 } ],
"quotes": ["error", "single", { "allowTemplateLiterals": true }],
"space-infix-ops": ["error", {"int32Hint": false}],
"comma-dangle": ["error", "always-multiline"],
"semi": [ "error", "always" ]
}
}
107 changes: 107 additions & 0 deletions lab-andrew/backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Created by https://www.gitignore.io/api/node,macos

### macOS ###
*.DS_Store
.AppleDouble
.LSOverride
*/.DS_Store

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
temp

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Node ###
# Logs
logs
log.json
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

### VisualStudioCode ###
.vscode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
*/.env


# mongo db
db

# End of https://www.gitignore.io/api/node,macos
18 changes: 18 additions & 0 deletions lab-andrew/backend/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
language: node_js
node_js:
- '8.9.3'
services:
- mongodb
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.8
- g++-4.8
env:
- CXX=g++-4.8
sudo: required
before_script: npm i
script:
- npm test
21 changes: 21 additions & 0 deletions lab-andrew/backend/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2017 ScrambleVox

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
135 changes: 135 additions & 0 deletions lab-andrew/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# SCRAMBLE VOX
[![Build Status](https://travis-ci.org/ScrambleVox/server.svg?branch=readme)](https://travis-ci.org/ScrambleVox/server)
![Heroku](http://heroku-badge.herokuapp.com/?app=angularjs-crypto&style=flat&svg=1)

_scramble your voice by the method of your choice_


![picture of WAV file](/assets/AudacityWAV.png)
## Overview
This API is designed to take an audio file and return a transformed version of that file. HTTP requests can be made to the server, which is built on RESTful principles. Users can send an 8 bit or 16 bit uncompressed WAV audio file, and depending on the request, one of a number of provided transforms will be performed (see 'Transforms'). A command line tool is provided for proof of concept, and as a handy way to easily perform the various transforms by making requests to the deployed server on Heroku.
***

## Getting Started
Familiarity with node, git and the command line are expected. To set up ScrambleVox on your own machine, take the following steps:
1. Fork or clone the repository onto your machine
2. Run 'npm i -g' from the cloned repo
3. To use the command line tools, type 'scramblevox `<command>`'. To see how to interact with the server using the CLI, simply type 'scramblevox', or 'scamblevox help' and the help file will be shown. Requests will be made to the deployed Heroku app.

## To Record a WAV format audio sample for use with this app
[Audacity](https://www.audacityteam.org/) : free, open source, cross-platform audio software for multi-track recording and editing.
***
## Models
### User
The user schema defines a userame, passwordHash, passwordSalt and email. The username and email must be unique. When a user signs up, a passwordSalt is randomly generated, and a hash is created using this along with their password. The password is never stored anywhere. A token seed is then randomly generated and encrypted with the application's secret salt, and the resulting token is returned to the user. When the user logs back in, their password is hashed along with their passwordSalt, and if this matches the stored hash, a new tokenSeed is generated, stored, encrypted and the resulting token is sent back to the user. When certain requests are made, the user sends their token, which is decrypted by the secret salt, and if it matches their tokenseed, they are authorized to finish making the request.
### Wave
The wave schema defines a user, a wavename and a url. When a wave is posted, the token sent with the request is decrypted and matched to a user. If a valid user is found, the wave's user property is set to reference that user's mongodb _id. The wave file will be transformed and posted to AWS, and the link to the AWS-hosted resource is returned and set to the wave's url property. The wavename is set to the value passed in the relevant field, however this is not a required parameter.
***
## Transforms
*Bitcrusher*: Reduces the resolution of the audio from 8 or 16 bits to 3 bits without affecting the actual bit depth of the audio file.

![picture of sound wave](/assets/bitcrusher.png)

*Down Pitcher*: Reduces the sample rate of the audio file by half, reducing the maximum possible frequency of the recording which results in a lower pitch.

![picture of sound wave](/assets/downpitcher.png)

*Delay*: Adds a portion of the sound wave from a prior sample in the audio buffer to the current position via a fixed interval; simulating an echo.

![picture of sound wave](/assets/delay.png)
![picture of sound wave](/assets/delay2.png)

*Noise Addition*: Adds or subtracts a small random number to each sample which has the effect of adding noise to the sound wave.

![picture of sound wave](/assets/noise.png)

*Reverse*: Reverses the order of the bytes in the audio buffer of the sound wave.

![picture of sound wave](/assets/reverse.png)
***
## Routes
### Account setup
1. **POST** __api_url__/signup : Creates a new account and responds with a token. You must include a username (String), email (String), and password (String).
2. **GET** __api_url__/login : Accesses an account and returns a new token. You must send the account's username and password in the auth header of the request. If no basic authentication is included a 400 error will occur.

### Transforming files
1. **POST** __api_url__/waves/:transform : Transforms an audio file with the given transform function and returns a url to the modified file. You must send the token for your account in the authorization header of the request. If no bearer authorization is included a 401 error will occur. If a file already exists in the database, it will be removed from both AWS and the database first before uploading the new file.
2. **GET** __api_url__/waves : Returns the wave that is stored in the database which belongs to the user with whom the sent token is associated. A 401 will occur if the bearer authorization fails.
2 **DELETE** __api_url__/waves : Removes the wave which belongs to the user with whom the sent token is associated. The file will be removed from both AWS and the database. A 401 will occur if bearer authorization fails.

***
## Tests
ScrambleVox implements continuous integration (CI) via Travis CI and is deployed on Heroku. Tests are performed with Jest. Pushes to master will be tested by Travis, and if all tests pass, an updated build will be automatically deployed on Heroku.

Tests examine both proper behavior for each route as well as behavior when errors occur. The following tests can be executed by running 'npm run test' after installing Jest with 'npm i jest'. Note: in order to successfully run the tests, the mongodb server must be on, and the server must be off.

1. User Router Tests
* POST
* Tests success case in which the username, email, and password are included and a new account and token are successfully created.
* Tests failure cases in which:
* The request is missing information (username, email, and password are all required)
* The username and/or email provided are already being used on an existing account

* GET
* Tests success case in which the account username and password are verified and a token can successfully be returned.
* Tests failure cases in which:
* No bearer authorization is provided in the HTTP authorization header.
* No user can be found with the specified username and password.

2. Wave Router Tests
* Tests success case in which a user successfully makes an account, the file provided is modified, and the url to the modified file is returned.
* Tests failure cases in which:
* The user is verified using bearer authorization but the request is bad.
* No authorization header or a bad token is sent with the request.

3. Wave Parser Tests
* Tests success case in which file meets all requirements and a new Constructed Wave File is created.
* Tests failure cases in which:
* The file is the incorrect format (not RIFF or not WAV)
* The file size is too large
* The file has additional pieces of data that are unexpected (subchunk id 1 or subchunk id 2 do not match the expected values of 'fmt' and 'data' respectively)
* The file is not linear PCM encoded (i.e. the file is compressed)
* The file has more than two channels (it is not mono or stereo)
* The sample rate is too high (above 48k)
* The file has a bit depth other than 8 or 16 bits

4. Transform Tests
* Tests success cases for 8 bit and 16 bit files, i.e. that the expected results from the transform in question are properly returned.
***
## Technologies Used
### Production
* ES6
* node
* aws-sdk
* bcrypt
* dotenv
* express
* fs-extra
* http-errors
* jsonwebtoken
* mongodb
* mongoose
* multer
* winston

### Development
* aws-sdk-mock
* eslint
* faker
* jest
* superagent
***
## To Contribute
If you would like to help improve this API you can do so by opening an issue under the 'Issues' tab on the repo. We welcome any helpful feedback! Be sure to include a label to help us better understand the issue (i.e. 'bug' to report a problem).
***
## License
MIT (see License file)
***
## Authors
- Andrew Bloom | [GitHub](https://github.com/ALB37)
- Shannon Dillon | [GitHub](https://github.com/sedillon93)
- Jeff Kusowski | [GitHub](https://github.com/jjkusowski)
- David A. Lindahl | [GitHub](https://github.com/austriker27)
***
## Special Thanks
Thank you to Vinicio Vladimir Sanchez Trejo, Steve Geluso, Izzy Baer, Joshua Evans, and Ron Dunphy for help problem solving and identifying useful tools to examine WAV files.
Binary file added lab-andrew/backend/__test__/assets/bad1.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/bad2.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/bad3.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/bad4.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/bad5.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/bad6.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/bad7.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/bad8.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/bad9.wav
Binary file not shown.
Binary file added lab-andrew/backend/__test__/assets/testclip.wav
Binary file not shown.
40 changes: 40 additions & 0 deletions lab-andrew/backend/__test__/lib/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict';

const faker = require('faker');
const awsSDKMock = require('aws-sdk-mock');

process.env.AWS_ACCESS_KEY_ID = 'secretkeyid';
process.env.AWS_BUCKET = 'mycoolbucket';
process.env.AWS_SECRET_ACCESS_KEY = 'mysecretkeyshhhhh';
process.env.SECRET_SALT = 'Password123!';
process.env.MONGODB_URI = 'mongodb://localhost/testing';
process.env.PORT = 3000;

awsSDKMock.mock('S3', 'upload', (params, callback) => {
if (!params.Key || !params.Bucket || !params.Body || !params.ACL){
return callback(new Error('__ERROR__', 'key, bucket, body and ACL are required'));
}

if (params.ACL !== 'public-read'){
return callback(new Error('__ERROR__', 'ACL should be public-read'));
}

if (params.Bucket !== process.env.AWS_BUCKET){
return callback(new Error('__ERROR__', 'bucket is incorrect'));
}

callback(null, {Location: faker.internet.url()});
});

awsSDKMock.mock('S3', 'deleteObject', (params, callback) => {
if (!params.Key || !params.Bucket){
return callback(new Error('__ERROR__', 'key, and bucket are required'));
}

if (params.Bucket !== process.env.AWS_BUCKET) {
return callback(new Error('__ERROR__', 'bucket is incorrect'));
}

callback(null, {});
});

31 changes: 31 additions & 0 deletions lab-andrew/backend/__test__/lib/transforms/bitcrusher.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

const bitcrusher = require('../../../lib/transforms/bitcrusher');

describe('testing bitcrusher transform module', () => {
test('expect that bitcrusher changes values for 8 bit file', () => {
const file = {};
file.bitsPerSample = 8;
file.data = Buffer.from([248, 129, 70, 4]);
bitcrusher(file);
expect(file.data[0]).toEqual(224);
expect(file.data[1]).toEqual(128);
expect(file.data[2]).toEqual(64);
expect(file.data[3]).toEqual(0);
});

test('expect that bitcrusher changes values for 16 bit file', () => {
const bigFile = {};
bigFile.bitsPerSample = 16;
bigFile.data = Buffer.from(new Uint16Array(8));
bigFile.data.writeUInt16LE(50000, 0);
bigFile.data.writeUInt16LE(33000, 2);
bigFile.data.writeUInt16LE(20000, 4);
bigFile.data.writeUInt16LE(100, 6);
bitcrusher(bigFile);
expect(bigFile.data.readUInt16LE(0)).toEqual(49152);
expect(bigFile.data.readUInt16LE(2)).toEqual(32768);
expect(bigFile.data.readUInt16LE(4)).toEqual(16384);
expect(bigFile.data.readUInt16LE(6)).toEqual(0);
});
});
Loading