From abcdd1f54735183ec40ceb5d0e44d64c1a77ad69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=E2=80=99Aquino?= Date: Fri, 2 May 2025 13:41:43 -0700 Subject: [PATCH 1/2] Add type-check-compare npm script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps us quickly sift through and see new type issues we introduced. Even if we don't go back to fix the previous type warnings, at least we should prevent new type issues. Signed-off-by: Daniel D’Aquino --- .type_check.txt | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 +- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 .type_check.txt diff --git a/.type_check.txt b/.type_check.txt new file mode 100644 index 0000000..51315c8 --- /dev/null +++ b/.type_check.txt @@ -0,0 +1,91 @@ +src/app_store_receipt_verifier.js(86,57): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. +src/index.js(12,32): error TS2307: Cannot find module 'nostr-tools/pool' or its corresponding type declarations. +src/index.js(36,34): error TS2345: Argument of type 'string' is not assignable to parameter of type 'DatabaseOptions & { name: string; }'. + Type 'string' is not assignable to type '{ name: string; }'. +src/index.js(37,30): error TS2345: Argument of type 'string' is not assignable to parameter of type 'DatabaseOptions & { name: string; }'. + Type 'string' is not assignable to type '{ name: string; }'. +src/index.js(38,41): error TS2345: Argument of type 'string' is not assignable to parameter of type 'DatabaseOptions & { name: string; }'. + Type 'string' is not assignable to type '{ name: string; }'. +src/index.js(39,43): error TS2345: Argument of type 'string' is not assignable to parameter of type 'DatabaseOptions & { name: string; }'. + Type 'string' is not assignable to type '{ name: string; }'. +src/index.js(40,30): error TS2345: Argument of type 'string' is not assignable to parameter of type 'DatabaseOptions & { name: string; }'. + Type 'string' is not assignable to type '{ name: string; }'. +src/index.js(41,39): error TS2345: Argument of type 'string' is not assignable to parameter of type 'DatabaseOptions & { name: string; }'. + Type 'string' is not assignable to type '{ name: string; }'. +src/index.js(42,31): error TS2345: Argument of type 'string' is not assignable to parameter of type 'DatabaseOptions & { name: string; }'. + Type 'string' is not assignable to type '{ name: string; }'. +src/index.js(43,30): error TS2345: Argument of type 'string' is not assignable to parameter of type 'DatabaseOptions & { name: string; }'. + Type 'string' is not assignable to type '{ name: string; }'. +src/invoicing.js(187,53): error TS2554: Expected 0 arguments, but got 1. +src/nip98_auth.js(25,5): error TS2304: Cannot find name 'auth_header_parts'. +src/nip98_auth.js(26,9): error TS2304: Cannot find name 'auth_header_parts'. +src/nip98_auth.js(30,9): error TS2304: Cannot find name 'auth_header_parts'. +src/translate.js(110,36): error TS2538: Type 'Buffer' cannot be used as an index type. +src/web_auth.js(7,35): error TS2307: Cannot find module 'nostr-tools/pure' or its corresponding type declarations. +src/web_auth.js(9,48): error TS2307: Cannot find module 'nostr-tools/pool' or its corresponding type declarations. +src/web_auth.js(11,32): error TS2307: Cannot find module 'nostr-tools/pool' or its corresponding type declarations. +src/web_auth.js(43,25): error TS2365: Operator '+' cannot be applied to types 'number' and 'string | number'. +src/web_auth.js(161,9): error TS2365: Operator '>' cannot be applied to types 'number' and 'string | number'. +test/controllers/mock_iap_controller.js(85,60): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. +test/controllers/purple_test_controller.js(49,5): error TS2322: Type 'boolean' is not assignable to type 'string'. +test/controllers/purple_test_controller.js(55,5): error TS2322: Type 'number' is not assignable to type 'string'. +test/controllers/purple_test_controller.js(56,5): error TS2322: Type 'number' is not assignable to type 'string'. +test/controllers/purple_test_controller.js(57,5): error TS2322: Type 'number' is not assignable to type 'string'. +test/otp_login.test.js(104,90): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. +test/otp_login.test.js(134,21): error TS2365: Operator '<' cannot be applied to types 'number' and 'string'. +test/otp_login.test.js(186,44): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +test/otp_login.test.js(239,44): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +test/transaction_management.test.js(34,45): error TS2345: Argument of type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(63,45): error TS2345: Argument of type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(92,45): error TS2345: Argument of type '{ type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(121,45): error TS2345: Argument of type '{ type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(150,45): error TS2345: Argument of type '{ type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(186,45): error TS2345: Argument of type '{ type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(204,45): error TS2345: Argument of type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(230,45): error TS2345: Argument of type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(256,45): error TS2345: Argument of type '({ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; } | { type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; })[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; } | { type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }' is not assignable to type 'Transaction'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(307,45): error TS2345: Argument of type '({ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; } | { type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; })[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; } | { type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }' is not assignable to type 'Transaction'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(385,45): error TS2345: Argument of type '({ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; } | { type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; } | { ...; })[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; } | { type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; } | { ...; }' is not assignable to type 'Transaction'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(430,45): error TS2345: Argument of type '({ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; } | { type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; })[]' is not assignable to parameter of type 'Transaction[]'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; } | { type: string; id: any; start_date: any; end_date: any; purchased_date: number; duration: number; }' is not assignable to type 'Transaction'. + Type '{ type: string; id: string; start_date: number; end_date: number; purchased_date: number; duration: any; }' is not assignable to type 'Transaction'. + Types of property 'type' are incompatible. + Type 'string' is not assignable to type '"iap" | "ln" | "legacy"'. +test/transaction_management.test.js(436,10): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. +test/translate.test.js(7,27): error TS2305: Module '"./controllers/utils"' has no exported member 'TEST_BASE_URL'. diff --git a/package.json b/package.json index 62cff14..125b387 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "dev": "TRANSLATION_PROVIDER=mock ENABLE_HTTP_AUTH=\"true\" node src/index.js", "dev-debug": "TRANSLATION_PROVIDER=mock ENABLE_HTTP_AUTH=\"true\" node --inspect src/index.js", "dev-debug-cli": "TRANSLATION_PROVIDER=mock ENABLE_HTTP_AUTH=\"true\" node inspect src/index.js", - "type-check": "tsc --checkJs --allowJs src/*.js --noEmit --skipLibCheck", + "type-check": "tsc --checkJs --allowJs src/*.js test/*.js --noEmit --skipLibCheck", + "type-check-compare": "tsc --checkJs --allowJs src/*.js test/*.js --noEmit --skipLibCheck > .type_check.txt", "type-check-path": "tsc --checkJs --allowJs --noEmit --skipLibCheck" }, "dependencies": { From 8ff20f041d68af83cbbfca8a61a9c91537830a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=E2=80=99Aquino?= Date: Fri, 2 May 2025 13:37:20 -0700 Subject: [PATCH 2/2] Separate free and premium notedeck install instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes: https://github.com/damus-io/notedeck/issues/829 Signed-off-by: Daniel D’Aquino --- .type_check.txt | 1 - README.md | 4 +- notedeck-install-instructions-premium.md | 15 +++ notedeck-install-instructions.md | 2 + src/router_config.js | 44 ++++---- src/web_auth.js | 47 ++++++++- test/controllers/purple_test_client.js | 12 ++- test/controllers/purple_test_controller.js | 21 +++- test/notedeck_install_instructions.test.js | 111 +++++++++++++++++++++ test/router_config.test.js | 4 + test/translate.test.js | 4 + 11 files changed, 236 insertions(+), 29 deletions(-) create mode 100644 notedeck-install-instructions-premium.md create mode 100644 test/notedeck_install_instructions.test.js diff --git a/.type_check.txt b/.type_check.txt index 51315c8..8d8c921 100644 --- a/.type_check.txt +++ b/.type_check.txt @@ -25,7 +25,6 @@ src/web_auth.js(7,35): error TS2307: Cannot find module 'nostr-tools/pure' or it src/web_auth.js(9,48): error TS2307: Cannot find module 'nostr-tools/pool' or its corresponding type declarations. src/web_auth.js(11,32): error TS2307: Cannot find module 'nostr-tools/pool' or its corresponding type declarations. src/web_auth.js(43,25): error TS2365: Operator '+' cannot be applied to types 'number' and 'string | number'. -src/web_auth.js(161,9): error TS2365: Operator '>' cannot be applied to types 'number' and 'string | number'. test/controllers/mock_iap_controller.js(85,60): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. test/controllers/purple_test_controller.js(49,5): error TS2322: Type 'boolean' is not assignable to type 'string'. test/controllers/purple_test_controller.js(55,5): error TS2322: Type 'number' is not assignable to type 'string'. diff --git a/README.md b/README.md index bbe833b..dc32dab 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ The Damus API backend for Damus Purple and other functionality. - `DB_PATH`: Path to the folder where to save mdb files. - `TESTFLIGHT_URL`: URL for the TestFlight app (optional) -- `NOTEDECK_INSTALL_MD`: URL for the notedeck installation instructions markdown -- `NO_AUTH_WALL_NOTEDECK_INSTALL`: Disables the authentication wall for the notedeck installation instructions when set to `"true"`. +- `NOTEDECK_INSTALL_MD`: Path to the freely available notedeck installation instructions (markdown file) +- `NOTEDECK_INSTALL_PREMIUM_MD`: Path to the premium notedeck installation instructions (markdown file) #### Translations diff --git a/notedeck-install-instructions-premium.md b/notedeck-install-instructions-premium.md new file mode 100644 index 0000000..974d0d6 --- /dev/null +++ b/notedeck-install-instructions-premium.md @@ -0,0 +1,15 @@ +# Installing Notedeck + +Thank you for your interest in the Notedeck Beta release! We are excited to have you try out our software. Below are the instructions for installing Notedeck on your system. + +If you encounter any issues, please [contact us](support@damus.io). + +## Binaries + +Please find the download link for your operating system below. + +- macOS (Apple Silicon): [notedeck_macos_silicon.dmg](#) +- macOS (Intel): [notedeck_macos_intel.dmg](#) +- Linux Debian package: [notedeck_linux_debian.deb](#) +- Linux x86 generic: [notedeck_linux_generic.zip](#) +- Linux ARM generic: [notedeck_linux_generic.zip](#) diff --git a/notedeck-install-instructions.md b/notedeck-install-instructions.md index 7983edf..f319a99 100644 --- a/notedeck-install-instructions.md +++ b/notedeck-install-instructions.md @@ -2,6 +2,8 @@ Thank you for your interest in the Notedeck Alpha release! We are excited to have you try out our software. Below are the instructions for installing Notedeck on your system. +If you are a Purple user, you can now access our beta release! To access the beta install instructions, click [here](/purple/login). + If you encounter any issues, please [contact us](support@damus.io). ## Binaries diff --git a/src/router_config.js b/src/router_config.js index 5e39bb1..a8244f8 100644 --- a/src/router_config.js +++ b/src/router_config.js @@ -445,26 +445,28 @@ function config_router(app) { return }); - if(process.env.NO_AUTH_WALL_NOTEDECK_INSTALL == "true") { - router.get('/notedeck-install-instructions', async (req, res) => { - provide_notedeck_instructions(req, res) - }); - } - else { - router.get('/notedeck-install-instructions', app.web_auth_manager.require_web_auth.bind(app.web_auth_manager), async (req, res) => { - const pubkey = req.authorized_pubkey - const { account, user_id } = get_account_and_user_id(app, pubkey) - if (!account) { - simple_response(res, 401) - return - } - const account_info = get_account_info_payload(user_id, account, true) - if(account_info.active == true) { - provide_notedeck_instructions(req, res) - } + router.get('/notedeck-install-instructions', app.web_auth_manager.use_web_auth.bind(app.web_auth_manager), async (req, res) => { + if(!req.authorized_pubkey) { + provide_notedeck_instructions(req, res, false) // Provides free download instructions return - }); - } + } + + const { account, user_id } = get_account_and_user_id(app, req.authorized_pubkey) + if (!account) { + simple_response(res, 401) + return + } + + const account_info = get_account_info_payload(user_id, account, true) + if (account_info.active == true) { + provide_notedeck_instructions(req, res, true) // Provide premium download instructions + return + } + else { + provide_notedeck_instructions(req, res, false) // Provide free download instructions + return + } + }); // MARK: Admin routes @@ -681,8 +683,8 @@ function get_allowed_cors_origins() { } } -async function provide_notedeck_instructions(req, res) { - const installInstructionsPath = path.resolve(process.env.NOTEDECK_INSTALL_MD); +async function provide_notedeck_instructions(req, res, user_authenticated) { + const installInstructionsPath = user_authenticated == true ? path.resolve(process.env.NOTEDECK_INSTALL_PREMIUM_MD) : path.resolve(process.env.NOTEDECK_INSTALL_MD); try { const installInstructions = fs.readFileSync(installInstructionsPath, { encoding: 'utf8' }); json_response(res, { value: installInstructions }); diff --git a/src/web_auth.js b/src/web_auth.js index 8d0c0ed..72b3414 100644 --- a/src/web_auth.js +++ b/src/web_auth.js @@ -26,7 +26,7 @@ class WebAuthManager { this.dbs = dbs this.pool = pool this.otp_max_tries = process.env.OTP_MAX_TRIES || DEFAULT_OTP_MAX_TRIES - this.session_expiry = process.env.SESSION_EXPIRY || DEFAULT_SESSION_EXPIRY + this.session_expiry = parseInt(process.env.SESSION_EXPIRY) || DEFAULT_SESSION_EXPIRY this.otp_expiry = process.env.OTP_EXPIRY || DEFAULT_OTP_EXPIRY } @@ -128,7 +128,7 @@ class WebAuthManager { // MARK: Middleware /** - * Middleware to check if a user is authenticated + * Middleware to check and require a user to be authenticated * @param {object} req - The Express request object * @param {object} res - The Express response object * @param {function} next - The next middleware function @@ -167,6 +167,49 @@ class WebAuthManager { req.authorized_pubkey = session_data.pubkey; next(); } + + /** + * Middleware to check if a user is authenticated, but does not require authentication + * @param {object} req - The Express request object + * @param {object} res - The Express response object + * @param {function} next - The next middleware function + */ + async use_web_auth(req, res, next) { + const auth_header = req.header('Authorization'); + + if (!auth_header) { + next(); + return; + } + + const [auth_type, token] = auth_header.split(' '); + if (auth_type !== 'Bearer') { + next(); + return; + } + + if (!token) { + next(); + return; + } + + const session_data = await this.dbs.sessions.get(token); + if (!session_data) { + next(); + return; + } + + // Check if the session has expired + if (current_time() - session_data.created_at > this.session_expiry) { + next(); + return; + } + + // User authenticated! + + req.authorized_pubkey = session_data.pubkey; + next(); + } } diff --git a/test/controllers/purple_test_client.js b/test/controllers/purple_test_client.js index f39e432..d180551 100644 --- a/test/controllers/purple_test_client.js +++ b/test/controllers/purple_test_client.js @@ -38,9 +38,19 @@ class PurpleTestClient { return await this.get('/accounts/' + this.public_key, options) } + /** + * Gets the notedeck install instructions + * + * @param {PurpleTestClientRequestOptions} options - The request options + * @returns {Promise} The response + */ + async get_notedeck_install_instructions(options = {}) { + return await this.get('/notedeck-install-instructions', options) + } + /** * Gets the product template options. - * + * * @param {PurpleTestClientRequestOptions} options - The request options * @returns {Promise} The product information */ diff --git a/test/controllers/purple_test_controller.js b/test/controllers/purple_test_controller.js index 1571de8..618282d 100644 --- a/test/controllers/purple_test_controller.js +++ b/test/controllers/purple_test_controller.js @@ -57,6 +57,8 @@ class PurpleTestController { process.env.OTP_EXPIRY = 60*5 process.env.TESTFLIGHT_URL = "https://testflight.apple.com/join/abc123" process.env.NOTEDECK_INSTALL_MD = "./notedeck-install-instructions.md" + process.env.NOTEDECK_INSTALL_PREMIUM_MD = "./notedeck-install-instructions-premium.md" + this.env = process.env } setup_stubs() { @@ -193,8 +195,23 @@ class PurpleTestController { const check_invoice_status_response = await this.clients[pubkey].check_invoice(verify_checkout_response.body.id); this.t.same(check_invoice_status_response.status, 200) } - - + + async login(pubkey) { + // Let's request an OTP + const test_otp = "432931"; + this.web_auth_controller.set_next_random_otp(test_otp); + const otp_response = await this.clients[pubkey].request_otp(); + this.t.same(otp_response.statusCode, 200); + this.t.same(otp_response.body, { success: true }); + + // Login with the correct OTP + const login_response = await this.clients[pubkey].verify_otp(test_otp); + this.t.same(login_response.statusCode, 200); + this.t.same(login_response.body.valid, true); + this.t.ok(login_response.body.session_token); + return login_response.body.session_token + } + // MARK: - Account UUID control /** diff --git a/test/notedeck_install_instructions.test.js b/test/notedeck_install_instructions.test.js new file mode 100644 index 0000000..dedf253 --- /dev/null +++ b/test/notedeck_install_instructions.test.js @@ -0,0 +1,111 @@ +"use strict"; +// @ts-check + +const test = require('tap').test; +const { PurpleTestController } = require('./controllers/purple_test_controller.js'); +const { PURPLE_ONE_MONTH } = require('../src/invoicing.js'); +const { v4: uuidv4 } = require('uuid'); +const path = require('path'); +const fs = require('fs'); + +const PREMIUM_INSTRUCTIONS = 'premium' +const FREE_INSTRUCTIONS = 'free' + +function get_notedeck_instructions(purple_test_controller, instruction_type) { + const installInstructionsPath = instruction_type == PREMIUM_INSTRUCTIONS ? path.resolve(purple_test_controller.env.NOTEDECK_INSTALL_PREMIUM_MD) : path.resolve(purple_test_controller.env.NOTEDECK_INSTALL_MD); + return fs.readFileSync(installInstructionsPath, { encoding: 'utf8' }); +} + +test('Notedeck free install instructions flow', async (t) => { + // Initialize the PurpleTestController + const purple_api_controller = await PurpleTestController.new(t); + + // Instantiate a new client + const user_pubkey_1 = purple_api_controller.new_client(); + + const notedeck_install_response = await purple_api_controller.clients[user_pubkey_1].get_notedeck_install_instructions() + t.same(notedeck_install_response.statusCode, 200); + t.same(notedeck_install_response.body.value, get_notedeck_instructions(purple_api_controller, FREE_INSTRUCTIONS)); + + t.end(); +}); + +test('Notedeck premium install instructions flow', async (t) => { + // Initialize the PurpleTestController + const purple_api_controller = await PurpleTestController.new(t); + + // Instantiate a new client + const user_pubkey_1 = purple_api_controller.new_client(); + + // Let's get them an account + await purple_api_controller.ln_flow_buy_subscription(user_pubkey_1, PURPLE_ONE_MONTH); + + // Get the account info + const response = await purple_api_controller.clients[user_pubkey_1].get_account(); + t.same(response.statusCode, 200); + + // Let's login to get a session token + // (We could probably get it from the ln subscription flow part, but we are not testing that here, so it's fine) + let session_token = await purple_api_controller.login(user_pubkey_1); + + const notedeck_install_response = await purple_api_controller.clients[user_pubkey_1].get_notedeck_install_instructions({ session_token: session_token }) + t.same(notedeck_install_response.statusCode, 200); + t.same(notedeck_install_response.body.value, get_notedeck_instructions(purple_api_controller, PREMIUM_INSTRUCTIONS)); + + t.end(); +}); + +test('Notedeck unauthorized premium install instructions flow', async (t) => { + // Initialize the PurpleTestController + const purple_api_controller = await PurpleTestController.new(t); + + // Instantiate a new client but don't get an account + const user_pubkey_1 = purple_api_controller.new_client(); + + // Get the account info + const response = await purple_api_controller.clients[user_pubkey_1].get_account(); + t.same(response.statusCode, 404); + + const notedeck_install_response = await purple_api_controller.clients[user_pubkey_1].get_notedeck_install_instructions({ session_token: "fakesessiontoken" }) + t.same(notedeck_install_response.statusCode, 200); + t.same(notedeck_install_response.body.value, get_notedeck_instructions(purple_api_controller, FREE_INSTRUCTIONS)); + + t.end(); +}); + + +test('Notedeck expired account install instructions flow', async (t) => { + // Initialize the PurpleTestController + const purple_api_controller = await PurpleTestController.new(t); + purple_api_controller.set_current_time(1706659200) // 2024-01-31 00:00:00 UTC + + // Instantiate a new client + const user_pubkey_1 = purple_api_controller.new_client(); + + const initial_account_info_response = await purple_api_controller.clients[user_pubkey_1].get_account(); + t.same(initial_account_info_response.statusCode, 404); + + // Buy a one month subscription + await purple_api_controller.ln_flow_buy_subscription(user_pubkey_1, PURPLE_ONE_MONTH); + + // Check expiry + const account_info_response_1 = await purple_api_controller.clients[user_pubkey_1].get_account(); + t.same(account_info_response_1.statusCode, 200); + t.same(account_info_response_1.body.expiry, purple_api_controller.current_time() + 30 * 24 * 60 * 60); + t.same(account_info_response_1.body.active, true); + + // Move time forward by 35 days, and make sure the account is not active anymore + purple_api_controller.set_current_time(purple_api_controller.current_time() + 35 * 24 * 60 * 60); + const account_info_response_2 = await purple_api_controller.clients[user_pubkey_1].get_account(); + t.same(account_info_response_2.statusCode, 200); + t.same(account_info_response_2.body.active, false); + + let session_token = await purple_api_controller.login(user_pubkey_1); + + // Now try to get notedeck instructions + const notedeck_install_response = await purple_api_controller.clients[user_pubkey_1].get_notedeck_install_instructions({ session_token: session_token }) + t.same(notedeck_install_response.statusCode, 200); + t.same(notedeck_install_response.body.value, get_notedeck_instructions(purple_api_controller, FREE_INSTRUCTIONS)); + + t.end(); +}); diff --git a/test/router_config.test.js b/test/router_config.test.js index 5331dc2..ea262c6 100644 --- a/test/router_config.test.js +++ b/test/router_config.test.js @@ -67,6 +67,10 @@ test('config_router - Account management routes', async (t) => { require_web_auth: async (req, res, next) => { req.authorized_pubkey = 'abc123'; next(); + }, + use_web_auth: async (req, res, next) => { + req.authorized_pubkey = 'abc123'; + next(); } } }; diff --git a/test/translate.test.js b/test/translate.test.js index 691e98a..05cefcf 100644 --- a/test/translate.test.js +++ b/test/translate.test.js @@ -188,6 +188,10 @@ async function generate_test_api(t, config) { require_web_auth: async (req, res, next) => { req.authorized_pubkey = 'abc123'; next(); + }, + use_web_auth: async (req, res, next) => { + req.authorized_pubkey = 'abc123'; + next(); } } };