I am almost sure I had this working a couple months a go, but now I came back to add some other functions to the API and it has type errors on all my sqlx calls.
the trait `std::convert::From<std::option::Option<std::string::String>>` is not implemented for `std::string::String`
#[post("/auth/register_usenet")]
async fn register_usenet_handler(
req: HttpRequest,
body: web::Json<RegisterUsenetSchema>,
data: web::Data<AppState>,
) -> impl Responder {
let ext = req.extensions();
let user_id = ext.get::<uuid::Uuid>().unwrap();
// TODO here we need to also test if usenet is true or false FOR the user making the query.
let exists: bool = sqlx::query("SELECT EXISTS(SELECT 1 FROM users WHERE usenet_username = $1)")
.bind(body.usenet_username.to_owned())
.fetch_one(&data.db)
.await
.unwrap()
.get(0);
if exists {
return HttpResponse::Conflict().json(
serde_json::json!({"status": "fail","message": "User with that email already exists"}),
);
}
let salt = SaltString::generate(&mut OsRng);
let hashed_password = Argon2::default()
.hash_password(body.usenet_password.as_bytes(), &salt)
.expect("Error while hashing password")
.to_string();
let query_result = sqlx::query_as!(
User,
"UPDATE users SET usenet_username = $1, usenet_password = $2 WHERE id = $3 RETURNING *",
body.usenet_username.to_string(),
hashed_password,
user_id
)
.fetch_one(&data.db)
.await;
match query_result {
Ok(user) => {
let user_response = serde_json::json!({"status": "success","data": serde_json::json!({
"user": filter_user_record(&user)
})});
return HttpResponse::Ok().json(user_response);
}
Err(e) => {
return HttpResponse::InternalServerError()
.json(serde_json::json!({"status": "error","message": format!("{:?}", e)}));
}
}
}
I banging my head trying to see where my types are diff, but can't see it.
[update] cargo check output snip.
error[E0277]: the trait bound `std::string::String: std::convert::From<std::option::Option<std::string::String>>` is not satisfied
--> src/handler.rs:103:24
|
103 | let query_result = sqlx::query_as!(
| ________________________^
104 | | User,
105 | | "UPDATE users SET usenet_username = $1, usenet_password = $2 WHERE id = $3 RETURNING *",
106 | | body.usenet_username.to_string(),
107 | | hashed_password,
108 | | user_id
109 | | )
| |_____^ the trait `std::convert::From<std::option::Option<std::string::String>>` is not implemented for `std::string::String`
|
= help: the following other types implement trait `std::convert::From<T>`:
<std::string::String as std::convert::From<&mut str>>
<std::string::String as std::convert::From<&std::string::String>>
<std::string::String as std::convert::From<&str>>
<std::string::String as std::convert::From<Box<str>>>
<std::string::String as std::convert::From<Cow<'a, str>>>
<std::string::String as std::convert::From<bytestring::ByteString>>
<std::string::String as std::convert::From<char>>
<std::string::String as std::convert::From<url::Url>>
= note: required for `std::option::Option<std::string::String>` to implement `Into<std::string::String>`
= note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
Ok, @drewtato's comment made me realize the issues was not on my funtions but on the User
struct! Apparently on a simple look it seems ok but the documentation says that if a colum may be NULL
as @drewtato pointed out I need to wrap the type in Option
.
Example:
pub usenet_username: Option<String>,
it was:
pub usenet_username: String,