Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
kresusapp
kresus
Commits
f4cd2c51
Commit
f4cd2c51
authored
Apr 11, 2020
by
Antoine
Browse files
[server] Force the declaration of variable with const, when the variable is not reassigned.
parent
09e30d57
Pipeline
#294382
passed with stages
in 4 minutes and 56 seconds
Changes
27
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
.eslintrc.yml
View file @
f4cd2c51
...
...
@@ -31,7 +31,10 @@
# 'plugin:@typescript-eslint/recommended' sets it to "warn"
'
@typescript-eslint/no-unused-vars'
:
-
2
-
files
:
'
server/**/*.js'
rules
:
prefer-const
:
-
2
rules
:
prettier/prettier
:
...
...
server/controllers/accesses.js
View file @
f4cd2c51
...
...
@@ -10,13 +10,13 @@ import { isDemoEnabled } from './settings';
import
{
asyncErr
,
getErrorCode
,
KError
,
makeLogger
}
from
'
../helpers
'
;
import
{
checkHasAllFields
,
checkAllowedFields
}
from
'
../shared/validators
'
;
le
t
log
=
makeLogger
(
'
controllers/accesses
'
);
cons
t
log
=
makeLogger
(
'
controllers/accesses
'
);
// Preloads a bank access (sets @access).
export
async
function
preloadAccess
(
req
,
res
,
next
,
accessId
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
access
=
await
Access
.
find
(
userId
,
accessId
);
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
access
=
await
Access
.
find
(
userId
,
accessId
);
if
(
!
access
)
{
throw
new
KError
(
'
bank access not found
'
,
404
);
}
...
...
@@ -37,7 +37,7 @@ export async function destroyWithData(userId, access) {
// Destroy a given access, including accounts, alerts and operations.
export
async
function
destroy
(
req
,
res
)
{
try
{
le
t
{
cons
t
{
user
:
{
id
:
userId
}
}
=
req
;
...
...
@@ -53,7 +53,7 @@ export async function destroy(req, res) {
}
export
async
function
createAndRetrieveData
(
userId
,
params
)
{
le
t
error
=
cons
t
error
=
checkHasAllFields
(
params
,
[
'
vendorId
'
,
'
login
'
,
'
password
'
])
||
checkAllowedFields
(
params
,
[
'
vendorId
'
,
'
login
'
,
'
password
'
,
'
fields
'
,
'
customLabel
'
]);
if
(
error
)
{
...
...
@@ -64,7 +64,7 @@ export async function createAndRetrieveData(userId, params) {
try
{
access
=
await
Access
.
create
(
userId
,
params
);
await
accountManager
.
retrieveAndAddAccountsByAccess
(
userId
,
access
,
/* interactive */
true
);
le
t
{
accounts
,
newOperations
}
=
await
accountManager
.
retrieveOperationsByAccess
(
cons
t
{
accounts
,
newOperations
}
=
await
accountManager
.
retrieveOperationsByAccess
(
userId
,
access
,
/* ignoreLastFetchDate */
false
,
...
...
@@ -93,7 +93,7 @@ export async function createAndRetrieveData(userId, params) {
// password)), and retrieves its accounts and operations.
export
async
function
create
(
req
,
res
)
{
try
{
le
t
{
cons
t
{
user
:
{
id
:
userId
}
}
=
req
;
...
...
@@ -111,16 +111,16 @@ export async function create(req, res) {
// Fetch operations using the backend and return the operations to the client.
export
async
function
fetchOperations
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
access
=
req
.
preloaded
.
access
;
le
t
bankVendor
=
bankVendorByUuid
(
access
.
vendorId
);
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
access
=
req
.
preloaded
.
access
;
cons
t
bankVendor
=
bankVendorByUuid
(
access
.
vendorId
);
if
(
!
access
.
isEnabled
()
||
bankVendor
.
deprecated
)
{
le
t
errcode
=
getErrorCode
(
'
DISABLED_ACCESS
'
);
cons
t
errcode
=
getErrorCode
(
'
DISABLED_ACCESS
'
);
throw
new
KError
(
'
disabled access
'
,
403
,
errcode
);
}
le
t
{
accounts
,
newOperations
}
=
await
accountManager
.
retrieveOperationsByAccess
(
cons
t
{
accounts
,
newOperations
}
=
await
accountManager
.
retrieveOperationsByAccess
(
userId
,
access
,
/* ignoreLastFetchDate */
false
,
...
...
@@ -140,18 +140,18 @@ export async function fetchOperations(req, res) {
// return both to the client.
export
async
function
fetchAccounts
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
access
=
req
.
preloaded
.
access
;
le
t
bankVendor
=
bankVendorByUuid
(
access
.
vendorId
);
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
access
=
req
.
preloaded
.
access
;
cons
t
bankVendor
=
bankVendorByUuid
(
access
.
vendorId
);
if
(
!
access
.
isEnabled
()
||
bankVendor
.
deprecated
)
{
le
t
errcode
=
getErrorCode
(
'
DISABLED_ACCESS
'
);
cons
t
errcode
=
getErrorCode
(
'
DISABLED_ACCESS
'
);
throw
new
KError
(
'
disabled access
'
,
403
,
errcode
);
}
await
accountManager
.
retrieveAndAddAccountsByAccess
(
userId
,
access
,
/* interactive */
true
);
le
t
{
accounts
,
newOperations
}
=
await
accountManager
.
retrieveOperationsByAccess
(
cons
t
{
accounts
,
newOperations
}
=
await
accountManager
.
retrieveOperationsByAccess
(
userId
,
access
,
/* ignoreLastFetchDate */
true
,
...
...
@@ -171,7 +171,7 @@ export async function fetchAccounts(req, res) {
// any regular poll.
export
async
function
poll
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
id
:
userId
}
=
req
.
user
;
await
fullPoll
(
userId
);
res
.
status
(
200
).
json
({
status
:
'
OK
'
...
...
@@ -188,12 +188,12 @@ export async function poll(req, res) {
// Updates a bank access.
export
async
function
update
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
{
access
}
=
req
.
preloaded
;
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
access
}
=
req
.
preloaded
;
le
t
attrs
=
req
.
body
;
cons
t
attrs
=
req
.
body
;
le
t
error
=
checkAllowedFields
(
attrs
,
[
'
enabled
'
,
'
customLabel
'
]);
cons
t
error
=
checkAllowedFields
(
attrs
,
[
'
enabled
'
,
'
customLabel
'
]);
if
(
error
)
{
throw
new
KError
(
`when updating an access:
${
error
}
`
,
400
);
}
...
...
@@ -216,22 +216,22 @@ export async function update(req, res) {
export
async
function
updateAndFetchAccounts
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
{
access
}
=
req
.
preloaded
;
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
access
}
=
req
.
preloaded
;
le
t
attrs
=
req
.
body
;
cons
t
attrs
=
req
.
body
;
le
t
error
=
checkAllowedFields
(
attrs
,
[
'
login
'
,
'
password
'
,
'
fields
'
]);
cons
t
error
=
checkAllowedFields
(
attrs
,
[
'
login
'
,
'
password
'
,
'
fields
'
]);
if
(
error
)
{
throw
new
KError
(
`when updating and polling an access:
${
error
}
`
,
400
);
}
if
(
typeof
attrs
.
fields
!==
'
undefined
'
)
{
le
t
newFields
=
attrs
.
fields
;
cons
t
newFields
=
attrs
.
fields
;
delete
attrs
.
fields
;
for
(
le
t
{
name
,
value
}
of
newFields
)
{
le
t
previous
=
access
.
fields
.
find
(
existing
=>
existing
.
name
===
name
);
for
(
cons
t
{
name
,
value
}
of
newFields
)
{
cons
t
previous
=
access
.
fields
.
find
(
existing
=>
existing
.
name
===
name
);
if
(
value
===
null
)
{
// Delete the custom field if necessary.
if
(
typeof
previous
!==
'
undefined
'
)
{
...
...
server/controllers/accounts.js
View file @
f4cd2c51
...
...
@@ -5,13 +5,13 @@ import accountManager from '../lib/accounts-manager';
import
{
isDemoEnabled
}
from
'
./settings
'
;
le
t
log
=
makeLogger
(
'
controllers/accounts
'
);
cons
t
log
=
makeLogger
(
'
controllers/accounts
'
);
// Prefills the @account field with a queried bank account.
export
async
function
preloadAccount
(
req
,
res
,
next
,
accountID
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
account
=
await
Account
.
find
(
userId
,
accountID
);
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
account
=
await
Account
.
find
(
userId
,
accountID
);
if
(
!
account
)
{
throw
new
KError
(
'
Bank account not found
'
,
404
);
}
...
...
@@ -23,9 +23,9 @@ export async function preloadAccount(req, res, next, accountID) {
}
export
async
function
fixupDefaultAccount
(
userId
)
{
le
t
found
=
await
Setting
.
findOrCreateDefault
(
userId
,
'
default-account-id
'
);
cons
t
found
=
await
Setting
.
findOrCreateDefault
(
userId
,
'
default-account-id
'
);
if
(
found
&&
found
.
value
!==
''
)
{
le
t
accountFound
=
await
Account
.
find
(
userId
,
found
.
value
);
cons
t
accountFound
=
await
Account
.
find
(
userId
,
found
.
value
);
if
(
!
accountFound
)
{
log
.
info
(
"
-> Removing the default account setting since the account doesn't exist anymore.
"
...
...
@@ -45,7 +45,7 @@ export async function destroyWithOperations(userId, account) {
await
fixupDefaultAccount
(
userId
);
le
t
accounts
=
await
Account
.
byAccess
(
userId
,
{
id
:
account
.
accessId
});
cons
t
accounts
=
await
Account
.
byAccess
(
userId
,
{
id
:
account
.
accessId
});
if
(
accounts
&&
accounts
.
length
===
0
)
{
log
.
info
(
'
\t
-> No other accounts bound: destroying access.
'
);
await
Access
.
destroy
(
userId
,
account
.
accessId
);
...
...
@@ -54,16 +54,16 @@ export async function destroyWithOperations(userId, account) {
export
async
function
update
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
id
:
userId
}
=
req
.
user
;
le
t
newFields
=
req
.
body
;
le
t
error
=
checkAllowedFields
(
newFields
,
[
'
excludeFromBalance
'
,
'
customLabel
'
]);
cons
t
newFields
=
req
.
body
;
cons
t
error
=
checkAllowedFields
(
newFields
,
[
'
excludeFromBalance
'
,
'
customLabel
'
]);
if
(
error
)
{
throw
new
KError
(
`when updating an account:
${
error
}
`
,
400
);
}
le
t
account
=
req
.
preloaded
.
account
;
le
t
newAccount
=
await
Account
.
update
(
userId
,
account
.
id
,
newFields
);
cons
t
account
=
req
.
preloaded
.
account
;
cons
t
newAccount
=
await
Account
.
update
(
userId
,
account
.
id
,
newFields
);
res
.
status
(
200
).
json
(
newAccount
);
}
catch
(
err
)
{
return
asyncErr
(
res
,
err
,
'
when updating an account
'
);
...
...
@@ -73,7 +73,7 @@ export async function update(req, res) {
// Delete account, operations and alerts.
export
async
function
destroy
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
id
:
userId
}
=
req
.
user
;
if
(
await
isDemoEnabled
(
userId
))
{
throw
new
KError
(
"
account deletion isn't allowed in demo mode
"
,
400
);
...
...
@@ -88,9 +88,9 @@ export async function destroy(req, res) {
export
async
function
resyncBalance
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
account
=
req
.
preloaded
.
account
;
le
t
updatedAccount
=
await
accountManager
.
resyncAccountBalance
(
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
account
=
req
.
preloaded
.
account
;
cons
t
updatedAccount
=
await
accountManager
.
resyncAccountBalance
(
userId
,
account
,
/* interactive */
true
...
...
server/controllers/alerts.js
View file @
f4cd2c51
...
...
@@ -4,8 +4,8 @@ import { checkAlert } from '../shared/validators';
export
async
function
loadAlert
(
req
,
res
,
next
,
alertId
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
alert
=
await
Alert
.
find
(
userId
,
alertId
);
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
alert
=
await
Alert
.
find
(
userId
,
alertId
);
if
(
!
alert
)
{
throw
new
KError
(
'
bank alert not found
'
,
404
);
}
...
...
@@ -19,9 +19,9 @@ export async function loadAlert(req, res, next, alertId) {
export
async
function
create
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
id
:
userId
}
=
req
.
user
;
le
t
newAlert
=
req
.
body
;
cons
t
newAlert
=
req
.
body
;
if
(
!
newAlert
||
typeof
newAlert
.
accountId
!==
'
number
'
||
...
...
@@ -30,17 +30,17 @@ export async function create(req, res) {
throw
new
KError
(
'
missing parameters
'
,
400
);
}
le
t
validationError
=
checkAlert
(
newAlert
);
cons
t
validationError
=
checkAlert
(
newAlert
);
if
(
validationError
)
{
throw
new
KError
(
validationError
,
400
);
}
le
t
account
=
await
Account
.
find
(
userId
,
newAlert
.
accountId
);
cons
t
account
=
await
Account
.
find
(
userId
,
newAlert
.
accountId
);
if
(
!
account
)
{
throw
new
KError
(
'
bank account not found
'
,
404
);
}
le
t
alert
=
await
Alert
.
create
(
userId
,
newAlert
);
cons
t
alert
=
await
Alert
.
create
(
userId
,
newAlert
);
res
.
status
(
201
).
json
(
alert
);
}
catch
(
err
)
{
return
asyncErr
(
res
,
err
,
'
when creating an alert
'
);
...
...
@@ -49,7 +49,7 @@ export async function create(req, res) {
export
async
function
destroy
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
id
:
userId
}
=
req
.
user
;
await
Alert
.
destroy
(
userId
,
req
.
preloaded
.
alert
.
id
);
res
.
status
(
204
).
end
();
...
...
@@ -60,8 +60,8 @@ export async function destroy(req, res) {
export
async
function
update
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
{
alert
}
=
req
.
preloaded
;
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
alert
}
=
req
.
preloaded
;
let
newAlert
=
req
.
body
;
if
(
typeof
newAlert
.
type
!==
'
undefined
'
)
{
...
...
@@ -70,7 +70,7 @@ export async function update(req, res) {
newAlert
=
Object
.
assign
({},
alert
,
newAlert
);
le
t
validationError
=
checkAlert
(
newAlert
);
cons
t
validationError
=
checkAlert
(
newAlert
);
if
(
validationError
)
{
throw
new
KError
(
validationError
,
400
);
}
...
...
server/controllers/all.js
View file @
f4cd2c51
...
...
@@ -23,7 +23,7 @@ import { cleanData } from './helpers';
import
{
isDemoEnabled
}
from
'
./settings
'
;
import
{
ofxToKresus
}
from
'
./ofx
'
;
le
t
log
=
makeLogger
(
'
controllers/all
'
);
cons
t
log
=
makeLogger
(
'
controllers/all
'
);
const
ERR_MSG_LOADING_ALL
=
'
Error when loading all Kresus data
'
;
...
...
@@ -41,11 +41,11 @@ function cleanMeta(obj) {
*/
async
function
getAllData
(
userId
,
options
=
{})
{
const
{
isExport
=
false
,
cleanPassword
=
true
}
=
options
;
le
t
ret
=
{};
cons
t
ret
=
{};
ret
.
accounts
=
(
await
Account
.
all
(
userId
)).
map
(
cleanMeta
);
ret
.
accesses
=
(
await
Access
.
all
(
userId
)).
map
(
cleanMeta
);
for
(
le
t
access
of
ret
.
accesses
)
{
for
(
cons
t
access
of
ret
.
accesses
)
{
// Process enabled status only for the /all request.
if
(
!
isExport
)
{
access
.
enabled
=
access
.
isEnabled
();
...
...
@@ -89,8 +89,8 @@ async function getAllData(userId, options = {}) {
export
async
function
all
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
le
t
ret
=
await
getAllData
(
userId
);
cons
t
{
id
:
userId
}
=
req
.
user
;
cons
t
ret
=
await
getAllData
(
userId
);
res
.
status
(
200
).
json
(
ret
);
}
catch
(
err
)
{
err
.
code
=
ERR_MSG_LOADING_ALL
;
...
...
@@ -104,9 +104,9 @@ const ENCRYPTED_CONTENT_TAG = Buffer.from('KRE');
function
encryptData
(
data
,
passphrase
)
{
assert
(
process
.
kresus
.
salt
!==
null
,
'
must have provided a salt
'
);
le
t
initVector
=
crypto
.
randomBytes
(
16
);
le
t
key
=
crypto
.
pbkdf2Sync
(
passphrase
,
process
.
kresus
.
salt
,
100000
,
32
,
'
sha512
'
);
le
t
cipher
=
crypto
.
createCipheriv
(
ENCRYPTION_ALGORITHM
,
key
,
initVector
);
cons
t
initVector
=
crypto
.
randomBytes
(
16
);
cons
t
key
=
crypto
.
pbkdf2Sync
(
passphrase
,
process
.
kresus
.
salt
,
100000
,
32
,
'
sha512
'
);
cons
t
cipher
=
crypto
.
createCipheriv
(
ENCRYPTION_ALGORITHM
,
key
,
initVector
);
return
Buffer
.
concat
([
initVector
,
...
...
@@ -119,8 +119,8 @@ function encryptData(data, passphrase) {
function
decryptData
(
data
,
passphrase
)
{
assert
(
process
.
kresus
.
salt
!==
null
,
'
must have provided a salt
'
);
le
t
rawData
=
Buffer
.
from
(
data
,
'
base64
'
);
le
t
[
initVector
,
tag
,
encrypted
]
=
[
cons
t
rawData
=
Buffer
.
from
(
data
,
'
base64
'
);
cons
t
[
initVector
,
tag
,
encrypted
]
=
[
rawData
.
slice
(
0
,
16
),
rawData
.
slice
(
16
,
16
+
3
),
rawData
.
slice
(
16
+
3
)
...
...
@@ -134,15 +134,15 @@ function decryptData(data, passphrase) {
);
}
le
t
key
=
crypto
.
pbkdf2Sync
(
passphrase
,
process
.
kresus
.
salt
,
100000
,
32
,
'
sha512
'
);
cons
t
key
=
crypto
.
pbkdf2Sync
(
passphrase
,
process
.
kresus
.
salt
,
100000
,
32
,
'
sha512
'
);
le
t
decipher
=
crypto
.
createDecipheriv
(
ENCRYPTION_ALGORITHM
,
key
,
initVector
);
cons
t
decipher
=
crypto
.
createDecipheriv
(
ENCRYPTION_ALGORITHM
,
key
,
initVector
);
return
Buffer
.
concat
([
decipher
.
update
(
encrypted
),
decipher
.
final
()]).
toString
();
}
export
async
function
export_
(
req
,
res
)
{
try
{
le
t
{
id
:
userId
}
=
req
.
user
;
cons
t
{
id
:
userId
}
=
req
.
user
;
let
passphrase
=
null
;
if
(
req
.
body
.
encrypted
)
{
...
...
@@ -194,8 +194,8 @@ function applyRenamings(model) {
return
obj
=>
obj
;
}
return
obj
=>
{
for
(
le
t
from
of
Object
.
keys
(
model
.
renamings
))
{
le
t
to
=
model
.
renamings
[
from
];
for
(
cons
t
from
of
Object
.
keys
(
model
.
renamings
))
{
cons
t
to
=
model
.
renamings
[
from
];
if
(
typeof
obj
[
from
]
!==
'
undefined
'
)
{
if
(
typeof
obj
[
to
]
===
'
undefined
'
)
{
obj
[
to
]
=
obj
[
from
];
...
...
@@ -260,11 +260,11 @@ export async function importData(userId, world) {
`
);
log
.
info
(
'
Import accesses...
'
);
le
t
accessMap
=
{};
for
(
le
t
access
of
world
.
accesses
)
{
le
t
accessId
=
access
.
id
;
cons
t
accessMap
=
{};
for
(
cons
t
access
of
world
.
accesses
)
{
cons
t
accessId
=
access
.
id
;
delete
access
.
id
;
le
t
sanitizedCustomFields
=
[];
cons
t
sanitizedCustomFields
=
[];
// Support legacy "customFields" value.
if
(
typeof
access
.
customFields
===
'
string
'
&&
!
access
.
fields
)
{
...
...
@@ -275,7 +275,7 @@ export async function importData(userId, world) {
}
}
for
(
le
t
{
name
,
value
}
of
access
.
fields
||
[])
{
for
(
cons
t
{
name
,
value
}
of
access
.
fields
||
[])
{
if
(
typeof
name
!==
'
string
'
)
{
log
.
warn
(
'
Ignoring customField because of non-string "name" property.
'
);
continue
;
...
...
@@ -291,22 +291,22 @@ export async function importData(userId, world) {
access
.
fields
=
sanitizedCustomFields
;
le
t
created
=
await
Access
.
create
(
userId
,
access
);
cons
t
created
=
await
Access
.
create
(
userId
,
access
);
accessMap
[
accessId
]
=
created
.
id
;
}
log
.
info
(
'
Done.
'
);
log
.
info
(
'
Import accounts...
'
);
le
t
accountIdToAccount
=
new
Map
();
le
t
vendorToOwnAccountId
=
new
Map
();
for
(
le
t
account
of
world
.
accounts
)
{
cons
t
accountIdToAccount
=
new
Map
();
cons
t
vendorToOwnAccountId
=
new
Map
();
for
(
cons
t
account
of
world
.
accounts
)
{
if
(
typeof
accessMap
[
account
.
accessId
]
===
'
undefined
'
)
{
log
.
warn
(
'
Ignoring orphan account:
\n
'
,
account
);
continue
;
}
le
t
accountId
=
account
.
id
;
cons
t
accountId
=
account
.
id
;
delete
account
.
id
;
// For an initial import which does not come from Kresus (ex: a
...
...
@@ -315,9 +315,9 @@ export async function importData(userId, world) {
if
(
account
.
lastCheckDate
===
null
)
{
let
latestOpDate
=
null
;
if
(
world
.
operations
)
{
le
t
accountOps
=
world
.
operations
.
filter
(
op
=>
op
.
accountId
===
accountId
);
for
(
le
t
op
of
accountOps
)
{
le
t
opDate
=
parseDate
(
op
.
date
);
cons
t
accountOps
=
world
.
operations
.
filter
(
op
=>
op
.
accountId
===
accountId
);
for
(
cons
t
op
of
accountOps
)
{
cons
t
opDate
=
parseDate
(
op
.
date
);
if
(
opDate
!==
null
&&
(
latestOpDate
===
null
||
opDate
>
latestOpDate
))
{
latestOpDate
=
opDate
;
}
...
...
@@ -327,7 +327,7 @@ export async function importData(userId, world) {
}
account
.
accessId
=
accessMap
[
account
.
accessId
];
le
t
created
=
await
Account
.
create
(
userId
,
account
);
cons
t
created
=
await
Account
.
create
(
userId
,
account
);
accountIdToAccount
.
set
(
accountId
,
created
.
id
);
vendorToOwnAccountId
.
set
(
created
.
vendorAccountId
,
created
.
id
);
...
...
@@ -335,40 +335,40 @@ export async function importData(userId, world) {
log
.
info
(
'
Done.
'
);
log
.
info
(
'
Import categories...
'
);
le
t
existingCategories
=
await
Category
.
all
(
userId
);
le
t
existingCategoriesMap
=
new
Map
();
for
(
le
t
category
of
existingCategories
)
{
cons
t
existingCategories
=
await
Category
.
all
(
userId
);
cons
t
existingCategoriesMap
=
new
Map
();
for
(
cons
t
category
of
existingCategories
)
{
existingCategoriesMap
.
set
(
category
.
label
,
category
);
}
le
t
categoryMap
=
{};
for
(
le
t
category
of
world
.
categories
)
{
le
t
catId
=
category
.
id
;
cons
t
categoryMap
=
{};
for
(
cons
t
category
of
world
.
categories
)
{
cons
t
catId
=
category
.
id
;
delete
category
.
id
;
if
(
existingCategoriesMap
.
has
(
category
.
label
))
{
le
t
existing
=
existingCategoriesMap
.
get
(
category
.
label
);
cons
t
existing
=
existingCategoriesMap
.
get
(
category
.
label
);
categoryMap
[
catId
]
=
existing
.
id
;
}
else
{
le
t
created
=
await
Category
.
create
(
userId
,
category
);
cons
t
created
=
await
Category
.
create
(
userId
,
category
);
categoryMap
[
catId
]
=
created
.
id
;
}
}
log
.
info
(
'
Done.
'
);
log
.
info
(
'
Import budgets...
'
);
le
t
makeBudgetKey
=
b
=>
`
${
b
.
categoryId
}
-
${
b
.
year
}
-
${
b
.
month
}
`
;
cons
t
makeBudgetKey
=
b
=>
`
${
b
.
categoryId
}
-
${
b
.
year
}
-
${
b
.
month
}
`
;
le
t
existingBudgets
=
await
Budget
.
all
(
userId
);
le
t
existingBudgetsMap
=
new
Map
();
for
(
le
t
budget
of
existingBudgets
)
{
cons
t
existingBudgets
=
await
Budget
.
all
(
userId
);
cons
t
existingBudgetsMap
=
new
Map
();
for
(
cons
t
budget
of
existingBudgets
)
{
existingBudgetsMap
.
set
(
makeBudgetKey
(
budget
),
budget
);
}
for
(
le
t
importedBudget
of
world
.
budgets
)
{
for
(
cons
t
importedBudget
of
world
.
budgets
)
{
// Note the order here: first map to the actual category id, so the
// map lookup thereafter uses an existing category id.
importedBudget
.
categoryId
=
categoryMap
[
importedBudget
.
categoryId
];
le
t
existingBudget
=
existingBudgetsMap
.
get
(
makeBudgetKey
(
importedBudget
));
cons
t
existingBudget
=
existingBudgetsMap
.
get
(
makeBudgetKey
(
importedBudget
));
if
(
existingBudget
)
{
if
(
!
existingBudget
.
threshold
||
...
...
@@ -388,16 +388,16 @@ export async function importData(userId, world) {
// No need to import operation types.
// importedTypesMap is used to set type to imported operations (backward compatibility).
le
t
importedTypes
=
world
.
operationtypes
||
[];
le
t
importedTypesMap
=
new
Map
();
for
(
le
t
type
of
importedTypes
)
{
cons
t
importedTypes
=
world
.
operationtypes
||
[];
cons
t
importedTypesMap
=
new
Map
();
for
(
cons
t
type
of
importedTypes
)
{
importedTypesMap
.
set
(
type
.
id
.
toString
(),
type
.
name
);
}
log
.
info
(
'
Import transactions...
'
);
le
t
skipTransactions
=
[];
cons
t
skipTransactions
=
[];
for
(
let
i
=
0
;
i
<
world
.
operations
.
length
;
i
++
)
{
le
t
op
=
world
.
operations
[
i
];
cons
t
op
=
world
.
operations
[
i
];
op
.
date
=
parseDate
(
op
.
date
);
op
.
debitDate
=
parseDate
(
op
.
debitDate
);
...
...
@@ -435,7 +435,7 @@ export async function importData(userId, world) {
// Remove bankAccount as the operation is now linked to account with accountId prop.
delete
op
.
bankAccount
;
le
t
categoryId
=
op
.
categoryId
;
cons
t
categoryId
=
op
.
categoryId
;
if
(
typeof
categoryId
!==
'
undefined
'
&&
categoryId
!==
null
)
{
if
(
typeof
categoryMap
[
categoryId
]
===
'
undefined
'
)
{
log
.
warn
(
'
Unknown category, unsetting for operation:
\n
'
,
op
);
...
...
@@ -445,7 +445,7 @@ export async function importData(userId, world) {
// Set operation type base on operationId.
if
(
typeof
op
.
operationTypeID
!==
'
undefined
'
)
{
le
t
key
=
op
.
operationTypeID
.
toString
();
cons
t
key
=
op
.
operationTypeID
.
toString
();
if
(
importedTypesMap
.
has
(
key
))
{
op
.
type
=
importedTypesMap
.
get
(
key
);
}
else
{
...
...
@@ -492,7 +492,7 @@ export async function importData(userId, world) {
log
.
info
(
'
Done.
'
);
log
.
info
(
'
Import settings...
'
);
for
(
le
t
setting
of
world
.
settings
)
{
for
(
cons
t
setting
of
world
.
settings
)
{
if
(
ConfigGhostSettings
.
has
(
setting
.
key
)
||
setting
.
key
===
'
migration-version
'
)
{
continue
;
}
...
...
@@ -514,7 +514,7 @@ export async function importData(userId, world) {
// Overwrite the previous value of the demo-mode, if it was set.
if
(
setting
.
key
===
'
demo-mode
'
&&
setting
.
value
===
'
true
'
)
{
le
t
found
=
await
Setting
.
byKey
(
userId
,
'
demo-mode
'
);
cons
t
found
=
await
Setting
.
byKey
(
userId
,
'
demo-mode
'
);
if
(
found
&&
found
.
value
!==
'
true
'
)
{
await
Setting
.
updateByKey
(
userId
,
'
demo-mode
'
,
true
);
continue
;
...
...
@@ -528,7 +528,7 @@ export async function importData(userId, world) {
log
.
info
(
'
Done.
'
);
log
.
info
(
'
Import alerts...
'
);
for
(
le
t
a
of
world
.
alerts
)
{
for
(
cons
t
a
of
world
.
alerts
)
{
// Map alert to account.
if
(
typeof
a
.
accountId
!==
'
undefined
'
)
{