~vpzom/lotide

f93374da8def63517d9f878c08deeebfd40ddb06 — Colin Reeder 6 months ago 1eac81c
Add logout endpoint
3 files changed, 47 insertions(+), 18 deletions(-)

M openapi/openapi.json
M src/main.rs
M src/routes/api/mod.rs
M openapi/openapi.json => openapi/openapi.json +10 -0
@@ 945,6 945,16 @@
					}
				},
				"security": [{"bearer": []}]
			},
			"delete": {
				"summary": "Log out",
				"description": "Invalidates the current login session.",
				"responses": {
					"204": {
						"description": "Successfully ended."
					}
				},
				"security": [{"bearer": []}]
			}
		},
		"/api/unstable/misc/render_markdown": {

M src/main.rs => src/main.rs +21 -17
@@ 488,10 488,7 @@ pub fn get_lang_for_req(req: &impl ReqParts) -> Translator {
    Translator { bundle }
}

pub async fn authenticate(
    req: &impl ReqParts,
    db: &tokio_postgres::Client,
) -> Result<Option<UserLocalID>, Error> {
pub fn get_auth_token(req: &impl ReqParts) -> Option<uuid::Uuid> {
    use headers::Header;

    let value = match req.headers().get(hyper::header::AUTHORIZATION) {


@@ 499,25 496,32 @@ pub async fn authenticate(
            match headers::Authorization::<headers::authorization::Bearer>::decode(
                &mut std::iter::once(value),
            ) {
                Ok(value) => value.0.token().to_owned(),
                Err(_) => return Ok(None),
                Ok(value) => Some(value.0.token().to_owned()),
                Err(_) => None,
            }
        }
        None => return Ok(None),
    };

    let token = match value.parse::<uuid::Uuid>() {
        Ok(value) => value,
        Err(_) => return Ok(None),
        None => None,
    };

    let row = db
        .query_opt("SELECT person FROM login WHERE token=$1", &[&token])
        .await?;
    value.and_then(|value| value.parse::<uuid::Uuid>().ok())
}

    match row {
        Some(row) => Ok(Some(UserLocalID(row.get(0)))),
pub async fn authenticate(
    req: &impl ReqParts,
    db: &tokio_postgres::Client,
) -> Result<Option<UserLocalID>, Error> {
    match get_auth_token(req) {
        None => Ok(None),
        Some(token) => {
            let row = db
                .query_opt("SELECT person FROM login WHERE token=$1", &[&token])
                .await?;

            match row {
                Some(row) => Ok(Some(UserLocalID(row.get(0)))),
                None => Ok(None),
            }
        }
    }
}


M src/routes/api/mod.rs => src/routes/api/mod.rs +16 -1
@@ 153,7 153,8 @@ pub fn route_api() -> crate::RouteNode<()> {
                    .with_child(
                        "~current",
                        crate::RouteNode::new()
                            .with_handler_async("GET", route_unstable_logins_current_get),
                            .with_handler_async("GET", route_unstable_logins_current_get)
                            .with_handler_async("DELETE", route_unstable_logins_current_delete),
                    ),
            )
            .with_child(


@@ 388,6 389,20 @@ async fn route_unstable_logins_current_get(
        .body(body)?)
}

async fn route_unstable_logins_current_delete(
    _: (),
    ctx: Arc<crate::RouteContext>,
    req: hyper::Request<hyper::Body>,
) -> Result<hyper::Response<hyper::Body>, crate::Error> {
    if let Some(token) = crate::get_auth_token(&req) {
        let db = ctx.db_pool.get().await?;
        db.execute("DELETE FROM login WHERE token=$1", &[&token])
            .await?;
    }

    Ok(crate::empty_response())
}

async fn route_unstable_nodeinfo_20_get(
    _: (),
    ctx: Arc<crate::RouteContext>,