diff --git a/src/action/updatecategoryblockedtimes.ts b/src/action/updatecategoryblockedtimes.ts index c29c7e4..bd351e5 100644 --- a/src/action/updatecategoryblockedtimes.ts +++ b/src/action/updatecategoryblockedtimes.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 Jonas Lochmann + * Copyright (C) 2019 - 2020 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -19,6 +19,8 @@ import { validateBitmask } from '../util/bitmask' import { assertIdWithinFamily } from '../util/token' import { ParentAction } from './basetypes' +export const blockedTimesBitmaskLength = 60 * 24 * 7 /* number of minutes per week */ + export class UpdateCategoryBlockedTimesAction extends ParentAction { readonly categoryId: string readonly blockedTimes: string @@ -30,7 +32,7 @@ export class UpdateCategoryBlockedTimesAction extends ParentAction { super() assertIdWithinFamily(categoryId) - validateBitmask(blockedTimes, 60 * 24 * 7 /* number of minutes per week */) + validateBitmask(blockedTimes, blockedTimesBitmaskLength) this.categoryId = categoryId this.blockedTimes = blockedTimes diff --git a/src/function/sync/apply-actions/dispatch-parent-action/index.ts b/src/function/sync/apply-actions/dispatch-parent-action/index.ts index 1e1f0fc..058c685 100644 --- a/src/function/sync/apply-actions/dispatch-parent-action/index.ts +++ b/src/function/sync/apply-actions/dispatch-parent-action/index.ts @@ -125,6 +125,8 @@ export const dispatchParentAction = async ({ action, cache, parentUserId, source return dispatchSetParentCategory({ action, cache, fromChildSelfLimitAddChildUserId }) } else if (action instanceof UpdateCategoryTemporarilyBlockedAction) { return dispatchUpdateCategoryTemporarilyBlocked({ action, cache, fromChildSelfLimitAddChildUserId }) + } else if (action instanceof UpdateCategoryBlockedTimesAction) { + return dispatchUpdateCategoryBlockedTimes({ action, cache, fromChildSelfLimitAddChildUserId }) } if (fromChildSelfLimitAddChildUserId === null) { @@ -164,8 +166,6 @@ export const dispatchParentAction = async ({ action, cache, parentUserId, source return dispatchSetUserTimezone({ action, cache }) } else if (action instanceof UpdateCategoryBatteryLimitAction) { return dispatchUpdateCategoryBatteryLimit({ action, cache }) - } else if (action instanceof UpdateCategoryBlockedTimesAction) { - return dispatchUpdateCategoryBlockedTimes({ action, cache }) } else if (action instanceof UpdateCategorySortingAction) { return dispatchUpdateCategorySorting({ action, cache }) } else if (action instanceof IncrementCategoryExtraTimeAction) { diff --git a/src/function/sync/apply-actions/dispatch-parent-action/updatecategoryblockedtimes.ts b/src/function/sync/apply-actions/dispatch-parent-action/updatecategoryblockedtimes.ts index cc8bad4..4fda2bf 100644 --- a/src/function/sync/apply-actions/dispatch-parent-action/updatecategoryblockedtimes.ts +++ b/src/function/sync/apply-actions/dispatch-parent-action/updatecategoryblockedtimes.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 Jonas Lochmann + * Copyright (C) 2019 - 2020 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -15,14 +15,49 @@ * along with this program. If not, see . */ -import { UpdateCategoryBlockedTimesAction } from '../../../../action' +import { blockedTimesBitmaskLength, UpdateCategoryBlockedTimesAction } from '../../../../action/updatecategoryblockedtimes' +import { validateAndParseBitmask } from '../../../../util/bitmask' import { Cache } from '../cache' -export async function dispatchUpdateCategoryBlockedTimes ({ action, cache }: { +export async function dispatchUpdateCategoryBlockedTimes ({ action, cache, fromChildSelfLimitAddChildUserId }: { action: UpdateCategoryBlockedTimesAction cache: Cache + fromChildSelfLimitAddChildUserId: string | null }) { - const [affectedRows] = await cache.database.category.update({ + const categoryEntryUnsafe = await cache.database.category.findOne({ + where: { + familyId: cache.familyId, + categoryId: action.categoryId + }, + transaction: cache.transaction, + attributes: ['childId', 'blockedMinutesInWeek'] + }) + + if (!categoryEntryUnsafe) { + throw new Error('can not update blocked time areas for a category which does not exist') + } + + const categoryEntry = { + childId: categoryEntryUnsafe.childId, + blockedMinutesInWeek: categoryEntryUnsafe.blockedMinutesInWeek + } + + if (fromChildSelfLimitAddChildUserId !== null) { + if (categoryEntry.childId !== fromChildSelfLimitAddChildUserId) { + throw new Error('can not update blocked time areas for other child users') + } + + const oldBlocked = validateAndParseBitmask(categoryEntry.blockedMinutesInWeek, blockedTimesBitmaskLength) + const newBlocked = validateAndParseBitmask(action.blockedTimes, blockedTimesBitmaskLength) + + oldBlocked.forEach((value, index) => { + if (value && !newBlocked[index]) { + throw new Error('new blocked time areas are smaller') + } + }) + } + + await cache.database.category.update({ blockedMinutesInWeek: action.blockedTimes }, { where: { @@ -32,10 +67,6 @@ export async function dispatchUpdateCategoryBlockedTimes ({ action, cache }: { transaction: cache.transaction }) - if (affectedRows === 0) { - throw new Error('invalid category id provided') - } - cache.categoriesWithModifiedBaseData.push(action.categoryId) cache.areChangesImportant = true } diff --git a/src/util/bitmask.ts b/src/util/bitmask.ts index a774848..2d3b529 100644 --- a/src/util/bitmask.ts +++ b/src/util/bitmask.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 Jonas Lochmann + * Copyright (C) 2019 - 2020 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as