Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[server] Move username to post body in login #936 #950

Merged
merged 3 commits into from
Dec 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 23 additions & 27 deletions agdb_api/typescript/src/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,10 @@ declare namespace Components {
export interface UserCredentials {
password: string;
}
export interface UserLogin {
password: string;
username: string;
}
export interface UserStatus {
name: string;
}
Expand Down Expand Up @@ -1689,19 +1693,11 @@ declare namespace Paths {
}
}
namespace UserLogin {
namespace Parameters {
export type Username = string;
}
export interface PathParameters {
username: Parameters.Username;
}
export type RequestBody = Components.Schemas.UserCredentials;
export type RequestBody = Components.Schemas.UserLogin;
namespace Responses {
export type $200 = string;
export interface $401 {
}
export interface $404 {
}
}
}
}
Expand Down Expand Up @@ -1963,6 +1959,14 @@ export interface OperationMethods {
data?: any,
config?: AxiosRequestConfig
): OperationResponse<Paths.Status.Responses.$200>
/**
* user_login
*/
'user_login'(
parameters?: Parameters<UnknownParamsObject> | null,
data?: Paths.UserLogin.RequestBody,
config?: AxiosRequestConfig
): OperationResponse<Paths.UserLogin.Responses.$200>
/**
* user_change_password
*/
Expand All @@ -1971,14 +1975,6 @@ export interface OperationMethods {
data?: Paths.UserChangePassword.RequestBody,
config?: AxiosRequestConfig
): OperationResponse<Paths.UserChangePassword.Responses.$201>
/**
* user_login
*/
'user_login'(
parameters?: Parameters<Paths.UserLogin.PathParameters> | null,
data?: Paths.UserLogin.RequestBody,
config?: AxiosRequestConfig
): OperationResponse<Paths.UserLogin.Responses.$200>
}

export interface PathsDictionary {
Expand Down Expand Up @@ -2302,6 +2298,16 @@ export interface PathsDictionary {
config?: AxiosRequestConfig
): OperationResponse<Paths.Status.Responses.$200>
}
['/api/v1/user/login']: {
/**
* user_login
*/
'post'(
parameters?: Parameters<UnknownParamsObject> | null,
data?: Paths.UserLogin.RequestBody,
config?: AxiosRequestConfig
): OperationResponse<Paths.UserLogin.Responses.$200>
}
['/api/v1/user/{username}/change_password']: {
/**
* user_change_password
Expand All @@ -2312,16 +2318,6 @@ export interface PathsDictionary {
config?: AxiosRequestConfig
): OperationResponse<Paths.UserChangePassword.Responses.$201>
}
['/api/v1/user/{username}/login']: {
/**
* user_login
*/
'post'(
parameters?: Parameters<Paths.UserLogin.PathParameters> | null,
data?: Paths.UserLogin.RequestBody,
config?: AxiosRequestConfig
): OperationResponse<Paths.UserLogin.Responses.$200>
}
}

export type Client = OpenAPIClient<OperationMethods, PathsDictionary>
4 changes: 2 additions & 2 deletions agdb_api/typescript/tests/OpenApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { Api } from "./client";
describe("openapi test", () => {
it("insert node", async () => {
let client = await Api.client();
let admin_token = await client.user_login("admin", { password: "admin" });
let admin_token = await client.user_login(null, { username: "admin", password: "admin" });
Api.setToken(admin_token.data);

await client.admin_user_add("user1", { password: "password123" });
let token = await client.user_login("user1", { password: "password123" });
let token = await client.user_login(null, { username: "user1", password: "password123" });
Api.setToken(token.data);

await client.db_add({
Expand Down
87 changes: 44 additions & 43 deletions agdb_server/openapi/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1559,60 +1559,45 @@
}
}
},
"/api/v1/user/{username}/change_password": {
"put": {
"/api/v1/user/login": {
"post": {
"tags": [
"crate::routes::user"
],
"operationId": "user_change_password",
"parameters": [
{
"name": "username",
"in": "path",
"description": "username",
"required": true,
"schema": {
"type": "string"
}
}
],
"operationId": "user_login",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChangePassword"
"$ref": "#/components/schemas/UserLogin"
}
}
},
"required": true
},
"responses": {
"201": {
"description": "password changed"
"200": {
"description": "login successful",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
},
"401": {
"description": "invalid credentials"
},
"404": {
"description": "user not found"
},
"461": {
"description": "password too short (<8)"
}
},
"security": [
{
"Token": []
}
]
}
}
},
"/api/v1/user/{username}/login": {
"post": {
"/api/v1/user/{username}/change_password": {
"put": {
"tags": [
"crate::routes::user"
],
"operationId": "user_login",
"operationId": "user_change_password",
"parameters": [
{
"name": "username",
Expand All @@ -1628,30 +1613,31 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserCredentials"
"$ref": "#/components/schemas/ChangePassword"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "login successful",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
"201": {
"description": "password changed"
},
"401": {
"description": "invalid credentials"
},
"404": {
"description": "user not found"
},
"461": {
"description": "password too short (<8)"
}
}
},
"security": [
{
"Token": []
}
]
}
}
},
Expand Down Expand Up @@ -2823,6 +2809,21 @@
}
}
},
"UserLogin": {
"type": "object",
"required": [
"username",
"password"
],
"properties": {
"password": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
"UserStatus": {
"type": "object",
"required": [
Expand Down
1 change: 1 addition & 0 deletions agdb_server/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ use utoipa::OpenApi;
crate::routes::db::user::DbUserRole,
crate::routes::db::user::DbUserRoleParam,
crate::routes::user::ChangePassword,
crate::routes::user::UserLogin,
crate::routes::user::UserCredentials,
agdb::QueryResult,
agdb::DbElement,
Expand Down
2 changes: 1 addition & 1 deletion agdb_server/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub(crate) fn app(config: Config, shutdown_sender: Sender<()>, db_pool: DbPool)
"/db/:user/:db/user/:other/remove",
routing::delete(routes::db::user::remove),
)
.route("/user/:user/login", routing::post(routes::user::login))
.route("/user/login", routing::post(routes::user::login))
.route(
"/user/:user/change_password",
routing::put(routes::user::change_password),
Expand Down
26 changes: 15 additions & 11 deletions agdb_server/src/routes/user.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::db_pool::DbPool;
use crate::password::Password;
use crate::server_error::ServerError;
use crate::server_error::ServerResponse;
use axum::extract::Path;
use axum::extract::State;
Expand All @@ -14,35 +15,38 @@ pub(crate) struct UserCredentials {
pub(crate) password: String,
}

#[derive(Deserialize, ToSchema)]
pub(crate) struct UserLogin {
pub(crate) username: String,
pub(crate) password: String,
}

#[derive(Deserialize, ToSchema)]
pub(crate) struct ChangePassword {
pub(crate) password: String,
pub(crate) new_password: String,
}

#[utoipa::path(post,
path = "/api/v1/user/{username}/login",
path = "/api/v1/user/login",
operation_id = "user_login",
params(
("username" = String, Path, description = "username"),
),
request_body = UserCredentials,
request_body = UserLogin,
responses(
(status = 200, description = "login successful", body = String),
(status = 401, description = "invalid credentials"),
(status = 404, description = "user not found")
)
)]
pub(crate) async fn login(
State(db_pool): State<DbPool>,
Path(username): Path<String>,
Json(request): Json<UserCredentials>,
Json(request): Json<UserLogin>,
) -> ServerResponse<(StatusCode, String)> {
let user = db_pool.find_user(&username)?;
let user = db_pool
.find_user(&request.username)
.map_err(|_| ServerError::new(StatusCode::UNAUTHORIZED, "unuauthorized"))?;
let pswd = Password::new(&user.name, &user.password, &user.salt)?;

if !pswd.verify_password(&request.password) {
return Ok((StatusCode::UNAUTHORIZED, String::new()));
return Err(ServerError::new(StatusCode::UNAUTHORIZED, "unuauthorized"));
}

let token_uuid = Uuid::new_v4();
Expand Down Expand Up @@ -76,7 +80,7 @@ pub(crate) async fn change_password(
let old_pswd = Password::new(&user.name, &user.password, &user.salt)?;

if !old_pswd.verify_password(&request.password) {
return Ok(StatusCode::UNAUTHORIZED);
return Err(ServerError::new(StatusCode::UNAUTHORIZED, "unuauthorized"));
}

db_pool.change_password(user, &request.new_password)?;
Expand Down
26 changes: 19 additions & 7 deletions agdb_server/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ pub struct UserCredentials<'a> {
pub password: &'a str,
}

#[derive(Serialize, Deserialize)]
pub struct UserLogin<'a> {
pub username: &'a str,
pub password: &'a str,
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub struct UserStatus {
pub name: String,
Expand Down Expand Up @@ -116,13 +122,12 @@ impl TestServer {
.await
{
Ok(_) => {
let credentials = UserCredentials { password: ADMIN };
let credentials = UserLogin {
username: ADMIN,
password: ADMIN,
};
let response = client
.post(format!(
"{}:{}/api/v1/user/{ADMIN}/login",
Self::url_base(),
port
))
.post(format!("{}:{}/api/v1/user/login", Self::url_base(), port))
.json(&credentials)
.send()
.await?;
Expand Down Expand Up @@ -193,7 +198,14 @@ impl TestServer {
201
);
let response = self
.post(&format!("/user/{name}/login"), &credentials, &None)
.post(
"/user/login",
&Some(UserLogin {
username: &name,
password: &name,
}),
&None,
)
.await?;
assert_eq!(response.0, 200);
Ok(ServerUser {
Expand Down
Loading