Strong typing for passport data.
GitOrigin-RevId: 766b671c97d8deb1e32bbfb4972c5a59a67f8435
This commit is contained in:
parent
7149f65461
commit
0bfe50a7b7
@ -745,6 +745,10 @@ webPageInstantView page_blocks:vector<PageBlock> is_full:Bool = WebPageInstantVi
|
||||
webPage url:string display_url:string type:string site_name:string title:string description:string photo:photo embed_url:string embed_type:string embed_width:int32 embed_height:int32 duration:int32 author:string animation:animation audio:audio document:document sticker:sticker video:video video_note:videoNote voice_note:voiceNote has_instant_view:Bool = WebPage;
|
||||
|
||||
|
||||
//@description Describes an address @country_code A two-letter ISO 3166-1 alpha-2 country code @state State, if applicable @city City @street_line1 First line of the address @street_line2 Second line of the address @postal_code Address postal code
|
||||
address country_code:string state:string city:string street_line1:string street_line2:string postal_code:string = Address;
|
||||
|
||||
|
||||
//@description Portion of the price of a product (e.g., "delivery cost", "tax amount") @label Label for this portion of the product price @amount Currency amount in minimal quantity of the currency
|
||||
labeledPricePart label:string amount:int53 = LabeledPricePart;
|
||||
|
||||
@ -754,11 +758,8 @@ labeledPricePart label:string amount:int53 = LabeledPricePart;
|
||||
//@send_email_address_to_provider True, if the user's email address will be sent to the provider @is_flexible True, if the total price depends on the shipping method
|
||||
invoice currency:string price_parts:vector<labeledPricePart> is_test:Bool need_name:Bool need_phone_number:Bool need_email_address:Bool need_shipping_address:Bool send_phone_number_to_provider:Bool send_email_address_to_provider:Bool is_flexible:Bool = Invoice;
|
||||
|
||||
//@description Describes a shipping address @country_code Two-letter ISO 3166-1 alpha-2 country code @state State, if applicable @city City @street_line1 First line of the address @street_line2 Second line of the address @postal_code Address postal code
|
||||
shippingAddress country_code:string state:string city:string street_line1:string street_line2:string postal_code:string = ShippingAddress;
|
||||
|
||||
//@description Order information @name Name of the user @phone_number Phone number of the user @email_address Email address of the user @shipping_address Shipping address for this order; may be null
|
||||
orderInfo name:string phone_number:string email_address:string shipping_address:shippingAddress = OrderInfo;
|
||||
orderInfo name:string phone_number:string email_address:string shipping_address:address = OrderInfo;
|
||||
|
||||
//@description One shipping option @id Shipping option identifier @title Option title @price_parts A list of objects used to calculate the total shipping costs
|
||||
shippingOption id:string title:string price_parts:vector<labeledPricePart> = ShippingOption;
|
||||
@ -831,18 +832,92 @@ passportDataTypePhoneNumber = PassportDataType;
|
||||
passportDataTypeEmailAddress = PassportDataType;
|
||||
|
||||
|
||||
//@description Contains information about a Telegram Passport data @type Telegram Passport data type @data TODO data should be typed @files List of attached files with a document @selfie Selfie with the document
|
||||
passportData type:PassportDataType data:string files:vector<file> selfie:file = PassportData;
|
||||
//@description Represents a date according to Gregorian calendar @day A day of a month, 1-31 @month A month, 1-12 @year A year, 1-9999
|
||||
date day:int32 month:int32 year:int32 = Date;
|
||||
|
||||
//@description Contains information about a Telegram Passport data to save @type Telegram Passport data type @data TODO data should be typed @files List of attached files with a document @selfie Selfie with the document
|
||||
inputPassportData type:PassportDataType data:string files:vector<InputFile> selfie:InputFile = InputPassportData;
|
||||
//@description Contains user's personal details @first_name First name of the user @last_name Last name of the user @birthdate Birthdate of the user
|
||||
//@gender Gender of the user, "male" or "female" @country_code A two-letter ISO 3166-1 alpha-2 country code for the user's country
|
||||
personalDetails first_name:string last_name:string birthdate:date gender:string country_code:string = PersonalDetails;
|
||||
|
||||
//@description Contains information about all filled Telegram Passport data @data All filled Telegram Passport data
|
||||
allPassportData data:vector<passportData> = AllPassportData;
|
||||
//@description An identity document @number Document's number @expiry_date Document's expiry date @files List of files with the document images @selfie Selfie with the document; may be null
|
||||
identityDocument number:string expiry_date:date files:vector<file> selfie:file = IdentityDocument;
|
||||
|
||||
//@description An identity document to save @number Document's number @expiry_date Document's expiry date @files List of files with the document images @selfie Selfie with the document, if available
|
||||
inputIdentityDocument number:string expiry_date:date files:vector<InputFile> selfie:InputFile = InputIdentityDocument;
|
||||
|
||||
|
||||
//@class PassportData @description Contains information about a Telegram Passport data
|
||||
|
||||
//@description The Telegram Passport data contains a user's personal details @personal_details Personal details of the user
|
||||
passportDataPersonalDetails personal_details:personalDetails = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's passport @passport The passport
|
||||
passportDataPassport passport:identityDocument = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's driver license @driver_license The driver license
|
||||
passportDataDriverLicense driver_license:identityDocument = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's identity card @identity_card The identity card
|
||||
passportDataIdentityCard identity_card:identityDocument = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's address @address The address
|
||||
passportDataAddress address:address = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's utility bill @files List of files with the utility bill
|
||||
passportDataUtilityBill files:vector<file> = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's bank statement @files List of files with the bank statement
|
||||
passportDataBankStatement files:vector<file> = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's rental agreement @files List of files with the rental agreement
|
||||
passportDataRentalAgreement files:vector<file> = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's phone number @phone_number The phone number
|
||||
passportDataPhoneNumber phone_number:string = PassportData;
|
||||
|
||||
//@description The Telegram Passport data contains a user's email address @email_address The email address
|
||||
passportDataEmailAddress email_address:string = PassportData;
|
||||
|
||||
|
||||
//@class InputPassportData @description Contains information about a Telegram Passport data to save
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's personal details @personal_details Personal details of the user
|
||||
inputPassportDataPersonalDetails personal_details:personalDetails = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's passport @passport The passport to save
|
||||
inputPassportDataPassport passport:inputIdentityDocument = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's driver license @driver_license The driver license to save
|
||||
inputPassportDataDriverLicense driver_license:inputIdentityDocument = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's identity card @identity_card The identity card to save
|
||||
inputPassportDataIdentityCard identity_card:inputIdentityDocument = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's address @address The address
|
||||
inputPassportDataAddress address:address = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's utility bill @files List of files with the utility bill
|
||||
inputPassportDataUtilityBill files:vector<InputFile> = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's bank statement @files List of files with the bank statement
|
||||
inputPassportDataBankStatement files:vector<InputFile> = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's rental agreement @files List of files with the rental agreement
|
||||
inputPassportDataRentalAgreement files:vector<InputFile> = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's phone number @phone_number The phone number
|
||||
inputPassportDataPhoneNumber phone_number:string = InputPassportData;
|
||||
|
||||
//@description The Telegram Passport data to save contains a user's email address @email_address The email address
|
||||
inputPassportDataEmailAddress email_address:string = InputPassportData;
|
||||
|
||||
|
||||
//@description Contains information about all saved Telegram Passport data @data All saved Telegram Passport data
|
||||
allPassportData data:vector<PassportData> = AllPassportData;
|
||||
|
||||
|
||||
//@description Contains information about requested Telegram Passport authorization form @id Authorization form unique identifier @data Available data @is_selfie_required True, if selfie is required with a document @privacy_policy_url URL with the service privacy policy
|
||||
passportAuthorizationForm id:int32 data:vector<passportData> is_selfie_required:Bool privacy_policy_url:string = PassportAuthorizationForm;
|
||||
passportAuthorizationForm id:int32 data:vector<PassportData> is_selfie_required:Bool privacy_policy_url:string = PassportAuthorizationForm;
|
||||
|
||||
|
||||
//@description Contains an encrypted Telegram Passport data credentials @data The encrypted credentials @hash The decrypted data hash @secret Encrypted by service public key secret for data decryption
|
||||
@ -2011,7 +2086,7 @@ updateNewCallbackQuery id:int64 sender_user_id:int32 chat_id:int53 message_id:in
|
||||
updateNewInlineCallbackQuery id:int64 sender_user_id:int32 inline_message_id:string chat_instance:int64 payload:CallbackQueryPayload = Update;
|
||||
|
||||
//@description A new incoming shipping query; for bots only. Only for invoices with flexible price @id Unique query identifier @sender_user_id Identifier of the user who sent the query @invoice_payload Invoice payload @shipping_address User shipping address
|
||||
updateNewShippingQuery id:int64 sender_user_id:int32 invoice_payload:string shipping_address:shippingAddress = Update;
|
||||
updateNewShippingQuery id:int64 sender_user_id:int32 invoice_payload:string shipping_address:address = Update;
|
||||
|
||||
//@description A new incoming pre-checkout query; for bots only. Contains full information about a checkout @id Unique query identifier @sender_user_id Identifier of the user who sent the query @currency Currency for the product price @total_amount Total price for the product, in the minimal quantity of the currency
|
||||
//@invoice_payload Invoice payload @shipping_option_id Identifier of a shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null
|
||||
@ -2894,7 +2969,7 @@ getPassportData type:PassportDataType password:string = PassportData;
|
||||
getAllPassportData password:string = AllPassportData;
|
||||
|
||||
//@description Sets Telegram Passport data @data Input Telegram Passport data @password Password of the current user
|
||||
setPassportData data:inputPassportData password:string = PassportData;
|
||||
setPassportData data:InputPassportData password:string = PassportData;
|
||||
|
||||
//@description Deletes Telegram Passport data @type Data type
|
||||
deletePassportData type:PassportDataType = Ok;
|
||||
|
Binary file not shown.
@ -175,7 +175,7 @@ void DeviceTokenManager::register_device(tl_object_ptr<td_api::DeviceToken> devi
|
||||
token = json_encode<string>(json_object([&device_token](auto &o) {
|
||||
o("endpoint", device_token->endpoint_);
|
||||
o("keys", json_object([&device_token](auto &o) {
|
||||
o("pb256dh", device_token->p256dh_base64url_);
|
||||
o("p256dh", device_token->p256dh_base64url_);
|
||||
o("auth", device_token->auth_base64url_);
|
||||
}));
|
||||
}));
|
||||
|
@ -174,18 +174,16 @@ static tl_object_ptr<td_api::paymentsProviderStripe> convert_payment_provider(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static tl_object_ptr<td_api::shippingAddress> convert_shipping_address(
|
||||
tl_object_ptr<telegram_api::postAddress> address) {
|
||||
static tl_object_ptr<td_api::address> convert_address(tl_object_ptr<telegram_api::postAddress> address) {
|
||||
if (address == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return make_tl_object<td_api::shippingAddress>(std::move(address->country_iso2_), std::move(address->state_),
|
||||
return make_tl_object<td_api::address>(std::move(address->country_iso2_), std::move(address->state_),
|
||||
std::move(address->city_), std::move(address->street_line1_),
|
||||
std::move(address->street_line2_), std::move(address->post_code_));
|
||||
}
|
||||
|
||||
static tl_object_ptr<telegram_api::postAddress> convert_shipping_address(
|
||||
tl_object_ptr<td_api::shippingAddress> address) {
|
||||
static tl_object_ptr<telegram_api::postAddress> convert_address(tl_object_ptr<td_api::address> address) {
|
||||
if (address == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -201,7 +199,7 @@ static tl_object_ptr<td_api::orderInfo> convert_order_info(
|
||||
}
|
||||
return make_tl_object<td_api::orderInfo>(std::move(order_info->name_), std::move(order_info->phone_),
|
||||
std::move(order_info->email_),
|
||||
convert_shipping_address(std::move(order_info->shipping_address_)));
|
||||
convert_address(std::move(order_info->shipping_address_)));
|
||||
}
|
||||
|
||||
static tl_object_ptr<td_api::labeledPricePart> convert_labeled_price(
|
||||
@ -240,7 +238,7 @@ static tl_object_ptr<telegram_api::paymentRequestedInfo> convert_order_info(
|
||||
}
|
||||
return make_tl_object<telegram_api::paymentRequestedInfo>(
|
||||
flags, std::move(order_info->name_), std::move(order_info->phone_number_), std::move(order_info->email_address_),
|
||||
convert_shipping_address(std::move(order_info->shipping_address_)));
|
||||
convert_address(std::move(order_info->shipping_address_)));
|
||||
}
|
||||
|
||||
static tl_object_ptr<td_api::savedCredentials> convert_saved_credentials(
|
||||
@ -525,41 +523,141 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Invoice &invoice)
|
||||
<< invoice.currency << " with price parts " << format::as_array(invoice.price_parts) << "]";
|
||||
}
|
||||
|
||||
bool operator==(const ShippingAddress &lhs, const ShippingAddress &rhs) {
|
||||
bool operator==(const Address &lhs, const Address &rhs) {
|
||||
return lhs.country_code == rhs.country_code && lhs.state == rhs.state && lhs.city == rhs.city &&
|
||||
lhs.street_line1 == rhs.street_line1 && lhs.street_line2 == rhs.street_line2 &&
|
||||
lhs.postal_code == rhs.postal_code;
|
||||
}
|
||||
|
||||
bool operator!=(const ShippingAddress &lhs, const ShippingAddress &rhs) {
|
||||
bool operator!=(const Address &lhs, const Address &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const ShippingAddress &shipping_address) {
|
||||
return string_builder << "[Address " << tag("country_code", shipping_address.country_code)
|
||||
<< tag("state", shipping_address.state) << tag("city", shipping_address.city)
|
||||
<< tag("street_line1", shipping_address.street_line1)
|
||||
<< tag("street_line2", shipping_address.street_line2)
|
||||
<< tag("postal_code", shipping_address.postal_code) << "]";
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const Address &address) {
|
||||
return string_builder << "[Address " << tag("country_code", address.country_code) << tag("state", address.state)
|
||||
<< tag("city", address.city) << tag("street_line1", address.street_line1)
|
||||
<< tag("street_line2", address.street_line2) << tag("postal_code", address.postal_code) << "]";
|
||||
}
|
||||
|
||||
unique_ptr<ShippingAddress> get_shipping_address(tl_object_ptr<telegram_api::postAddress> address) {
|
||||
unique_ptr<Address> get_address(tl_object_ptr<telegram_api::postAddress> &&address) {
|
||||
if (address == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return make_unique<ShippingAddress>(std::move(address->country_iso2_), std::move(address->state_),
|
||||
std::move(address->city_), std::move(address->street_line1_),
|
||||
std::move(address->street_line2_), std::move(address->post_code_));
|
||||
return make_unique<Address>(std::move(address->country_iso2_), std::move(address->state_), std::move(address->city_),
|
||||
std::move(address->street_line1_), std::move(address->street_line2_),
|
||||
std::move(address->post_code_));
|
||||
}
|
||||
|
||||
tl_object_ptr<td_api::shippingAddress> get_shipping_address_object(
|
||||
const unique_ptr<ShippingAddress> &shipping_address) {
|
||||
if (shipping_address == nullptr) {
|
||||
static bool is_capital_alpha(char c) {
|
||||
return 'A' <= c && c <= 'Z';
|
||||
}
|
||||
|
||||
Status check_country_code(string &country_code) {
|
||||
if (!clean_input_string(country_code)) {
|
||||
return Status::Error(400, "Country code must be encoded in UTF-8");
|
||||
}
|
||||
if (country_code.size() != 2 || !is_capital_alpha(country_code[0]) || !is_capital_alpha(country_code[1])) {
|
||||
return Status::Error(400, "Wrong country code specified");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Status check_state(string &state) {
|
||||
if (!clean_input_string(state)) {
|
||||
return Status::Error(400, "State must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Status check_city(string &city) {
|
||||
if (!clean_input_string(city)) {
|
||||
return Status::Error(400, "City must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Status check_street_line(string &street_line) {
|
||||
if (!clean_input_string(street_line)) {
|
||||
return Status::Error(400, "Street line must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Status check_postal_code(string &postal_code) {
|
||||
if (!clean_input_string(postal_code)) {
|
||||
return Status::Error(400, "Postal code must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Result<Address> get_address(td_api::object_ptr<td_api::address> &&address) {
|
||||
if (address == nullptr) {
|
||||
return Status::Error(400, "Address must not be empty");
|
||||
}
|
||||
TRY_STATUS(check_country_code(address->country_code_));
|
||||
TRY_STATUS(check_state(address->state_));
|
||||
TRY_STATUS(check_city(address->city_));
|
||||
TRY_STATUS(check_street_line(address->street_line1_));
|
||||
TRY_STATUS(check_street_line(address->street_line2_));
|
||||
TRY_STATUS(check_postal_code(address->postal_code_));
|
||||
|
||||
return Address(std::move(address->country_code_), std::move(address->state_), std::move(address->city_),
|
||||
std::move(address->street_line1_), std::move(address->street_line2_),
|
||||
std::move(address->postal_code_));
|
||||
}
|
||||
|
||||
tl_object_ptr<td_api::address> get_address_object(const unique_ptr<Address> &address) {
|
||||
if (address == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return make_tl_object<td_api::shippingAddress>(shipping_address->country_code, shipping_address->state,
|
||||
shipping_address->city, shipping_address->street_line1,
|
||||
shipping_address->street_line2, shipping_address->postal_code);
|
||||
return get_address_object(*address);
|
||||
}
|
||||
|
||||
tl_object_ptr<td_api::address> get_address_object(const Address &address) {
|
||||
return make_tl_object<td_api::address>(address.country_code, address.state, address.city, address.street_line1,
|
||||
address.street_line2, address.postal_code);
|
||||
}
|
||||
|
||||
string address_to_json(const Address &address) {
|
||||
return json_encode<std::string>(json_object([&](auto &o) {
|
||||
o("country_code", address.country_code);
|
||||
o("state", address.state);
|
||||
o("city", address.city);
|
||||
o("street_line1", address.street_line1);
|
||||
o("street_line2", address.street_line2);
|
||||
o("postal_code", address.postal_code);
|
||||
}));
|
||||
}
|
||||
|
||||
Result<Address> address_from_json(Slice json) {
|
||||
auto json_copy = json.str();
|
||||
auto r_value = json_decode(json_copy);
|
||||
if (r_value.is_error()) {
|
||||
return Status::Error(400, "Can't parse address JSON object");
|
||||
}
|
||||
|
||||
auto value = r_value.move_as_ok();
|
||||
if (value.type() != JsonValue::Type::Object) {
|
||||
return Status::Error(400, "Address should be an Object");
|
||||
}
|
||||
|
||||
auto &object = value.get_object();
|
||||
TRY_RESULT(country_code, get_json_object_string_field(object, "country_code", true));
|
||||
TRY_RESULT(state, get_json_object_string_field(object, "state", true));
|
||||
TRY_RESULT(city, get_json_object_string_field(object, "city", true));
|
||||
TRY_RESULT(street_line1, get_json_object_string_field(object, "street_line1", true));
|
||||
TRY_RESULT(street_line2, get_json_object_string_field(object, "street_line2", true));
|
||||
TRY_RESULT(postal_code, get_json_object_string_field(object, "postal_code", true));
|
||||
|
||||
TRY_STATUS(check_country_code(country_code));
|
||||
TRY_STATUS(check_state(state));
|
||||
TRY_STATUS(check_city(city));
|
||||
TRY_STATUS(check_street_line(street_line1));
|
||||
TRY_STATUS(check_street_line(street_line2));
|
||||
TRY_STATUS(check_postal_code(postal_code));
|
||||
|
||||
return Address(std::move(country_code), std::move(state), std::move(city), std::move(street_line1),
|
||||
std::move(street_line2), std::move(postal_code));
|
||||
}
|
||||
|
||||
bool operator==(const OrderInfo &lhs, const OrderInfo &rhs) {
|
||||
@ -587,8 +685,7 @@ unique_ptr<OrderInfo> get_order_info(tl_object_ptr<telegram_api::paymentRequeste
|
||||
return nullptr;
|
||||
}
|
||||
return make_unique<OrderInfo>(std::move(order_info->name_), std::move(order_info->phone_),
|
||||
std::move(order_info->email_),
|
||||
get_shipping_address(std::move(order_info->shipping_address_)));
|
||||
std::move(order_info->email_), get_address(std::move(order_info->shipping_address_)));
|
||||
}
|
||||
|
||||
tl_object_ptr<td_api::orderInfo> get_order_info_object(const unique_ptr<OrderInfo> &order_info) {
|
||||
@ -596,7 +693,7 @@ tl_object_ptr<td_api::orderInfo> get_order_info_object(const unique_ptr<OrderInf
|
||||
return nullptr;
|
||||
}
|
||||
return make_tl_object<td_api::orderInfo>(order_info->name, order_info->phone_number, order_info->email_address,
|
||||
get_shipping_address_object(order_info->shipping_address));
|
||||
get_address_object(order_info->shipping_address));
|
||||
}
|
||||
|
||||
bool operator==(const ShippingOption &lhs, const ShippingOption &rhs) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "td/telegram/Photo.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
@ -46,7 +47,7 @@ struct Invoice {
|
||||
}
|
||||
};
|
||||
|
||||
struct ShippingAddress {
|
||||
struct Address {
|
||||
string country_code;
|
||||
string state;
|
||||
string city;
|
||||
@ -54,8 +55,8 @@ struct ShippingAddress {
|
||||
string street_line2;
|
||||
string postal_code;
|
||||
|
||||
ShippingAddress() = default;
|
||||
ShippingAddress(string &&country_code, string &&state, string &&city, string &&street_line1, string &&street_line2,
|
||||
Address() = default;
|
||||
Address(string &&country_code, string &&state, string &&city, string &&street_line1, string &&street_line2,
|
||||
string &&postal_code)
|
||||
: country_code(std::move(country_code))
|
||||
, state(std::move(state))
|
||||
@ -70,11 +71,10 @@ struct OrderInfo {
|
||||
string name;
|
||||
string phone_number;
|
||||
string email_address;
|
||||
unique_ptr<ShippingAddress> shipping_address;
|
||||
unique_ptr<Address> shipping_address;
|
||||
|
||||
OrderInfo() = default;
|
||||
OrderInfo(string &&name, string &&phone_number, string &&email_address,
|
||||
unique_ptr<ShippingAddress> &&shipping_address)
|
||||
OrderInfo(string &&name, string &&phone_number, string &&email_address, unique_ptr<Address> &&shipping_address)
|
||||
: name(std::move(name))
|
||||
, phone_number(std::move(phone_number))
|
||||
, email_address(std::move(email_address))
|
||||
@ -98,14 +98,24 @@ bool operator!=(const Invoice &lhs, const Invoice &rhs);
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const Invoice &invoice);
|
||||
|
||||
bool operator==(const ShippingAddress &lhs, const ShippingAddress &rhs);
|
||||
bool operator!=(const ShippingAddress &lhs, const ShippingAddress &rhs);
|
||||
bool operator==(const Address &lhs, const Address &rhs);
|
||||
bool operator!=(const Address &lhs, const Address &rhs);
|
||||
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const ShippingAddress &shipping_address);
|
||||
StringBuilder &operator<<(StringBuilder &string_builder, const Address &address);
|
||||
|
||||
unique_ptr<ShippingAddress> get_shipping_address(tl_object_ptr<telegram_api::postAddress> address);
|
||||
unique_ptr<Address> get_address(tl_object_ptr<telegram_api::postAddress> &&address);
|
||||
|
||||
tl_object_ptr<td_api::shippingAddress> get_shipping_address_object(const unique_ptr<ShippingAddress> &shipping_address);
|
||||
Result<Address> get_address(td_api::object_ptr<td_api::address> &&address);
|
||||
|
||||
tl_object_ptr<td_api::address> get_address_object(const unique_ptr<Address> &address);
|
||||
|
||||
tl_object_ptr<td_api::address> get_address_object(const Address &address);
|
||||
|
||||
string address_to_json(const Address &address);
|
||||
|
||||
Result<Address> address_from_json(Slice json);
|
||||
|
||||
Status check_country_code(string &country_code);
|
||||
|
||||
bool operator==(const OrderInfo &lhs, const OrderInfo &rhs);
|
||||
bool operator!=(const OrderInfo &lhs, const OrderInfo &rhs);
|
||||
|
@ -59,23 +59,23 @@ void parse(Invoice &invoice, ParserT &parser) {
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
void store(const ShippingAddress &shipping_address, StorerT &storer) {
|
||||
store(shipping_address.country_code, storer);
|
||||
store(shipping_address.state, storer);
|
||||
store(shipping_address.city, storer);
|
||||
store(shipping_address.street_line1, storer);
|
||||
store(shipping_address.street_line2, storer);
|
||||
store(shipping_address.postal_code, storer);
|
||||
void store(const Address &address, StorerT &storer) {
|
||||
store(address.country_code, storer);
|
||||
store(address.state, storer);
|
||||
store(address.city, storer);
|
||||
store(address.street_line1, storer);
|
||||
store(address.street_line2, storer);
|
||||
store(address.postal_code, storer);
|
||||
}
|
||||
|
||||
template <class ParserT>
|
||||
void parse(ShippingAddress &shipping_address, ParserT &parser) {
|
||||
parse(shipping_address.country_code, parser);
|
||||
parse(shipping_address.state, parser);
|
||||
parse(shipping_address.city, parser);
|
||||
parse(shipping_address.street_line1, parser);
|
||||
parse(shipping_address.street_line2, parser);
|
||||
parse(shipping_address.postal_code, parser);
|
||||
void parse(Address &address, ParserT &parser) {
|
||||
parse(address.country_code, parser);
|
||||
parse(address.state, parser);
|
||||
parse(address.city, parser);
|
||||
parse(address.street_line1, parser);
|
||||
parse(address.street_line2, parser);
|
||||
parse(address.postal_code, parser);
|
||||
}
|
||||
|
||||
template <class StorerT>
|
||||
@ -126,7 +126,7 @@ void parse(OrderInfo &order_info, ParserT &parser) {
|
||||
parse(order_info.email_address, parser);
|
||||
}
|
||||
if (has_shipping_address) {
|
||||
order_info.shipping_address = make_unique<ShippingAddress>();
|
||||
order_info.shipping_address = make_unique<Address>();
|
||||
parse(*order_info.shipping_address, parser);
|
||||
}
|
||||
}
|
||||
|
@ -386,28 +386,28 @@ class GetPassportAuthorizationForm : public NetQueryCallback {
|
||||
std::vector<TdApiSecureValue> values;
|
||||
auto types = get_secure_value_types(std::move(authorization_form_->required_types_));
|
||||
for (auto type : types) {
|
||||
optional<EncryptedSecureValue> encrypted_secure_value;
|
||||
for (auto &value : authorization_form_->values_) {
|
||||
auto value_type = get_secure_value_type(std::move(value->type_));
|
||||
if (value_type != type) {
|
||||
continue;
|
||||
}
|
||||
encrypted_secure_value = get_encrypted_secure_value(file_manager, std::move(value));
|
||||
|
||||
auto r_secure_value = decrypt_encrypted_secure_value(
|
||||
file_manager, *secret_, get_encrypted_secure_value(file_manager, std::move(value)));
|
||||
if (r_secure_value.is_error()) {
|
||||
LOG(ERROR) << "Failed to decrypt secure value: " << r_secure_value.error();
|
||||
break;
|
||||
}
|
||||
|
||||
SecureValue secure_value;
|
||||
secure_value.type = type;
|
||||
if (encrypted_secure_value) {
|
||||
auto r_secure_value =
|
||||
decrypt_encrypted_secure_value(file_manager, *secret_, std::move(*encrypted_secure_value));
|
||||
if (r_secure_value.is_ok()) {
|
||||
secure_value = r_secure_value.move_as_ok().value;
|
||||
} else {
|
||||
LOG(ERROR) << "Failed to decrypt secure value: " << r_secure_value.error();
|
||||
auto r_passport_data = get_passport_data_object(file_manager, std::move(r_secure_value.move_as_ok().value));
|
||||
if (r_passport_data.is_error()) {
|
||||
LOG(ERROR) << "Failed to get passport data object: " << r_passport_data.error();
|
||||
break;
|
||||
}
|
||||
|
||||
values.push_back(r_passport_data.move_as_ok());
|
||||
break;
|
||||
}
|
||||
values.push_back(get_passport_data_object(file_manager, std::move(secure_value)));
|
||||
}
|
||||
promise_.set_value(make_tl_object<td_api::passportAuthorizationForm>(authorization_form_id_, std::move(values),
|
||||
authorization_form_->selfie_required_,
|
||||
@ -426,7 +426,12 @@ void SecureManager::get_secure_value(std::string password, SecureValueType type,
|
||||
return promise.set_error(r_secure_value.move_as_error());
|
||||
}
|
||||
auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get();
|
||||
promise.set_value(get_passport_data_object(file_manager, r_secure_value.move_as_ok().value));
|
||||
auto r_passport_data = get_passport_data_object(file_manager, r_secure_value.move_as_ok().value);
|
||||
if (r_passport_data.is_error()) {
|
||||
LOG(ERROR) << "Failed to get passport data object: " << r_passport_data.error();
|
||||
return promise.set_value(nullptr);
|
||||
}
|
||||
promise.set_value(r_passport_data.move_as_ok());
|
||||
});
|
||||
do_get_secure_value(std::move(password), type, std::move(new_promise));
|
||||
}
|
||||
@ -453,7 +458,12 @@ void SecureManager::set_secure_value(string password, SecureValue secure_value,
|
||||
return promise.set_error(r_secure_value.move_as_error());
|
||||
}
|
||||
auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get();
|
||||
promise.set_value(get_passport_data_object(file_manager, r_secure_value.move_as_ok().value));
|
||||
auto r_passport_data = get_passport_data_object(file_manager, r_secure_value.move_as_ok().value);
|
||||
if (r_passport_data.is_error()) {
|
||||
LOG(ERROR) << "Failed to get passport data object: " << r_passport_data.error();
|
||||
return promise.set_error(Status::Error(500, "Failed to get passport data object"));
|
||||
}
|
||||
promise.set_value(r_passport_data.move_as_ok());
|
||||
});
|
||||
set_secure_value_queries_[type] = create_actor<SetSecureValue>("SetSecureValue", actor_shared(), std::move(password),
|
||||
std::move(secure_value), std::move(new_promise));
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
namespace td {
|
||||
|
||||
using TdApiSecureValue = td_api::object_ptr<td_api::passportData>;
|
||||
using TdApiSecureValue = td_api::object_ptr<td_api::PassportData>;
|
||||
using TdApiAllSecureValues = td_api::object_ptr<td_api::allPassportData>;
|
||||
using TdApiAuthorizationForm = td_api::object_ptr<td_api::passportAuthorizationForm>;
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/files/FileManager.h"
|
||||
#include "td/telegram/misc.h"
|
||||
#include "td/telegram/Payments.h"
|
||||
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
@ -392,45 +394,360 @@ td_api::object_ptr<td_api::encryptedCredentials> get_encrypted_credentials_objec
|
||||
credentials.encrypted_secret);
|
||||
}
|
||||
|
||||
Result<SecureValue> get_secure_value(FileManager *file_manager,
|
||||
td_api::object_ptr<td_api::inputPassportData> &&input_passport_data) {
|
||||
if (input_passport_data == nullptr) {
|
||||
return Status::Error(400, "InputPassportData must not be empty");
|
||||
static string lpad0(string str, size_t size) {
|
||||
if (str.size() >= size) {
|
||||
return str;
|
||||
}
|
||||
return string(size - str.size(), '0') + str;
|
||||
}
|
||||
|
||||
SecureValue res;
|
||||
res.type = get_secure_value_type_td_api(std::move(input_passport_data->type_));
|
||||
res.data = std::move(input_passport_data->data_);
|
||||
for (auto &file : input_passport_data->files_) {
|
||||
TRY_RESULT(file_id, file_manager->get_input_file_id(FileType::Secure, std::move(file), DialogId(), false, false,
|
||||
false, true));
|
||||
res.files.push_back(file_id);
|
||||
// TODO tests
|
||||
static Status check_date(int32 day, int32 month, int32 year) {
|
||||
if (day < 1 || day > 31) {
|
||||
return Status::Error(400, "Wrong day number specified");
|
||||
}
|
||||
if (input_passport_data->selfie_) {
|
||||
TRY_RESULT(file_id, file_manager->get_input_file_id(FileType::Secure, std::move(input_passport_data->selfie_),
|
||||
DialogId(), false, false, false, true));
|
||||
if (month < 1 || month > 12) {
|
||||
return Status::Error(400, "Wrong month number specified");
|
||||
}
|
||||
if (year < 1 || year > 9999) {
|
||||
return Status::Error(400, "Wrong year number specified");
|
||||
}
|
||||
|
||||
bool is_leap = month == 2 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
|
||||
const int32 days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
if (day > days_in_month[month - 1] + static_cast<int32>(is_leap)) {
|
||||
return Status::Error(400, "Wrong day in month number specified");
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Result<string> get_date(td_api::object_ptr<td_api::date> &&date) {
|
||||
if (date == nullptr) {
|
||||
return Status::Error(400, "Date must not be empty");
|
||||
}
|
||||
TRY_STATUS(check_date(date->day_, date->month_, date->year_));
|
||||
|
||||
return PSTRING() << lpad0(to_string(date->day_), 2) << '.' << lpad0(to_string(date->month_), 2) << '.'
|
||||
<< lpad0(to_string(date->year_), 4);
|
||||
}
|
||||
|
||||
static Result<td_api::object_ptr<td_api::date>> get_date_object(Slice date) {
|
||||
if (date.size() != 10u) {
|
||||
return Status::Error(400, "Date has wrong size");
|
||||
}
|
||||
auto parts = full_split(date, '.');
|
||||
if (parts.size() != 3 || parts[0].size() != 2 || parts[1].size() != 2 || parts[2].size() != 4) {
|
||||
return Status::Error(400, "Date has wrong parts");
|
||||
}
|
||||
TRY_RESULT(day, to_integer_safe<int32>(parts[0]));
|
||||
TRY_RESULT(month, to_integer_safe<int32>(parts[1]));
|
||||
TRY_RESULT(year, to_integer_safe<int32>(parts[2]));
|
||||
TRY_STATUS(check_date(day, month, year));
|
||||
|
||||
return td_api::make_object<td_api::date>(day, month, year);
|
||||
}
|
||||
|
||||
static Status check_first_name(string &first_name) {
|
||||
if (!clean_input_string(first_name)) {
|
||||
return Status::Error(400, "First name must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Status check_last_name(string &last_name) {
|
||||
if (!clean_input_string(last_name)) {
|
||||
return Status::Error(400, "Last name must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Status check_gender(string &gender) {
|
||||
if (gender != "male" && gender != "female") {
|
||||
return Status::Error(400, "Unsupported gender specified");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Result<string> get_personal_details(td_api::object_ptr<td_api::personalDetails> &&personal_details) {
|
||||
if (personal_details == nullptr) {
|
||||
return Status::Error(400, "Personal details must not be empty");
|
||||
}
|
||||
TRY_STATUS(check_first_name(personal_details->first_name_));
|
||||
TRY_STATUS(check_last_name(personal_details->last_name_));
|
||||
TRY_RESULT(birthdate, get_date(std::move(personal_details->birthdate_)));
|
||||
TRY_STATUS(check_gender(personal_details->gender_));
|
||||
TRY_STATUS(check_country_code(personal_details->country_code_));
|
||||
|
||||
return json_encode<std::string>(json_object([&](auto &o) {
|
||||
o("first_name", personal_details->first_name_);
|
||||
o("last_name", personal_details->last_name_);
|
||||
o("birth_date", birthdate);
|
||||
o("gender", personal_details->gender_);
|
||||
o("country_code", personal_details->country_code_);
|
||||
}));
|
||||
}
|
||||
|
||||
static Result<td_api::object_ptr<td_api::personalDetails>> get_personal_details_object(Slice personal_details) {
|
||||
auto personal_details_copy = personal_details.str();
|
||||
auto r_value = json_decode(personal_details_copy);
|
||||
if (r_value.is_error()) {
|
||||
return Status::Error(400, "Can't parse personal details JSON object");
|
||||
}
|
||||
|
||||
auto value = r_value.move_as_ok();
|
||||
if (value.type() != JsonValue::Type::Object) {
|
||||
return Status::Error(400, "Personal details should be an Object");
|
||||
}
|
||||
|
||||
auto &object = value.get_object();
|
||||
TRY_RESULT(first_name, get_json_object_string_field(object, "first_name", true));
|
||||
TRY_RESULT(last_name, get_json_object_string_field(object, "last_name", true));
|
||||
TRY_RESULT(birthdate, get_json_object_string_field(object, "birth_date", true));
|
||||
TRY_RESULT(gender, get_json_object_string_field(object, "gender", true));
|
||||
TRY_RESULT(country_code, get_json_object_string_field(object, "country_code", true));
|
||||
|
||||
TRY_STATUS(check_first_name(first_name));
|
||||
TRY_STATUS(check_last_name(last_name));
|
||||
TRY_RESULT(date, get_date_object(birthdate));
|
||||
TRY_STATUS(check_gender(gender));
|
||||
TRY_STATUS(check_country_code(country_code));
|
||||
|
||||
return td_api::make_object<td_api::personalDetails>(std::move(first_name), std::move(last_name), std::move(date),
|
||||
std::move(gender), std::move(country_code));
|
||||
}
|
||||
|
||||
static Status check_document_number(string &number) {
|
||||
if (!clean_input_string(number)) {
|
||||
return Status::Error(400, "Document number must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Result<FileId> get_secure_file(FileManager *file_manager, td_api::object_ptr<td_api::InputFile> &&file) {
|
||||
return file_manager->get_input_file_id(FileType::Secure, std::move(file), DialogId(), false, false, false, true);
|
||||
}
|
||||
|
||||
static Result<vector<FileId>> get_secure_files(FileManager *file_manager,
|
||||
vector<td_api::object_ptr<td_api::InputFile>> &&files) {
|
||||
vector<FileId> result;
|
||||
for (auto &file : files) {
|
||||
TRY_RESULT(file_id, get_secure_file(file_manager, std::move(file)));
|
||||
result.push_back(file_id);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static Result<SecureValue> get_identity_document(
|
||||
SecureValueType type, FileManager *file_manager,
|
||||
td_api::object_ptr<td_api::inputIdentityDocument> &&identity_document) {
|
||||
if (identity_document == nullptr) {
|
||||
return Status::Error(400, "Identity document must not be empty");
|
||||
}
|
||||
TRY_STATUS(check_document_number(identity_document->number_));
|
||||
TRY_RESULT(date, get_date(std::move(identity_document->expiry_date_)));
|
||||
TRY_RESULT(files, get_secure_files(file_manager, std::move(identity_document->files_)));
|
||||
|
||||
SecureValue res;
|
||||
res.type = type;
|
||||
res.data = json_encode<std::string>(json_object([&](auto &o) {
|
||||
o("document_no", identity_document->number_);
|
||||
o("expiry_date", date);
|
||||
}));
|
||||
|
||||
res.files = std::move(files);
|
||||
if (identity_document->selfie_ != nullptr) {
|
||||
TRY_RESULT(file_id, get_secure_file(file_manager, std::move(identity_document->selfie_)));
|
||||
res.selfie = file_id;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::passportData> get_passport_data_object(FileManager *file_manager, const SecureValue &value) {
|
||||
std::vector<td_api::object_ptr<td_api::file>> files;
|
||||
files = transform(value.files, [&](FileId id) { return file_manager->get_file_object(id, true); });
|
||||
static Result<td_api::object_ptr<td_api::identityDocument>> get_identity_document_object(FileManager *file_manager,
|
||||
const SecureValue &value) {
|
||||
auto files = transform(value.files, [file_manager](FileId id) { return file_manager->get_file_object(id); });
|
||||
|
||||
td_api::object_ptr<td_api::file> selfie;
|
||||
if (value.selfie.is_valid()) {
|
||||
selfie = file_manager->get_file_object(value.selfie, true);
|
||||
selfie = file_manager->get_file_object(value.selfie);
|
||||
}
|
||||
|
||||
return td_api::make_object<td_api::passportData>(get_passport_data_type_object(value.type), value.data,
|
||||
std::move(files), std::move(selfie));
|
||||
auto data_copy = value.data;
|
||||
auto r_value = json_decode(data_copy);
|
||||
if (r_value.is_error()) {
|
||||
return Status::Error(400, "Can't parse identity document JSON object");
|
||||
}
|
||||
|
||||
auto json_value = r_value.move_as_ok();
|
||||
if (json_value.type() != JsonValue::Type::Object) {
|
||||
return Status::Error(400, "Identity document should be an Object");
|
||||
}
|
||||
|
||||
auto &object = json_value.get_object();
|
||||
TRY_RESULT(number, get_json_object_string_field(object, "document_no", true));
|
||||
TRY_RESULT(expiry_date, get_json_object_string_field(object, "expiry_date", true));
|
||||
|
||||
TRY_STATUS(check_document_number(number));
|
||||
TRY_RESULT(date, get_date_object(expiry_date));
|
||||
|
||||
return td_api::make_object<td_api::identityDocument>(std::move(number), std::move(date), std::move(files),
|
||||
std::move(selfie));
|
||||
}
|
||||
|
||||
static Status check_phone_number(string &phone_number) {
|
||||
if (!clean_input_string(phone_number)) {
|
||||
return Status::Error(400, "Phone number must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
static Status check_email_address(string &email_address) {
|
||||
if (!clean_input_string(email_address)) {
|
||||
return Status::Error(400, "Email address must be encoded in UTF-8");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Result<SecureValue> get_secure_value(FileManager *file_manager,
|
||||
td_api::object_ptr<td_api::InputPassportData> &&input_passport_data) {
|
||||
if (input_passport_data == nullptr) {
|
||||
return Status::Error(400, "InputPassportData must not be empty");
|
||||
}
|
||||
|
||||
SecureValue res;
|
||||
switch (input_passport_data->get_id()) {
|
||||
case td_api::inputPassportDataPersonalDetails::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataPersonalDetails>(input_passport_data);
|
||||
res.type = SecureValueType::PersonalDetails;
|
||||
TRY_RESULT(personal_details, get_personal_details(std::move(input->personal_details_)));
|
||||
res.data = std::move(personal_details);
|
||||
break;
|
||||
}
|
||||
case td_api::inputPassportDataPassport::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataPassport>(input_passport_data);
|
||||
return get_identity_document(SecureValueType::Passport, file_manager, std::move(input->passport_));
|
||||
}
|
||||
case td_api::inputPassportDataDriverLicense::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataDriverLicense>(input_passport_data);
|
||||
return get_identity_document(SecureValueType::DriverLicense, file_manager, std::move(input->driver_license_));
|
||||
}
|
||||
case td_api::inputPassportDataIdentityCard::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataIdentityCard>(input_passport_data);
|
||||
return get_identity_document(SecureValueType::IdentityCard, file_manager, std::move(input->identity_card_));
|
||||
}
|
||||
case td_api::inputPassportDataAddress::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataAddress>(input_passport_data);
|
||||
res.type = SecureValueType::Address;
|
||||
TRY_RESULT(address, get_address(std::move(input->address_)));
|
||||
res.data = address_to_json(address);
|
||||
break;
|
||||
}
|
||||
case td_api::inputPassportDataUtilityBill::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataUtilityBill>(input_passport_data);
|
||||
res.type = SecureValueType::UtilityBill;
|
||||
TRY_RESULT(files, get_secure_files(file_manager, std::move(input->files_)));
|
||||
res.files = std::move(files);
|
||||
break;
|
||||
}
|
||||
case td_api::inputPassportDataBankStatement::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataBankStatement>(input_passport_data);
|
||||
res.type = SecureValueType::BankStatement;
|
||||
TRY_RESULT(files, get_secure_files(file_manager, std::move(input->files_)));
|
||||
res.files = std::move(files);
|
||||
break;
|
||||
}
|
||||
case td_api::inputPassportDataRentalAgreement::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataRentalAgreement>(input_passport_data);
|
||||
res.type = SecureValueType::RentalAgreement;
|
||||
TRY_RESULT(files, get_secure_files(file_manager, std::move(input->files_)));
|
||||
res.files = std::move(files);
|
||||
break;
|
||||
}
|
||||
case td_api::inputPassportDataPhoneNumber::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataPhoneNumber>(input_passport_data);
|
||||
res.type = SecureValueType::PhoneNumber;
|
||||
TRY_STATUS(check_phone_number(input->phone_number_));
|
||||
res.data = std::move(input->phone_number_);
|
||||
break;
|
||||
}
|
||||
case td_api::inputPassportDataEmailAddress::ID: {
|
||||
auto input = td_api::move_object_as<td_api::inputPassportDataEmailAddress>(input_passport_data);
|
||||
res.type = SecureValueType::EmailAddress;
|
||||
TRY_STATUS(check_email_address(input->email_address_));
|
||||
res.data = std::move(input->email_address_);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<td_api::object_ptr<td_api::PassportData>> get_passport_data_object(FileManager *file_manager,
|
||||
const SecureValue &value) {
|
||||
switch (value.type) {
|
||||
case SecureValueType::PersonalDetails: {
|
||||
TRY_RESULT(personal_details, get_personal_details_object(value.data));
|
||||
return td_api::make_object<td_api::passportDataPersonalDetails>(std::move(personal_details));
|
||||
}
|
||||
case SecureValueType::Passport: {
|
||||
TRY_RESULT(passport, get_identity_document_object(file_manager, value));
|
||||
return td_api::make_object<td_api::passportDataPassport>(std::move(passport));
|
||||
}
|
||||
case SecureValueType::DriverLicense: {
|
||||
TRY_RESULT(driver_license, get_identity_document_object(file_manager, value));
|
||||
return td_api::make_object<td_api::passportDataDriverLicense>(std::move(driver_license));
|
||||
}
|
||||
case SecureValueType::IdentityCard: {
|
||||
TRY_RESULT(identity_card, get_identity_document_object(file_manager, value));
|
||||
return td_api::make_object<td_api::passportDataIdentityCard>(std::move(identity_card));
|
||||
}
|
||||
case SecureValueType::Address: {
|
||||
TRY_RESULT(address, address_from_json(value.data));
|
||||
return td_api::make_object<td_api::passportDataAddress>(get_address_object(address));
|
||||
}
|
||||
case SecureValueType::UtilityBill:
|
||||
case SecureValueType::BankStatement:
|
||||
case SecureValueType::RentalAgreement: {
|
||||
auto files = transform(value.files, [file_manager](FileId id) { return file_manager->get_file_object(id); });
|
||||
if (value.type == SecureValueType::UtilityBill) {
|
||||
return td_api::make_object<td_api::passportDataUtilityBill>(std::move(files));
|
||||
}
|
||||
if (value.type == SecureValueType::BankStatement) {
|
||||
return td_api::make_object<td_api::passportDataBankStatement>(std::move(files));
|
||||
}
|
||||
if (value.type == SecureValueType::RentalAgreement) {
|
||||
return td_api::make_object<td_api::passportDataRentalAgreement>(std::move(files));
|
||||
}
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
case SecureValueType::PhoneNumber:
|
||||
return td_api::make_object<td_api::passportDataPhoneNumber>(value.data);
|
||||
case SecureValueType::EmailAddress:
|
||||
return td_api::make_object<td_api::passportDataEmailAddress>(value.data);
|
||||
case SecureValueType::None:
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Status::Error(400, "Wrong value type");
|
||||
}
|
||||
}
|
||||
|
||||
td_api::object_ptr<td_api::allPassportData> get_all_passport_data_object(FileManager *file_manager,
|
||||
const vector<SecureValue> &value) {
|
||||
return td_api::make_object<td_api::allPassportData>(transform(
|
||||
value, [file_manager](const SecureValue &value) { return get_passport_data_object(file_manager, value); }));
|
||||
const vector<SecureValue> &values) {
|
||||
vector<td_api::object_ptr<td_api::PassportData>> result;
|
||||
result.reserve(values.size());
|
||||
for (auto &value : values) {
|
||||
auto r_obj = get_passport_data_object(file_manager, value);
|
||||
if (r_obj.is_error()) {
|
||||
LOG(ERROR) << "Can't get passport data object: " << r_obj.error();
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push_back(r_obj.move_as_ok());
|
||||
}
|
||||
|
||||
return td_api::make_object<td_api::allPassportData>(std::move(result));
|
||||
}
|
||||
|
||||
Result<std::pair<FileId, SecureFileCredentials>> decrypt_secure_file(FileManager *file_manager,
|
||||
@ -588,21 +905,21 @@ EncryptedSecureValue encrypt_secure_value(FileManager *file_manager, const secur
|
||||
return res;
|
||||
}
|
||||
|
||||
auto as_jsonable(const SecureDataCredentials &credentials) {
|
||||
static auto as_jsonable(const SecureDataCredentials &credentials) {
|
||||
return json_object([&credentials](auto &o) {
|
||||
o("data_hash", base64_encode(credentials.hash));
|
||||
o("secret", base64_encode(credentials.secret));
|
||||
});
|
||||
}
|
||||
|
||||
auto as_jsonable(const SecureFileCredentials &credentials) {
|
||||
static auto as_jsonable(const SecureFileCredentials &credentials) {
|
||||
return json_object([&credentials](auto &o) {
|
||||
o("file_hash", base64_encode(credentials.hash));
|
||||
o("secret", base64_encode(credentials.secret));
|
||||
});
|
||||
}
|
||||
|
||||
auto as_jsonable(const vector<SecureFileCredentials> &files) {
|
||||
static auto as_jsonable(const vector<SecureFileCredentials> &files) {
|
||||
return json_array([&files](auto &arr) {
|
||||
for (auto &file : files) {
|
||||
arr(as_jsonable(file));
|
||||
@ -610,7 +927,7 @@ auto as_jsonable(const vector<SecureFileCredentials> &files) {
|
||||
});
|
||||
}
|
||||
|
||||
Slice secure_value_type_as_slice(SecureValueType type) {
|
||||
static Slice secure_value_type_as_slice(SecureValueType type) {
|
||||
switch (type) {
|
||||
case SecureValueType::PersonalDetails:
|
||||
return Slice("personal_details");
|
||||
@ -629,7 +946,7 @@ Slice secure_value_type_as_slice(SecureValueType type) {
|
||||
case SecureValueType::RentalAgreement:
|
||||
return Slice("rental_agreement");
|
||||
case SecureValueType::PhoneNumber:
|
||||
return Slice("phone");
|
||||
return Slice("phone_number");
|
||||
case SecureValueType::EmailAddress:
|
||||
return Slice("email");
|
||||
default:
|
||||
@ -639,10 +956,14 @@ Slice secure_value_type_as_slice(SecureValueType type) {
|
||||
}
|
||||
}
|
||||
|
||||
auto credentials_as_jsonable(std::vector<SecureValueCredentials> &credentials, Slice payload) {
|
||||
static auto credentials_as_jsonable(std::vector<SecureValueCredentials> &credentials, Slice payload) {
|
||||
return json_object([&credentials, &payload](auto &o) {
|
||||
o("secure_data", json_object([&credentials](auto &o) {
|
||||
for (auto &c : credentials) {
|
||||
if (c.type == SecureValueType::PhoneNumber || c.type == SecureValueType::EmailAddress) {
|
||||
continue;
|
||||
}
|
||||
|
||||
o(secure_value_type_as_slice(c.type), json_object([&credentials = c](auto &o) {
|
||||
if (credentials.data) {
|
||||
o("data", as_jsonable(credentials.data.value()));
|
||||
@ -673,4 +994,5 @@ Result<EncryptedSecureCredentials> encrypted_credentials(std::vector<SecureValue
|
||||
res.encrypted_secret = encrypted_secret.as_slice().str();
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -172,12 +172,13 @@ struct SecureValueWithCredentials {
|
||||
};
|
||||
|
||||
Result<SecureValue> get_secure_value(FileManager *file_manager,
|
||||
td_api::object_ptr<td_api::inputPassportData> &&input_passport_data);
|
||||
td_api::object_ptr<td_api::InputPassportData> &&input_passport_data);
|
||||
|
||||
td_api::object_ptr<td_api::passportData> get_passport_data_object(FileManager *file_manager, const SecureValue &value);
|
||||
Result<td_api::object_ptr<td_api::PassportData>> get_passport_data_object(FileManager *file_manager,
|
||||
const SecureValue &value);
|
||||
|
||||
td_api::object_ptr<td_api::allPassportData> get_all_passport_data_object(FileManager *file_manager,
|
||||
const vector<SecureValue> &value);
|
||||
const vector<SecureValue> &values);
|
||||
|
||||
Result<std::pair<FileId, SecureFileCredentials>> decrypt_secure_file(FileManager *file_manager,
|
||||
const secure_storage::Secret &secret,
|
||||
|
@ -1777,8 +1777,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateBotShippingQuer
|
||||
make_tl_object<td_api::updateNewShippingQuery>(
|
||||
update->query_id_, td_->contacts_manager_->get_user_id_object(user_id, "updateNewShippingQuery"),
|
||||
update->payload_.as_slice().str(),
|
||||
get_shipping_address_object(get_shipping_address(
|
||||
std::move(update->shipping_address_))))); // TODO use convert_shipping_address
|
||||
get_address_object(get_address(std::move(update->shipping_address_))))); // TODO use convert_address
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateBotPrecheckoutQuery> update, bool /*force_apply*/) {
|
||||
|
@ -952,28 +952,30 @@ class CliClient final : public Actor {
|
||||
return transform(full_split(types, delimiter), [](Slice str) { return as_passport_data_type(str); });
|
||||
}
|
||||
|
||||
static tl_object_ptr<td_api::inputPassportData> as_input_passport_data(string passport_data_type, string file) {
|
||||
static tl_object_ptr<td_api::InputPassportData> as_input_passport_data(string passport_data_type, string arg) {
|
||||
vector<td_api::object_ptr<td_api::InputFile>> files;
|
||||
LOG(ERROR) << "FILE " << file;
|
||||
if (!file.empty()) {
|
||||
files.push_back(make_tl_object<td_api::inputFileLocal>(file));
|
||||
if (!arg.empty()) {
|
||||
files.push_back(make_tl_object<td_api::inputFileLocal>(arg));
|
||||
}
|
||||
auto data_type = as_passport_data_type(passport_data_type);
|
||||
string data;
|
||||
if (passport_data_type == "address" || passport_data_type == "a") {
|
||||
data = "cucumber lives here";
|
||||
return make_tl_object<td_api::inputPassportDataAddress>(
|
||||
make_tl_object<td_api::address>("US", "CA", "Los Angeles", "Washington", "", "90001"));
|
||||
} else if (passport_data_type == "email" || passport_data_type == "e") {
|
||||
data = file;
|
||||
files.clear();
|
||||
return make_tl_object<td_api::inputPassportDataEmailAddress>(arg);
|
||||
} else if (passport_data_type == "phone" || passport_data_type == "p") {
|
||||
data = file;
|
||||
files.clear();
|
||||
return make_tl_object<td_api::inputPassportDataPhoneNumber>(arg);
|
||||
} else if (passport_data_type == "pd") {
|
||||
data = "{todo}";
|
||||
} else {
|
||||
data = "I am cucumber";
|
||||
return make_tl_object<td_api::inputPassportDataPersonalDetails>(make_tl_object<td_api::personalDetails>(
|
||||
"Mike", "Towers", make_tl_object<td_api::date>(29, 2, 1999), "male", "US"));
|
||||
} else if (passport_data_type == "driver_license" || passport_data_type == "dl") {
|
||||
return make_tl_object<td_api::inputPassportDataDriverLicense>(make_tl_object<td_api::inputIdentityDocument>(
|
||||
"1234567890", make_tl_object<td_api::date>(1, 3, 2029), std::move(files), nullptr));
|
||||
} else if (passport_data_type == "rental_aggrement" || passport_data_type == "ra") {
|
||||
return make_tl_object<td_api::inputPassportDataRentalAgreement>(std::move(files));
|
||||
}
|
||||
return make_tl_object<td_api::inputPassportData>(std::move(data_type), std::move(data), std::move(files), nullptr);
|
||||
|
||||
LOG(ERROR) << "Unsupported passport data type " << passport_data_type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static td_api::object_ptr<td_api::Object> execute(tl_object_ptr<td_api::Function> f) {
|
||||
@ -1143,10 +1145,10 @@ class CliClient final : public Actor {
|
||||
} else if (op == "spd") {
|
||||
string password;
|
||||
string passport_data_type;
|
||||
string file;
|
||||
string arg;
|
||||
std::tie(password, args) = split(args);
|
||||
std::tie(passport_data_type, file) = split(args);
|
||||
send_request(make_tl_object<td_api::setPassportData>(as_input_passport_data(passport_data_type, file), password));
|
||||
std::tie(passport_data_type, arg) = split(args);
|
||||
send_request(make_tl_object<td_api::setPassportData>(as_input_passport_data(passport_data_type, arg), password));
|
||||
} else if (op == "pdu" || op == "processDcUpdate") {
|
||||
string dc_id;
|
||||
string ip_port;
|
||||
|
@ -371,8 +371,7 @@ struct PhotoRemoteFileLocation {
|
||||
|
||||
inline StringBuilder &operator<<(StringBuilder &string_builder, const PhotoRemoteFileLocation &location) {
|
||||
return string_builder << "[id = " << location.id_ << ", access_hash = " << location.access_hash_
|
||||
<< ", volume_id = " << location.volume_id_ << ", secret = " << location.secret_
|
||||
<< ", local_id = " << location.local_id_ << "]";
|
||||
<< ", volume_id = " << location.volume_id_ << ", local_id = " << location.local_id_ << "]";
|
||||
}
|
||||
|
||||
struct WebRemoteFileLocation {
|
||||
|
@ -1976,9 +1976,6 @@ Result<FileId> FileManager::get_input_thumbnail_file_id(const tl_object_ptr<td_a
|
||||
Result<FileId> FileManager::get_input_file_id(FileType type, const tl_object_ptr<td_api::InputFile> &file,
|
||||
DialogId owner_dialog_id, bool allow_zero, bool is_encrypted,
|
||||
bool get_by_hash, bool is_secure) {
|
||||
if (is_encrypted) {
|
||||
get_by_hash = false;
|
||||
}
|
||||
if (!file) {
|
||||
if (allow_zero) {
|
||||
return FileId();
|
||||
@ -1986,6 +1983,10 @@ Result<FileId> FileManager::get_input_file_id(FileType type, const tl_object_ptr
|
||||
return Status::Error(6, "InputFile not specified");
|
||||
}
|
||||
|
||||
if (is_encrypted || is_secure) {
|
||||
get_by_hash = false;
|
||||
}
|
||||
|
||||
auto new_type = is_encrypted ? FileType::Encrypted : (is_secure ? FileType::Secure : type);
|
||||
|
||||
auto r_file_id = [&]() -> Result<FileId> {
|
||||
|
@ -774,7 +774,7 @@ void to_json(JsonValueScope &jv, const T &value) {
|
||||
template <class F>
|
||||
class JsonObjectImpl : Jsonable {
|
||||
public:
|
||||
JsonObjectImpl(F &&f) : f_(std::forward<F>(f)) {
|
||||
explicit JsonObjectImpl(F &&f) : f_(std::forward<F>(f)) {
|
||||
}
|
||||
void store(JsonValueScope *scope) const {
|
||||
auto object = scope->enter_object();
|
||||
@ -792,7 +792,7 @@ auto json_object(F &&f) {
|
||||
template <class F>
|
||||
class JsonArrayImpl : Jsonable {
|
||||
public:
|
||||
JsonArrayImpl(F &&f) : f_(std::forward<F>(f)) {
|
||||
explicit JsonArrayImpl(F &&f) : f_(std::forward<F>(f)) {
|
||||
}
|
||||
void store(JsonValueScope *scope) const {
|
||||
auto array = scope->enter_array();
|
||||
@ -802,6 +802,7 @@ class JsonArrayImpl : Jsonable {
|
||||
private:
|
||||
F f_;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
auto json_array(F &&f) {
|
||||
return JsonArrayImpl<F>(std::forward<F>(f));
|
||||
|
Loading…
Reference in New Issue
Block a user