diff --git a/backend/Cargo.lock b/backend/Cargo.lock
index c79987c..e4c2e52 100644
--- a/backend/Cargo.lock
+++ b/backend/Cargo.lock
@@ -1,3 +1,5 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
[[package]]
name = "adler32"
version = "1.0.3"
@@ -246,6 +248,18 @@ name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "google-signin"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper-rustls 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "gzip-header"
version = "0.2.0"
@@ -259,6 +273,35 @@ name = "httparse"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "hyper"
+version = "0.10.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "hyper-rustls"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "idna"
version = "0.1.5"
@@ -274,6 +317,11 @@ name = "itoa"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "language-tags"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "lazy_static"
version = "1.2.0"
@@ -619,6 +667,17 @@ dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "ring"
+version = "0.13.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "rouille"
version = "3.0.0"
@@ -656,6 +715,19 @@ dependencies = [
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "rustls"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "ryu"
version = "0.2.7"
@@ -671,6 +743,15 @@ name = "safemem"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "sct"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "semver"
version = "0.9.0"
@@ -835,6 +916,11 @@ dependencies = [
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "traitobject"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "twoway"
version = "0.1.8"
@@ -843,6 +929,11 @@ dependencies = [
"memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "typeable"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "ucd-util"
version = "0.1.3"
@@ -890,6 +981,11 @@ dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "untrusted"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "url"
version = "1.7.2"
@@ -928,6 +1024,7 @@ dependencies = [
"diesel 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel_migrations 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dotenv 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "google-signin 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rouille 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -936,6 +1033,24 @@ dependencies = [
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "webpki"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "winapi"
version = "0.3.6"
@@ -987,10 +1102,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+"checksum google-signin 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2a88c191e9a56f44f057a9e49b330f9eb2164f865472ca3777b631f51d1e46"
"checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586"
"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
+"checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c"
+"checksum hyper-rustls 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71f7b2e5858ab9e19771dc361159f09ee5031734a6f7471fe0947db0238d92b7"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
+"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)" = "48450664a984b25d5b479554c29cc04e3150c97aa4c01da5604a2d4ed9151476"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
@@ -1032,12 +1151,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
+"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
"checksum rouille 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "112568052ec17fa26c6c11c40acbb30d3ad244bf3d6da0be181f5e7e42e5004f"
"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+"checksum rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "942b71057b31981152970d57399c25f72e27a6ee0d207a669d8304cabf44705b"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
+"checksum sct 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb8f61f9e6eadd062a71c380043d28036304a4706b3c4dd001ff3387ed00745a"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752"
@@ -1057,7 +1179,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951"
+"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
+"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
@@ -1065,11 +1189,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
+"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+"checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f"
+"checksum webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85d1f408918fd590908a70d36b7ac388db2edc221470333e4d6e5b598e44cabf"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/backend/Cargo.toml b/backend/Cargo.toml
index 697c6cd..eddc757 100644
--- a/backend/Cargo.toml
+++ b/backend/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
[dependencies]
rouille = "3.0.0"
+google-signin = "0.3.0"
diesel = { version = "1.3.3", features = ["mysql"] }
diesel_migrations = "1.4.0"
dotenv = "0.13.0"
diff --git a/backend/README.md b/backend/README.md
index 26697bf..888af15 100644
--- a/backend/README.md
+++ b/backend/README.md
@@ -4,12 +4,43 @@ Coded in Rust, manages database manipulation using AJAX requests from frontend.
### Dependencies:
* [Rouille 3.0.0](https://github.com/tomaka/rouille)
* [Diesel 1.3.3](https://github.com/diesel-rs/diesel)
+* [Google Sign-In 0.3.0](https://github.com/wyyerd/google-signin-rs)
* [dotenv 0.13.0](https://github.com/sgrif/rust-dotenv)
* [serde 1.0](https://github.com/serde-rs/serde)
* [serde_json 1.0](https://github.com/serde-rs/json)
* [log 0.4](https://github.com/rust-lang-nursery/log)
* [simplelog](https://github.com/drakulix/simplelog.rs)
+### Authentication and Authorization
+
+#### Authentication and Authorization Flow
+1. On the frontend, a sign-in button that redirects to Google sign-in calls `onSignIn()` afterwards to set a cookie for the `id_token` of the logged in user.
+ * That cookie has an expire date, and will delete itself from the browser once that date has passed.
+ * If a user on the frontend prompts an action that attempts to access the `id_token` cookie and it is not present, a login is automatically prompted.
+2. The frontend generates an xmlHTTP request over HTTPS with `id_token` in the header.
+ * Sending the ID token over HTTP exposes the user's token to packet sniffing vulnerabilities, allowing sniffers to impersonate the user by submitting unauthentic requests with the unencrypted token.
+3. The backend attempts authentication before processing the requests (some requests might need authorization, some might not).
+ * The token is sent back to Google's servers with our services information, Google does their own verification and sends back valid user data.
+4. The email is taken from the Google user's data and cross checked with the `users` database.
+ * NOTE: AN EMAIL IS NECESSARY FOR AUTHORIZED REQUESTS
+5. The request is processed and just before execution of the request, the backend checks for authorization on the found user if needed.
+ * A `user_access` request is made to verify authorization
+
+#### Making Authorized API Calls
+
+To make an authorized API call, a valid ID token from Google's sign-in services must be present in the HTTPS request.
+
+Add the following script imports to HTML pages that make requests.
+
+``
+
+``
+
+
+And add the following to JavaScript functions that make xmlHTTP requests
+
+`mlhttp.setRequestHeader("id_token", getID_Token());`
+
### API Calls
`GET /users`
diff --git a/backend/diesel.toml b/backend/diesel.toml
index e0be62f..3333d2b 100644
--- a/backend/diesel.toml
+++ b/backend/diesel.toml
@@ -3,4 +3,4 @@
# see diesel.rs/guides/configuring-diesel-cli
[print_schema]
-file = "src/schema.rs
\ No newline at end of file
+file = "src/schema.rs"
diff --git a/backend/migrations/2019-01-13-203149_create_users/down.sql b/backend/migrations/2019-01-13-203149_create_users/down.sql
index c8b9a69..dc3714b 100644
--- a/backend/migrations/2019-01-13-203149_create_users/down.sql
+++ b/backend/migrations/2019-01-13-203149_create_users/down.sql
@@ -1,2 +1,2 @@
-- This file should undo anything in `up.sql`
-DROP TABLE users
\ No newline at end of file
+DROP TABLE users;
diff --git a/backend/migrations/2019-01-13-203149_create_users/up.sql b/backend/migrations/2019-01-13-203149_create_users/up.sql
index 2968d06..d853a64 100644
--- a/backend/migrations/2019-01-13-203149_create_users/up.sql
+++ b/backend/migrations/2019-01-13-203149_create_users/up.sql
@@ -5,4 +5,11 @@ CREATE TABLE users (
last_name VARCHAR(255) NOT NULL,
banner_id INT(9) UNSIGNED NOT NULL,
email VARCHAR(255)
-)
\ No newline at end of file
+);
+
+INSERT INTO users (first_name, last_name, banner_id) VALUES ("root", "root", 0);
+UPDATE users
+SET
+ id = 0
+WHERE
+ first_name="root" AND last_name="root" AND banner_id=0 AND id != 0;
diff --git a/backend/migrations/2019-03-08-171503_create_access/down.sql b/backend/migrations/2019-03-08-171503_create_access/down.sql
new file mode 100644
index 0000000..fac3ecb
--- /dev/null
+++ b/backend/migrations/2019-03-08-171503_create_access/down.sql
@@ -0,0 +1,3 @@
+-- This file should undo anything in `up.sql`
+DROP TABLE user_access;
+DROP TABLE access;
diff --git a/backend/migrations/2019-03-08-171503_create_access/up.sql b/backend/migrations/2019-03-08-171503_create_access/up.sql
new file mode 100644
index 0000000..42c9ff0
--- /dev/null
+++ b/backend/migrations/2019-03-08-171503_create_access/up.sql
@@ -0,0 +1,53 @@
+-- Your SQL goes here
+CREATE TABLE access (
+ id SERIAL PRIMARY KEY,
+ access_name VARCHAR(255) NOT NULL
+);
+
+INSERT INTO access (access_name) VALUES
+ ("RootAccess"),
+
+ ("GetUsers"),
+ ("CreateUsers"),
+ ("UpdateUsers"),
+ ("DeleteUsers"),
+
+ ("GetAccess"),
+ ("CreateAccess"),
+ ("UpdateAccess"),
+ ("DeleteAccess"),
+
+ ("GetUserAccess"),
+ ("CreateUserAccess"),
+ ("UpdateUserAccess"),
+ ("DeleteUserAccess"),
+
+ ("GetChemical"),
+ ("CreateChemical"),
+ ("UpdateChemical"),
+ ("DeleteChemical"),
+
+ ("GetChemicalInventory"),
+ ("CreateChemicalInventory"),
+ ("UpdateChemicalInventory"),
+ ("DeleteChemicalInventory");
+
+CREATE TABLE user_access (
+ permission_id SERIAL PRIMARY KEY,
+ access_id BIGINT UNSIGNED NOT NULL,
+ user_id BIGINT UNSIGNED NOT NULL,
+ FOREIGN KEY (access_id)
+ REFERENCES access(id)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE,
+ FOREIGN KEY (user_id)
+ REFERENCES users(id)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE,
+ permission_level VARCHAR(255)
+);
+
+INSERT INTO user_access(access_id, user_id, permission_level)
+ SELECT (select access.id as access_id from access where access.name = "RootAccess"),
+ (select users.id as user_id from users where user.id = 0),
+ (select "RootAccess" as permission_level);
diff --git a/backend/migrations/2019-04-15-150025_chemicals/down.sql b/backend/migrations/2019-04-15-150025_chemicals/down.sql
new file mode 100644
index 0000000..62a3643
--- /dev/null
+++ b/backend/migrations/2019-04-15-150025_chemicals/down.sql
@@ -0,0 +1,3 @@
+-- This file should undo anything in `up.sql`
+DROP chemical_inventory;
+DROP chemical;
diff --git a/backend/migrations/2019-04-15-150025_chemicals/up.sql b/backend/migrations/2019-04-15-150025_chemicals/up.sql
new file mode 100644
index 0000000..b34a79f
--- /dev/null
+++ b/backend/migrations/2019-04-15-150025_chemicals/up.sql
@@ -0,0 +1,30 @@
+-- Your SQL goes here
+CREATE TABLE chemical (
+ id SERIAL PRIMARY KEY,
+ name VARCHAR(255) NOT NULL,
+ purpose VARCHAR(1023) NOT NULL,
+ company_name VARCHAR(255) NOT NULL,
+ ingredients VARCHAR(1023) NOT NULL,
+ manual_link VARCHAR(1023) NOT NULL
+);
+
+CREATE TABLE chemical_inventory (
+ id SERIAL PRIMARY KEY,
+ purchaser_id BIGINT UNSIGNED NOT NULL,
+ custodian_id BIGINT UNSIGNED NOT NULL,
+ chemical_id BIGINT UNSIGNED NOT NULL,
+ storage_location VARCHAR(255) NOT NULL,
+ amount VARCHAR(255) NOT NULL,
+ FOREIGN KEY (purchaser_id)
+ REFERENCES users(id)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE,
+ FOREIGN KEY (custodian_id)
+ REFERENCES users(id)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE,
+ FOREIGN KEY (chemical_id)
+ REFERENCES chemical(id)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE
+);
diff --git a/backend/src/access.rs b/backend/src/access.rs
new file mode 100644
index 0000000..849c906
--- /dev/null
+++ b/backend/src/access.rs
@@ -0,0 +1,3 @@
+pub mod models;
+pub mod requests;
+pub mod schema;
diff --git a/backend/src/access/models.rs b/backend/src/access/models.rs
new file mode 100644
index 0000000..2d0881c
--- /dev/null
+++ b/backend/src/access/models.rs
@@ -0,0 +1,228 @@
+use diesel::Queryable;
+
+use rouille::router;
+
+use serde::Deserialize;
+use serde::Serialize;
+
+use url::form_urlencoded;
+
+use log::{trace, warn};
+
+use crate::errors::{WebdevError, WebdevErrorKind};
+
+use crate::search::{NullableSearch, Search};
+
+use super::schema::{access, user_access};
+
+#[derive(Queryable, Serialize, Deserialize)]
+pub struct Access {
+ pub id: u64,
+ pub access_name: String,
+}
+
+#[derive(Insertable, Serialize, Deserialize)]
+#[table_name = "access"]
+pub struct NewAccess {
+ pub access_name: String,
+}
+
+#[derive(AsChangeset, Serialize, Deserialize)]
+#[table_name = "access"]
+pub struct PartialAccess {
+ pub access_name: Option,
+}
+
+pub enum AccessRequest {
+ GetAccess(u64), //id of access name searched
+ CreateAccess(NewAccess), //new access type of some name to be created
+ UpdateAccess(u64, PartialAccess), //Contains id to be changed to new access_name
+ DeleteAccess(u64), //if of access to be deleted
+}
+
+impl AccessRequest {
+ pub fn from_rouille(request: &rouille::Request) -> Result {
+ trace!("Creating AccessRequest from {:#?}", request);
+
+ router!(request,
+ (GET) (/{id: u64}) => {
+ Ok(AccessRequest::GetAccess(id))
+ },
+
+ (POST) (/) => {
+ let request_body = request.data().ok_or(WebdevError::new(WebdevErrorKind::Format))?;
+ let new_access: NewAccess = serde_json::from_reader(request_body)?;
+
+ Ok(AccessRequest::CreateAccess(new_access))
+ },
+
+ (POST) (/{id: u64}) => {
+ let request_body = request.data().ok_or(WebdevError::new(WebdevErrorKind::Format))?;
+ let update_access: PartialAccess = serde_json::from_reader(request_body)?;
+
+ Ok(AccessRequest::UpdateAccess(id, update_access))
+ },
+
+ (DELETE) (/{id: u64}) => {
+ Ok(AccessRequest::DeleteAccess(id))
+ },
+
+ _ => {
+ warn!("Could not create an access request for the given rouille request");
+ Err(WebdevError::new(WebdevErrorKind::NotFound))
+ }
+ ) //end router
+ }
+}
+
+pub enum AccessResponse {
+ OneAccess(Access),
+ NoResponse,
+}
+
+impl AccessResponse {
+ pub fn to_rouille(self) -> rouille::Response {
+ match self {
+ AccessResponse::OneAccess(access) => rouille::Response::json(&access),
+ AccessResponse::NoResponse => rouille::Response::empty_204(),
+ }
+ }
+}
+
+#[derive(Queryable, Serialize, Deserialize)]
+pub struct UserAccess {
+ pub permission_id: u64,
+ pub access_id: u64,
+ pub user_id: u64,
+ pub permission_level: Option,
+}
+
+#[derive(Insertable, Serialize, Deserialize)]
+#[table_name = "user_access"]
+pub struct NewUserAccess {
+ pub access_id: u64,
+ pub user_id: u64,
+ pub permission_level: Option,
+}
+
+#[derive(AsChangeset, Serialize, Deserialize)]
+#[table_name = "user_access"]
+pub struct PartialUserAccess {
+ pub access_id: Option,
+ pub user_id: Option,
+ pub permission_level: Option