@actual-app/sync-server 25.5.0 → 25.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{app.js → build/app.js} +4 -5
- package/build/bin/actual-server.js +101 -0
- package/build/migrations/1694360000000-create-folders.js +21 -0
- package/{migrations → build/migrations}/1694360479680-create-account-db.js +2 -4
- package/{migrations → build/migrations}/1694362247011-create-secret-table.js +2 -4
- package/build/migrations/1702667624000-rename-nordigen-secrets.js +9 -0
- package/{migrations → build/migrations}/1718889148000-openid.js +4 -10
- package/{migrations → build/migrations}/1719409568000-multiuser.js +10 -26
- package/build/src/account-db.js +182 -0
- package/build/src/accounts/openid.js +287 -0
- package/build/src/accounts/password.js +98 -0
- package/build/src/app-account.js +125 -0
- package/build/src/app-admin.js +317 -0
- package/build/src/app-admin.test.js +303 -0
- package/build/src/app-gocardless/app-gocardless.js +193 -0
- package/build/src/app-gocardless/bank-factory.js +84 -0
- package/build/src/app-gocardless/banks/abanca_caglesmm.js +17 -0
- package/build/src/app-gocardless/banks/abnamro_abnanl2a.js +37 -0
- package/build/src/app-gocardless/banks/american_express_aesudef1.js +32 -0
- package/build/src/app-gocardless/banks/bancsabadell_bsabesbbb.js +22 -0
- package/build/src/app-gocardless/banks/bank.interface.js +1 -0
- package/build/src/app-gocardless/banks/bank_of_ireland_b365_bofiie2d.js +25 -0
- package/build/src/app-gocardless/banks/bankinter_bkbkesmm.js +18 -0
- package/build/src/app-gocardless/banks/belfius_gkccbebb.js +13 -0
- package/build/src/app-gocardless/banks/berliner_sparkasse_beladebexxx.js +48 -0
- package/build/src/app-gocardless/banks/bnp_be_gebabebb.js +64 -0
- package/build/src/app-gocardless/banks/boursobank_bousfrppxxx.js +73 -0
- package/build/src/app-gocardless/banks/cbc_cregbebb.js +27 -0
- package/build/src/app-gocardless/banks/commerzbank_cobadeff.js +43 -0
- package/build/src/app-gocardless/banks/danskebank_dabno22.js +26 -0
- package/build/src/app-gocardless/banks/direkt_heladef1822.js +13 -0
- package/build/src/app-gocardless/banks/easybank_bawaatww.js +42 -0
- package/build/src/app-gocardless/banks/entercard_swednokk.js +28 -0
- package/build/src/app-gocardless/banks/fortuneo_ftnofrp1xxx.js +34 -0
- package/build/src/app-gocardless/banks/hype_hyeeit22.js +63 -0
- package/build/src/app-gocardless/banks/ing_ingbrobu.js +56 -0
- package/build/src/app-gocardless/banks/ing_ingddeff.js +34 -0
- package/build/src/app-gocardless/banks/ing_pl_ingbplpw.js +29 -0
- package/build/src/app-gocardless/banks/integration-bank.js +78 -0
- package/build/src/app-gocardless/banks/isybank_itbbitmm.js +13 -0
- package/build/src/app-gocardless/banks/kbc_kredbebb.js +26 -0
- package/build/src/app-gocardless/banks/lhv-lhvbee22.js +24 -0
- package/build/src/app-gocardless/banks/mbank_retail_brexplpw.js +41 -0
- package/build/src/app-gocardless/banks/nationwide_naiagb21.js +32 -0
- package/build/src/app-gocardless/banks/nbg_ethngraaxxx.js +39 -0
- package/build/src/app-gocardless/banks/norwegian_xx_norwnok1.js +61 -0
- package/build/src/app-gocardless/banks/revolut_revolt21.js +20 -0
- package/build/src/app-gocardless/banks/sandboxfinance_sfin0000.js +21 -0
- package/build/src/app-gocardless/banks/seb_kort_bank_ab.js +63 -0
- package/build/src/app-gocardless/banks/seb_privat.js +19 -0
- package/build/src/app-gocardless/banks/sparnord_spnodk22.js +19 -0
- package/build/src/app-gocardless/banks/spk_karlsruhe_karsde66.js +48 -0
- package/build/src/app-gocardless/banks/spk_marburg_biedenkopf_heladef1mar.js +25 -0
- package/build/src/app-gocardless/banks/spk_worms_alzey_ried_malade51wor.js +14 -0
- package/build/src/app-gocardless/banks/ssk_dusseldorf_dussdeddxxx.js +36 -0
- package/build/src/app-gocardless/banks/swedbank_habalv22.js +30 -0
- package/build/src/app-gocardless/banks/tests/abanca_caglesmm.spec.js +17 -0
- package/build/src/app-gocardless/banks/tests/abnamro_abnanl2a.spec.js +45 -0
- package/build/src/app-gocardless/banks/tests/bancsabadell_bsabesbbb.spec.js +41 -0
- package/build/src/app-gocardless/banks/tests/belfius_gkccbebb.spec.js +16 -0
- package/build/src/app-gocardless/banks/tests/boursobank_bousfrppxxx.spec.js +102 -0
- package/build/src/app-gocardless/banks/tests/cbc_cregbebb.spec.js +24 -0
- package/build/src/app-gocardless/banks/tests/commerzbank_cobadeff.spec.js +105 -0
- package/build/src/app-gocardless/banks/tests/easybank_bawaatww.spec.js +36 -0
- package/build/src/app-gocardless/banks/tests/fortuneo_ftnofrp1xxx.spec.js +159 -0
- package/build/src/app-gocardless/banks/tests/ing_ingddeff.spec.js +267 -0
- package/build/src/app-gocardless/banks/tests/ing_pl_ingbplpw.spec.js +186 -0
- package/build/src/app-gocardless/banks/tests/integration_bank.spec.js +127 -0
- package/build/src/app-gocardless/banks/tests/kbc_kredbebb.spec.js +24 -0
- package/build/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js +50 -0
- package/build/src/app-gocardless/banks/tests/mbank_retail_brexplpw.spec.js +156 -0
- package/build/src/app-gocardless/banks/tests/nationwide_naiagb21.spec.js +64 -0
- package/build/src/app-gocardless/banks/tests/nbg_ethngraaxxx.spec.js +36 -0
- package/build/src/app-gocardless/banks/tests/revolut_revolt21.spec.js +30 -0
- package/build/src/app-gocardless/banks/tests/sandboxfinance_sfin0000.spec.js +112 -0
- package/build/src/app-gocardless/banks/tests/spk_marburg_biedenkopf_heladef1mar.spec.js +214 -0
- package/build/src/app-gocardless/banks/tests/ssk_dusseldorf_dussdeddxxx.spec.js +60 -0
- package/build/src/app-gocardless/banks/tests/swedbank_habalv22.spec.js +45 -0
- package/build/src/app-gocardless/banks/tests/virgin_nrnbgb22.spec.js +36 -0
- package/{src → build/src}/app-gocardless/banks/util/escape-regexp.js +1 -1
- package/{src → build/src}/app-gocardless/banks/util/extract-payeeName-from-remittanceInfo.js +11 -16
- package/build/src/app-gocardless/banks/virgin_nrnbgb22.js +31 -0
- package/build/src/app-gocardless/errors.js +67 -0
- package/build/src/app-gocardless/gocardless-node.types.js +1 -0
- package/build/src/app-gocardless/gocardless.types.js +1 -0
- package/build/src/app-gocardless/services/gocardless-service.js +504 -0
- package/build/src/app-gocardless/services/tests/fixtures.js +165 -0
- package/build/src/app-gocardless/services/tests/gocardless-service.spec.js +387 -0
- package/build/src/app-gocardless/tests/bank-factory.spec.js +13 -0
- package/build/src/app-gocardless/tests/utils.spec.js +158 -0
- package/build/src/app-gocardless/util/handle-error.js +15 -0
- package/build/src/app-gocardless/utils.js +41 -0
- package/build/src/app-openid.js +83 -0
- package/build/src/app-pluggyai/app-pluggyai.js +164 -0
- package/build/src/app-pluggyai/pluggyai-service.js +97 -0
- package/build/src/app-secrets.js +48 -0
- package/build/src/app-simplefin/app-simplefin.js +335 -0
- package/build/src/app-sync/errors.js +12 -0
- package/build/src/app-sync/services/files-service.js +158 -0
- package/build/src/app-sync/tests/services/files-service.test.js +192 -0
- package/build/src/app-sync/validation.js +65 -0
- package/build/src/app-sync.js +302 -0
- package/build/src/app-sync.test.js +655 -0
- package/build/src/app.js +138 -0
- package/build/src/config-types.js +1 -0
- package/build/src/db.js +50 -0
- package/build/src/load-config.js +274 -0
- package/build/src/migrations.js +23 -0
- package/build/src/scripts/disable-openid.js +31 -0
- package/build/src/scripts/enable-openid.js +36 -0
- package/build/src/scripts/health-check.js +16 -0
- package/build/src/scripts/reset-password.js +40 -0
- package/build/src/scripts/run-migrations.js +6 -0
- package/build/src/secrets.test.js +68 -0
- package/build/src/services/secrets-service.js +79 -0
- package/build/src/services/user-service.js +201 -0
- package/build/src/sync-simple.js +68 -0
- package/{src → build/src}/util/hash.js +1 -2
- package/build/src/util/middlewares.js +49 -0
- package/{src → build/src}/util/paths.js +3 -6
- package/build/src/util/payee-name.js +37 -0
- package/build/src/util/prompt.js +70 -0
- package/build/src/util/title/index.js +43 -0
- package/build/src/util/title/lower-case.js +90 -0
- package/build/src/util/title/specials.js +21 -0
- package/build/src/util/validate-user.js +55 -0
- package/package.json +32 -36
- package/bin/actual-server.js +0 -117
- package/migrations/1694360000000-create-folders.js +0 -25
- package/migrations/1702667624000-rename-nordigen-secrets.js +0 -19
- package/src/account-db.js +0 -239
- package/src/accounts/openid.js +0 -368
- package/src/accounts/password.js +0 -149
- package/src/app-account.js +0 -155
- package/src/app-admin.js +0 -410
- package/src/app-admin.test.js +0 -381
- package/src/app-gocardless/app-gocardless.js +0 -274
- package/src/app-gocardless/bank-factory.js +0 -91
- package/src/app-gocardless/banks/abanca_caglesmm.js +0 -22
- package/src/app-gocardless/banks/abnamro_abnanl2a.js +0 -57
- package/src/app-gocardless/banks/american_express_aesudef1.js +0 -40
- package/src/app-gocardless/banks/bancsabadell_bsabesbbb.js +0 -31
- package/src/app-gocardless/banks/bank.interface.ts +0 -51
- package/src/app-gocardless/banks/bank_of_ireland_b365_bofiie2d.js +0 -39
- package/src/app-gocardless/banks/bankinter_bkbkesmm.js +0 -24
- package/src/app-gocardless/banks/belfius_gkccbebb.js +0 -17
- package/src/app-gocardless/banks/berliner_sparkasse_beladebexxx.js +0 -61
- package/src/app-gocardless/banks/bnp_be_gebabebb.js +0 -73
- package/src/app-gocardless/banks/cbc_cregbebb.js +0 -34
- package/src/app-gocardless/banks/commerzbank_cobadeff.js +0 -54
- package/src/app-gocardless/banks/danskebank_dabno22.js +0 -39
- package/src/app-gocardless/banks/direkt_heladef1822.js +0 -18
- package/src/app-gocardless/banks/easybank_bawaatww.js +0 -50
- package/src/app-gocardless/banks/entercard_swednokk.js +0 -40
- package/src/app-gocardless/banks/fortuneo_ftnofrp1xxx.js +0 -46
- package/src/app-gocardless/banks/hype_hyeeit22.js +0 -74
- package/src/app-gocardless/banks/ing_ingbrobu.js +0 -70
- package/src/app-gocardless/banks/ing_ingddeff.js +0 -47
- package/src/app-gocardless/banks/ing_pl_ingbplpw.js +0 -46
- package/src/app-gocardless/banks/integration-bank.js +0 -115
- package/src/app-gocardless/banks/isybank_itbbitmm.js +0 -18
- package/src/app-gocardless/banks/kbc_kredbebb.js +0 -33
- package/src/app-gocardless/banks/lhv-lhvbee22.js +0 -36
- package/src/app-gocardless/banks/mbank_retail_brexplpw.js +0 -56
- package/src/app-gocardless/banks/nationwide_naiagb21.js +0 -46
- package/src/app-gocardless/banks/nbg_ethngraaxxx.js +0 -51
- package/src/app-gocardless/banks/norwegian_xx_norwnok1.js +0 -74
- package/src/app-gocardless/banks/revolut_revolt21.js +0 -37
- package/src/app-gocardless/banks/sandboxfinance_sfin0000.js +0 -28
- package/src/app-gocardless/banks/seb_kort_bank_ab.js +0 -59
- package/src/app-gocardless/banks/seb_privat.js +0 -29
- package/src/app-gocardless/banks/sparnord_spnodk22.js +0 -24
- package/src/app-gocardless/banks/spk_karlsruhe_karsde66.js +0 -61
- package/src/app-gocardless/banks/spk_marburg_biedenkopf_heladef1mar.js +0 -30
- package/src/app-gocardless/banks/spk_worms_alzey_ried_malade51wor.js +0 -19
- package/src/app-gocardless/banks/ssk_dusseldorf_dussdeddxxx.js +0 -50
- package/src/app-gocardless/banks/swedbank_habalv22.js +0 -47
- package/src/app-gocardless/banks/tests/abanca_caglesmm.spec.js +0 -21
- package/src/app-gocardless/banks/tests/abnamro_abnanl2a.spec.js +0 -61
- package/src/app-gocardless/banks/tests/bancsabadell_bsabesbbb.spec.js +0 -53
- package/src/app-gocardless/banks/tests/belfius_gkccbebb.spec.js +0 -22
- package/src/app-gocardless/banks/tests/cbc_cregbebb.spec.js +0 -34
- package/src/app-gocardless/banks/tests/commerzbank_cobadeff.spec.js +0 -133
- package/src/app-gocardless/banks/tests/easybank_bawaatww.spec.js +0 -54
- package/src/app-gocardless/banks/tests/fortuneo_ftnofrp1xxx.spec.js +0 -206
- package/src/app-gocardless/banks/tests/ing_ingddeff.spec.js +0 -302
- package/src/app-gocardless/banks/tests/ing_pl_ingbplpw.spec.js +0 -202
- package/src/app-gocardless/banks/tests/integration_bank.spec.js +0 -156
- package/src/app-gocardless/banks/tests/kbc_kredbebb.spec.js +0 -38
- package/src/app-gocardless/banks/tests/lhv-lhvbee22.spec.js +0 -68
- package/src/app-gocardless/banks/tests/mbank_retail_brexplpw.spec.js +0 -171
- package/src/app-gocardless/banks/tests/nationwide_naiagb21.spec.js +0 -105
- package/src/app-gocardless/banks/tests/nbg_ethngraaxxx.spec.js +0 -48
- package/src/app-gocardless/banks/tests/revolut_revolt21.spec.js +0 -42
- package/src/app-gocardless/banks/tests/sandboxfinance_sfin0000.spec.js +0 -133
- package/src/app-gocardless/banks/tests/spk_marburg_biedenkopf_heladef1mar.spec.js +0 -255
- package/src/app-gocardless/banks/tests/ssk_dusseldorf_dussdeddxxx.spec.js +0 -100
- package/src/app-gocardless/banks/tests/swedbank_habalv22.spec.js +0 -57
- package/src/app-gocardless/banks/tests/virgin_nrnbgb22.spec.js +0 -54
- package/src/app-gocardless/banks/virgin_nrnbgb22.js +0 -39
- package/src/app-gocardless/errors.js +0 -84
- package/src/app-gocardless/gocardless-node.types.ts +0 -497
- package/src/app-gocardless/gocardless.types.ts +0 -93
- package/src/app-gocardless/link.html +0 -18
- package/src/app-gocardless/services/gocardless-service.js +0 -620
- package/src/app-gocardless/services/tests/fixtures.js +0 -181
- package/src/app-gocardless/services/tests/gocardless-service.spec.js +0 -537
- package/src/app-gocardless/tests/bank-factory.spec.js +0 -20
- package/src/app-gocardless/tests/utils.spec.js +0 -162
- package/src/app-gocardless/util/handle-error.js +0 -16
- package/src/app-gocardless/utils.js +0 -45
- package/src/app-openid.js +0 -108
- package/src/app-pluggyai/app-pluggyai.js +0 -215
- package/src/app-pluggyai/pluggyai-service.js +0 -120
- package/src/app-secrets.js +0 -61
- package/src/app-simplefin/app-simplefin.js +0 -405
- package/src/app-sync/errors.js +0 -13
- package/src/app-sync/services/files-service.js +0 -243
- package/src/app-sync/tests/services/files-service.test.js +0 -247
- package/src/app-sync/validation.js +0 -77
- package/src/app-sync.js +0 -391
- package/src/app-sync.test.js +0 -877
- package/src/app.js +0 -149
- package/src/config-types.ts +0 -44
- package/src/db.js +0 -58
- package/src/load-config.js +0 -307
- package/src/migrations.js +0 -36
- package/src/run-migrations.js +0 -8
- package/src/scripts/disable-openid.js +0 -44
- package/src/scripts/enable-openid.js +0 -53
- package/src/scripts/health-check.js +0 -23
- package/src/scripts/reset-password.js +0 -51
- package/src/secrets.test.js +0 -83
- package/src/services/secrets-service.js +0 -94
- package/src/services/user-service.js +0 -272
- package/src/sync-simple.js +0 -95
- package/src/util/middlewares.js +0 -62
- package/src/util/payee-name.js +0 -45
- package/src/util/prompt.js +0 -88
- package/src/util/title/index.js +0 -59
- package/src/util/title/lower-case.js +0 -93
- package/src/util/title/specials.js +0 -21
- package/src/util/validate-user.js +0 -68
- /package/{src → build/src}/sql/messages.sql +0 -0
package/{app.js → build/app.js}
RENAMED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { run as runMigrations } from './src/migrations.js';
|
|
2
|
-
|
|
3
2
|
runMigrations()
|
|
4
|
-
|
|
3
|
+
.then(() => {
|
|
5
4
|
//import the app here becasue initial migrations need to be run first - they are dependencies of the app.js
|
|
6
5
|
import('./src/app.js').then(app => app.run()); // run the app
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
})
|
|
7
|
+
.catch(err => {
|
|
9
8
|
console.log('Error starting app:', err);
|
|
10
9
|
process.exit(1);
|
|
11
|
-
|
|
10
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { parseArgs } from 'node:util';
|
|
6
|
+
const args = process.argv;
|
|
7
|
+
const options = {
|
|
8
|
+
help: {
|
|
9
|
+
type: 'boolean',
|
|
10
|
+
short: 'h',
|
|
11
|
+
},
|
|
12
|
+
version: {
|
|
13
|
+
type: 'boolean',
|
|
14
|
+
short: 'v',
|
|
15
|
+
},
|
|
16
|
+
config: {
|
|
17
|
+
type: 'string',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const { values } = parseArgs({
|
|
21
|
+
args,
|
|
22
|
+
options,
|
|
23
|
+
allowPositionals: true,
|
|
24
|
+
});
|
|
25
|
+
if (values.help) {
|
|
26
|
+
console.log([
|
|
27
|
+
'usage: actual-server [options]',
|
|
28
|
+
'',
|
|
29
|
+
'options:',
|
|
30
|
+
' --config Path to config file',
|
|
31
|
+
'',
|
|
32
|
+
' -h --help Print this list and exit.',
|
|
33
|
+
' -v --version Print the version and exit.',
|
|
34
|
+
'',
|
|
35
|
+
'Examples:',
|
|
36
|
+
'',
|
|
37
|
+
'Runs actual-server with default configuration',
|
|
38
|
+
' actual-server',
|
|
39
|
+
'',
|
|
40
|
+
'Runs actual-server with custom configuration',
|
|
41
|
+
' actual-server --config ./config.json',
|
|
42
|
+
].join('\n'));
|
|
43
|
+
process.exit();
|
|
44
|
+
}
|
|
45
|
+
if (values.version) {
|
|
46
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
47
|
+
const packageJsonPath = resolve(__dirname, '../../package.json');
|
|
48
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
49
|
+
console.log('v' + packageJson.version);
|
|
50
|
+
process.exit();
|
|
51
|
+
}
|
|
52
|
+
const setupDataDir = (dataDir = undefined) => {
|
|
53
|
+
if (process.env.ACTUAL_DATA_DIR) {
|
|
54
|
+
return; // Env variables must not be overwritten
|
|
55
|
+
}
|
|
56
|
+
if (dataDir) {
|
|
57
|
+
process.env.ACTUAL_DATA_DIR = dataDir; // Use the dir specified
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Setup defaults
|
|
61
|
+
if (existsSync('./data')) {
|
|
62
|
+
// The default data directory exists - use it
|
|
63
|
+
console.info('Found existing data directory');
|
|
64
|
+
process.env.ACTUAL_DATA_DIR = resolve('./data');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.info('Using default data directory. You can specify a custom config with --config');
|
|
68
|
+
process.env.ACTUAL_DATA_DIR = resolve('./');
|
|
69
|
+
}
|
|
70
|
+
console.info(`Data directory: ${process.env.ACTUAL_DATA_DIR}`);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
if (values.config) {
|
|
74
|
+
const configExists = existsSync(values.config);
|
|
75
|
+
if (!configExists) {
|
|
76
|
+
console.log(`Please specify a valid config path. The path ${values.config} does not exist.`);
|
|
77
|
+
process.exit();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
console.log(`Loading config from ${values.config}`);
|
|
81
|
+
const configJson = JSON.parse(readFileSync(values.config, 'utf-8'));
|
|
82
|
+
process.env.ACTUAL_CONFIG_PATH = values.config;
|
|
83
|
+
setupDataDir(configJson.dataDir);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// If no config is specified, check for a default config in the current directory
|
|
88
|
+
const defaultConfigJsonFile = './config.json';
|
|
89
|
+
const configExists = existsSync(defaultConfigJsonFile);
|
|
90
|
+
if (configExists) {
|
|
91
|
+
console.info('Found config.json in the current directory');
|
|
92
|
+
const configJson = JSON.parse(readFileSync(defaultConfigJsonFile, 'utf-8'));
|
|
93
|
+
process.env.ACTUAL_CONFIG_PATH = defaultConfigJsonFile;
|
|
94
|
+
setupDataDir(configJson.dataDir);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
setupDataDir(); // No default config exists - setup data dir with defaults
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// start the sync server
|
|
101
|
+
import('../app.js');
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import { config } from '../src/load-config.js';
|
|
3
|
+
async function ensureExists(path) {
|
|
4
|
+
try {
|
|
5
|
+
await fs.mkdir(path);
|
|
6
|
+
}
|
|
7
|
+
catch (err) {
|
|
8
|
+
if (err.code === 'EEXIST') {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
throw err;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export const up = async function () {
|
|
15
|
+
await ensureExists(config.get('serverFiles'));
|
|
16
|
+
await ensureExists(config.get('userFiles'));
|
|
17
|
+
};
|
|
18
|
+
export const down = async function () {
|
|
19
|
+
await fs.rm(config.get('serverFiles'), { recursive: true, force: true });
|
|
20
|
+
await fs.rm(config.get('userFiles'), { recursive: true, force: true });
|
|
21
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getAccountDb } from '../src/account-db.js';
|
|
2
|
-
|
|
3
2
|
export const up = async function () {
|
|
4
|
-
|
|
3
|
+
await getAccountDb().exec(`
|
|
5
4
|
CREATE TABLE IF NOT EXISTS auth
|
|
6
5
|
(password TEXT PRIMARY KEY);
|
|
7
6
|
|
|
@@ -20,9 +19,8 @@ export const up = async function () {
|
|
|
20
19
|
name TEXT);
|
|
21
20
|
`);
|
|
22
21
|
};
|
|
23
|
-
|
|
24
22
|
export const down = async function () {
|
|
25
|
-
|
|
23
|
+
await getAccountDb().exec(`
|
|
26
24
|
DROP TABLE auth;
|
|
27
25
|
DROP TABLE sessions;
|
|
28
26
|
DROP TABLE files;
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { getAccountDb } from '../src/account-db.js';
|
|
2
|
-
|
|
3
2
|
export const up = async function () {
|
|
4
|
-
|
|
3
|
+
await getAccountDb().exec(`
|
|
5
4
|
CREATE TABLE IF NOT EXISTS secrets (
|
|
6
5
|
name TEXT PRIMARY KEY,
|
|
7
6
|
value BLOB
|
|
8
7
|
);
|
|
9
8
|
`);
|
|
10
9
|
};
|
|
11
|
-
|
|
12
10
|
export const down = async function () {
|
|
13
|
-
|
|
11
|
+
await getAccountDb().exec(`
|
|
14
12
|
DROP TABLE secrets;
|
|
15
13
|
`);
|
|
16
14
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { getAccountDb } from '../src/account-db.js';
|
|
2
|
+
export const up = async function () {
|
|
3
|
+
await getAccountDb().exec(`UPDATE secrets SET name = 'gocardless_secretId' WHERE name = 'nordigen_secretId'`);
|
|
4
|
+
await getAccountDb().exec(`UPDATE secrets SET name = 'gocardless_secretKey' WHERE name = 'nordigen_secretKey'`);
|
|
5
|
+
};
|
|
6
|
+
export const down = async function () {
|
|
7
|
+
await getAccountDb().exec(`UPDATE secrets SET name = 'nordigen_secretId' WHERE name = 'gocardless_secretId'`);
|
|
8
|
+
await getAccountDb().exec(`UPDATE secrets SET name = 'nordigen_secretKey' WHERE name = 'gocardless_secretKey'`);
|
|
9
|
+
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { getAccountDb } from '../src/account-db.js';
|
|
2
|
-
|
|
3
2
|
export const up = async function () {
|
|
4
|
-
|
|
5
|
-
`
|
|
3
|
+
await getAccountDb().exec(`
|
|
6
4
|
BEGIN TRANSACTION;
|
|
7
5
|
CREATE TABLE auth_new
|
|
8
6
|
(method TEXT PRIMARY KEY,
|
|
@@ -19,13 +17,10 @@ export const up = async function () {
|
|
|
19
17
|
code_verifier TEXT,
|
|
20
18
|
return_url TEXT,
|
|
21
19
|
expiry_time INTEGER);
|
|
22
|
-
COMMIT
|
|
23
|
-
);
|
|
20
|
+
COMMIT;`);
|
|
24
21
|
};
|
|
25
|
-
|
|
26
22
|
export const down = async function () {
|
|
27
|
-
|
|
28
|
-
`
|
|
23
|
+
await getAccountDb().exec(`
|
|
29
24
|
BEGIN TRANSACTION;
|
|
30
25
|
ALTER TABLE auth RENAME TO auth_temp;
|
|
31
26
|
CREATE TABLE auth
|
|
@@ -36,6 +31,5 @@ export const down = async function () {
|
|
|
36
31
|
|
|
37
32
|
DROP TABLE pending_openid_requests;
|
|
38
33
|
COMMIT;
|
|
39
|
-
|
|
40
|
-
);
|
|
34
|
+
`);
|
|
41
35
|
};
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
-
|
|
3
2
|
import { getAccountDb } from '../src/account-db.js';
|
|
4
|
-
|
|
5
3
|
export const up = async function () {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
accountDb.exec(
|
|
10
|
-
`
|
|
4
|
+
const accountDb = getAccountDb();
|
|
5
|
+
accountDb.transaction(() => {
|
|
6
|
+
accountDb.exec(`
|
|
11
7
|
CREATE TABLE users
|
|
12
8
|
(id TEXT PRIMARY KEY,
|
|
13
9
|
user_name TEXT,
|
|
@@ -35,25 +31,14 @@ export const up = async function () {
|
|
|
35
31
|
|
|
36
32
|
ALTER TABLE sessions
|
|
37
33
|
ADD COLUMN auth_method TEXT;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
'INSERT INTO users (id, user_name, display_name, enabled, owner, role) VALUES (?, ?, ?, 1, 1, ?)',
|
|
44
|
-
[userId, '', '', 'ADMIN'],
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
accountDb.mutate(
|
|
48
|
-
'UPDATE sessions SET user_id = ?, expires_at = ?, auth_method = ? WHERE auth_method IS NULL',
|
|
49
|
-
[userId, -1, 'password'],
|
|
50
|
-
);
|
|
51
|
-
});
|
|
34
|
+
`);
|
|
35
|
+
const userId = uuidv4();
|
|
36
|
+
accountDb.mutate('INSERT INTO users (id, user_name, display_name, enabled, owner, role) VALUES (?, ?, ?, 1, 1, ?)', [userId, '', '', 'ADMIN']);
|
|
37
|
+
accountDb.mutate('UPDATE sessions SET user_id = ?, expires_at = ?, auth_method = ? WHERE auth_method IS NULL', [userId, -1, 'password']);
|
|
38
|
+
});
|
|
52
39
|
};
|
|
53
|
-
|
|
54
40
|
export const down = async function () {
|
|
55
|
-
|
|
56
|
-
`
|
|
41
|
+
await getAccountDb().exec(`
|
|
57
42
|
BEGIN TRANSACTION;
|
|
58
43
|
|
|
59
44
|
DROP TABLE IF EXISTS user_access;
|
|
@@ -111,6 +96,5 @@ export const down = async function () {
|
|
|
111
96
|
DROP TABLE IF EXISTS users;
|
|
112
97
|
|
|
113
98
|
COMMIT;
|
|
114
|
-
|
|
115
|
-
);
|
|
99
|
+
`);
|
|
116
100
|
};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { join, resolve } from 'node:path';
|
|
2
|
+
import * as bcrypt from 'bcrypt';
|
|
3
|
+
import { bootstrapOpenId } from './accounts/openid.js';
|
|
4
|
+
import { bootstrapPassword, loginWithPassword } from './accounts/password.js';
|
|
5
|
+
import { openDatabase } from './db.js';
|
|
6
|
+
import { config } from './load-config.js';
|
|
7
|
+
let _accountDb;
|
|
8
|
+
export function getAccountDb() {
|
|
9
|
+
if (_accountDb === undefined) {
|
|
10
|
+
const dbPath = join(resolve(config.get('serverFiles')), 'account.sqlite');
|
|
11
|
+
_accountDb = openDatabase(dbPath);
|
|
12
|
+
}
|
|
13
|
+
return _accountDb;
|
|
14
|
+
}
|
|
15
|
+
export function needsBootstrap() {
|
|
16
|
+
const accountDb = getAccountDb();
|
|
17
|
+
const rows = accountDb.all('SELECT * FROM auth');
|
|
18
|
+
return rows.length === 0;
|
|
19
|
+
}
|
|
20
|
+
export function listLoginMethods() {
|
|
21
|
+
const accountDb = getAccountDb();
|
|
22
|
+
const rows = accountDb.all('SELECT method, display_name, active FROM auth');
|
|
23
|
+
return rows
|
|
24
|
+
.filter(f => rows.length > 1 && config.get('enforceOpenId')
|
|
25
|
+
? f.method === 'openid'
|
|
26
|
+
: true)
|
|
27
|
+
.map(r => ({
|
|
28
|
+
method: r.method,
|
|
29
|
+
active: r.active,
|
|
30
|
+
displayName: r.display_name,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
export function getActiveLoginMethod() {
|
|
34
|
+
const accountDb = getAccountDb();
|
|
35
|
+
const { method } = accountDb.first('SELECT method FROM auth WHERE active = 1') || {};
|
|
36
|
+
return method;
|
|
37
|
+
}
|
|
38
|
+
/*
|
|
39
|
+
* Get the Login Method in the following order
|
|
40
|
+
* req (the frontend can say which method in the case it wants to resort to forcing password auth)
|
|
41
|
+
* config options
|
|
42
|
+
* fall back to using password
|
|
43
|
+
*/
|
|
44
|
+
export function getLoginMethod(req) {
|
|
45
|
+
if (typeof req !== 'undefined' &&
|
|
46
|
+
(req.body || { loginMethod: null }).loginMethod &&
|
|
47
|
+
config.get('allowedLoginMethods').includes(req.body.loginMethod)) {
|
|
48
|
+
return req.body.loginMethod;
|
|
49
|
+
}
|
|
50
|
+
//BY-PASS ANY OTHER CONFIGURATION TO ENSURE HEADER AUTH
|
|
51
|
+
if (config.get('loginMethod') === 'header' &&
|
|
52
|
+
config.get('allowedLoginMethods').includes('header')) {
|
|
53
|
+
return config.get('loginMethod');
|
|
54
|
+
}
|
|
55
|
+
const activeMethod = getActiveLoginMethod();
|
|
56
|
+
return activeMethod || config.get('loginMethod');
|
|
57
|
+
}
|
|
58
|
+
export async function bootstrap(loginSettings, forced = false) {
|
|
59
|
+
if (!loginSettings) {
|
|
60
|
+
return { error: 'invalid-login-settings' };
|
|
61
|
+
}
|
|
62
|
+
const passEnabled = 'password' in loginSettings;
|
|
63
|
+
const openIdEnabled = 'openId' in loginSettings;
|
|
64
|
+
const accountDb = getAccountDb();
|
|
65
|
+
accountDb.mutate('BEGIN TRANSACTION');
|
|
66
|
+
try {
|
|
67
|
+
const { countOfOwner } = accountDb.first(`SELECT count(*) as countOfOwner
|
|
68
|
+
FROM users
|
|
69
|
+
WHERE users.user_name <> '' and users.owner = 1`) || {};
|
|
70
|
+
if (!forced && (!openIdEnabled || countOfOwner > 0)) {
|
|
71
|
+
if (!needsBootstrap()) {
|
|
72
|
+
accountDb.mutate('ROLLBACK');
|
|
73
|
+
return { error: 'already-bootstrapped' };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (!passEnabled && !openIdEnabled) {
|
|
77
|
+
accountDb.mutate('ROLLBACK');
|
|
78
|
+
return { error: 'no-auth-method-selected' };
|
|
79
|
+
}
|
|
80
|
+
if (passEnabled && openIdEnabled && !forced) {
|
|
81
|
+
accountDb.mutate('ROLLBACK');
|
|
82
|
+
return { error: 'max-one-method-allowed' };
|
|
83
|
+
}
|
|
84
|
+
if (passEnabled) {
|
|
85
|
+
const { error } = bootstrapPassword(loginSettings.password);
|
|
86
|
+
if (error) {
|
|
87
|
+
accountDb.mutate('ROLLBACK');
|
|
88
|
+
return { error };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (openIdEnabled && forced) {
|
|
92
|
+
const { error } = await bootstrapOpenId(loginSettings.openId);
|
|
93
|
+
if (error) {
|
|
94
|
+
accountDb.mutate('ROLLBACK');
|
|
95
|
+
return { error };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
accountDb.mutate('COMMIT');
|
|
99
|
+
return passEnabled ? loginWithPassword(loginSettings.password) : {};
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
accountDb.mutate('ROLLBACK');
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export function isAdmin(userId) {
|
|
107
|
+
return hasPermission(userId, 'ADMIN');
|
|
108
|
+
}
|
|
109
|
+
export function hasPermission(userId, permission) {
|
|
110
|
+
return getUserPermission(userId) === permission;
|
|
111
|
+
}
|
|
112
|
+
export async function enableOpenID(loginSettings) {
|
|
113
|
+
if (!loginSettings || !loginSettings.openId) {
|
|
114
|
+
return { error: 'invalid-login-settings' };
|
|
115
|
+
}
|
|
116
|
+
const { error } = (await bootstrapOpenId(loginSettings.openId)) || {};
|
|
117
|
+
if (error) {
|
|
118
|
+
return { error };
|
|
119
|
+
}
|
|
120
|
+
getAccountDb().mutate('DELETE FROM sessions');
|
|
121
|
+
}
|
|
122
|
+
export async function disableOpenID(loginSettings) {
|
|
123
|
+
if (!loginSettings || !loginSettings.password) {
|
|
124
|
+
return { error: 'invalid-login-settings' };
|
|
125
|
+
}
|
|
126
|
+
const accountDb = getAccountDb();
|
|
127
|
+
const { extra_data: passwordHash } = accountDb.first('SELECT extra_data FROM auth WHERE method = ?', [
|
|
128
|
+
'password',
|
|
129
|
+
]) || {};
|
|
130
|
+
if (!passwordHash) {
|
|
131
|
+
return { error: 'invalid-password' };
|
|
132
|
+
}
|
|
133
|
+
if (!loginSettings?.password) {
|
|
134
|
+
return { error: 'invalid-password' };
|
|
135
|
+
}
|
|
136
|
+
if (passwordHash) {
|
|
137
|
+
const confirmed = bcrypt.compareSync(loginSettings.password, passwordHash);
|
|
138
|
+
if (!confirmed) {
|
|
139
|
+
return { error: 'invalid-password' };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const { error } = (await bootstrapPassword(loginSettings.password)) || {};
|
|
143
|
+
if (error) {
|
|
144
|
+
return { error };
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
accountDb.transaction(() => {
|
|
148
|
+
accountDb.mutate('DELETE FROM sessions');
|
|
149
|
+
accountDb.mutate(`DELETE FROM user_access
|
|
150
|
+
WHERE user_access.user_id IN (
|
|
151
|
+
SELECT users.id
|
|
152
|
+
FROM users
|
|
153
|
+
WHERE users.user_name <> ?
|
|
154
|
+
);`, ['']);
|
|
155
|
+
accountDb.mutate('DELETE FROM users WHERE user_name <> ?', ['']);
|
|
156
|
+
accountDb.mutate('DELETE FROM auth WHERE method = ?', ['openid']);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
console.error('Error cleaning up openid information:', err);
|
|
161
|
+
return { error: 'database-error' };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export function getSession(token) {
|
|
165
|
+
const accountDb = getAccountDb();
|
|
166
|
+
return accountDb.first('SELECT * FROM sessions WHERE token = ?', [token]);
|
|
167
|
+
}
|
|
168
|
+
export function getUserInfo(userId) {
|
|
169
|
+
const accountDb = getAccountDb();
|
|
170
|
+
return accountDb.first('SELECT * FROM users WHERE id = ?', [userId]);
|
|
171
|
+
}
|
|
172
|
+
export function getUserPermission(userId) {
|
|
173
|
+
const accountDb = getAccountDb();
|
|
174
|
+
const { role } = accountDb.first(`SELECT role FROM users
|
|
175
|
+
WHERE users.id = ?`, [userId]) || { role: '' };
|
|
176
|
+
return role;
|
|
177
|
+
}
|
|
178
|
+
export function clearExpiredSessions() {
|
|
179
|
+
const clearThreshold = Math.floor(Date.now() / 1000) - 3600;
|
|
180
|
+
const deletedSessions = getAccountDb().mutate('DELETE FROM sessions WHERE expires_at <> -1 and expires_at < ?', [clearThreshold]).changes;
|
|
181
|
+
console.log(`Deleted ${deletedSessions} old sessions`);
|
|
182
|
+
}
|