Skip to content

Commit 27285d1

Browse files
committed
fix: add mocking of tracked proFeaturesBitset to userprofile
1 parent 20a3c4f commit 27285d1

File tree

9 files changed

+93
-121
lines changed

9 files changed

+93
-121
lines changed

include/pro/pro.hpp

Lines changed: 0 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -111,22 +111,6 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
111111
"proStatusRequestBody",
112112
static_cast<napi_property_attributes>(
113113
napi_writable | napi_configurable)),
114-
115-
// Note: those are not plugged in for now as we do this parsing through zod
116-
// on desktop.
117-
// Pro responses parsing
118-
// StaticMethod<&ProWrapper::proProofParseResponse>(
119-
// "proProofParseResponse",
120-
// static_cast<napi_property_attributes>(
121-
// napi_writable | napi_configurable)),
122-
// StaticMethod<&ProWrapper::proRevocationsParseResponse>(
123-
// "proRevocationsParseResponse",
124-
// static_cast<napi_property_attributes>(
125-
// napi_writable | napi_configurable)),
126-
// StaticMethod<&ProWrapper::proStatusParseResponse>(
127-
// "proStatusParseResponse",
128-
// static_cast<napi_property_attributes>(
129-
// napi_writable | napi_configurable)),
130114
});
131115
}
132116

@@ -206,13 +190,9 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
206190
std::string rotating_privkey =
207191
toCppString(rotating_privkey_js, "proProofRequestBody.rotatingPrivKeyHex");
208192

209-
210193
auto master_privkey_decoded = from_hex(master_privkey);
211194
auto rotating_privkey_decoded = from_hex(rotating_privkey);
212195

213-
assert_length(master_privkey_decoded, 64, "masterPrivKeyHex");
214-
assert_length(rotating_privkey_decoded, 64, "rotatingPrivkey");
215-
216196
std::string json = pro_backend::GetProProofRequest::build_to_json(
217197
static_cast<uint8_t>(requestVersion.Int32Value()),
218198
to_span(master_privkey_decoded),
@@ -223,33 +203,6 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
223203
});
224204
};
225205

226-
static Napi::Value proProofParseResponse(const Napi::CallbackInfo& info) {
227-
return wrapResult(info, [&] {
228-
// we expect arguments that match:
229-
// first: {
230-
// "json": string,
231-
// }
232-
233-
assertInfoLength(info, 1);
234-
assertIsObject(info[0]);
235-
auto env = info.Env();
236-
237-
auto first = info[0].As<Napi::Object>();
238-
239-
if (first.IsEmpty())
240-
throw std::invalid_argument("proProofParseResponse first received empty");
241-
242-
assertIsString(first.Get("json"), "proProofParseResponse.json");
243-
auto json_str = toCppString(first.Get("json"), "proProofParseResponse.json");
244-
auto parsed = pro_backend::AddProPaymentOrGetProProofResponse::parse(json_str);
245-
246-
auto obj = toJs(env, static_cast<pro_backend::ResponseHeader>(parsed));
247-
obj["proof"] = toJsOrNullIfErrors(env, parsed.proof, parsed.errors);
248-
249-
return obj;
250-
});
251-
};
252-
253206
static Napi::Value proRevocationsRequestBody(const Napi::CallbackInfo& info) {
254207
return wrapResult(info, [&] {
255208
// we expect arguments that match:
@@ -281,35 +234,6 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
281234
});
282235
};
283236

284-
static Napi::Value proRevocationsParseResponse(const Napi::CallbackInfo& info) {
285-
return wrapResult(info, [&] {
286-
// we expect arguments that match:
287-
// first: {
288-
// "json": string,
289-
// }
290-
291-
assertInfoLength(info, 1);
292-
assertIsObject(info[0]);
293-
auto env = info.Env();
294-
295-
auto first = info[0].As<Napi::Object>();
296-
297-
if (first.IsEmpty())
298-
throw std::invalid_argument("proRevocationsParseResponse first received empty");
299-
300-
assertIsString(first.Get("json"), "proRevocationsParseResponse.json");
301-
auto json_str = toCppString(first.Get("json"), "proRevocationsParseResponse.json");
302-
auto parsed = pro_backend::GetProRevocationsResponse::parse(json_str);
303-
304-
auto obj = toJs(env, static_cast<pro_backend::ResponseHeader>(parsed));
305-
// if error is set, the body might not be parsable so don't try to use it
306-
obj["ticket"] = parsed.errors.size() ? env.Null() : toJs(env, parsed.ticket);
307-
obj["items"] = parsed.errors.size() ? env.Null() : toJs(env, parsed.items);
308-
309-
return obj;
310-
});
311-
};
312-
313237
static Napi::Value proStatusRequestBody(const Napi::CallbackInfo& info) {
314238
return wrapResult(info, [&] {
315239
// we expect arguments that match:
@@ -344,7 +268,6 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
344268
toCppString(master_privkey_js, "proStatusRequestBody.masterPrivKeyHex");
345269

346270
auto master_privkey_decoded = from_hex(master_privkey);
347-
assert_length(master_privkey_decoded, 64, "proStatusRequestBody.masterPrivKeyHex");
348271

349272
auto json = pro_backend::GetProStatusRequest::build_to_json(
350273
static_cast<uint8_t>(requestVersion.Int32Value()),
@@ -355,44 +278,6 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
355278
return json;
356279
});
357280
};
358-
359-
static Napi::Value proStatusParseResponse(const Napi::CallbackInfo& info) {
360-
return wrapResult(info, [&] {
361-
// we expect arguments that match:
362-
// first: {
363-
// "json": string,
364-
// }
365-
366-
assertInfoLength(info, 1);
367-
assertIsObject(info[0]);
368-
auto env = info.Env();
369-
370-
auto first = info[0].As<Napi::Object>();
371-
372-
if (first.IsEmpty())
373-
throw std::invalid_argument("proStatusParseResponse first received empty");
374-
375-
assertIsString(first.Get("json"), "proStatusParseResponse.json");
376-
auto json_str = toCppString(first.Get("json"), "proStatusParseResponse.json");
377-
auto parsed = pro_backend::GetProStatusResponse::parse(json_str);
378-
379-
auto obj = toJs(env, static_cast<pro_backend::ResponseHeader>(parsed));
380-
381-
obj["items"] = toJsOrNullIfErrors(env, parsed.items, parsed.errors);
382-
obj["userStatus"] = toJsOrNullIfErrors(
383-
env, proBackendEnumToString(parsed.user_status), parsed.errors);
384-
385-
obj["errorReport"] = toJsOrNullIfErrors(
386-
env, proBackendEnumToString(parsed.error_report), parsed.errors);
387-
388-
obj["autoRenewing"] = toJsOrNullIfErrors(env, parsed.auto_renewing, parsed.errors);
389-
obj["expiryTsMs"] = toJsOrNullIfErrors(env, parsed.expiry_unix_ts_ms, parsed.errors);
390-
obj["gracePeriodMs"] =
391-
toJsOrNullIfErrors(env, parsed.grace_period_duration_ms, parsed.errors);
392-
393-
return obj;
394-
});
395-
};
396281
};
397282

398283
}; // namespace session::nodeapi

include/pro/types.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct toJs_impl<session::ProProof> {
1919
obj["genIndexHashB64"] = toJs(env, oxenc::to_base64(pro_proof.gen_index_hash));
2020
obj["rotatingPubkeyHex"] = toJs(env, oxenc::to_hex(pro_proof.rotating_pubkey));
2121
obj["expiryMs"] = toJs(env, pro_proof.expiry_unix_ts.time_since_epoch().count());
22+
obj["signatureHex"] = toJs(env, oxenc::to_hex(pro_proof.sig));
2223

2324
return obj;
2425
}

include/user_config.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <napi.h>
44

55
#include "base_config.hpp"
6+
#include "session/config/pro.hpp"
67
#include "session/config/user_profile.hpp"
78
#include "utilities.hpp"
89

@@ -15,6 +16,10 @@ class UserConfigWrapper : public ConfigBaseImpl, public Napi::ObjectWrap<UserCon
1516
explicit UserConfigWrapper(const Napi::CallbackInfo& info);
1617

1718
private:
19+
// FIXME: wrap those in the extra data field of UserConfig instead
20+
std::optional<config::ProConfig> pro_config;
21+
int64_t pro_user_features = 0;
22+
1823
config::UserProfile& config{get_config<config::UserProfile>()};
1924

2025
Napi::Value getPriority(const Napi::CallbackInfo& info);
@@ -37,8 +42,10 @@ class UserConfigWrapper : public ConfigBaseImpl, public Napi::ObjectWrap<UserCon
3742

3843
Napi::Value getProConfig(const Napi::CallbackInfo& info);
3944
void setProConfig(const Napi::CallbackInfo& info);
45+
Napi::Value getProFeaturesBitset(const Napi::CallbackInfo& info);
46+
void setProFeaturesBitset(const Napi::CallbackInfo& info);
47+
4048
Napi::Value generateProMasterKey(const Napi::CallbackInfo& info);
4149
Napi::Value generateRotatingPrivKeyHex(const Napi::CallbackInfo& info);
42-
4350
};
4451
}; // namespace session::nodeapi

include/utilities.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ std::span<const unsigned char> toCppBufferView(Napi::Value x, const std::string&
7373
std::vector<unsigned char> toCppBuffer(Napi::Value x, const std::string& identifier);
7474

7575
int64_t toCppInteger(Napi::Value x, const std::string& identifier, bool allowUndefined = false);
76+
77+
/**
78+
* Same as toCppInteger, but for BigInt
79+
*/
80+
int64_t toCppIntegerB(Napi::Value x, const std::string& identifier, bool allowUndefined = false);
81+
7682
std::optional<int64_t> maybeNonemptyInt(Napi::Value x, const std::string& identifier);
7783
std::optional<bool> maybeNonemptyBoolean(Napi::Value x, const std::string& identifier);
7884
std::optional<std::chrono::sys_seconds> maybeNonemptySysSeconds(

src/encrypt_decrypt/encrypt_decrypt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ std::optional<std::vector<unsigned char>> extractProRotatingEd25519PrivKeyAsVect
9595
maybeNonemptyString(obj.Get("proRotatingEd25519PrivKey"), identifier);
9696

9797
if (proRotatingEd25519PrivKeyHex.has_value() && proRotatingEd25519PrivKeyHex.value().size()) {
98-
assert_length(*proRotatingEd25519PrivKeyHex, 64, identifier);
9998

10099
auto ret = from_hex_to_vector(*proRotatingEd25519PrivKeyHex);
101100

101+
assert_length(ret, 64, identifier);
102102
return ret;
103103
}
104104

src/user_config.cpp

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "user_config.hpp"
22

3+
#include <napi.h>
4+
35
#include <iostream>
46

57
#include "base_config.hpp"
@@ -10,6 +12,7 @@
1012
#include "session/config/base.hpp"
1113
#include "session/config/user_profile.hpp"
1214
#include "session/ed25519.hpp"
15+
#include "utilities.hpp"
1316

1417
namespace session::nodeapi {
1518

@@ -59,6 +62,15 @@ session::config::ProConfig pro_config_from_object(Napi::Object input) {
5962
rotating_pubkey_cpp.end(),
6063
pro_config.proof.rotating_pubkey.begin());
6164

65+
// extract backend signature
66+
auto signature_hex_js = proof_js.Get("signatureHex");
67+
assertIsString(signature_hex_js, "pro_config_from_object.signature_hex_js");
68+
auto signature_hex_cpp =
69+
toCppString(signature_hex_js, "pro_config_from_object.signature_hex_js");
70+
auto signature_cpp = from_hex_to_vector(signature_hex_cpp);
71+
std::copy(signature_cpp.begin(), signature_cpp.end(), pro_config.proof.sig.begin());
72+
assert_length(signature_cpp, 64, "pro_config_from_object.signature_cpp");
73+
6274
// extract expiryMs
6375
assertIsNumber(proof_js.Get("expiryMs"), "pro_config_from_object.expiryMs");
6476
pro_config.proof.expiry_unix_ts =
@@ -95,6 +107,10 @@ void UserConfigWrapper::Init(Napi::Env env, Napi::Object exports) {
95107
InstanceMethod("setNoteToSelfExpiry", &UserConfigWrapper::setNoteToSelfExpiry),
96108
InstanceMethod("getProConfig", &UserConfigWrapper::getProConfig),
97109
InstanceMethod("setProConfig", &UserConfigWrapper::setProConfig),
110+
InstanceMethod(
111+
"setProFeaturesBitset", &UserConfigWrapper::setProFeaturesBitset),
112+
InstanceMethod(
113+
"getProFeaturesBitset", &UserConfigWrapper::getProFeaturesBitset),
98114
InstanceMethod(
99115
"generateProMasterKey", &UserConfigWrapper::generateProMasterKey),
100116
InstanceMethod(
@@ -251,10 +267,11 @@ void UserConfigWrapper::setNoteToSelfExpiry(const Napi::CallbackInfo& info) {
251267
Napi::Value UserConfigWrapper::getProConfig(const Napi::CallbackInfo& info) {
252268
return wrapResult(info, [&] {
253269
// TODO fixme once extra_data is implemented
254-
// auto pro_config = config.get_pro_config();
255-
// if (pro_config) {
256-
// return toJs(info.Env(), *pro_config);
257-
// }
270+
271+
oxen::log::warning(cat, "getProConfig() is not wrapped to libsession");
272+
if (this->pro_config.has_value()) {
273+
return toJs(info.Env(), this->pro_config);
274+
}
258275

259276
return info.Env().Null();
260277
});
@@ -271,6 +288,35 @@ void UserConfigWrapper::setProConfig(const Napi::CallbackInfo& info) {
271288
// TODO fixme once extra_data is implemented
272289

273290
// config.set_pro_config(pro_config);
291+
this->pro_config = pro_config;
292+
});
293+
}
294+
295+
Napi::Value UserConfigWrapper::getProFeaturesBitset(const Napi::CallbackInfo& info) {
296+
return wrapResult(info, [&] {
297+
// TODO fixme once extra_data is implemented
298+
// config.get_pro_features_bitset();
299+
oxen::log::warning(cat, "getProFeaturesBitset() is not wrapped to libsession");
300+
return toJs(info.Env(), this->pro_user_features);
301+
});
302+
}
303+
304+
void UserConfigWrapper::setProFeaturesBitset(const Napi::CallbackInfo& info) {
305+
wrapExceptions(info, [&] {
306+
assertInfoLength(info, 1);
307+
auto pro_features = info[0];
308+
assertIsObject(info[0]);
309+
auto obj = info[0].As<Napi::Object>();
310+
assertIsBigint(obj.Get("proFeaturesBitset"), "UserConfigWrapper::setProFeaturesBitset");
311+
312+
auto pro_user_features_js = obj.Get("proFeaturesBitset");
313+
auto pro_user_features_cpp = toCppIntegerB(
314+
pro_user_features_js, "UserConfigWrapper::setProFeaturesBitset", false);
315+
316+
// TODO fixme once extra_data is implemented
317+
318+
// config.set_pro_features_bitset(pro_user_features_cpp);
319+
this->pro_user_features = pro_user_features_cpp;
274320
});
275321
}
276322

src/utilities.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,16 @@ int64_t toCppInteger(Napi::Value x, const std::string& identifier, bool allowUnd
141141
throw std::invalid_argument{"Unsupported type for "s + identifier + ": expected a number"};
142142
}
143143

144+
int64_t toCppIntegerB(Napi::Value x, const std::string& identifier, bool allowUndefined) {
145+
auto lossless = true;
146+
if (allowUndefined && (x.IsNull() || x.IsUndefined()))
147+
return 0;
148+
if (x.IsBigInt())
149+
return x.As<Napi::BigInt>().Int64Value(&lossless);
150+
151+
throw std::invalid_argument{"Unsupported type for "s + identifier + ": expected a bigint"};
152+
}
153+
144154
std::optional<int64_t> maybeNonemptyInt(Napi::Value x, const std::string& identifier) {
145155
if (x.IsNull() || x.IsUndefined())
146156
return std::nullopt;

types/pro/pro.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ declare module 'libsession_util_nodejs' {
2828
*/
2929
rotatingPubkeyHex: string;
3030
expiryMs: number;
31+
/**
32+
* signature of the pro proof provided by the backend (hex)
33+
* 64 bytes, 128 chars
34+
*/
35+
signatureHex: string;
3136
};
3237

3338
type WithRotatingPrivKeyHex = {
@@ -37,6 +42,7 @@ declare module 'libsession_util_nodejs' {
3742
rotatingPrivKeyHex: string;
3843
};
3944

45+
4046
type ProConfig = WithRotatingPrivKeyHex & {
4147
proProof: ProProof;
4248
};

types/user/userconfig.d.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ declare module 'libsession_util_nodejs' {
4141
setProConfig: (proConfig: ProConfig) => void;
4242
getProConfig: () => ProConfig | null;
4343

44+
setProFeaturesBitset: (args: WithProFeaturesBitset) => void;
45+
/**
46+
*
47+
* @returns 0 if no pro user features are enabled, the bitset of pro features enabled otherwise
48+
*/
49+
getProFeaturesBitset: () => bigint;
50+
4451
generateProMasterKey: ({
4552
ed25519SeedHex,
4653
}: {
@@ -84,6 +91,8 @@ declare module 'libsession_util_nodejs' {
8491
public setNoteToSelfExpiry: UserConfigWrapper['setNoteToSelfExpiry'];
8592
public getProConfig: UserConfigWrapper['getProConfig'];
8693
public setProConfig: UserConfigWrapper['setProConfig'];
94+
public getProFeaturesBitset: UserConfigWrapper['getProFeaturesBitset'];
95+
public setProFeaturesBitset: UserConfigWrapper['setProFeaturesBitset'];
8796
public generateProMasterKey: UserConfigWrapper['generateProMasterKey'];
8897
public generateRotatingPrivKeyHex: UserConfigWrapper['generateRotatingPrivKeyHex'];
8998
}
@@ -111,6 +120,8 @@ declare module 'libsession_util_nodejs' {
111120
| MakeActionCall<UserConfigWrapper, 'setNoteToSelfExpiry'>
112121
| MakeActionCall<UserConfigWrapper, 'getProConfig'>
113122
| MakeActionCall<UserConfigWrapper, 'setProConfig'>
123+
| MakeActionCall<UserConfigWrapper, 'getProFeaturesBitset'>
124+
| MakeActionCall<UserConfigWrapper, 'setProFeaturesBitset'>
114125
| MakeActionCall<UserConfigWrapper, 'generateProMasterKey'>
115126
| MakeActionCall<UserConfigWrapper, 'generateRotatingPrivKeyHex'>;
116127
}

0 commit comments

Comments
 (0)