Replace cookie auth with token auth

This commit is contained in:
silverpill 2021-10-05 18:10:14 +00:00
parent 9519786788
commit d4adb55c53
16 changed files with 44 additions and 305 deletions

167
Cargo.lock generated
View file

@ -186,21 +186,6 @@ dependencies = [
"pin-project 0.4.28",
]
[[package]]
name = "actix-session"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "559b815f2b3ad84f8a17256069d7df16c3ee8069635c86758729521d62ca891d"
dependencies = [
"actix-service",
"actix-web",
"derive_more",
"futures-util",
"serde",
"serde_json",
"time 0.2.26",
]
[[package]]
name = "actix-testing"
version = "1.0.1"
@ -329,60 +314,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aead"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331"
dependencies = [
"generic-array",
]
[[package]]
name = "aes"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
dependencies = [
"aes-soft",
"aesni",
"cipher",
]
[[package]]
name = "aes-gcm"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
[[package]]
name = "aes-soft"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
dependencies = [
"cipher",
"opaque-debug",
]
[[package]]
name = "aesni"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
dependencies = [
"cipher",
"opaque-debug",
]
[[package]]
name = "aho-corasick"
version = "0.7.18"
@ -639,15 +570,6 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "cipher"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
dependencies = [
"generic-array",
]
[[package]]
name = "clap"
version = "3.0.0-beta.2"
@ -727,13 +649,7 @@ version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951"
dependencies = [
"aes-gcm",
"base64 0.13.0",
"hkdf",
"hmac 0.10.1",
"percent-encoding 2.1.0",
"rand 0.8.3",
"sha2",
"time 0.2.26",
"version_check 0.9.3",
]
@ -775,12 +691,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
[[package]]
name = "cpuid-bool"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
[[package]]
name = "crc32fast"
version = "1.2.1"
@ -860,25 +770,6 @@ dependencies = [
"subtle",
]
[[package]]
name = "crypto-mac"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "ctr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f"
dependencies = [
"cipher",
]
[[package]]
name = "deadpool"
version = "0.5.2"
@ -1279,16 +1170,6 @@ dependencies = [
"wasi 0.10.0+wasi-snapshot-preview1",
]
[[package]]
name = "ghash"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
name = "h2"
version = "0.2.7"
@ -1339,33 +1220,13 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hkdf"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
dependencies = [
"digest",
"hmac 0.10.1",
]
[[package]]
name = "hmac"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "deae6d9dbb35ec2c502d62b8f7b1c000a0822c3b0794ba36b3149c0a1c840dff"
dependencies = [
"crypto-mac 0.9.1",
"digest",
]
[[package]]
name = "hmac"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15"
dependencies = [
"crypto-mac 0.10.0",
"crypto-mac",
"digest",
]
@ -1847,7 +1708,6 @@ dependencies = [
"actix-cors",
"actix-files",
"actix-rt",
"actix-session",
"actix-web",
"actix-web-httpauth",
"ammonia",
@ -2233,17 +2093,6 @@ version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "polyval"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd"
dependencies = [
"cpuid-bool 0.2.0",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "postgres-derive"
version = "0.4.0"
@ -2265,7 +2114,7 @@ dependencies = [
"byteorder",
"bytes 0.5.6",
"fallible-iterator",
"hmac 0.9.0",
"hmac",
"md5",
"memchr",
"rand 0.7.3",
@ -2919,7 +2768,7 @@ checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f"
dependencies = [
"block-buffer",
"cfg-if 1.0.0",
"cpuid-bool 0.1.2",
"cpuid-bool",
"digest",
"opaque-debug",
]
@ -3528,16 +3377,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "universal-hash"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "url"
version = "1.7.2"

View file

@ -12,7 +12,6 @@ default-run = "mitra"
# Used to handle incoming HTTP requests
actix-cors = "0.5.4"
actix-files = "0.5.0"
actix-session = "0.4.1"
actix-web = "3.3.2"
actix-web-httpauth = "0.5.1"
# Used for managing async tasks

View file

@ -66,6 +66,7 @@ cargo build --release
Endpoints are similar to Mastodon API:
```
POST /api/v1/accounts
GET /api/v1/accounts/{account_id}
GET /api/v1/accounts/verify_credentials
PATCH /api/v1/accounts/update_credentials

View file

@ -3,9 +3,6 @@ database_url: postgres://mitra:mitra@127.0.0.1:5432/mitra
http_host: '127.0.0.1'
http_port: 8380
# 32 symbols or more
cookie_secret_key: null
# domain name
instance_uri: myserver.net
instance_title: myserver

View file

@ -62,8 +62,6 @@ fn default_storage_dir() -> PathBuf { PathBuf::from("files") }
fn default_contract_dir() -> PathBuf { PathBuf::from("contracts") }
fn default_cookie_name() -> String { "session".to_string() }
#[derive(Clone, Deserialize)]
pub struct EthereumContract {
pub address: String,
@ -89,11 +87,6 @@ pub struct Config {
pub http_host: String,
pub http_port: u32,
#[serde(default = "default_cookie_name")]
pub cookie_name: String,
pub cookie_secret_key: String,
// Instance info
pub instance_uri: String,
pub instance_title: String,

View file

@ -1,5 +1,4 @@
use actix_cors::Cors;
use actix_session::CookieSession;
use actix_web::{
web,
App, HttpServer,
@ -20,7 +19,6 @@ use mitra::mastodon_api::oauth::views::oauth_api_scope;
use mitra::mastodon_api::search::views::search;
use mitra::mastodon_api::statuses::views::status_api_scope;
use mitra::mastodon_api::timelines::views as timeline_api;
use mitra::mastodon_api::users::views as user_api;
use mitra::nodeinfo::views as nodeinfo;
use mitra::scheduler;
use mitra::webfinger::views as webfinger;
@ -59,14 +57,9 @@ async fn main() -> std::io::Result<()> {
.allow_any_header()
},
};
let cookie_config = CookieSession::signed(config.cookie_secret_key.as_bytes())
.name(config.cookie_name.clone())
.max_age(86400 * 30)
.secure(true);
App::new()
.wrap(ActixLogger::new("%r : %s : %{r}a"))
.wrap(cors_config)
.wrap(cookie_config)
.wrap(create_auth_error_handler())
.data(web::PayloadConfig::default().limit(MAX_UPLOAD_SIZE))
.data(web::JsonConfig::default().limit(MAX_UPLOAD_SIZE))
@ -81,9 +74,6 @@ async fn main() -> std::io::Result<()> {
config.contract_dir.clone(),
))
.service(oauth_api_scope())
.service(user_api::login_view)
.service(user_api::current_user_view)
.service(user_api::logout_view)
.service(profile_directory)
.service(account_api_scope())
.service(media_api_scope())

View file

@ -1,4 +1,3 @@
use actix_session::Session;
use actix_web::{get, post, patch, web, HttpResponse, Scope};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use serde::Deserialize;
@ -14,8 +13,7 @@ use crate::config::Config;
use crate::database::{Pool, get_database_client};
use crate::errors::HttpError;
use crate::mastodon_api::statuses::types::Status;
use crate::mastodon_api::oauth::auth::get_current_user as get_current_user_;
use crate::mastodon_api::users::auth::get_current_user;
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::mastodon_api::users::views::create_user_view;
use crate::models::posts::queries::get_posts_by_author;
use crate::models::profiles::queries::{
@ -40,25 +38,25 @@ async fn get_account(
#[get("/verify_credentials")]
async fn verify_credentials(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
auth: BearerAuth,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let user = get_current_user_(db_client, auth.token()).await?;
let user = get_current_user(db_client, auth.token()).await?;
let account = Account::from_user(user, &config.instance_url());
Ok(HttpResponse::Ok().json(account))
}
#[patch("/update_credentials")]
async fn update_credentials(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
data: web::Json<AccountUpdateData>,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let mut current_user = get_current_user(db_client, session).await?;
let mut current_user = get_current_user(db_client, auth.token()).await?;
let mut profile_data = data.into_inner()
.into_profile_data(
&current_user.profile.avatar_file_name,
@ -96,12 +94,12 @@ pub struct RelationshipQueryParams {
#[get("/relationships")]
async fn get_relationships(
auth: BearerAuth,
db_pool: web::Data<Pool>,
session: Session,
query_params: web::Query<RelationshipQueryParams>,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, session).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let relationships = follows::get_relationships(
db_client,
current_user.id,
@ -112,13 +110,13 @@ async fn get_relationships(
#[post("/{account_id}/follow")]
async fn follow(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
web::Path(account_id): web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, session).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let profile = get_profile_by_id(db_client, &account_id).await?;
let relationship = if let Some(actor_value) = profile.actor_json {
// Remote follow
@ -149,13 +147,13 @@ async fn follow(
#[post("/{account_id}/unfollow")]
async fn unfollow(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
web::Path(account_id): web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, session).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let target_profile = get_profile_by_id(db_client, &account_id).await?;
let relationship = if let Some(actor_value) = target_profile.actor_json {
// Remote follow

View file

@ -1,21 +1,21 @@
use actix_session::Session;
use actix_web::{get, web, HttpResponse};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use crate::config::Config;
use crate::database::{Pool, get_database_client};
use crate::errors::HttpError;
use crate::mastodon_api::accounts::types::Account;
use crate::mastodon_api::users::auth::get_current_user;
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::models::profiles::queries::get_profiles;
#[get("/api/v1/directory")]
pub async fn profile_directory(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
get_current_user(db_client, session).await?;
get_current_user(db_client, auth.token()).await?;
let accounts: Vec<Account> = get_profiles(db_client).await?
.into_iter()
.map(|profile| Account::from_profile(profile, &config.instance_url()))

View file

@ -1,23 +1,23 @@
use actix_session::Session;
use actix_web::{post, web, HttpResponse, Scope};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use crate::config::Config;
use crate::database::{Pool, get_database_client};
use crate::errors::HttpError;
use crate::mastodon_api::users::auth::get_current_user;
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::models::attachments::queries::create_attachment;
use crate::utils::files::{FileError, save_b64_file};
use super::types::{AttachmentCreateData, Attachment};
#[post("")]
async fn create_attachment_view(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
data: web::Json<AttachmentCreateData>,
) -> Result<HttpResponse, HttpError> {
let db_client = get_database_client(&db_pool).await?;
let current_user = get_current_user(&**db_client, session).await?;
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let (file_name, media_type) = save_b64_file(
&data.file,
&config.media_dir(),
@ -26,7 +26,7 @@ async fn create_attachment_view(
_ => HttpError::InternalError,
})?;
let db_attachment = create_attachment(
&**db_client,
db_client,
&current_user.id,
media_type,
file_name,

View file

@ -1,12 +1,12 @@
use actix_session::Session;
use actix_web::{get, web, HttpResponse};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use serde::Deserialize;
use crate::config::Config;
use crate::database::{Pool, get_database_client};
use crate::errors::HttpError;
use crate::mastodon_api::accounts::types::Account;
use crate::mastodon_api::users::auth::get_current_user;
use crate::mastodon_api::oauth::auth::get_current_user;
use super::queries;
use super::types::SearchResults;
@ -17,14 +17,14 @@ struct SearchQueryParams {
#[get("/api/v2/search")]
async fn search(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
query_params: web::Query<SearchQueryParams>,
) -> Result<HttpResponse, HttpError> {
let db_client = get_database_client(&db_pool).await?;
get_current_user(&**db_client, session).await?;
let profiles = queries::search(&config, &**db_client, &query_params.q).await?;
let db_client = &**get_database_client(&db_pool).await?;
get_current_user(db_client, auth.token()).await?;
let profiles = queries::search(&config, db_client, &query_params.q).await?;
let accounts: Vec<Account> = profiles.into_iter()
.map(|profile| Account::from_profile(profile, &config.instance_url()))
.collect();

View file

@ -1,5 +1,5 @@
use actix_session::Session;
use actix_web::{get, post, web, HttpResponse, Scope};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use serde::Serialize;
use uuid::Uuid;
@ -12,7 +12,7 @@ use crate::errors::HttpError;
use crate::ethereum::nft::create_mint_signature;
use crate::ipfs::store as ipfs_store;
use crate::ipfs::utils::{IPFS_LOGO, get_ipfs_url};
use crate::mastodon_api::users::auth::get_current_user;
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::models::attachments::queries::set_attachment_ipfs_cid;
use crate::models::profiles::queries::get_followers;
use crate::models::posts::queries::{
@ -26,13 +26,13 @@ use super::types::{Status, StatusData};
#[post("")]
async fn create_status(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
data: web::Json<StatusData>,
) -> Result<HttpResponse, HttpError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, session).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let mut post_data = PostCreateData::from(data.into_inner());
post_data.validate()?;
let post = create_post(db_client, &current_user.id, post_data).await?;
@ -97,13 +97,13 @@ struct PostMetadata {
#[post("/{status_id}/make_permanent")]
async fn make_permanent(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
web::Path(status_id): web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
get_current_user(db_client, session).await?;
get_current_user(db_client, auth.token()).await?;
let mut post = get_post_by_id(db_client, &status_id).await?;
let ipfs_api_url = config.ipfs_api_url.as_ref()
.ok_or(HttpError::NotSupported)?;
@ -143,13 +143,13 @@ async fn make_permanent(
#[get("/{status_id}/signature")]
async fn get_signature(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
web::Path(status_id): web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, session).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let contract_config = config.ethereum_contract.as_ref()
.ok_or(HttpError::NotSupported)?;
let post = get_post_by_id(db_client, &status_id).await?;

View file

@ -1,21 +1,21 @@
use actix_session::Session;
use actix_web::{get, web, HttpResponse};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use crate::config::Config;
use crate::database::{Pool, get_database_client};
use crate::errors::HttpError;
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::mastodon_api::statuses::types::Status;
use crate::mastodon_api::users::auth::get_current_user;
use crate::models::posts::queries::get_posts;
#[get("/api/v1/timelines/home")]
pub async fn home_timeline(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, session).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let statuses: Vec<Status> = get_posts(db_client, &current_user.id).await?
.into_iter()
.map(|post| Status::from_post(post, &config.instance_url()))

View file

@ -1,25 +0,0 @@
use actix_session::Session;
use tokio_postgres::GenericClient;
use uuid::Uuid;
use crate::errors::HttpError;
use crate::models::users::queries::get_user_by_id;
use crate::models::users::types::User;
pub async fn get_current_user(
db_client: &impl GenericClient,
session: Session,
) -> Result<User, HttpError> {
let maybe_user_id = session.get::<String>("id")
.map_err(|_| HttpError::SessionError("failed to read cookie"))?;
if let Some(user_id) = maybe_user_id {
let user_uuid = Uuid::parse_str(&user_id)
.map_err(|_| HttpError::SessionError("invalid uuid"))?;
let user = get_user_by_id(db_client, &user_uuid)
.await
.map_err(|_| HttpError::SessionError("user not found"))?;
Ok(user)
} else {
return Err(HttpError::SessionError("session not found"));
}
}

View file

@ -1,2 +1 @@
pub mod auth;
pub mod views;

View file

@ -1,6 +1,5 @@
use actix_session::Session;
use actix_web::{
get, post, web,
post, web,
HttpResponse,
};
@ -11,16 +10,12 @@ use crate::mastodon_api::accounts::types::{Account, AccountCreateData};
use crate::models::users::queries::{
is_valid_invite_code,
create_user,
get_user_by_wallet_address,
};
use crate::models::users::types::UserLoginData;
use crate::utils::crypto::{
hash_password,
verify_password,
generate_private_key,
serialize_private_key,
};
use super::auth::get_current_user;
// /api/v1/accounts
#[post("")]
@ -28,7 +23,6 @@ pub async fn create_user_view(
config: web::Data<Config>,
db_pool: web::Data<Pool>,
account_data: web::Json<AccountCreateData>,
session: Session,
) -> Result<HttpResponse, HttpError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let user_data = account_data.into_inner().into_user_data();
@ -57,47 +51,7 @@ pub async fn create_user_view(
password_hash,
private_key_pem,
).await?;
session.set("id", user.id)?;
let account = Account::from_user(user, &config.instance_url());
Ok(HttpResponse::Created().json(account))
}
#[post("/api/v0/login")]
async fn login_view(
config: web::Data<Config>,
db_pool: web::Data<Pool>,
form: web::Json<UserLoginData>,
session: Session,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let user = get_user_by_wallet_address(db_client, &form.wallet_address).await?;
let result = verify_password(&user.password_hash, &form.signature)
.map_err(|_| ValidationError("incorrect password"))?;
if !result {
// Invalid signature/password
Err(ValidationError("incorrect password"))?;
}
session.set("id", &user.id)?;
let account = Account::from_user(user, &config.instance_url());
Ok(HttpResponse::Ok().json(account))
}
#[get("/api/v0/current-user")]
async fn current_user_view(
config: web::Data<Config>,
db_pool: web::Data<Pool>,
session: Session,
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let user = get_current_user(db_client, session).await?;
let account = Account::from_user(user, &config.instance_url());
Ok(HttpResponse::Ok().json(account))
}
#[post("/api/v0/logout")]
async fn logout_view(
session: Session,
) -> Result<HttpResponse, HttpError> {
session.clear();
Ok(HttpResponse::Ok().body("logged out"))
}

View file

@ -52,12 +52,6 @@ impl UserCreateData {
}
}
#[derive(Deserialize)]
pub struct UserLoginData {
pub signature: String,
pub wallet_address: String,
}
#[cfg(test)]
mod tests {
use super::*;