From 1794802ba1a173052f37b0483c5a334f4e61182a Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Tue, 28 Sep 2021 18:56:07 +0100 Subject: [PATCH] Log the user out if the API returns a 401 --- Cargo.lock | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ chartered-frontend/src/index.tsx | 12 +++++++++--- chartered-frontend/src/useAuth.tsx | 31 ++++++++++++++++++++----------- chartered-frontend/src/util.tsx | 20 ++++++++++++++------ chartered-web/src/main.rs | 3 ++- chartered-web/src/endpoints/mod.rs | 6 ++++-- chartered-web/src/middleware/auth.rs | 17 ++++++++++++----- chartered-web/src/endpoints/web_api/organisations/crud.rs | 2 +- 8 files changed, 134 insertions(+), 107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 695139c..ebd92b8 100644 --- a/Cargo.lock +++ a/Cargo.lock @@ -32,9 +32,9 @@ [[package]] name = "anyhow" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" +checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" [[package]] name = "async-trait" @@ -66,9 +66,9 @@ [[package]] name = "axum" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2423522684032529c51d209740c77d57cc56bfef7b9a18630f919a974d2616" +checksum = "b6519a24c07bab4effe38e226c447faef56869f99aa66aa92502aba7ad47b168" dependencies = [ "async-trait", "bitflags", @@ -100,9 +100,9 @@ [[package]] name = "base64ct" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" +checksum = "40a96587c05c810ddbb79e2674d519cff1379517e7b91d166dff7a7cc0e9af6e" [[package]] name = "bcrypt-pbkdf" @@ -179,9 +179,9 @@ [[package]] name = "cc" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" [[package]] name = "cfg-if" @@ -388,9 +388,9 @@ [[package]] name = "diesel" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bba51ca66f57261fd17cadf8b73e4775cc307d0521d855de3f5de91a8f074e0e" +checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d" dependencies = [ "byteorder", "chrono", @@ -487,9 +487,9 @@ [[package]] name = "flate2" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ "cfg-if", "crc32fast", @@ -537,9 +537,9 @@ [[package]] name = "futures" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" +checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" dependencies = [ "futures-channel", "futures-core", @@ -552,9 +552,9 @@ [[package]] name = "futures-channel" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" +checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" dependencies = [ "futures-core", "futures-sink", @@ -562,15 +562,15 @@ [[package]] name = "futures-core" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" +checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" [[package]] name = "futures-executor" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" +checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" dependencies = [ "futures-core", "futures-task", @@ -579,15 +579,15 @@ [[package]] name = "futures-io" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" +checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" [[package]] name = "futures-macro" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" +checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" dependencies = [ "autocfg", "proc-macro-hack", @@ -598,21 +598,21 @@ [[package]] name = "futures-sink" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" +checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" [[package]] name = "futures-task" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" +checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" [[package]] name = "futures-util" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" +checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" dependencies = [ "autocfg", "futures-channel", @@ -711,9 +711,9 @@ [[package]] name = "http" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ "bytes", "fnv", @@ -751,9 +751,9 @@ [[package]] name = "hyper" -version = "0.14.12" +version = "0.14.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f67199e765030fa08fe0bd581af683f0d5bc04ea09c2b1102012c5fb90e7fd" +checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" dependencies = [ "bytes", "futures-channel", @@ -783,9 +783,9 @@ [[package]] name = "instant" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" +checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" dependencies = [ "cfg-if", ] @@ -813,9 +813,9 @@ [[package]] name = "libc" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" [[package]] name = "libsodium-sys" @@ -883,9 +883,9 @@ [[package]] name = "minimal-lexical" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6595bb28ed34f43c3fe088e48f6cfb2e033cab45f25a5384d5fdf564fbc8c4b2" +checksum = "0c835948974f68e0bd58636fc6c5b1fbff7b297e3046f11b3b3c18bbac012c6d" [[package]] name = "miniz_oxide" @@ -941,9 +941,9 @@ [[package]] name = "num-bigint" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" +checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535" dependencies = [ "autocfg", "num-integer", @@ -1090,9 +1090,9 @@ [[package]] name = "pkg-config" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" [[package]] name = "ppv-lite86" @@ -1114,9 +1114,9 @@ [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" dependencies = [ "unicode-xid", ] @@ -1249,18 +1249,18 @@ [[package]] name = "serde" -version = "1.0.129" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.129" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ "proc-macro2", "quote", @@ -1269,9 +1269,9 @@ [[package]] name = "serde_json" -version = "1.0.67" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950" +checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" dependencies = [ "itoa", "ryu", @@ -1305,9 +1305,9 @@ [[package]] name = "sha2" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9204c41a1597a8c5af23c82d1c921cb01ec0a4c59e07a9c7306062829a3903f3" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer", "cfg-if", @@ -1345,9 +1345,9 @@ [[package]] name = "socket2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" +checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" dependencies = [ "libc", "winapi", @@ -1361,9 +1361,9 @@ [[package]] name = "syn" -version = "1.0.75" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" +checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0" dependencies = [ "proc-macro2", "quote", @@ -1387,18 +1387,18 @@ [[package]] name = "thiserror" -version = "1.0.26" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.26" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c" dependencies = [ "proc-macro2", "quote", @@ -1484,9 +1484,9 @@ [[package]] name = "tokio" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92036be488bb6594459f2e03b60e42df6f937fe6ca5c5ffdcb539c6b84dc40f5" +checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" dependencies = [ "autocfg", "bytes", @@ -1526,9 +1526,9 @@ [[package]] name = "tokio-util" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" +checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" dependencies = [ "bytes", "futures-core", @@ -1573,7 +1573,7 @@ [[package]] name = "tower-http" version = "0.1.1" -source = "git+https://github.com/tower-rs/tower-http?branch=cors#c07f4582491f8eb667dca5440b0870bcd68b47a4" +source = "git+https://github.com/tower-rs/tower-http?branch=cors#9f09fc55bf74b5b9a8bd79cbede7e73d37a3e79b" dependencies = [ "bytes", "futures-core", @@ -1600,9 +1600,9 @@ [[package]] name = "tracing" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" +checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" dependencies = [ "cfg-if", "log", @@ -1613,9 +1613,9 @@ [[package]] name = "tracing-attributes" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" +checksum = "98863d0dd09fa59a1b79c6750ad80dbda6b75f4e71c437a6a1a8cb91a8bcbd77" dependencies = [ "proc-macro2", "quote", @@ -1624,9 +1624,9 @@ [[package]] name = "tracing-core" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8" +checksum = "46125608c26121c81b0c6d693eab5a420e416da7e43c426d2e8f7df8da8a3acf" dependencies = [ "lazy_static", ] @@ -1639,9 +1639,9 @@ [[package]] name = "typenum" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "unicode-segmentation" diff --git a/chartered-frontend/src/index.tsx b/chartered-frontend/src/index.tsx index 783ed87..51d6620 100644 --- a/chartered-frontend/src/index.tsx +++ a/chartered-frontend/src/index.tsx @@ -117,8 +117,7 @@ if ( !unauthedOnly || !auth || - !auth.authKey || - auth.expires < new Date() + !auth?.getAuthKey() ) { return ; } else { @@ -150,12 +149,19 @@ } & { [r: string]: any }) { const auth = useAuth(); + const isAuthenticated = auth?.getAuthKey(); + React.useEffect(() => { + if (!isAuthenticated) { + auth.logout(); + } + }, [isAuthenticated]); + return ( { // TODO: check if valid key - if (auth && auth?.authKey && auth.expires > new Date()) { + if (auth && isAuthenticated) { return ; } else { return ( diff --git a/chartered-frontend/src/useAuth.tsx b/chartered-frontend/src/useAuth.tsx index bbee601..eec1f0b 100644 --- a/chartered-frontend/src/useAuth.tsx +++ a/chartered-frontend/src/useAuth.tsx @@ -1,12 +1,11 @@ import React = require("react"); import { useState, useEffect, useContext, createContext } from "react"; import { unauthenticatedEndpoint } from "./util"; export interface AuthContext { - authKey?: string; - expires?: Date; login: (username: string, password: string) => Promise; logout: () => Promise; + getAuthKey: () => Promise; } const authContext = createContext(null); @@ -21,15 +20,17 @@ }; function useProvideAuth(): AuthContext { - const [authKey, setAuthKey] = useState(() => getAuthStorage().authKey); - const [expires, setExpires] = useState(() => getAuthStorage().expires); + const [auth, setAuth] = useState(() => { + let authStorage = getAuthStorage(); + return [authStorage.authKey, authStorage.expires]; + }); useEffect(() => { localStorage.setItem( "charteredAuthentication", - JSON.stringify({ authKey, expires }) + JSON.stringify({ authKey: auth?.[0], expires: auth?.[1] }) ); - }, [authKey, expires]); + }, [auth]); const login = async (username: string, password: string) => { let res = await fetch(unauthenticatedEndpoint("login"), { @@ -46,22 +47,26 @@ throw new Error(json.error); } - setExpires(new Date(json.expires)); - setAuthKey(json.key); + setAuth([json.key, new Date(json.expires)]); }; const logout = async () => { // todo call the service so we can purge the key from the db - localStorage.removeItem("charteredAuthentication"); - setExpires(null); - setAuthKey(null); + setAuth(null); }; + const getAuthKey = () => { + if (auth?.[1] > new Date()) { + return auth[0]; + } else if (auth) { + return null; + } + }; + return { - authKey, - expires, login, logout, + getAuthKey, }; } diff --git a/chartered-frontend/src/util.tsx b/chartered-frontend/src/util.tsx index 27b8940..dc3233c 100644 --- a/chartered-frontend/src/util.tsx +++ a/chartered-frontend/src/util.tsx @@ -12,7 +12,7 @@ auth: AuthContext, endpoint: string ): string { - return `${BASE_URL}/a/${auth.authKey}/web/v1/${endpoint}`; + return `${BASE_URL}/a/${auth.getAuthKey()}/web/v1/${endpoint}`; } export function useAuthenticatedRequest( @@ -24,13 +24,19 @@ React.useEffect(async () => { try { - let req = await fetch(authenticatedEndpoint(auth, endpoint)); - let res = await req.json(); - - if (res.error) { - setError(res.error); + let res = await fetch(authenticatedEndpoint(auth, endpoint)); + + if (res.status == 401) { + await auth.logout(); + return null; + } + + let jsonRes = await res.json(); + + if (jsonRes.error) { + setError(jsonRes.error); } else { - setResponse(res); + setResponse(jsonRes); } } catch (e) { setError(e.message); diff --git a/chartered-web/src/main.rs b/chartered-web/src/main.rs index dbb71e7..57f478e 100644 --- a/chartered-web/src/main.rs +++ a/chartered-web/src/main.rs @@ -6,7 +6,7 @@ use axum::{ handler::{delete, get, patch, post, put}, - http::Method, + http::{Method, header}, AddExtensionLayer, Router, }; use tower::ServiceBuilder; @@ -149,6 +149,7 @@ Method::PUT, Method::OPTIONS, ]) + .allow_headers(vec![header::CONTENT_TYPE, header::USER_AGENT]) .allow_origin(Any) .allow_credentials(false), ) diff --git a/chartered-web/src/endpoints/mod.rs b/chartered-web/src/endpoints/mod.rs index 3625724..3597b8a 100644 --- a/chartered-web/src/endpoints/mod.rs +++ a/chartered-web/src/endpoints/mod.rs @@ -1,6 +1,8 @@ +use std::borrow::Cow; + #[derive(serde::Serialize)] pub struct ErrorResponse { - error: Option, + pub error: Option>, } macro_rules! define_error_response { @@ -13,7 +15,7 @@ fn into_response(self) -> axum::http::Response { let body = serde_json::to_vec(&crate::endpoints::ErrorResponse { - error: Some(self.to_string()), + error: Some(self.to_string().into()), }) .unwrap(); diff --git a/chartered-web/src/middleware/auth.rs b/chartered-web/src/middleware/auth.rs index 96e2ab0..cde7c22 100644 --- a/chartered-web/src/middleware/auth.rs +++ a/chartered-web/src/middleware/auth.rs @@ -1,4 +1,5 @@ use axum::{ + body::{box_body, Body, BoxBody}, extract::{self, FromRequest, RequestParts}, http::{Request, Response, StatusCode}, }; @@ -10,15 +11,16 @@ }; use tower::Service; +use crate::endpoints::ErrorResponse; + #[derive(Clone)] pub struct AuthMiddleware(pub S); -impl Service> for AuthMiddleware +impl Service> for AuthMiddleware where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, ReqBody: Send + 'static, - ResBody: Default + Send + 'static, { type Response = S::Response; type Error = S::Error; @@ -58,14 +60,19 @@ None => { return Ok(Response::builder() .status(StatusCode::UNAUTHORIZED) - .body(ResBody::default()) + .body(box_body(Body::from( + serde_json::to_vec(&ErrorResponse { + error: Some("Expired auth token".into()), + }) + .unwrap(), + ))) .unwrap()) } }; req.extensions_mut().unwrap().insert(user); - let response: Response = inner.call(req.try_into_request().unwrap()).await?; + let response: Response = inner.call(req.try_into_request().unwrap()).await?; Ok(response) }) diff --git a/chartered-web/src/endpoints/web_api/organisations/crud.rs b/chartered-web/src/endpoints/web_api/organisations/crud.rs index 396975a..2751a32 100644 --- a/chartered-web/src/endpoints/web_api/organisations/crud.rs +++ a/chartered-web/src/endpoints/web_api/organisations/crud.rs @@ -34,6 +34,6 @@ extract::Json(req): extract::Json, ) -> Result, Error> { Organisation::create(db, req.name, req.description, user.id).await?; - + Ok(Json(ErrorResponse { error: None })) } -- rgit 0.1.3