|
7 | 7 | #include <session/config.hpp>
|
8 | 8 |
|
9 | 9 | #include "base.hpp"
|
| 10 | +#include "community.hpp" |
10 | 11 | #include "expiring.hpp"
|
11 | 12 | #include "namespaces.hpp"
|
12 | 13 | #include "notify.hpp"
|
13 | 14 | #include "profile_pic.hpp"
|
14 | 15 |
|
15 | 16 | extern "C" struct contacts_contact;
|
| 17 | +extern "C" struct contacts_blinded_contact; |
16 | 18 |
|
17 | 19 | using namespace std::literals;
|
18 | 20 |
|
@@ -44,8 +46,24 @@ namespace session::config {
|
44 | 46 | /// E - Disappearing message timer, in seconds. Omitted when `e` is omitted.
|
45 | 47 | /// j - Unix timestamp (seconds) when the contact was created ("j" to match user_groups
|
46 | 48 | /// equivalent "j"oined field). Omitted if 0.
|
| 49 | +/// |
| 50 | +/// b - dict of blinded contacts. This is a nested dict where the outkey keys are the BASE_URL of |
| 51 | +/// the community the blinded contact originated from and the outer value is a dict containing: |
| 52 | +/// `#` - the 32-byte server pubkey |
| 53 | +/// `R` - dict of blinded contacts from the server; each key is the blinded session pubkey |
| 54 | +/// without the prefix ("R" to match user_groups equivalent "R"oom field, and to make use of |
| 55 | +/// existing community iterators, binary, 32 bytes), value is a dict containing keys: |
| 56 | +/// containing keys: |
| 57 | +/// |
| 58 | +/// n - contact name (string). This is always serialized, even if empty (but empty indicates |
| 59 | +/// no name) so that we always have at least one key set (required to keep the dict value |
| 60 | +/// alive as empty dicts get pruned). |
| 61 | +/// p - profile url (string) |
| 62 | +/// q - profile decryption key (binary) |
| 63 | +/// j - Unix timestamp (seconds) when the contact was created ("j" to match user_groups |
| 64 | +/// equivalent "j"oined field). Omitted if 0. |
| 65 | +/// y - flag indicating whether the blinded message request is using legac"y" blinding. |
47 | 66 |
|
48 |
| -/// Struct containing contact info. |
49 | 67 | struct contact_info {
|
50 | 68 | static constexpr size_t MAX_NAME_LENGTH = 100;
|
51 | 69 |
|
@@ -97,6 +115,47 @@ struct contact_info {
|
97 | 115 | void load(const dict& info_dict);
|
98 | 116 | };
|
99 | 117 |
|
| 118 | +struct blinded_contact_info : community { |
| 119 | + using community::community; |
| 120 | + |
| 121 | + const std::string session_id() const; // in hex |
| 122 | + std::string name; |
| 123 | + profile_pic profile_picture; |
| 124 | + bool legacy_blinding; |
| 125 | + int64_t created = 0; // Unix timestamp (seconds) when this contact was added |
| 126 | + |
| 127 | + explicit blinded_contact_info( |
| 128 | + std::string_view base_url, |
| 129 | + std::string_view blinded_id, |
| 130 | + std::span<const unsigned char> pubkey, |
| 131 | + bool legacy_blinding); |
| 132 | + |
| 133 | + // Internal ctor/method for C API implementations: |
| 134 | + blinded_contact_info(const struct contacts_blinded_contact& c); // From c struct |
| 135 | + |
| 136 | + /// API: contacts/blinded_contact_info::into |
| 137 | + /// |
| 138 | + /// converts the contact info into a c struct |
| 139 | + /// |
| 140 | + /// Inputs: |
| 141 | + /// - `c` -- Return Parameter that will be filled with data in blinded_contact_info |
| 142 | + void into(contacts_blinded_contact& c) const; |
| 143 | + |
| 144 | + /// API: contacts/contact_info::set_name |
| 145 | + /// |
| 146 | + /// Sets a name; this is exactly the same as assigning to .name directly, |
| 147 | + /// except that we throw an exception if the given name is longer than MAX_NAME_LENGTH. |
| 148 | + /// |
| 149 | + /// Inputs: |
| 150 | + /// - `name` -- Name to assign to the contact |
| 151 | + void set_name(std::string name); |
| 152 | + |
| 153 | + private: |
| 154 | + friend class Contacts; |
| 155 | + friend struct session::config::comm_iterator_helper; |
| 156 | + void load(const dict& info_dict); |
| 157 | +}; |
| 158 | + |
100 | 159 | class Contacts : public ConfigBase {
|
101 | 160 |
|
102 | 161 | public:
|
@@ -339,6 +398,70 @@ class Contacts : public ConfigBase {
|
339 | 398 |
|
340 | 399 | bool accepts_protobuf() const override { return true; }
|
341 | 400 |
|
| 401 | + protected: |
| 402 | + // Drills into the nested dicts to access open group details |
| 403 | + DictFieldProxy blinded_contact_field( |
| 404 | + const blinded_contact_info& bc, |
| 405 | + std::span<const unsigned char>* get_pubkey = nullptr) const; |
| 406 | + |
| 407 | + public: |
| 408 | + /// API: contacts/Contacts::blinded_contacts |
| 409 | + /// |
| 410 | + /// Retrieves a list of all known blinded contacts. |
| 411 | + /// |
| 412 | + /// Inputs: None |
| 413 | + /// |
| 414 | + /// Outputs: |
| 415 | + /// - `std::vector<blinded_contact_info>` - Returns a list of blinded_contact_info |
| 416 | + std::vector<blinded_contact_info> blinded_contacts() const; |
| 417 | + |
| 418 | + /// API: contacts/Contacts::get_blinded |
| 419 | + /// |
| 420 | + /// Looks up and returns a blinded contact by blinded session ID (hex). Returns nullopt if the |
| 421 | + /// blinded session ID was not found, otherwise returns a filled out `blinded_contact_info`. |
| 422 | + /// |
| 423 | + /// Inputs: |
| 424 | + /// - `pubkey_hex` -- hex string of the session id |
| 425 | + /// - `legacy_blinding` -- flag indicating whether the pubkey is using legacy blinding |
| 426 | + /// |
| 427 | + /// Outputs: |
| 428 | + /// - `std::optional<blinded_contact_info>` - Returns nullopt if blinded session ID was not |
| 429 | + /// found, otherwise a filled out blinded_contact_info |
| 430 | + std::optional<blinded_contact_info> get_blinded( |
| 431 | + std::string_view pubkey_hex, bool legacy_blinding) const; |
| 432 | + |
| 433 | + /// API: contacts/contacts::set_blinded_contact |
| 434 | + /// |
| 435 | + /// Sets or updates multiple blinded contact info values at once with the given info. The usual |
| 436 | + /// use is to access the current info, change anything desired, then pass it back into |
| 437 | + /// set_blinded_contact, e.g.: |
| 438 | + /// |
| 439 | + ///```cpp |
| 440 | + /// auto c = contacts.get_blinded(pubkey, legacy_blinding); |
| 441 | + /// c.name = "Session User 42"; |
| 442 | + /// contacts.set_blinded_contact(c); |
| 443 | + ///``` |
| 444 | + /// |
| 445 | + /// Inputs: |
| 446 | + /// - `bc` -- set_blinded_contact value to set |
| 447 | + bool set_blinded_contact(const blinded_contact_info& bc); |
| 448 | + |
| 449 | + /// API: contacts/contacts::erase_blinded_contact |
| 450 | + /// |
| 451 | + /// Removes a blinded contact, if present. Returns true if it was found and removed, false |
| 452 | + /// otherwise. Note that this removes all fields related to a blinded contact, even fields we do |
| 453 | + /// not know about. |
| 454 | + /// |
| 455 | + /// Inputs: |
| 456 | + /// - `base_url` -- the base url for the community this blinded contact originated from |
| 457 | + /// - `blinded_id` -- hex string of the blinded id |
| 458 | + /// - `legacy_blinding` -- flag indicating whether `blinded_id` is using legacy blinding |
| 459 | + /// |
| 460 | + /// Outputs: |
| 461 | + /// - `bool` - Returns true if contact was found and removed, false otherwise |
| 462 | + bool erase_blinded_contact( |
| 463 | + std::string_view base_url, std::string_view blinded_id, bool legacy_blinding); |
| 464 | + |
342 | 465 | struct iterator;
|
343 | 466 | /// API: contacts/contacts::begin
|
344 | 467 | ///
|
|
0 commit comments