Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 212 additions & 1 deletion include/pro/pro.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@
#include "../../node_modules/node-addon-api/napi.h"
#include "../meta/meta_base_wrapper.hpp"
#include "../utilities.hpp"
#include "./types.hpp"
#include "meta/meta_base_wrapper.hpp"
#include "session/pro_backend.h"
#include "session/pro_backend.hpp"
#include "session/session_protocol.h"
#include "session/session_protocol.hpp"

namespace session::nodeapi {
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_PROVIDER v);
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_STATUS v);
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PLAN v);
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_USER_PRO_STATUS v);
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT v);

class ProWrapper : public Napi::ObjectWrap<ProWrapper> {

Expand All @@ -36,6 +44,26 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
"proProofRequestBody",
static_cast<napi_property_attributes>(
napi_writable | napi_configurable)),
StaticMethod<&ProWrapper::proProofResponseBody>(
"proProofResponseBody",
static_cast<napi_property_attributes>(
napi_writable | napi_configurable)),
StaticMethod<&ProWrapper::proRevocationsRequestBody>(
"proRevocationsRequestBody",
static_cast<napi_property_attributes>(
napi_writable | napi_configurable)),
StaticMethod<&ProWrapper::proRevocationsResponseBody>(
"proRevocationsResponseBody",
static_cast<napi_property_attributes>(
napi_writable | napi_configurable)),
StaticMethod<&ProWrapper::proStatusRequestBody>(
"proStatusRequestBody",
static_cast<napi_property_attributes>(
napi_writable | napi_configurable)),
StaticMethod<&ProWrapper::proStatusResponseBody>(
"proStatusResponseBody",
static_cast<napi_property_attributes>(
napi_writable | napi_configurable)),
});
}

Expand Down Expand Up @@ -99,7 +127,7 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
return wrapResult(info, [&] {
// we expect arguments that match:
// first: {
// "requestVersion": string,
// "requestVersion": number,
// "masterPrivkey": Uint8Array,
// "rotatingPrivkey": Uint8Array,
// "unixTsMs": number,
Expand Down Expand Up @@ -141,6 +169,189 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
return json;
});
};

static Napi::Value proProofResponseBody(const Napi::CallbackInfo& info) {
return wrapResult(info, [&] {
// we expect arguments that match:
// first: {
// "json": string,
// }

assertInfoLength(info, 1);
assertIsObject(info[0]);
auto env = info.Env();

auto first = info[0].As<Napi::Object>();

if (first.IsEmpty())
throw std::invalid_argument("proProofResponseBody first received empty");

assertIsString(first.Get("json"), "proProofResponseBody.jsonStr");
auto json_str = toCppString(first.Get("json"), "proProofResponseBody.jsonStr");
auto json = pro_backend::AddProPaymentOrGetProProofResponse::parse(json_str);

auto obj = Napi::Object::New(env);

obj["status"] = toJs(env, json.status);
obj["errors"] = toJs(env, json.errors);
obj["proof"] = json.errors.empty() ? toJs(env, json.proof) : env.Null();

return obj;
});
};

static Napi::Value proRevocationsRequestBody(const Napi::CallbackInfo& info) {
return wrapResult(info, [&] {
// we expect arguments that match:
// first: {
// "requestVersion": number,
// "ticket": number,
// }

assertInfoLength(info, 1);
assertIsObject(info[0]);
auto env = info.Env();

auto first = info[0].As<Napi::Object>();

if (first.IsEmpty())
throw std::invalid_argument("proRevocationsRequestBody first received empty");

assertIsNumber(first.Get("requestVersion"), "proRevocationsRequestBody.requestVersion");
assertIsNumber(first.Get("ticket"), "proRevocationsRequestBody.ticket");
auto requestVersion = first.Get("requestVersion").As<Napi::Number>();
auto ticket = first.Get("ticket").As<Napi::Number>();

auto revocationsRequest = pro_backend::GetProRevocationsRequest{
.version = static_cast<uint8_t>(requestVersion.Int32Value()),
.ticket = ticket.Uint32Value(),
};

auto json = revocationsRequest.to_json();

return json;
});
};

static Napi::Value proRevocationsResponseBody(const Napi::CallbackInfo& info) {
return wrapResult(info, [&] {
// we expect arguments that match:
// first: {
// "json": string,
// }

assertInfoLength(info, 1);
assertIsObject(info[0]);
auto env = info.Env();

auto first = info[0].As<Napi::Object>();

if (first.IsEmpty())
throw std::invalid_argument("proRevocationsResponseBody first received empty");

assertIsString(first.Get("json"), "proRevocationsResponseBody.jsonStr");
auto json_str = toCppString(first.Get("json"), "proRevocationsResponseBody.jsonStr");
auto json = pro_backend::GetProRevocationsResponse::parse(json_str);

auto obj = Napi::Object::New(env);

obj["status"] = toJs(env, json.status);
obj["errors"] = toJs(env, json.errors);
obj["ticket"] = json.errors.empty() ? toJs(env, json.ticket) : env.Null();
// FIXME: implement
// obj["items"] = json.errors.empty() ? toJs(env, json.items) : env.Null();

return obj;
});
};

static Napi::Value proStatusRequestBody(const Napi::CallbackInfo& info) {
return wrapResult(info, [&] {
// we expect arguments that match:
// first: {
// "requestVersion": number,
// "masterPrivkey": Uint8Array,
// "unixTsMs": number,
// "withPaymentHistory": boolean,
// }

assertInfoLength(info, 1);
assertIsObject(info[0]);
auto env = info.Env();

auto first = info[0].As<Napi::Object>();

if (first.IsEmpty())
throw std::invalid_argument("proStatusRequestBody first received empty");

assertIsNumber(first.Get("requestVersion"), "proStatusRequestBody.requestVersion");
assertIsNumber(first.Get("unixTsMs"), "proStatusRequestBody.unixTsMs");
assertIsBoolean(
first.Get("withPaymentHistory"), "proStatusRequestBody.withPaymentHistory");
auto requestVersion = first.Get("requestVersion").As<Napi::Number>();
auto unix_ts_ms = toCppSysMs(first.Get("unixTsMs"), "proStatusRequestBody.unixTsMs");
auto withPaymentHistory = toCppBoolean(
first.Get("withPaymentHistory"), "proStatusRequestBody.withPaymentHistory");
assertIsUInt8Array(first.Get("masterPrivkey"), "proStatusRequestBody.masterPrivkey");

auto master_privkey_js = first.Get("masterPrivkey");
auto master_privkey =
toCppBuffer(master_privkey_js, "proStatusRequestBody.masterPrivkey");

assert_length(master_privkey, 64, "master_privkey");

auto json = pro_backend::GetProStatusRequest::build_to_json(
static_cast<uint8_t>(requestVersion.Int32Value()),
master_privkey,
unix_ts_ms,
withPaymentHistory);

return json;
});
};

static Napi::Value proStatusResponseBody(const Napi::CallbackInfo& info) {
return wrapResult(info, [&] {
// we expect arguments that match:
// first: {
// "json": string,
// }

assertInfoLength(info, 1);
assertIsObject(info[0]);
auto env = info.Env();

auto first = info[0].As<Napi::Object>();

if (first.IsEmpty())
throw std::invalid_argument("proStatusResponseBody first received empty");

assertIsString(first.Get("json"), "proStatusResponseBody.jsonStr");
auto json_str = toCppString(first.Get("json"), "proStatusResponseBody.jsonStr");
auto json = pro_backend::GetProStatusResponse::parse(json_str);

auto obj = Napi::Object::New(env);

obj["status"] = toJs(env, json.status);
obj["errors"] = toJs(env, json.errors);
// FIXME: implement
// obj["items"] = json.errors.empty() ? toJs(env, json.items) : env.Null();
obj["userStatus"] = json.errors.empty()
? toJs(env, ProBackendEnumToString(json.user_status))
: env.Null();
obj["errorReport"] = json.errors.empty()
? toJs(env, ProBackendEnumToString(json.error_report))
: env.Null();
obj["autoRenewing"] = json.errors.empty() ? toJs(env, json.auto_renewing) : env.Null();

// FIXME: implement
// obj["expiryUnixTsMs"] = json.errors.empty() ? toJs(env, json.expiry_unix_ts_ms) :
// env.Null(); obj["gracePeriodDurationMs"] = json.errors.empty() ? toJs(env,
// json.grace_period_duration_ms) : env.Null();

return obj;
});
};
};

}; // namespace session::nodeapi
1 change: 1 addition & 0 deletions include/utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <napi.h>

#include <chrono>
#include <optional>
#include <span>
#include <stdexcept>
Expand Down
62 changes: 61 additions & 1 deletion src/pro/pro.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,61 @@
#include "pro/pro.hpp"
#include "pro/pro.hpp"

namespace session::nodeapi {
std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_PROVIDER v) {
switch (v) {
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_NIL: return "NIL";
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_GOOGLE_PLAY_STORE: return "GOOGLE_PLAY_STORE";
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_IOS_APP_STORE: return "IOS_APP_STORE";
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_COUNT:
// TODO: do we want to assert this cant happen? or should it be allowed?
return "Count";
}
}

std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_STATUS v) {
switch (v) {
case SESSION_PRO_BACKEND_PAYMENT_STATUS_NIL: return "NIL";
case SESSION_PRO_BACKEND_PAYMENT_STATUS_UNREDEEMED: return "UNREDEEMED";
case SESSION_PRO_BACKEND_PAYMENT_STATUS_REDEEMED: return "REDEEMED";
case SESSION_PRO_BACKEND_PAYMENT_STATUS_EXPIRED: return "EXPIRED";
case SESSION_PRO_BACKEND_PAYMENT_STATUS_REFUNDED: return "REFUNDED";
case SESSION_PRO_BACKEND_PAYMENT_STATUS_COUNT:
// TODO: do we want to assert this cant happen? or should it be allowed?
return "COUNT";
}
}

std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PLAN v) {
switch (v) {
case SESSION_PRO_BACKEND_PLAN_NIL: return "NIL";
case SESSION_PRO_BACKEND_PLAN_ONE_MONTH: return "ONE_MONTH";
case SESSION_PRO_BACKEND_PLAN_THREE_MONTHS: return "THREE_MONTHS";
case SESSION_PRO_BACKEND_PLAN_TWELVE_MONTHS: return "TWELVE_MONTHS";
case SESSION_PRO_BACKEND_PLAN_COUNT:
// TODO: do we want to assert this cant happen? or should it be allowed?
return "COUNT";
}
}

std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_USER_PRO_STATUS v) {
switch (v) {
case SESSION_PRO_BACKEND_USER_PRO_STATUS_NEVER_BEEN_PRO: return "NEVER_BEEN_PRO";
case SESSION_PRO_BACKEND_USER_PRO_STATUS_ACTIVE: return "ACTIVE";
case SESSION_PRO_BACKEND_USER_PRO_STATUS_EXPIRED: return "EXPIRED";
case SESSION_PRO_BACKEND_USER_PRO_STATUS_COUNT:
// TODO: do we want to assert this cant happen? or should it be allowed?
return "COUNT";
}
}

std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT v) {
switch (v) {
case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_SUCCESS: return "SUCCESS";
case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_GENERIC_ERROR: return "GENERIC_ERROR";
case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_COUNT:
// TODO: do we want to assert this cant happen? or should it be allowed?
return "COUNT";
}
}

}
48 changes: 47 additions & 1 deletion types/pro/pro.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ declare module 'libsession_util_nodejs' {
proProof: ProProof;
};

type WithProBackendResponse = {
status: number;
errors: Array<string>;
}

// Must match session-desktop
export enum ProOriginatingPlatform {
Nil = 'Nil',
Expand Down Expand Up @@ -75,12 +80,53 @@ declare module 'libsession_util_nodejs' {
proFeatures: ProFeatures;
}) => WithProFeatures & { success: boolean; error: string | null; codepointCount: number };
proProofRequestBody: (args: {
requestVersion: string,
requestVersion: number,
masterPrivkey: Uint8Array,
rotatingPrivkey: Uint8Array,
unixTsMs: number,
}
) => string;

proProofResponseBody: (args: {
json: string,
}
) => WithProBackendResponse & { proof: ProProof | null };

proRevocationsRequestBody: (args: {
requestVersion: number,
ticket: number,
}
) => string;

proRevocationsResponseBody: (args: {
json: string,
}
) => WithProBackendResponse & {
ticket: number | null;
items: Array<ProRevocationItem>
};

proStatusRequestBody: (args: {
requestVersion: number,
masterPrivkey: Uint8Array,
unixTsMs: number,
withPaymentHistory: boolean,
}
) => string;

proStatusResponseBody: (args: {
json: string,
}
) => WithProBackendResponse & {
ticket: number | null;
items: Array<ProPaymentItem>;
userStatus: number;
errorReport: number;
autoRenewing: boolean;
expiryUnixTsMs: number;
gracePeriodDurationMs: number;
};

};

export type ProActionsCalls = MakeWrapperActionCalls<ProWrapper>;
Expand Down
Loading