11use crate :: error:: { ApiError , ApiResult , ToApiResult } ;
2+ use crate :: util:: secret:: Secret ;
3+ use anyhow:: anyhow;
24use axum:: extract:: multipart:: Field ;
35use axum:: extract:: Multipart ;
46use chrono:: { DateTime , Utc } ;
@@ -17,10 +19,10 @@ use crate::server::ApiState;
1719pub async fn store (
1820 state : & ApiState ,
1921 query : & UploadParamQuery ,
20- auth : Option < String > ,
22+ secret : Option < Secret > ,
2123 mut multipart : Multipart ,
2224) -> ApiResult < ( FilePath , DateTime < Utc > ) > {
23- let auth = hash ( auth ) ?;
25+ let auth = secret . map ( |s| s . hash ( ) ) . transpose ( ) ?;
2426 let expire_secs = query
2527 . expire_time
2628 . unwrap_or ( state. config . default_expire_secs ) as i64 ;
@@ -89,7 +91,7 @@ pub async fn info(
8991 state : & ApiState ,
9092 code : & str ,
9193 file_name : & str ,
92- auth : Option < String > ,
94+ auth : Option < Secret > ,
9395) -> ApiResult < MetaDataFile > {
9496 let path = FilePath {
9597 code : code. to_string ( ) ,
@@ -110,7 +112,7 @@ pub async fn fetch(
110112 state : & ApiState ,
111113 code : & str ,
112114 file_name : & str ,
113- auth : Option < String > ,
115+ secret : Option < Secret > ,
114116) -> ApiResult < ServeFile > {
115117 let path = FilePath {
116118 code : code. to_string ( ) ,
@@ -123,23 +125,23 @@ pub async fn fetch(
123125 return Err ( ApiError :: NotFound ( format ! ( "{} not found" , path. url_path( ) ) ) ) ;
124126 }
125127 }
126- authenticate ( auth , & meta. auth ) ?;
128+ authenticate ( secret , & meta. auth ) ?;
127129 read_file ( & state. config . fs . base_dir . join ( & path. url_path ( ) ) ) . await
128130}
129131
130132pub async fn delete (
131133 state : & ApiState ,
132134 code : & str ,
133135 file_name : & str ,
134- auth : Option < String > ,
136+ secret : Option < Secret > ,
135137) -> ApiResult < ( ) > {
136138 let path = FilePath {
137139 code : code. to_string ( ) ,
138140 file_name : file_name. to_string ( ) ,
139141 } ;
140142 if let Some ( meta) = state. db . fetch ( & path) ? {
141143 if meta. delete_manually {
142- authenticate ( auth , & meta. auth ) ?;
144+ authenticate ( secret , & meta. auth ) ?;
143145 let file_path = path. fs_path ( & state. config . fs . base_dir ) ;
144146 tokio:: fs:: remove_file ( file_path) . await ?;
145147 state. db . delete ( path) . await ?;
@@ -158,18 +160,24 @@ pub async fn read_file(file_path: &PathBuf) -> ApiResult<ServeFile> {
158160 Ok ( ServeFile :: new ( file_path) )
159161}
160162
161- pub fn authenticate ( auth : Option < String > , hash : & Option < String > ) -> ApiResult < ( ) > {
163+ pub fn authenticate ( secret : Option < Secret > , hash : & Option < String > ) -> ApiResult < ( ) > {
162164 if let Some ( hash) = hash {
163- if !matches ! (
164- auth. map( |p| crate :: util:: hash:: argon_verify( p, hash) ) ,
165- Some ( Ok ( ( ) ) )
166- ) {
167- return Err ( ApiError :: PermissionDenied (
168- "user and password is invalid" . to_string ( ) ,
169- ) ) ;
165+ match secret. map ( |s| s. check ( hash) ) {
166+ Some ( Ok ( _) ) => return Ok ( ( ) ) ,
167+ Some ( Err ( e) ) if e == argon2:: password_hash:: Error :: Password => Err (
168+ ApiError :: PermissionDenied ( "Secret token is invalid" . to_string ( ) ) ,
169+ ) ,
170+ Some ( Err ( e) ) => Err ( ApiError :: Unknown ( anyhow ! (
171+ "Unexpected error happened: {}" ,
172+ e
173+ ) ) ) ,
174+ None => Err ( ApiError :: PermissionDenied (
175+ "Authorization header should be set" . to_string ( ) ,
176+ ) ) ,
170177 }
178+ } else {
179+ Ok ( ( ) )
171180 }
172- Ok ( ( ) )
173181}
174182
175183pub fn hash ( auth : Option < String > ) -> ApiResult < Option < String > > {
0 commit comments