Add sample uploads

This commit is contained in:
Kevin Thomas
2021-08-16 21:04:49 -07:00
parent 78ddc3ee8f
commit 46033ce610
11 changed files with 440 additions and 34 deletions

3
.gitignore vendored
View File

@@ -111,3 +111,6 @@ db.sqlite3
# Sessions file store # Sessions file store
sessions/* sessions/*
# Samples
samples/*

View File

@@ -1,10 +1,11 @@
{ {
"Server": { "Server": {
"listeningPort": 3000, "listeningPort": 3000,
"sessionFileStorePath": "./sessions", "sessionFileStorePath": "sessions",
"sampleUploadPath": "samples",
"sessionSecret": "cats", "sessionSecret": "cats",
"tls": false, "tls": false,
"tlsKey": "./certs/key.pem", "tlsKey": "certs/key.pem",
"tlsCert": "./certs/cert.pem" "tlsCert": "certs/cert.pem"
} }
} }

205
package-lock.json generated
View File

@@ -13,6 +13,7 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"express": "^4.17.1", "express": "^4.17.1",
"express-session": "^1.17.2", "express-session": "^1.17.2",
"multer": "^1.4.3",
"passport": "^0.4.1", "passport": "^0.4.1",
"passport-local": "^1.0.0", "passport-local": "^1.0.0",
"path": "^0.12.7", "path": "^0.12.7",
@@ -3116,6 +3117,11 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/append-field": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY="
},
"node_modules/aproba": { "node_modules/aproba": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
@@ -3953,8 +3959,7 @@
"node_modules/buffer-from": { "node_modules/buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
"dev": true
}, },
"node_modules/buffer-indexof": { "node_modules/buffer-indexof": {
"version": "1.1.1", "version": "1.1.1",
@@ -3980,6 +3985,39 @@
"integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
"dev": true "dev": true
}, },
"node_modules/busboy": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
"dependencies": {
"dicer": "0.2.5",
"readable-stream": "1.1.x"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/busboy/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"node_modules/busboy/node_modules/readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"node_modules/busboy/node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"node_modules/bytes": { "node_modules/bytes": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
@@ -4756,7 +4794,6 @@
"version": "1.6.2", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"dev": true,
"engines": [ "engines": [
"node >= 0.8" "node >= 0.8"
], ],
@@ -5945,6 +5982,39 @@
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"dev": true "dev": true
}, },
"node_modules/dicer": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"dependencies": {
"readable-stream": "1.1.x",
"streamsearch": "0.1.2"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/dicer/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"node_modules/dicer/node_modules/readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"node_modules/dicer/node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"node_modules/diffie-hellman": { "node_modules/diffie-hellman": {
"version": "5.0.3", "version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
@@ -10430,6 +10500,24 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}, },
"node_modules/multer": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz",
"integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==",
"dependencies": {
"append-field": "^1.0.0",
"busboy": "^0.2.11",
"concat-stream": "^1.5.2",
"mkdirp": "^0.5.4",
"object-assign": "^4.1.1",
"on-finished": "^2.3.0",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/multicast-dns": { "node_modules/multicast-dns": {
"version": "6.2.3", "version": "6.2.3",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
@@ -14229,6 +14317,14 @@
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
"dev": true "dev": true
}, },
"node_modules/streamsearch": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/strict-uri-encode": { "node_modules/strict-uri-encode": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
@@ -14959,8 +15055,7 @@
"node_modules/typedarray": { "node_modules/typedarray": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
"dev": true
}, },
"node_modules/typedarray-to-buffer": { "node_modules/typedarray-to-buffer": {
"version": "3.1.5", "version": "3.1.5",
@@ -16791,7 +16886,6 @@
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"dev": true,
"engines": { "engines": {
"node": ">=0.4" "node": ">=0.4"
} }
@@ -19305,6 +19399,11 @@
"picomatch": "^2.0.4" "picomatch": "^2.0.4"
} }
}, },
"append-field": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY="
},
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
@@ -19981,8 +20080,7 @@
"buffer-from": { "buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
"dev": true
}, },
"buffer-indexof": { "buffer-indexof": {
"version": "1.1.1", "version": "1.1.1",
@@ -20008,6 +20106,38 @@
"integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
"dev": true "dev": true
}, },
"busboy": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
"requires": {
"dicer": "0.2.5",
"readable-stream": "1.1.x"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"bytes": { "bytes": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
@@ -20629,7 +20759,6 @@
"version": "1.6.2", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"dev": true,
"requires": { "requires": {
"buffer-from": "^1.0.0", "buffer-from": "^1.0.0",
"inherits": "^2.0.3", "inherits": "^2.0.3",
@@ -21569,6 +21698,38 @@
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"dev": true "dev": true
}, },
"dicer": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"requires": {
"readable-stream": "1.1.x",
"streamsearch": "0.1.2"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"diffie-hellman": { "diffie-hellman": {
"version": "5.0.3", "version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
@@ -25050,6 +25211,21 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}, },
"multer": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz",
"integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==",
"requires": {
"append-field": "^1.0.0",
"busboy": "^0.2.11",
"concat-stream": "^1.5.2",
"mkdirp": "^0.5.4",
"object-assign": "^4.1.1",
"on-finished": "^2.3.0",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
}
},
"multicast-dns": { "multicast-dns": {
"version": "6.2.3", "version": "6.2.3",
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
@@ -28184,6 +28360,11 @@
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
"dev": true "dev": true
}, },
"streamsearch": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
},
"strict-uri-encode": { "strict-uri-encode": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
@@ -28760,8 +28941,7 @@
"typedarray": { "typedarray": {
"version": "0.0.6", "version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
"dev": true
}, },
"typedarray-to-buffer": { "typedarray-to-buffer": {
"version": "3.1.5", "version": "3.1.5",
@@ -30213,8 +30393,7 @@
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
"dev": true
}, },
"y18n": { "y18n": {
"version": "4.0.3", "version": "4.0.3",

View File

@@ -16,6 +16,7 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"express": "^4.17.1", "express": "^4.17.1",
"express-session": "^1.17.2", "express-session": "^1.17.2",
"multer": "^1.4.3",
"passport": "^0.4.1", "passport": "^0.4.1",
"passport-local": "^1.0.0", "passport-local": "^1.0.0",
"path": "^0.12.7", "path": "^0.12.7",

View File

@@ -8,6 +8,7 @@ const config = require('config')
const authRouter = require('./routes/auth') const authRouter = require('./routes/auth')
const usersRouter = require('./routes/users') const usersRouter = require('./routes/users')
const profilesRouter = require('./routes/profiles') const profilesRouter = require('./routes/profiles')
const samplesRouter = require('./routes/samples')
const app = express() const app = express()
const fileStoreOptions = { const fileStoreOptions = {
path: config.get('Server.sessionFileStorePath') path: config.get('Server.sessionFileStorePath')
@@ -22,6 +23,7 @@ app.use(cookieParser())
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../dist'))) app.use(express.static(path.join(__dirname, '../dist')))
} }
app.use('/samples', express.static(path.join(__dirname, '../', config.get('Server.sampleUploadPath'))))
app.use(session({ app.use(session({
store: new FileStore(fileStoreOptions), store: new FileStore(fileStoreOptions),
secret: config.get('Server.sessionSecret'), secret: config.get('Server.sessionSecret'),
@@ -42,5 +44,6 @@ app.use(passport.authenticate('session'))
app.use('/', authRouter) app.use('/', authRouter)
app.use('/', usersRouter) app.use('/', usersRouter)
app.use('/', profilesRouter) app.use('/', profilesRouter)
app.use('/', samplesRouter)
module.exports = app module.exports = app

View File

@@ -29,7 +29,14 @@ module.exports = function () {
tremolo_enabled INTEGER, tremolo_enabled INTEGER,
tremolo_frequency REAL, tremolo_frequency REAL,
tremolo_depth REAL, tremolo_depth REAL,
FOREIGN KEY(user) REFERENCES user(id))` FOREIGN KEY(user) REFERENCES users(id))`
)
db.run(`CREATE TABLE IF NOT EXISTS samples (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE,
user INTEGER,
FOREIGN KEY(user) REFERENCES users(id))`
) )
}) })
} }

View File

@@ -45,9 +45,9 @@ router.post('/profiles', function (req, res) {
function (err) { function (err) {
if (err) { if (err) {
return res.sendStatus(500) return res.sendStatus(500)
} else {
return res.sendStatus(200)
} }
res.sendStatus(200)
} }
) )
}) })
@@ -86,6 +86,7 @@ router.get('/profiles/:profileId', function (req, res) {
db.get(`SELECT db.get(`SELECT
name, name,
user,
timer_enabled as isTimerEnabled, timer_enabled as isTimerEnabled,
duration, duration,
volume, volume,
@@ -105,6 +106,10 @@ router.get('/profiles/:profileId', function (req, res) {
return res.sendStatus(500) return res.sendStatus(500)
} }
if (row.user.toString() !== req.user.id) {
return res.sendStatus(401)
}
profile.name = row.name profile.name = row.name
profile.isTimerEnabled = row.isTimerEnabled === 1 profile.isTimerEnabled = row.isTimerEnabled === 1
profile.duration = row.duration profile.duration = row.duration
@@ -142,11 +147,11 @@ router.delete('/profiles/:profileId', function (req, res) {
db.run('DELETE FROM profiles WHERE id = ?', [req.params.profileId], (err) => { db.run('DELETE FROM profiles WHERE id = ?', [req.params.profileId], (err) => {
if (err) { if (err) {
return res.sendStatus(500) return res.sendStatus(500)
} else {
return res.sendStatus(200)
} }
}) })
}) })
res.sendStatus(200)
}) })
module.exports = router module.exports = router

57
server/routes/samples.js Normal file
View File

@@ -0,0 +1,57 @@
const express = require('express')
const config = require('config')
const multer = require('multer')
const storage = multer.diskStorage({
destination: config.get('Server.sampleUploadPath'),
filename: function (req, file, cb) {
cb(null, req.body.name)
}
})
const upload = multer({ storage: storage })
const db = require('../db')
const router = express.Router()
router.post('/samples', upload.single('sample'), function (req, res, next) {
if (!req.user) {
return res.sendStatus(401)
}
db.run('INSERT INTO samples (name, user) VALUES (?, ?)', [
req.body.name,
req.user.id
],
function (err) {
if (err) {
return res.sendStatus(500)
} else {
return res.sendStatus(200)
}
})
})
router.get('/samples', function (req, res) {
if (!req.user) {
return res.sendStatus(401)
}
const samples = []
db.all('SELECT id, name FROM samples WHERE user = ?', [req.user.id], (err, rows) => {
if (err) {
return res.sendStatus(500)
}
rows.forEach((row) => {
const sample = {}
sample.id = row.id
sample.name = row.name
samples.push(sample)
})
res.json({ samples: samples })
})
})
module.exports = router

View File

@@ -55,7 +55,7 @@ router.post('/users', function (req, res) {
const salt = crypto.randomBytes(16) const salt = crypto.randomBytes(16)
crypto.pbkdf2(req.body.password, salt, 10000, 32, 'sha256', function (err, hashedPassword) { crypto.pbkdf2(req.body.password, salt, 10000, 32, 'sha256', function (err, hashedPassword) {
if (err) { if (err) {
res.sendStatus(500) return res.sendStatus(500)
} }
db.run('INSERT INTO users (username, hashed_password, salt, name, is_admin) VALUES (?, ?, ?, ?, ?)', [ db.run('INSERT INTO users (username, hashed_password, salt, name, is_admin) VALUES (?, ?, ?, ?, ?)', [
@@ -66,7 +66,11 @@ router.post('/users', function (req, res) {
req.body.isAdmin req.body.isAdmin
], function (err) { ], function (err) {
if (err) { if (err) {
res.sendStatus(500) if (err.code === 'SQLITE_CONSTRAINT') {
return res.sendStatus(409)
} else {
return res.sendStatus(500)
}
} }
const user = { const user = {
@@ -76,12 +80,13 @@ router.post('/users', function (req, res) {
} }
req.login(user, function (err) { req.login(user, function (err) {
if (err) { if (err) {
res.sendStatus(500) return res.sendStatus(500)
} else {
return res.sendStatus(200)
} }
}) })
}) })
}) })
res.sendStatus(200)
}) })
router.patch('/users/:userId', function (req, res) { router.patch('/users/:userId', function (req, res) {
@@ -101,11 +106,11 @@ router.patch('/users/:userId', function (req, res) {
db.run('UPDATE users SET is_admin = ? WHERE id = ?', [req.body.isAdmin ? 1 : 0, req.params.userId], (err) => { db.run('UPDATE users SET is_admin = ? WHERE id = ?', [req.body.isAdmin ? 1 : 0, req.params.userId], (err) => {
if (err) { if (err) {
return res.sendStatus(500) return res.sendStatus(500)
} else {
return res.sendStatus(200)
} }
}) })
}) })
res.sendStatus(200)
}) })
router.delete('/users/:userId', function (req, res) { router.delete('/users/:userId', function (req, res) {
@@ -125,11 +130,11 @@ router.delete('/users/:userId', function (req, res) {
db.run('DELETE FROM users WHERE id = ?', [req.params.userId], (err) => { db.run('DELETE FROM users WHERE id = ?', [req.params.userId], (err) => {
if (err) { if (err) {
return res.sendStatus(500) return res.sendStatus(500)
} else {
return res.sendStatus(200)
} }
}) })
}) })
res.sendStatus(200)
}) })
module.exports = router module.exports = router

View File

@@ -273,6 +273,105 @@
</v-row> </v-row>
</v-col> </v-col>
<v-col cols="12">
<h2 class="headline font-weight-bold mb-5">
Samples
</h2>
<v-row
v-for="(sample, index) in samples"
:key="sample.name"
>
<v-container>
<v-row
justify="center"
>
<v-checkbox
v-model="checkedSamples"
:value="sample.id"
:label="`${sample.name}`"
class="mx-3"
/>
</v-row>
<v-row>
<v-slider
v-model="sample.volume"
label="Volume"
thumb-label
max="0"
min="-30"
class="mx-3"
@change="updateSampleVolume(sample.id, index)"
/>
<div
class="mx-3"
>
<p>{{ samples[index].volume }}</p>
</div>
</v-row>
</v-container>
</v-row>
<v-dialog
v-model="sampleDialog"
max-width="600px"
>
<template v-slot:activator="{ on, attrs }">
<v-btn
v-bind="attrs"
class="mx-3 mb-5"
v-on="on"
>
Upload Sample
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">Add a Sample</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<p><strong>WARNING:</strong> Uploaded samples are publicly accessible.</p>
</v-row>
<v-row>
<v-file-input
v-model="selectedSample"
accept="audio/*"
label="Upload a sample!"
/>
</v-row>
<v-row>
<v-col cols="12">
<v-text-field
v-model="sampleName"
label="Sample Name"
required
/>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
text
@click="sampleDialog = false"
>
Close
</v-btn>
<v-btn
text
@click="uploadSample"
>
Upload
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-col>
<v-col cols="12"> <v-col cols="12">
<h2 class="headline font-weight-bold mb-5"> <h2 class="headline font-weight-bold mb-5">
Profiles Profiles

View File

@@ -1,4 +1,4 @@
import { Filter, LFO, Noise, Transport, Tremolo } from 'tone' import { Filter, LFO, Noise, Players, Transport, Tremolo } from 'tone'
export default { export default {
name: 'Noise', name: 'Noise',
@@ -31,6 +31,12 @@ export default {
isTremoloEnabled: false, isTremoloEnabled: false,
tremoloFrequency: 0.5, tremoloFrequency: 0.5,
tremoloDepth: 0.5, tremoloDepth: 0.5,
samples: [],
checkedSamples: [],
selectedSample: null,
sampleDialog: false,
sampleName: '',
file: null,
rules: { rules: {
lt (n) { lt (n) {
return value => (!isNaN(parseInt(value, 10)) && value < n) || 'Must be less than ' + n return value => (!isNaN(parseInt(value, 10)) && value < n) || 'Must be less than ' + n
@@ -45,7 +51,9 @@ export default {
this.filter = new Filter() this.filter = new Filter()
this.tremolo = new Tremolo() this.tremolo = new Tremolo()
this.lfo = new LFO() this.lfo = new LFO()
this.players = new Players()
this.populateProfileItems() this.populateProfileItems()
this.getSamples()
}, },
methods: { methods: {
play () { play () {
@@ -73,18 +81,22 @@ export default {
} }
if (this.isTimerEnabled) { if (this.isTimerEnabled) {
console.log(this.hours)
console.log(this.minutes)
console.log(this.seconds)
this.duration = parseInt((this.hours * 3600)) + parseInt((this.minutes * 60)) + parseInt(this.seconds) this.duration = parseInt((this.hours * 3600)) + parseInt((this.minutes * 60)) + parseInt(this.seconds)
console.log(this.duration)
this.noise.sync().start(0).stop(this.duration) this.noise.sync().start(0).stop(this.duration)
Transport.loopEnd = this.duration Transport.loopEnd = this.duration
this.timeRemaining = this.duration this.timeRemaining = this.duration
this.transportInterval = setInterval(() => this.stop(), this.duration * 1000 + 100) this.transportInterval = setInterval(() => this.stop(), this.duration * 1000 + 100)
this.timeRemainingInterval = setInterval(() => this.startTimer(), 1000) this.timeRemainingInterval = setInterval(() => this.startTimer(), 1000)
this.checkedSamples.forEach(s => {
this.players.player(s).unsync().sync().start(0).stop(this.duration)
})
} else { } else {
this.noise.sync().start(0) this.noise.sync().start(0)
this.checkedSamples.forEach(s => {
this.players.player(s).unsync().sync().start(0)
})
} }
Transport.start() Transport.start()
@@ -222,6 +234,40 @@ export default {
.catch(function (error) { .catch(function (error) {
console.error(error.response) console.error(error.response)
}) })
},
getSamples () {
this.$http.get('/samples')
.then(response => {
if (response.status === 200) {
this.samples = response.data.samples
this.samples.forEach((s) => {
this.players.add(s.id, '/samples/' + s.name).toDestination()
})
}
})
.catch(function (error) {
console.error(error.response)
})
},
uploadSample () {
const formData = new FormData()
formData.append('name', this.sampleName)
formData.append('sample', this.selectedSample)
this.$http.post('/samples', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.catch(function (error) {
console.error(error.response)
})
this.sampleDialog = false
},
updateSampleVolume (id, index) {
this.players.player(id).volume.value = this.samples[index].volume
} }
} }
} }