feat: add explicit value checking on saving to / reading from budget
This commit is contained in:
parent
3a925948e2
commit
6cbc22312f
3 changed files with 24 additions and 5 deletions
|
@ -3,10 +3,11 @@ import * as db from '../db';
|
|||
import * as prefs from '../prefs';
|
||||
import * as sheet from '../sheet';
|
||||
import { batchMessages } from '../sync';
|
||||
import { safeNumber } from './util';
|
||||
|
||||
async function getSheetValue(sheetName, cell) {
|
||||
const node = await sheet.getCell(sheetName, cell);
|
||||
return typeof node.value === 'number' ? node.value : 0;
|
||||
return safeNumber(typeof node.value === 'number' ? node.value : 0);
|
||||
}
|
||||
|
||||
// We want to only allow the positive movement of money back and
|
||||
|
@ -71,9 +72,7 @@ export function getBudget({ category, month }) {
|
|||
}
|
||||
|
||||
export function setBudget({ category, month, amount }) {
|
||||
if (typeof amount !== 'number') {
|
||||
amount = 0;
|
||||
}
|
||||
amount = safeNumber(typeof amount === 'number' ? amount : 0);
|
||||
const table = getBudgetTable();
|
||||
|
||||
let existing = db.firstSync(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as monthUtils from '../../shared/months';
|
||||
import * as sheet from '../sheet';
|
||||
import { number, sumAmounts, flatten2, unflatten2 } from './util';
|
||||
import { number, sumAmounts, flatten2, unflatten2, safeNumber } from './util';
|
||||
|
||||
const { resolveName } = require('../spreadsheet/util');
|
||||
|
||||
|
|
|
@ -19,3 +19,23 @@ export function unflatten2(arr) {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Note that we don't restrict values to `Number.MIN_SAFE_INTEGER <= value <= Number.MAX_SAFE_INTEGER`
|
||||
// where `Number.MAX_SAFE_INTEGER == 2^53 - 1` but a smaller range over `-(2^43-1) <= value <= 2^43 - 1`.
|
||||
// This ensure that the number is accurate not just for the integer component but for 3 decimal places also.
|
||||
//
|
||||
// This gives us the guarantee that can use `safeNumber` on number whether they are unscaled user inputs
|
||||
// or they have been converted to integers (using `amountToInteger`).
|
||||
|
||||
const MAX_SAFE_NUMBER = 2 ** 43 - 1;
|
||||
const MIN_SAFE_NUMBER = -MAX_SAFE_NUMBER;
|
||||
|
||||
export function safeNumber(value) {
|
||||
value = number(value);
|
||||
if (value > MAX_SAFE_NUMBER || value < MIN_SAFE_NUMBER) {
|
||||
throw new Error(
|
||||
"Can't safely perform arithmetic with number: " + JSON.stringify(value)
|
||||
);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue