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 prefs from '../prefs';
|
||||||
import * as sheet from '../sheet';
|
import * as sheet from '../sheet';
|
||||||
import { batchMessages } from '../sync';
|
import { batchMessages } from '../sync';
|
||||||
|
import { safeNumber } from './util';
|
||||||
|
|
||||||
async function getSheetValue(sheetName, cell) {
|
async function getSheetValue(sheetName, cell) {
|
||||||
const node = await sheet.getCell(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
|
// 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 }) {
|
export function setBudget({ category, month, amount }) {
|
||||||
if (typeof amount !== 'number') {
|
amount = safeNumber(typeof amount === 'number' ? amount : 0);
|
||||||
amount = 0;
|
|
||||||
}
|
|
||||||
const table = getBudgetTable();
|
const table = getBudgetTable();
|
||||||
|
|
||||||
let existing = db.firstSync(
|
let existing = db.firstSync(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as monthUtils from '../../shared/months';
|
import * as monthUtils from '../../shared/months';
|
||||||
import * as sheet from '../sheet';
|
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');
|
const { resolveName } = require('../spreadsheet/util');
|
||||||
|
|
||||||
|
|
|
@ -19,3 +19,23 @@ export function unflatten2(arr) {
|
||||||
}
|
}
|
||||||
return res;
|
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