From 1215c0c8a29f7e35b8a9cc2ca2ab4db880099b6f Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 8 Apr 2024 02:00:00 +0200 Subject: [PATCH] Add support for time limit rules that expire --- .../schema/SerializedParentAction.schema.json | 6 +++ ...ns-serializedtimelimitrule-properties-e.md | 15 +++++++ ...ion-definitions-serializedtimelimitrule.md | 19 +++++++++ ...dupdatetimelimitruleaction-properties-e.md | 15 +++++++ ...imelimitruleaction-properties-expiresat.md | 15 +++++++ ...ons-serializedupdatetimelimitruleaction.md | 19 +++++++++ docs/schema/serializedparentaction.md | 38 ++++++++++++++++++ src/action/updatetimelimitrule.ts | 21 ++++++++-- src/api/validator.ts | 6 +++ .../migrations/20240408-add-rule-expires.ts | 39 +++++++++++++++++++ src/database/timelimitrule.ts | 23 +++++++++-- .../createtimelimitrule.ts | 5 ++- .../updatetimelimitrule.ts | 6 ++- .../get-server-data-status/category/rules.ts | 11 ++++-- .../sync/get-server-data-status/index.ts | 4 +- src/model/timelimitrule.ts | 24 +++++++++--- 16 files changed, 244 insertions(+), 22 deletions(-) create mode 100644 docs/schema/serializedparentaction-definitions-serializedtimelimitrule-properties-e.md create mode 100644 docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md create mode 100644 docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-expiresat.md create mode 100644 src/database/migration/migrations/20240408-add-rule-expires.ts diff --git a/docs/schema/SerializedParentAction.schema.json b/docs/schema/SerializedParentAction.schema.json index 9d59d4f..edca800 100644 --- a/docs/schema/SerializedParentAction.schema.json +++ b/docs/schema/SerializedParentAction.schema.json @@ -410,6 +410,9 @@ }, "perDay": { "type": "boolean" + }, + "e": { + "type": "number" } }, "additionalProperties": false, @@ -1458,6 +1461,9 @@ }, "perDay": { "type": "boolean" + }, + "e": { + "type": "number" } }, "additionalProperties": false, diff --git a/docs/schema/serializedparentaction-definitions-serializedtimelimitrule-properties-e.md b/docs/schema/serializedparentaction-definitions-serializedtimelimitrule-properties-e.md new file mode 100644 index 0000000..a76c551 --- /dev/null +++ b/docs/schema/serializedparentaction-definitions-serializedtimelimitrule-properties-e.md @@ -0,0 +1,15 @@ +# Untitled number in SerializedParentAction Schema + +```txt +https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e +``` + + + +| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In | +| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------------------ | +| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedParentAction.schema.json\*](SerializedParentAction.schema.json "open original schema") | + +## e Type + +`number` diff --git a/docs/schema/serializedparentaction-definitions-serializedtimelimitrule.md b/docs/schema/serializedparentaction-definitions-serializedtimelimitrule.md index 6b7629d..b7790ba 100644 --- a/docs/schema/serializedparentaction-definitions-serializedtimelimitrule.md +++ b/docs/schema/serializedparentaction-definitions-serializedtimelimitrule.md @@ -28,6 +28,7 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule | [dur](#dur) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-dur.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/dur") | | [pause](#pause) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-pause.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/pause") | | [perDay](#perday) | `boolean` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-perday.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/perDay") | +| [e](#e) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e") | ## ruleId @@ -208,3 +209,21 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule ### perDay Type `boolean` + +## e + + + +`e` + +* is optional + +* Type: `number` + +* cannot be null + +* defined in: [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e") + +### e Type + +`number` diff --git a/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md b/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md new file mode 100644 index 0000000..9fcd00f --- /dev/null +++ b/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md @@ -0,0 +1,15 @@ +# Untitled number in SerializedParentAction Schema + +```txt +https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e +``` + + + +| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In | +| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------------------ | +| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedParentAction.schema.json\*](SerializedParentAction.schema.json "open original schema") | + +## e Type + +`number` diff --git a/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-expiresat.md b/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-expiresat.md new file mode 100644 index 0000000..679af8b --- /dev/null +++ b/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-expiresat.md @@ -0,0 +1,15 @@ +# Untitled number in SerializedParentAction Schema + +```txt +https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/expiresAt +``` + + + +| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In | +| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------------------ | +| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedParentAction.schema.json\*](SerializedParentAction.schema.json "open original schema") | + +## expiresAt Type + +`number` diff --git a/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction.md b/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction.md index 3efa439..a29ea46 100644 --- a/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction.md +++ b/docs/schema/serializedparentaction-definitions-serializedupdatetimelimitruleaction.md @@ -28,6 +28,7 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelim | [dur](#dur) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-dur.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/dur") | | [pause](#pause) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-pause.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/pause") | | [perDay](#perday) | `boolean` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-perday.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/perDay") | +| [e](#e) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e") | ## type @@ -216,3 +217,21 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelim ### perDay Type `boolean` + +## e + + + +`e` + +* is optional + +* Type: `number` + +* cannot be null + +* defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e") + +### e Type + +`number` diff --git a/docs/schema/serializedparentaction.md b/docs/schema/serializedparentaction.md index 728a25c..37c19f9 100644 --- a/docs/schema/serializedparentaction.md +++ b/docs/schema/serializedparentaction.md @@ -899,6 +899,7 @@ Reference this group by using | [dur](#dur) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-dur.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/dur") | | [pause](#pause) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-pause.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/pause") | | [perDay](#perday) | `boolean` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-perday.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/perDay") | +| [e](#e) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e") | ### ruleId @@ -1080,6 +1081,24 @@ Reference this group by using `boolean` +### e + + + +`e` + +* is optional + +* Type: `number` + +* cannot be null + +* defined in: [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e") + +#### e Type + +`number` + ## Definitions group SerializedDeleteCategoryAction Reference this group by using @@ -4397,6 +4416,7 @@ Reference this group by using | [dur](#dur-1) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-dur.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/dur") | | [pause](#pause-1) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-pause.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/pause") | | [perDay](#perday-1) | `boolean` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-perday.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/perDay") | +| [e](#e-1) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e") | ### type @@ -4586,6 +4606,24 @@ Reference this group by using `boolean` +### e + + + +`e` + +* is optional + +* Type: `number` + +* cannot be null + +* defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e") + +#### e Type + +`number` + ## Definitions group SerializedUpdateUserFlagsAction Reference this group by using diff --git a/src/action/updatetimelimitrule.ts b/src/action/updatetimelimitrule.ts index 6a582f6..b59dfd0 100644 --- a/src/action/updatetimelimitrule.ts +++ b/src/action/updatetimelimitrule.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2020 Jonas Lochmann + * Copyright (C) 2019 - 2024 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 @@ -32,11 +32,12 @@ export class UpdateTimelimitRuleAction extends ParentAction { readonly sessionDurationMilliseconds: number readonly sessionPauseMilliseconds: number readonly perDay: boolean + readonly expiresAt?: number constructor ({ ruleId, maximumTimeInMillis, dayMask, applyToExtraTimeUsage, start, end, sessionDurationMilliseconds, sessionPauseMilliseconds, - perDay + perDay, expiresAt }: { ruleId: string maximumTimeInMillis: number @@ -47,6 +48,7 @@ export class UpdateTimelimitRuleAction extends ParentAction { sessionDurationMilliseconds: number sessionPauseMilliseconds: number perDay: boolean + expiresAt?: number }) { super() @@ -59,6 +61,7 @@ export class UpdateTimelimitRuleAction extends ParentAction { this.sessionDurationMilliseconds = sessionDurationMilliseconds this.sessionPauseMilliseconds = sessionPauseMilliseconds this.perDay = perDay + this.expiresAt = expiresAt assertIdWithinFamily({ actionType, field: 'ruleId', value: ruleId }) @@ -92,9 +95,17 @@ export class UpdateTimelimitRuleAction extends ParentAction { staticMessage: 'session duration lesser than zero' }) } + + if (expiresAt !== undefined) { + assertSafeInteger({ actionType, field: 'expiresAt', value: expiresAt }) + + if (expiresAt <= 0) { + throwOutOfRange({ actionType, field: 'expiresAt', value: expiresAt }) + } + } } - static parse = ({ ruleId, time, days, extraTime, start, end, dur, pause, perDay }: SerializedUpdateTimelimitRuleAction) => ( + static parse = ({ ruleId, time, days, extraTime, start, end, dur, pause, perDay, e }: SerializedUpdateTimelimitRuleAction) => ( new UpdateTimelimitRuleAction({ ruleId, maximumTimeInMillis: time, @@ -104,7 +115,8 @@ export class UpdateTimelimitRuleAction extends ParentAction { end: end ?? MinuteOfDay.MAX, sessionDurationMilliseconds: dur ?? 0, sessionPauseMilliseconds: pause ?? 0, - perDay: perDay ?? false + perDay: perDay ?? false, + expiresAt: e }) ) } @@ -120,4 +132,5 @@ export interface SerializedUpdateTimelimitRuleAction { dur?: number pause?: number perDay?: boolean + e?: number } diff --git a/src/api/validator.ts b/src/api/validator.ts index 408c934..4fab342 100644 --- a/src/api/validator.ts +++ b/src/api/validator.ts @@ -409,6 +409,9 @@ const definitions = { }, "perDay": { "type": "boolean" + }, + "e": { + "type": "number" } }, "additionalProperties": false, @@ -1417,6 +1420,9 @@ const definitions = { }, "perDay": { "type": "boolean" + }, + "e": { + "type": "number" } }, "additionalProperties": false, diff --git a/src/database/migration/migrations/20240408-add-rule-expires.ts b/src/database/migration/migrations/20240408-add-rule-expires.ts new file mode 100644 index 0000000..7525f00 --- /dev/null +++ b/src/database/migration/migrations/20240408-add-rule-expires.ts @@ -0,0 +1,39 @@ +/* + * server component for the TimeLimit App + * Copyright (C) 2019 - 2024 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 { attributesVersion4 as ruleAttributes } from '../../timelimitrule' + +export async function up (queryInterface: QueryInterface, sequelize: Sequelize) { + await sequelize.transaction({ + type: Transaction.TYPES.EXCLUSIVE + }, async (transaction) => { + await queryInterface.addColumn('TimelimitRules', 'expiresAt', { + ...ruleAttributes.expiresAt + }, { + transaction + }) + }) +} + +export async function down (queryInterface: QueryInterface, sequelize: Sequelize) { + await sequelize.transaction({ + type: Transaction.TYPES.EXCLUSIVE + }, async (transaction) => { + await queryInterface.removeColumn('TimelimitRules', 'expiresAt', { transaction }) + }) +} diff --git a/src/database/timelimitrule.ts b/src/database/timelimitrule.ts index 1d0aa1f..367396f 100644 --- a/src/database/timelimitrule.ts +++ b/src/database/timelimitrule.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2021 Jonas Lochmann + * Copyright (C) 2019 - 2024 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 @@ -41,8 +41,13 @@ interface TimelimitRuleAttributesVersion3 { perDay: number } +interface TimelimitRuleAttributesVersion4 { + expiresAt: string | null +} + type TimelimitRuleAttributes = TimelimitRuleAttributesVersion1 & - TimelimitRuleAttributesVersion2 & TimelimitRuleAttributesVersion3 + TimelimitRuleAttributesVersion2 & TimelimitRuleAttributesVersion3 & + TimelimitRuleAttributesVersion4 export type TimelimitRuleModel = Sequelize.Model & TimelimitRuleAttributes export type TimelimitRuleModelStatic = typeof Sequelize.Model & { @@ -137,10 +142,22 @@ export const attributesVersion3: SequelizeAttributes = { + expiresAt: { + type: Sequelize.BIGINT, + validate: { + min: 1 + }, + allowNull: true, + defaultValue: null + } +} + export const attributes: SequelizeAttributes = { ...attributesVersion1, ...attributesVersion2, - ...attributesVersion3 + ...attributesVersion3, + ...attributesVersion4 } export const createTimelimitRuleModel = (sequelize: Sequelize.Sequelize): TimelimitRuleModelStatic => sequelize.define('TimelimitRule', attributes) as TimelimitRuleModelStatic diff --git a/src/function/sync/apply-actions/dispatch-parent-action/createtimelimitrule.ts b/src/function/sync/apply-actions/dispatch-parent-action/createtimelimitrule.ts index 8e98ceb..6796b42 100644 --- a/src/function/sync/apply-actions/dispatch-parent-action/createtimelimitrule.ts +++ b/src/function/sync/apply-actions/dispatch-parent-action/createtimelimitrule.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2022 Jonas Lochmann + * Copyright (C) 2019 - 2024 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 @@ -55,7 +55,8 @@ export async function dispatchCreateTimeLimitRule ({ action, cache, fromChildSel endMinuteOfDay: action.rule.end, sessionDurationMilliseconds: action.rule.sessionDurationMilliseconds, sessionPauseMilliseconds: action.rule.sessionPauseMilliseconds, - perDay: action.rule.perDay ? 1 : 0 + perDay: action.rule.perDay ? 1 : 0, + expiresAt: action.rule.expiresAt ? action.rule.expiresAt.toString() : null }, { transaction: cache.transaction }) cache.categoriesWithModifiedTimeLimitRules.add(action.rule.categoryId) diff --git a/src/function/sync/apply-actions/dispatch-parent-action/updatetimelimitrule.ts b/src/function/sync/apply-actions/dispatch-parent-action/updatetimelimitrule.ts index a39a026..afae222 100644 --- a/src/function/sync/apply-actions/dispatch-parent-action/updatetimelimitrule.ts +++ b/src/function/sync/apply-actions/dispatch-parent-action/updatetimelimitrule.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2022 Jonas Lochmann + * Copyright (C) 2019 - 2024 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 @@ -81,7 +81,8 @@ export async function dispatchUpdateTimelimitRule ({ action.sessionDurationMilliseconds <= ruleEntry.sessionDurationMilliseconds && action.sessionPauseMilliseconds >= ruleEntry.sessionPauseMilliseconds )) && - (!action.perDay || ruleEntry.perDay || countOldAffectedDays <= 1) + (!action.perDay || ruleEntry.perDay || countOldAffectedDays <= 1) && + (action.expiresAt === undefined || (ruleEntry.expiresAt !== null && action.expiresAt >= parseInt(ruleEntry.expiresAt, 10))) if (!isAtLeastAsStrictAsPreviously) { throw new CanNotRelaxRestrictionsSelfLimitException() @@ -96,6 +97,7 @@ export async function dispatchUpdateTimelimitRule ({ ruleEntry.sessionDurationMilliseconds = action.sessionDurationMilliseconds ruleEntry.sessionPauseMilliseconds = action.sessionPauseMilliseconds ruleEntry.perDay = action.perDay ? 1 : 0 + ruleEntry.expiresAt = action.expiresAt ? action.expiresAt.toString() : null await ruleEntry.save({ transaction: cache.transaction }) diff --git a/src/function/sync/get-server-data-status/category/rules.ts b/src/function/sync/get-server-data-status/category/rules.ts index 263e01a..4405081 100644 --- a/src/function/sync/get-server-data-status/category/rules.ts +++ b/src/function/sync/get-server-data-status/category/rules.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2020 Jonas Lochmann + * Copyright (C) 2019 - 2024 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 @@ -45,7 +45,8 @@ export async function getRules ({ database, transaction, categoryIdsToSyncRules, 'endMinuteOfDay', 'sessionDurationMilliseconds', 'sessionPauseMilliseconds', - 'perDay' + 'perDay', + 'expiresAt' ], transaction })).map((item) => ({ @@ -58,7 +59,8 @@ export async function getRules ({ database, transaction, categoryIdsToSyncRules, endMinuteOfDay: item.endMinuteOfDay, sessionDurationMilliseconds: item.sessionDurationMilliseconds, sessionPauseMilliseconds: item.sessionPauseMilliseconds, - perDay: item.perDay + perDay: item.perDay, + expiresAt: item.expiresAt ? parseInt(item.expiresAt, 10) : undefined })) const getCategoryRulesVersion = (categoryId: string) => ( @@ -76,7 +78,8 @@ export async function getRules ({ database, transaction, categoryIdsToSyncRules, end: item.endMinuteOfDay, session: item.sessionDurationMilliseconds, pause: item.sessionPauseMilliseconds, - perDay: item.perDay !== 0 ? true : false + perDay: item.perDay !== 0 ? true : false, + e: item.expiresAt })), version: getCategoryRulesVersion(categoryId) })) diff --git a/src/function/sync/get-server-data-status/index.ts b/src/function/sync/get-server-data-status/index.ts index ec708ae..f5d57d7 100644 --- a/src/function/sync/get-server-data-status/index.ts +++ b/src/function/sync/get-server-data-status/index.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2022 Jonas Lochmann + * Copyright (C) 2019 - 2024 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 @@ -58,7 +58,7 @@ export const generateServerDataStatus = async ({ familyEntry.hasFullVersion ? parseInt(familyEntry.fullVersionUntil, 10) : 0 ), message: await getStatusMessage({ database, transaction }) || undefined, - apiLevel: 7 + apiLevel: 8 } if (familyEntry.deviceListVersion !== clientStatus.devices) { diff --git a/src/model/timelimitrule.ts b/src/model/timelimitrule.ts index f346dc5..9c0716d 100644 --- a/src/model/timelimitrule.ts +++ b/src/model/timelimitrule.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2020 Jonas Lochmann + * Copyright (C) 2019 - 2024 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 @@ -29,11 +29,12 @@ export class TimelimitRule { readonly sessionDurationMilliseconds: number readonly sessionPauseMilliseconds: number readonly perDay: boolean + readonly expiresAt?: number constructor ({ ruleId, categoryId, maxTimeInMillis, dayMask, applyToExtraTimeUsage, start, end, sessionDurationMilliseconds, sessionPauseMilliseconds, - perDay + perDay, expiresAt }: { ruleId: string categoryId: string @@ -45,6 +46,7 @@ export class TimelimitRule { sessionDurationMilliseconds: number sessionPauseMilliseconds: number perDay: boolean + expiresAt?: number }) { this.ruleId = ruleId this.categoryId = categoryId @@ -56,6 +58,7 @@ export class TimelimitRule { this.sessionDurationMilliseconds = sessionDurationMilliseconds this.sessionPauseMilliseconds = sessionPauseMilliseconds this.perDay = perDay + this.expiresAt = expiresAt assertIdWithinFamily(ruleId) assertIdWithinFamily(categoryId) @@ -88,6 +91,14 @@ export class TimelimitRule { if (sessionDurationMilliseconds < 0 || sessionPauseMilliseconds < 0) { throw new ParseTimeLimitRuleException() } + + if (expiresAt !== undefined) { + if (!Number.isSafeInteger(expiresAt)) throw new ParseTimeLimitRuleException() + + if (expiresAt <= 0) { + throw new ParseTimeLimitRuleException() + } + } } serialize = (): SerializedTimeLimitRule => ({ @@ -99,10 +110,11 @@ export class TimelimitRule { start: this.start, end: this.end, pause: this.sessionPauseMilliseconds, - dur: this.sessionDurationMilliseconds + dur: this.sessionDurationMilliseconds, + e: this.expiresAt }) - static parse = ({ ruleId, categoryId, time, days, extraTime, start, end, dur, pause, perDay }: SerializedTimeLimitRule) => ( + static parse = ({ ruleId, categoryId, time, days, extraTime, start, end, dur, pause, perDay, e }: SerializedTimeLimitRule) => ( new TimelimitRule({ ruleId, categoryId, @@ -113,7 +125,8 @@ export class TimelimitRule { end: end ?? MinuteOfDay.MAX, sessionDurationMilliseconds: dur ?? 0, sessionPauseMilliseconds: pause ?? 0, - perDay: perDay ?? false + perDay: perDay ?? false, + expiresAt: e }) ) } @@ -129,6 +142,7 @@ export interface SerializedTimeLimitRule { dur?: number pause?: number perDay?: boolean + e?: number // expiresAt } export class ParseTimeLimitRuleException extends Error {}