1
1
use std:: str:: FromStr ;
2
2
3
3
use super :: Result ;
4
+ use base64:: { Engine as _, engine:: general_purpose:: STANDARD } ;
4
5
use bcr_ebill_api:: {
5
6
data:: {
6
7
NodeId ,
@@ -25,7 +26,7 @@ use crate::{
25
26
api:: identity:: get_current_identity_node_id,
26
27
context:: get_ctx,
27
28
data:: {
28
- BinaryFileResponse , UploadFile , UploadFileResponse ,
29
+ Base64FileResponse , BinaryFileResponse , UploadFile , UploadFileResponse ,
29
30
bill:: {
30
31
AcceptBitcreditBillPayload , BillCombinedBitcoinKeyWeb , BillIdResponse ,
31
32
BillNumbersToWordsForSum , BillsResponse , BillsSearchFilterPayload ,
@@ -42,6 +43,44 @@ use crate::{
42
43
43
44
use super :: identity:: get_current_identity;
44
45
46
+ async fn get_attachment ( bill_id : & str , file_name : & str ) -> Result < ( Vec < u8 > , String ) > {
47
+ let parsed_bill_id = BillId :: from_str ( bill_id) ?;
48
+ let current_timestamp = util:: date:: now ( ) . timestamp ( ) as u64 ;
49
+ let identity = get_ctx ( ) . identity_service . get_identity ( ) . await ?;
50
+ // get bill
51
+ let bill = get_ctx ( )
52
+ . bill_service
53
+ . get_detail (
54
+ & parsed_bill_id,
55
+ & identity,
56
+ & get_current_identity_node_id ( ) . await ?,
57
+ current_timestamp,
58
+ )
59
+ . await ?;
60
+
61
+ // check if this file even exists on the bill
62
+ let file = match bill. data . files . iter ( ) . find ( |f| f. name == file_name) {
63
+ Some ( f) => f,
64
+ None => {
65
+ return Err ( bcr_ebill_api:: service:: bill_service:: Error :: NotFound . into ( ) ) ;
66
+ }
67
+ } ;
68
+
69
+ // fetch the attachment
70
+ let keys = get_ctx ( )
71
+ . bill_service
72
+ . get_bill_keys ( & parsed_bill_id)
73
+ . await ?;
74
+ let file_bytes = get_ctx ( )
75
+ . bill_service
76
+ . open_and_decrypt_attached_file ( & parsed_bill_id, file, & keys. private_key )
77
+ . await ?;
78
+
79
+ let content_type = detect_content_type_for_bytes ( & file_bytes)
80
+ . ok_or ( Error :: Validation ( ValidationError :: InvalidContentType ) ) ?;
81
+ Ok ( ( file_bytes, content_type) )
82
+ }
83
+
45
84
#[ wasm_bindgen]
46
85
pub struct Bill ;
47
86
@@ -111,41 +150,7 @@ impl Bill {
111
150
112
151
#[ wasm_bindgen( unchecked_return_type = "BinaryFileResponse" ) ]
113
152
pub async fn attachment ( & self , bill_id : & str , file_name : & str ) -> Result < JsValue > {
114
- let parsed_bill_id = BillId :: from_str ( bill_id) ?;
115
- let current_timestamp = util:: date:: now ( ) . timestamp ( ) as u64 ;
116
- let identity = get_ctx ( ) . identity_service . get_identity ( ) . await ?;
117
- // get bill
118
- let bill = get_ctx ( )
119
- . bill_service
120
- . get_detail (
121
- & parsed_bill_id,
122
- & identity,
123
- & get_current_identity_node_id ( ) . await ?,
124
- current_timestamp,
125
- )
126
- . await ?;
127
-
128
- // check if this file even exists on the bill
129
- let file = match bill. data . files . iter ( ) . find ( |f| f. name == file_name) {
130
- Some ( f) => f,
131
- None => {
132
- return Err ( bcr_ebill_api:: service:: bill_service:: Error :: NotFound . into ( ) ) ;
133
- }
134
- } ;
135
-
136
- // fetch the attachment
137
- let keys = get_ctx ( )
138
- . bill_service
139
- . get_bill_keys ( & parsed_bill_id)
140
- . await ?;
141
- let file_bytes = get_ctx ( )
142
- . bill_service
143
- . open_and_decrypt_attached_file ( & parsed_bill_id, file, & keys. private_key )
144
- . await ?;
145
-
146
- let content_type = detect_content_type_for_bytes ( & file_bytes)
147
- . ok_or ( Error :: Validation ( ValidationError :: InvalidContentType ) ) ?;
148
-
153
+ let ( file_bytes, content_type) = get_attachment ( bill_id, file_name) . await ?;
149
154
let res = serde_wasm_bindgen:: to_value ( & BinaryFileResponse {
150
155
data : file_bytes,
151
156
name : file_name. to_owned ( ) ,
@@ -154,6 +159,17 @@ impl Bill {
154
159
Ok ( res)
155
160
}
156
161
162
+ #[ wasm_bindgen( unchecked_return_type = "Base64FileResponse" ) ]
163
+ pub async fn attachment_base64 ( & self , bill_id : & str , file_name : & str ) -> Result < JsValue > {
164
+ let ( file_bytes, content_type) = get_attachment ( bill_id, file_name) . await ?;
165
+ let res = serde_wasm_bindgen:: to_value ( & Base64FileResponse {
166
+ data : STANDARD . encode ( & file_bytes) ,
167
+ name : file_name. to_owned ( ) ,
168
+ content_type,
169
+ } ) ?;
170
+ Ok ( res)
171
+ }
172
+
157
173
#[ wasm_bindgen( unchecked_return_type = "UploadFileResponse" ) ]
158
174
pub async fn upload (
159
175
& self ,
0 commit comments