diff --git a/src/action/updatecategoryblockallnotifications.ts b/src/action/updatecategoryblockallnotifications.ts index 40924e5..da59934 100644 --- a/src/action/updatecategoryblockallnotifications.ts +++ b/src/action/updatecategoryblockallnotifications.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2020 Jonas Lochmann + * Copyright (C) 2019 - 2021 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 @@ -16,25 +16,43 @@ */ import { ParentAction } from './basetypes' -import { assertIdWithinFamily } from './meta/util' +import { assertIdWithinFamily, assertSafeInteger, throwOutOfRange } from './meta/util' const actionType = 'UpdateCategoryBlockAllNotificationsAction' export class UpdateCategoryBlockAllNotificationsAction extends ParentAction { readonly categoryId: string readonly blocked: boolean + readonly blockDelay: number | undefined - constructor ({ categoryId, blocked }: {categoryId: string, blocked: boolean}) { + constructor ({ categoryId, blocked, blockDelay }: { + categoryId: string + blocked: boolean + blockDelay: number | undefined + }) { super() assertIdWithinFamily({ actionType, field: 'categoryId', value: categoryId }) + if (blockDelay !== undefined) { + assertSafeInteger({ actionType, field: 'blockDelay', value: blockDelay }) + + if (blockDelay < 0) { + throwOutOfRange({ actionType, field: 'blockDelay', value: blockDelay }) + } + } + this.categoryId = categoryId this.blocked = blocked + this.blockDelay = blockDelay } - static parse = ({ categoryId, blocked }: SerializedUpdateCategoryBlockAllNotificationsAction) => ( - new UpdateCategoryBlockAllNotificationsAction({ categoryId, blocked }) + static parse = ({ categoryId, blocked, blockDelay }: SerializedUpdateCategoryBlockAllNotificationsAction) => ( + new UpdateCategoryBlockAllNotificationsAction({ + categoryId, + blocked, + blockDelay: blockDelay + }) ) } @@ -42,4 +60,5 @@ export interface SerializedUpdateCategoryBlockAllNotificationsAction { type: 'UPDATE_CATEGORY_BLOCK_ALL_NOTIFICATIONS' categoryId: string blocked: boolean + blockDelay: number | undefined } diff --git a/src/api/validator.ts b/src/api/validator.ts index b254758..8d551af 100644 --- a/src/api/validator.ts +++ b/src/api/validator.ts @@ -940,6 +940,9 @@ const definitions = { }, "blocked": { "type": "boolean" + }, + "blockDelay": { + "type": "number" } }, "additionalProperties": false, @@ -2048,11 +2051,15 @@ const definitions = { }, "flags": { "type": "number" + }, + "blockNotificationDelay": { + "type": "number" } }, "additionalProperties": false, "required": [ "blockAllNotifications", + "blockNotificationDelay", "blockedTimes", "categoryId", "childId", diff --git a/src/database/category.ts b/src/database/category.ts index baf7997..f5e415a 100644 --- a/src/database/category.ts +++ b/src/database/category.ts @@ -83,10 +83,15 @@ export interface CategoryAttributesVersion11 { flags: string } +export interface CategoryAttributesVersion12 { + blockNotificationDelay: string +} + export type CategoryAttributes = CategoryAttributesVersion1 & CategoryAttributesVersion2 & CategoryAttributesVersion3 & CategoryAttributesVersion4 & CategoryAttributesVersion5 & CategoryAttributesVersion6 & CategoryAttributesVersion7 & CategoryAttributesVersion8 & - CategoryAttributesVersion9 & CategoryAttributesVersion10 & CategoryAttributesVersion11 + CategoryAttributesVersion9 & CategoryAttributesVersion10 & CategoryAttributesVersion11 & + CategoryAttributesVersion12 export type CategoryModel = Sequelize.Model & CategoryAttributes export type CategoryModelStatic = typeof Sequelize.Model & { @@ -232,6 +237,17 @@ export const attributesVersion11: SequelizeAttributes = { + blockNotificationDelay: { + type: Sequelize.BIGINT, + allowNull: false, + defaultValue: 0, + validate: { + min: 0 + } + } +} + export const attributes: SequelizeAttributes = { ...attributesVersion1, ...attributesVersion2, @@ -243,7 +259,8 @@ export const attributes: SequelizeAttributes = { ...attributesVersion8, ...attributesVersion9, ...attributesVersion10, - ...attributesVersion11 + ...attributesVersion11, + ...attributesVersion12 } export const createCategoryModel = (sequelize: Sequelize.Sequelize): CategoryModelStatic => sequelize.define('Category', attributes) as CategoryModelStatic diff --git a/src/database/migration/migrations/20211213-add-notification-block-delay.ts b/src/database/migration/migrations/20211213-add-notification-block-delay.ts new file mode 100644 index 0000000..5c5c295 --- /dev/null +++ b/src/database/migration/migrations/20211213-add-notification-block-delay.ts @@ -0,0 +1,39 @@ +/* + * server component for the TimeLimit App + * Copyright (C) 2019 - 2021 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 + * published by the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { QueryInterface, Sequelize, Transaction } from 'sequelize' +import { attributesVersion12 as categoryAttributes } from '../../category' + +export async function up (queryInterface: QueryInterface, sequelize: Sequelize) { + await sequelize.transaction({ + type: Transaction.TYPES.EXCLUSIVE + }, async (transaction) => { + await queryInterface.addColumn('Categories', 'blockNotificationDelay', { + ...categoryAttributes.blockNotificationDelay + }, { + transaction + }) + }) +} + +export async function down (queryInterface: QueryInterface, sequelize: Sequelize) { + await sequelize.transaction({ + type: Transaction.TYPES.EXCLUSIVE + }, async (transaction) => { + await queryInterface.removeColumn('Categories', 'blockNotificationDelay', { transaction }) + }) +} diff --git a/src/function/sync/apply-actions/dispatch-parent-action/createcategory.ts b/src/function/sync/apply-actions/dispatch-parent-action/createcategory.ts index 8faf1bb..a362e68 100644 --- a/src/function/sync/apply-actions/dispatch-parent-action/createcategory.ts +++ b/src/function/sync/apply-actions/dispatch-parent-action/createcategory.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2020 Jonas Lochmann + * Copyright (C) 2019 - 2021 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 @@ -80,7 +80,8 @@ export async function dispatchCreateCategory ({ action, cache, fromChildSelfLimi taskListVersion: generateVersionId(), minBatteryCharging: 0, minBatteryMobile: 0, - flags: '0' + flags: '0', + blockNotificationDelay: '0' }, { transaction: cache.transaction }) // update the cache diff --git a/src/function/sync/apply-actions/dispatch-parent-action/updatecategoryblockallnotifications.ts b/src/function/sync/apply-actions/dispatch-parent-action/updatecategoryblockallnotifications.ts index 59c025c..51fe5e8 100644 --- a/src/function/sync/apply-actions/dispatch-parent-action/updatecategoryblockallnotifications.ts +++ b/src/function/sync/apply-actions/dispatch-parent-action/updatecategoryblockallnotifications.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2020 Jonas Lochmann + * Copyright (C) 2019 - 2021 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 @@ -31,13 +31,18 @@ export async function dispatchUpdateCategoryBlockAllNotifications ({ action, cac categoryId: action.categoryId }, transaction: cache.transaction, - attributes: ['childId'] + attributes: ['childId', 'blockAllNotifications'] }) if (!categoryEntryUnsafe) { throw new MissingCategoryException() } + const categoryEntry = { + childId: categoryEntryUnsafe.childId, + blockAllNotifications: categoryEntryUnsafe.blockAllNotifications + } + if (fromChildSelfLimitAddChildUserId !== null) { if (fromChildSelfLimitAddChildUserId !== categoryEntryUnsafe.childId) { throw new CanNotModifyOtherUsersBySelfLimitationException() @@ -46,10 +51,17 @@ export async function dispatchUpdateCategoryBlockAllNotifications ({ action, cac if (!action.blocked) { throw new SelfLimitationException({ staticMessage: 'can not disable notification filter as child' }) } + + if (categoryEntry.blockAllNotifications && action.blockDelay !== undefined) { + throw new SelfLimitationException({ staticMessage: 'can not update the block delay as child' }) + } } - const [affectedRows] = await cache.database.category.update({ + const [affectedRows] = await cache.database.category.update(action.blockDelay === undefined ? { blockAllNotifications: action.blocked + } : { + blockAllNotifications: action.blocked, + blockNotificationDelay: action.blockDelay.toString(10) }, { where: { familyId: cache.familyId, diff --git a/src/function/sync/get-server-data-status/category/base-data.ts b/src/function/sync/get-server-data-status/category/base-data.ts index a90418c..c9e5cbd 100644 --- a/src/function/sync/get-server-data-status/category/base-data.ts +++ b/src/function/sync/get-server-data-status/category/base-data.ts @@ -52,7 +52,8 @@ export async function getCategoryBaseDatas ({ 'temporarilyBlockedEndTime', 'sort', 'disableLimitsUntil', - 'flags' + 'flags', + 'blockNotificationDelay' ], transaction })).map((item) => ({ @@ -72,7 +73,8 @@ export async function getCategoryBaseDatas ({ temporarilyBlockedEndTime: item.temporarilyBlockedEndTime, sort: item.sort, disableLimitsUntil: item.disableLimitsUntil, - flags: item.flags + flags: item.flags, + blockNotificationDelay: item.blockNotificationDelay })) const networkIdsForSyncing = (await database.categoryNetworkId.findAll({ @@ -117,6 +119,7 @@ export async function getCategoryBaseDatas ({ hashedNetworkId: network.hashedNetworkId })), dlu: parseInt(item.disableLimitsUntil, 10), - flags: parseInt(item.flags, 10) + flags: parseInt(item.flags, 10), + blockNotificationDelay: parseInt(item.blockNotificationDelay, 10) })) } diff --git a/src/object/serverdatastatus.ts b/src/object/serverdatastatus.ts index cd68325..334456c 100644 --- a/src/object/serverdatastatus.ts +++ b/src/object/serverdatastatus.ts @@ -118,6 +118,7 @@ export interface ServerUpdatedCategoryBaseData { // disable limits until dlu: number flags: number + blockNotificationDelay: number } export interface ServerCategoryNetworkId {