From 50766e804a5250e6f801ecb419b96ceeeaf02750 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 6 Jan 2020 00:00:00 +0000 Subject: [PATCH] Add battery limit support --- src/action/index.ts | 3 +- src/action/serialization/parentaction.ts | 6 +- src/action/updatecategorybatterylimit.ts | 69 +++++++++++++++++++ src/api/validator.ts | 28 ++++++++ src/database/category.ts | 33 ++++++++- .../20200113-add-min-battery-level.ts | 46 +++++++++++++ .../dispatch-parent-action/index.ts | 6 +- .../updatecategorybatterylimit.ts | 49 +++++++++++++ src/function/sync/get-server-data-status.ts | 14 ++-- src/object/serverdatastatus.ts | 5 +- 10 files changed, 248 insertions(+), 11 deletions(-) create mode 100644 src/action/updatecategorybatterylimit.ts create mode 100644 src/database/migration/migrations/20200113-add-min-battery-level.ts create mode 100644 src/function/sync/apply-actions/dispatch-parent-action/updatecategorybatterylimit.ts diff --git a/src/action/index.ts b/src/action/index.ts index 3c9b18a..3a0e707 100644 --- a/src/action/index.ts +++ b/src/action/index.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 @@ -51,6 +51,7 @@ export { SetUserTimezoneAction } from './setusertimezone' export { SignOutAtDeviceAction } from './signoutatdevice' export { TriedDisablingDeviceAdminAction } from './trieddisablingdeviceadmin' export { UpdateAppActivitiesAction } from './updateappactivities' +export { UpdateCategoryBatteryLimitAction } from './updatecategorybatterylimit' export { UpdateCategoryBlockAllNotificationsAction } from './updatecategoryblockallnotifications' export { UpdateCategoryBlockedTimesAction } from './updatecategoryblockedtimes' export { UpdateCategoryTemporarilyBlockedAction } from './updatecategorytemporarilyblocked' diff --git a/src/action/serialization/parentaction.ts b/src/action/serialization/parentaction.ts index 7556b80..dbd9f53 100644 --- a/src/action/serialization/parentaction.ts +++ b/src/action/serialization/parentaction.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 @@ -42,6 +42,7 @@ import { SerializedSetRelaxPrimaryDeviceAction, SetRelaxPrimaryDeviceAction } fr import { SerializedSetSendDeviceConnected, SetSendDeviceConnected } from '../setsenddeviceconnected' import { SerializedSetUserDisableLimitsUntilAction, SetUserDisableLimitsUntilAction } from '../setuserdisablelimitsuntil' import { SerializedSetUserTimezoneAction, SetUserTimezoneAction } from '../setusertimezone' +import { SerializedUpdateCategoryBatteryLimitAction, UpdateCategoryBatteryLimitAction } from '../updatecategorybatterylimit' import { SerializedUpdateCategoryBlockAllNotificationsAction, UpdateCategoryBlockAllNotificationsAction } from '../updatecategoryblockallnotifications' import { SerializedUpdateCategoryBlockedTimesAction, UpdateCategoryBlockedTimesAction } from '../updatecategoryblockedtimes' import { SerializedUpdateCategoryTemporarilyBlockedAction, UpdateCategoryTemporarilyBlockedAction } from '../updatecategorytemporarilyblocked' @@ -81,6 +82,7 @@ export type SerializedParentAction = SerializedSetSendDeviceConnected | SerializedSetUserDisableLimitsUntilAction | SerializedSetUserTimezoneAction | + SerializedUpdateCategoryBatteryLimitAction | SerializedUpdateCategoryBlockAllNotificationsAction | SerializedUpdateCategoryBlockedTimesAction | SerializedUpdateCategoryTemporarilyBlockedAction | @@ -146,6 +148,8 @@ export const parseParentAction = (action: SerializedParentAction): ParentAction return SetUserDisableLimitsUntilAction.parse(action) } else if (action.type === 'SET_USER_TIMEZONE') { return SetUserTimezoneAction.parse(action) + } else if (action.type === 'UPDATE_CATEGORY_BATTERY_LIMIT') { + return UpdateCategoryBatteryLimitAction.parse(action) } else if (action.type === 'UPDATE_CATEGORY_BLOCK_ALL_NOTIFICATIONS') { return UpdateCategoryBlockAllNotificationsAction.parse(action) } else if (action.type === 'UPDATE_CATEGORY_BLOCKED_TIMES') { diff --git a/src/action/updatecategorybatterylimit.ts b/src/action/updatecategorybatterylimit.ts new file mode 100644 index 0000000..71cf9f2 --- /dev/null +++ b/src/action/updatecategorybatterylimit.ts @@ -0,0 +1,69 @@ +/* + * server component for the TimeLimit App + * 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 + * 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 { assertIdWithinFamily } from '../util/token' +import { ParentAction } from './basetypes' + +export class UpdateCategoryBatteryLimitAction extends ParentAction { + readonly categoryId: string + readonly chargeLimit?: number + readonly mobileLimit?: number + + constructor ({ categoryId, chargeLimit, mobileLimit }: { + categoryId: string + chargeLimit?: number + mobileLimit?: number + }) { + super() + + assertIdWithinFamily(categoryId) + + if (chargeLimit !== undefined) { + if ((!Number.isSafeInteger(chargeLimit)) || chargeLimit < 0 || chargeLimit > 100) { + throw new Error('charge limit out of range') + } + } + + if (mobileLimit !== undefined) { + if ((!Number.isSafeInteger(mobileLimit)) || mobileLimit < 0 || mobileLimit > 100) { + throw new Error('mobile limit out of range') + } + } + + this.categoryId = categoryId + this.chargeLimit = chargeLimit + this.mobileLimit = mobileLimit + } + + serialize = (): SerializedUpdateCategoryBatteryLimitAction => ({ + type: 'UPDATE_CATEGORY_BATTERY_LIMIT', + categoryId: this.categoryId, + mobileLimit: this.mobileLimit, + chargeLimit: this.chargeLimit + }) + + static parse = ({ categoryId, chargeLimit, mobileLimit }: SerializedUpdateCategoryBatteryLimitAction) => ( + new UpdateCategoryBatteryLimitAction({ categoryId, chargeLimit, mobileLimit }) + ) +} + +export interface SerializedUpdateCategoryBatteryLimitAction { + type: 'UPDATE_CATEGORY_BATTERY_LIMIT' + categoryId: string + chargeLimit?: number + mobileLimit?: number +} diff --git a/src/api/validator.ts b/src/api/validator.ts index ce1ad26..7959c61 100644 --- a/src/api/validator.ts +++ b/src/api/validator.ts @@ -768,6 +768,31 @@ const definitions = { "userId" ] }, + "SerializedUpdateCategoryBatteryLimitAction": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "UPDATE_CATEGORY_BATTERY_LIMIT" + ] + }, + "categoryId": { + "type": "string" + }, + "chargeLimit": { + "type": "number" + }, + "mobileLimit": { + "type": "number" + } + }, + "additionalProperties": false, + "required": [ + "categoryId", + "type" + ] + }, "SerializedUpdateCategoryBlockAllNotificationsAction": { "type": "object", "properties": { @@ -1619,6 +1644,9 @@ export const isSerializedParentAction: (value: object) => value is SerializedPar { "$ref": "#/definitions/SerializedSetUserTimezoneAction" }, + { + "$ref": "#/definitions/SerializedUpdateCategoryBatteryLimitAction" + }, { "$ref": "#/definitions/SerializedUpdateCategoryBlockAllNotificationsAction" }, diff --git a/src/database/category.ts b/src/database/category.ts index d1dba5f..d88e43a 100644 --- a/src/database/category.ts +++ b/src/database/category.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 @@ -48,8 +48,13 @@ export interface CategoryAttributesVersion4 { timeWarningFlags: number } +export interface CategoryAttributesVersion5 { + minBatteryCharging: number + minBatteryMobile: number +} + export type CategoryAttributes = CategoryAttributesVersion1 & CategoryAttributesVersion2 & - CategoryAttributesVersion3 & CategoryAttributesVersion4 + CategoryAttributesVersion3 & CategoryAttributesVersion4 & CategoryAttributesVersion5 export type CategoryModel = Sequelize.Model & CategoryAttributes export type CategoryModelStatic = typeof Sequelize.Model & { @@ -119,11 +124,33 @@ export const attributesVersion4: SequelizeAttributes } } +export const attributesVersion5: SequelizeAttributes = { + minBatteryMobile: { + type: Sequelize.INTEGER, + defaultValue: 0, + allowNull: false, + validate: { + min: 0, + max: 100 + } + }, + minBatteryCharging: { + type: Sequelize.INTEGER, + defaultValue: 0, + allowNull: false, + validate: { + min: 0, + max: 100 + } + } +} + export const attributes: SequelizeAttributes = { ...attributesVersion1, ...attributesVersion2, ...attributesVersion3, - ...attributesVersion4 + ...attributesVersion4, + ...attributesVersion5 } export const createCategoryModel = (sequelize: Sequelize.Sequelize): CategoryModelStatic => sequelize.define('Category', attributes) as CategoryModelStatic diff --git a/src/database/migration/migrations/20200113-add-min-battery-level.ts b/src/database/migration/migrations/20200113-add-min-battery-level.ts new file mode 100644 index 0000000..bc0c429 --- /dev/null +++ b/src/database/migration/migrations/20200113-add-min-battery-level.ts @@ -0,0 +1,46 @@ +/* + * server component for the TimeLimit App + * 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 + * 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 { attributesVersion5 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', 'minBatteryMobile', { + ...categoryAttributes.minBatteryMobile + }, { + transaction + }) + + await queryInterface.addColumn('Categories', 'minBatteryCharging', { + ...categoryAttributes.minBatteryCharging + }, { + transaction + }) + }) +} + +export async function down (queryInterface: QueryInterface, sequelize: Sequelize) { + await sequelize.transaction({ + type: Transaction.TYPES.EXCLUSIVE + }, async (transaction) => { + await queryInterface.removeColumn('Categories', 'minBatteryMobile', { transaction }) + await queryInterface.removeColumn('Categories', 'minBatteryCharging', { transaction }) + }) +} 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 78f445a..4ce2b0c 100644 --- a/src/function/sync/apply-actions/dispatch-parent-action/index.ts +++ b/src/function/sync/apply-actions/dispatch-parent-action/index.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 @@ -43,6 +43,7 @@ import { SetSendDeviceConnected, SetUserDisableLimitsUntilAction, SetUserTimezoneAction, + UpdateCategoryBatteryLimitAction, UpdateCategoryBlockAllNotificationsAction, UpdateCategoryBlockedTimesAction, UpdateCategoryTemporarilyBlockedAction, @@ -82,6 +83,7 @@ import { dispatchSetRelaxPrimaryDevice } from './setrelaxprimarydevice' import { dispatchSetSendDeviceConnected } from './setsenddeviceconnected' import { dispatchUserSetDisableLimitsUntil } from './setuserdisablelmitsuntil' import { dispatchSetUserTimezone } from './setusertimezone' +import { dispatchUpdateCategoryBatteryLimit } from './updatecategorybatterylimit' import { dispatchUpdateCategoryBlockAllNotifications } from './updatecategoryblockallnotifications' import { dispatchUpdateCategoryBlockedTimes } from './updatecategoryblockedtimes' import { dispatchUpdateCategoryTemporarilyBlocked } from './updatecategorytemporarilyblocked' @@ -140,6 +142,8 @@ export const dispatchParentAction = async ({ action, cache, parentUserId, source await dispatchUserSetDisableLimitsUntil({ action, cache }) } else if (action instanceof SetUserTimezoneAction) { await dispatchSetUserTimezone({ action, cache }) + } else if (action instanceof UpdateCategoryBatteryLimitAction) { + await dispatchUpdateCategoryBatteryLimit({ action, cache }) } else if (action instanceof UpdateCategoryBlockAllNotificationsAction) { await dispatchUpdateCategoryBlockAllNotifications({ action, cache }) } else if (action instanceof UpdateCategoryBlockedTimesAction) { diff --git a/src/function/sync/apply-actions/dispatch-parent-action/updatecategorybatterylimit.ts b/src/function/sync/apply-actions/dispatch-parent-action/updatecategorybatterylimit.ts new file mode 100644 index 0000000..3f94679 --- /dev/null +++ b/src/function/sync/apply-actions/dispatch-parent-action/updatecategorybatterylimit.ts @@ -0,0 +1,49 @@ +/* + * server component for the TimeLimit App + * 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 + * 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 { UpdateCategoryBatteryLimitAction } from '../../../../action' +import { Cache } from '../cache' + +export async function dispatchUpdateCategoryBatteryLimit ({ action, cache }: { + action: UpdateCategoryBatteryLimitAction + cache: Cache +}) { + const categoryEntry = await cache.database.category.findOne({ + where: { + familyId: cache.familyId, + categoryId: action.categoryId + }, + transaction: cache.transaction + }) + + if (!categoryEntry) { + throw new Error('invalid category id') + } + + if (action.chargeLimit !== undefined) { + categoryEntry.minBatteryCharging = action.chargeLimit + } + + if (action.mobileLimit !== undefined) { + categoryEntry.minBatteryMobile = action.mobileLimit + } + + await categoryEntry.save({ transaction: cache.transaction }) + + cache.categoriesWithModifiedBaseData.push(action.categoryId) + cache.areChangesImportant = true +} diff --git a/src/function/sync/get-server-data-status.ts b/src/function/sync/get-server-data-status.ts index bba8e39..e93c379 100644 --- a/src/function/sync/get-server-data-status.ts +++ b/src/function/sync/get-server-data-status.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 @@ -339,7 +339,9 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI 'baseVersion', 'parentCategoryId', 'blockAllNotifications', - 'timeWarningFlags' + 'timeWarningFlags', + 'minBatteryCharging', + 'minBatteryMobile' ], transaction })).map((item) => ({ @@ -352,7 +354,9 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI baseVersion: item.baseVersion, parentCategoryId: item.parentCategoryId, blockAllNotifications: item.blockAllNotifications, - timeWarningFlags: item.timeWarningFlags + timeWarningFlags: item.timeWarningFlags, + minBatteryCharging: item.minBatteryCharging, + minBatteryMobile: item.minBatteryMobile })) result.categoryBase = dataForSyncing.map((item): ServerUpdatedCategoryBaseData => ({ @@ -365,7 +369,9 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI version: item.baseVersion, parentCategoryId: item.parentCategoryId, blockAllNotifications: item.blockAllNotifications, - timeWarnings: item.timeWarningFlags + timeWarnings: item.timeWarningFlags, + mblMobile: item.minBatteryMobile, + mblCharging: item.minBatteryCharging })) } diff --git a/src/object/serverdatastatus.ts b/src/object/serverdatastatus.ts index ca1e553..e514ff1 100644 --- a/src/object/serverdatastatus.ts +++ b/src/object/serverdatastatus.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 @@ -104,6 +104,9 @@ export interface ServerUpdatedCategoryBaseData { parentCategoryId: string blockAllNotifications: boolean timeWarnings: number + // mbl = minimum battery level + mblCharging: number + mblMobile: number } export interface ServerUpdatedCategoryAssignedApps {