~vpzom/lotide

ea9370a21336e9ed026380c90de8256b124fbbc3 — Colin Reeder 5 months ago 7127859
Breaking API change: make login user info more consistent
3 files changed, 54 insertions(+), 26 deletions(-)

M openapi/openapi.json
M src/routes/api/mod.rs
M src/routes/api/users.rs
M openapi/openapi.json => openapi/openapi.json +17 -15
@@ 16,6 16,16 @@
				"type": "string",
				"enum": ["hot", "new"]
			},
			"LoginUserInfo": {
				"type": "object",
				"required": ["id", "username", "is_site_admin", "has_unread_notification"],
				"properties": {
					"id": {"type": "integer"},
					"username": {"type": "string"},
					"is_site_admin": {"type": "boolean"},
					"has_unread_notification": {"type": "boolean"}
				}
			},
			"MinimalCommentInfo": {
				"type": "object",
				"required": ["id"],


@@ 905,9 915,12 @@
							"application/json": {
								"schema": {
									"type": "object",
									"required": ["token"],
									"required": ["token", "user"],
									"properties": {
										"token": {"type": "string"}
										"token": {"type": "string"},
										"user": {
											"$ref": "#/components/schemas/LoginUserInfo"
										}
									}
								}
							}


@@ 929,14 942,7 @@
									"required": ["user"],
									"properties": {
										"user": {
											"type": "object",
											"required": ["id", "name", "is_site_admin", "has_unread_notifications"],
											"properties": {
												"id": {"type": "integer"},
												"name": {"type": "string"},
												"is_site_admin": {"type": "boolean"},
												"has_unread_notifications": {"type": "boolean"}
											}
											"$ref": "#/components/schemas/LoginUserInfo"
										}
									}
								}


@@ 1294,11 1300,7 @@
									"required": ["user"],
									"properties": {
										"user": {
											"type": "object",
											"required": ["id"],
											"properties": {
												"id": {"type": "integer"}
											}
											"$ref": "#/components/schemas/LoginUserInfo"
										},
										"token": {
											"type": "string"

M src/routes/api/mod.rs => src/routes/api/mod.rs +25 -7
@@ 65,6 65,14 @@ struct RespMinimalAuthorInfo<'a> {
}

#[derive(Serialize)]
struct RespLoginUserInfo<'a> {
    id: UserLocalID,
    username: &'a str,
    is_site_admin: bool,
    has_unread_notifications: bool,
}

#[derive(Serialize)]
struct JustUser<'a> {
    user: RespMinimalAuthorInfo<'a>,
}


@@ 322,7 330,7 @@ async fn route_unstable_logins_create(

    let row = db
        .query_opt(
            "SELECT id, passhash FROM person WHERE LOWER(username)=LOWER($1) AND local",
            "SELECT id, username, passhash, is_site_admin, EXISTS(SELECT 1 FROM notification WHERE to_user = person.id AND created_at > person.last_checked_notifications) FROM person WHERE LOWER(username)=LOWER($1) AND local",
            &[&body.username],
        )
        .await?


@@ 334,7 342,8 @@ async fn route_unstable_logins_create(
        })?;

    let id = UserLocalID(row.get(0));
    let passhash: Option<String> = row.get(1);
    let username: &str = row.get(1);
    let passhash: Option<String> = row.get(2);

    let passhash = passhash.ok_or_else(|| {
        crate::Error::UserError(crate::simple_response(


@@ 352,7 361,14 @@ async fn route_unstable_logins_create(
    if correct {
        let token = insert_token(id, &db).await?;

        crate::json_response(&serde_json::json!({"token": token.to_string()}))
        crate::json_response(
            &serde_json::json!({"token": token.to_string(), "user": RespLoginUserInfo {
                id,
                username,
                is_site_admin: row.get(3),
                has_unread_notifications: row.get(4),
            }}),
        )
    } else {
        Ok(crate::simple_response(
            hyper::StatusCode::FORBIDDEN,


@@ 371,12 387,14 @@ async fn route_unstable_logins_current_get(
    let user = crate::require_login(&req, &db).await?;

    let row = db.query_one("SELECT username, is_site_admin, EXISTS(SELECT 1 FROM notification WHERE to_user = person.id AND created_at > person.last_checked_notifications) FROM person WHERE id=$1", &[&user]).await?;
    let username: &str = row.get(0);
    let is_site_admin: bool = row.get(1);
    let has_notifications: bool = row.get(2);

    crate::json_response(&serde_json::json!({
        "user": {"id": user, "name": username, "is_site_admin": is_site_admin, "has_unread_notifications": has_notifications}
        "user": RespLoginUserInfo {
            id: user,
            username: row.get(0),
            is_site_admin: row.get(1),
            has_unread_notifications: row.get(2),
        },
    }))
}


M src/routes/api/users.rs => src/routes/api/users.rs +12 -4
@@ 1,6 1,7 @@
use super::{
    handle_common_posts_list, MaybeIncludeYour, RespAvatarInfo, RespMinimalAuthorInfo,
    RespMinimalCommentInfo, RespMinimalCommunityInfo, RespMinimalPostInfo, RespThingInfo,
    handle_common_posts_list, MaybeIncludeYour, RespAvatarInfo, RespLoginUserInfo,
    RespMinimalAuthorInfo, RespMinimalCommentInfo, RespMinimalCommunityInfo, RespMinimalPostInfo,
    RespThingInfo,
};
use crate::{CommentLocalID, CommunityLocalID, PostLocalID, UserLocalID};
use serde_derive::{Deserialize, Serialize};


@@ 156,11 157,18 @@ async fn route_unstable_users_create(
        UserLocalID(row.get(0))
    };

    let info = RespLoginUserInfo {
        id: user_id,
        username: &body.username,
        is_site_admin: false,
        has_unread_notifications: false,
    };

    let output = if body.login {
        let token = super::insert_token(user_id, &db).await?;
        serde_json::json!({"user": {"id": user_id}, "token": token.to_string()})
        serde_json::json!({"user": info, "token": token.to_string()})
    } else {
        serde_json::json!({"user": {"id": user_id}})
        serde_json::json!({ "user": info })
    };

    crate::json_response(&output)