Compare commits

...
5 Commits
Author SHA1 Message Date
Jonas Lochmann 2bb3777484 Add preblocking 2020-12-21 01:00:00 +01:00
Jonas Lochmann 13ede06a91 Add task completion mails 2020-12-21 01:00:00 +01:00
Jonas Lochmann 2acee613f6 Sign in parents by default 2020-12-21 01:00:00 +01:00
Jonas Lochmann 9dc797a96c Remove parent blocked time support 2020-12-21 01:00:00 +01:00
Jonas Lochmann 3baab5072f Add simulating-a-device-from-the-shell.md 2020-12-07 01:00:00 +01:00
44 changed files with 1221 additions and 573 deletions
@@ -0,0 +1,50 @@
## Simulating a device from the shell
This document describes how one can register a device, read the status and add used time at the TimeLimit server using curl and jq.
It requires a previous installation of the official client at some other device.
---
First, setup TimeLimit somehwere and chose the "add device" option at the overview screen to get a code.
In this example, it's "Spagat vertreiben Waise Schnitzel subtil". The Server is running in localhost in this case.
Then one can register a new device using this token.
```
curl -X POST -H "Content-Type: application/json" --data '{"registerToken":"Spagat vertreiben Waise Schnitzel subtil","deviceName":"Test-PC","childDevice":{"model":"PC"}}' http://localhost:8080/child/add-device
# response:
# {"deviceAuthToken":"bAz5nArfZz8IbsPlpinav5ODHpl6KyrQ","ownDeviceId":"q61lT0"}
```
The TimeLimit client will now show this new minimal device. Both values are important and should be written down for using them later.
The first idea would be to get the current configuration:
```
curl -X POST -H "Content-Type: application/json" --data '{"deviceAuthToken":"bAz5nArfZz8IbsPlpinav5ODHpl6KyrQ","status":{"devices":"","apps":{},"categories":{},"users":"","clientLevel":3}}' http://localhost:8080/sync/pull-status | jq .
```
This status parameters are required to get the current status. They can be set for caching, but for testing it's enough to kepp the values empty.
By replacing the dot as parameter for jq, it's possible to get some specific data.
One example would be to get the info for the device itself using ``curl ... | jq '[ .devices.data[] | {key:.deviceId,value:.} ] | from_entries | .q61lT0'``.
It's a good idea to read <https://stedolan.github.io/jq/manual/> to know how to extract values from this data using jq.
In this case, there is the category "Erlaubte Spiele" with the categoryId ``SLwtDr`` (can be found in the response). The error diagnose of the client showed 18608 as current day of epoch.
```
# first encode the action itself
echo '{"type":"ADD_USED_TIME_V2","d":18608,"i":[{"categoryId":"SLwtDr","tta":60000,"etts":0}]}' | jq --raw-input .
# d = dayOfEpoch
# tta = time to add in milliseconds
# etts = extra time to subtract in milliseconds
# then put it as the encodedAction here
curl -X POST -H "Content-Type: application/json" --data '{"deviceAuthToken":"bAz5nArfZz8IbsPlpinav5ODHpl6KyrQ","actions":[{"encodedAction":"{\"type\":\"ADD_USED_TIME_V2\",\"d\":18608,\"i\":[{\"categoryId\":\"SLwtDr\",\"tta\":60000,\"etts\":0}]}","sequenceNumber":2,"integrity":"","type":"appLogic","userId":""}]}' http://localhost:8080/sync/push-actions
# response: {"shouldDoFullSync":false} which indicates success
```
The sequence number must be increased. Otherwise, the actions are ignored. This allows sending actions again if the connection was interrupted without counting the time twice.
After running this, the client should show one used minute for the day and the pull-status should report it too.
jq can be used for constructing the request bodies and correctly escaping the values during this. For this, ``--arg name value`` which is described in its documentation is useful. For reading and using values, ``--raw-output`` can help.
+53 -55
View File
@@ -55,137 +55,135 @@
- [ParentPassword](./serializedchildaction-definitions-serializedchildchangepasswordaction-properties-parentpassword.md) `https://timelimit.io/SerializedChildAction#/definitions/SerializedChildChangePasswordAction/properties/password`
- [SerialiezdTriedDisablingDeviceAdminAction](./serializedapplogicaction-definitions-serialiezdtrieddisablingdeviceadminaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerialiezdTriedDisablingDeviceAdminAction`
- [SerialiezdTriedDisablingDeviceAdminAction](./serializedapplogicaction-anyof-serialiezdtrieddisablingdeviceadminaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/7`
- [SerialiizedUpdateNetworkTimeVerificationAction](./serializedparentaction-anyof-serialiizedupdatenetworktimeverificationaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/41`
- [SerialiizedUpdateNetworkTimeVerificationAction](./serializedparentaction-definitions-serialiizedupdatenetworktimeverificationaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerialiizedUpdateNetworkTimeVerificationAction`
- [SerializeResetCategoryNetworkIdsAction](./serializedparentaction-anyof-serializeresetcategorynetworkidsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/14`
- [SerialiizedUpdateNetworkTimeVerificationAction](./serializedparentaction-anyof-serialiizedupdatenetworktimeverificationaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/40`
- [SerializeResetCategoryNetworkIdsAction](./serializedparentaction-definitions-serializeresetcategorynetworkidsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializeResetCategoryNetworkIdsAction`
- [SerializeResetCategoryNetworkIdsAction](./serializedparentaction-anyof-serializeresetcategorynetworkidsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/14`
- [SerializedAddCategoryAppsAction](./serializedparentaction-definitions-serializedaddcategoryappsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedAddCategoryAppsAction`
- [SerializedAddCategoryAppsAction](./serializedparentaction-anyof-serializedaddcategoryappsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/0`
- [SerializedAddCategoryNetworkIdAction](./serializedparentaction-definitions-serializedaddcategorynetworkidaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedAddCategoryNetworkIdAction`
- [SerializedAddCategoryNetworkIdAction](./serializedparentaction-anyof-serializedaddcategorynetworkidaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/1`
- [SerializedAddInstalledAppsAction](./serializedapplogicaction-definitions-serializedaddinstalledappsaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddInstalledAppsAction`
- [SerializedAddInstalledAppsAction](./serializedapplogicaction-anyof-serializedaddinstalledappsaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/0`
- [SerializedAddUsedTimeAction](./serializedapplogicaction-definitions-serializedaddusedtimeaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeAction`
- [SerializedAddUsedTimeAction](./serializedapplogicaction-anyof-serializedaddusedtimeaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/1`
- [SerializedAddUsedTimeAction](./serializedapplogicaction-definitions-serializedaddusedtimeaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeAction`
- [SerializedAddUsedTimeActionVersion2](./serializedapplogicaction-definitions-serializedaddusedtimeactionversion2.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeActionVersion2`
- [SerializedAddUsedTimeActionVersion2](./serializedapplogicaction-anyof-serializedaddusedtimeactionversion2.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/2`
- [SerializedAddUserAction](./serializedparentaction-definitions-serializedadduseraction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedAddUserAction`
- [SerializedAddUserAction](./serializedparentaction-anyof-serializedadduseraction.md) `https://timelimit.io/SerializedParentAction#/anyOf/2`
- [SerializedAppActivityItem](./serverdatastatus-definitions-serverinstalledappsdata-properties-activities-serializedappactivityitem.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/activities/items`
- [SerializedAppActivityItem](./serverdatastatus-definitions-serverinstalledappsdata-properties-activities-serializedappactivityitem.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/activities/items`
- [SerializedAppActivityItem](./serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-updatedoradded-serializedappactivityitem.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/updatedOrAdded/items`
- [SerializedAddUserAction](./serializedparentaction-definitions-serializedadduseraction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedAddUserAction`
- [SerializedAppActivityItem](./serializedapplogicaction-definitions-serializedappactivityitem.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAppActivityItem`
- [SerializedAppActivityItem](./serverdatastatus-definitions-serializedappactivityitem.md) `https://timelimit.io/ServerDataStatus#/definitions/SerializedAppActivityItem`
- [SerializedAppActivityItem](./serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-updatedoradded-serializedappactivityitem.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/updatedOrAdded/items`
- [SerializedAppActivityItem](./serializedapplogicaction-definitions-serializedappactivityitem.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAppActivityItem`
- [SerializedChangeParentPasswordAction](./serializedparentaction-definitions-serializedchangeparentpasswordaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedChangeParentPasswordAction`
- [SerializedAppActivityItem](./serverdatastatus-definitions-serverinstalledappsdata-properties-activities-serializedappactivityitem.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/activities/items`
- [SerializedAppActivityItem](./serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-updatedoradded-serializedappactivityitem.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/updatedOrAdded/items`
- [SerializedAppActivityItem](./serverdatastatus-definitions-serverinstalledappsdata-properties-activities-serializedappactivityitem.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/activities/items`
- [SerializedChangeParentPasswordAction](./serializedparentaction-anyof-serializedchangeparentpasswordaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/3`
- [SerializedChildChangePasswordAction](./serializedchildaction-definitions-serializedchildchangepasswordaction.md) `https://timelimit.io/SerializedChildAction#/definitions/SerializedChildChangePasswordAction`
- [SerializedChangeParentPasswordAction](./serializedparentaction-definitions-serializedchangeparentpasswordaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedChangeParentPasswordAction`
- [SerializedChildChangePasswordAction](./serializedchildaction-anyof-serializedchildchangepasswordaction.md) `https://timelimit.io/SerializedChildAction#/anyOf/0`
- [SerializedChildSignInAction](./serializedchildaction-definitions-serializedchildsigninaction.md) `https://timelimit.io/SerializedChildAction#/definitions/SerializedChildSignInAction`
- [SerializedChildChangePasswordAction](./serializedchildaction-definitions-serializedchildchangepasswordaction.md) `https://timelimit.io/SerializedChildAction#/definitions/SerializedChildChangePasswordAction`
- [SerializedChildSignInAction](./serializedchildaction-anyof-serializedchildsigninaction.md) `https://timelimit.io/SerializedChildAction#/anyOf/1`
- [SerializedChildSignInAction](./serializedchildaction-definitions-serializedchildsigninaction.md) `https://timelimit.io/SerializedChildAction#/definitions/SerializedChildSignInAction`
- [SerializedCreateCategoryAction](./serializedparentaction-anyof-serializedcreatecategoryaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/4`
- [SerializedCreateCategoryAction](./serializedparentaction-definitions-serializedcreatecategoryaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedCreateCategoryAction`
- [SerializedCreateTimelimtRuleAction](./serializedparentaction-anyof-serializedcreatetimelimtruleaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/5`
- [SerializedCreateTimelimtRuleAction](./serializedparentaction-definitions-serializedcreatetimelimtruleaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedCreateTimelimtRuleAction`
- [SerializedCreateTimelimtRuleAction](./serializedparentaction-anyof-serializedcreatetimelimtruleaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/5`
- [SerializedDeleteCategoryAction](./serializedparentaction-anyof-serializeddeletecategoryaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/6`
- [SerializedDeleteCategoryAction](./serializedparentaction-definitions-serializeddeletecategoryaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedDeleteCategoryAction`
- [SerializedDeleteChildTaskAction](./serializedparentaction-anyof-serializeddeletechildtaskaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/7`
- [SerializedDeleteChildTaskAction](./serializedparentaction-definitions-serializeddeletechildtaskaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedDeleteChildTaskAction`
- [SerializedDeleteTimeLimitRuleAction](./serializedparentaction-anyof-serializeddeletetimelimitruleaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/8`
- [SerializedDeleteTimeLimitRuleAction](./serializedparentaction-definitions-serializeddeletetimelimitruleaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedDeleteTimeLimitRuleAction`
- [SerializedForceSyncAction](./serializedapplogicaction-definitions-serializedforcesyncaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedForceSyncAction`
- [SerializedForceSyncAction](./serializedapplogicaction-anyof-serializedforcesyncaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/3`
- [SerializedIgnoreManipulationAction](./serializedparentaction-definitions-serializedignoremanipulationaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedIgnoreManipulationAction`
- [SerializedForceSyncAction](./serializedapplogicaction-definitions-serializedforcesyncaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedForceSyncAction`
- [SerializedIgnoreManipulationAction](./serializedparentaction-anyof-serializedignoremanipulationaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/9`
- [SerializedIgnoreManipulationAction](./serializedparentaction-definitions-serializedignoremanipulationaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedIgnoreManipulationAction`
- [SerializedIncrementCategoryExtraTimeAction](./serializedparentaction-definitions-serializedincrementcategoryextratimeaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedIncrementCategoryExtraTimeAction`
- [SerializedIncrementCategoryExtraTimeAction](./serializedparentaction-anyof-serializedincrementcategoryextratimeaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/10`
- [SerializedInstalledApp](./serializedapplogicaction-definitions-serializedinstalledapp.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedInstalledApp`
- [SerializedInstalledApp](./serializedapplogicaction-definitions-serializedaddinstalledappsaction-properties-apps-serializedinstalledapp.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddInstalledAppsAction/properties/apps/items`
- [SerializedInstalledApp](./serverdatastatus-definitions-serverinstalledappsdata-properties-apps-serializedinstalledapp.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/apps/items`
- [SerializedInstalledApp](./serverdatastatus-definitions-serverinstalledappsdata-properties-apps-serializedinstalledapp.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/apps/items`
- [SerializedInstalledApp](./serverdatastatus-definitions-serializedinstalledapp.md) `https://timelimit.io/ServerDataStatus#/definitions/SerializedInstalledApp`
- [SerializedInstalledApp](./serializedapplogicaction-definitions-serializedaddinstalledappsaction-properties-apps-serializedinstalledapp.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddInstalledAppsAction/properties/apps/items`
- [SerializedInstalledApp](./serverdatastatus-definitions-serverinstalledappsdata-properties-apps-serializedinstalledapp.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/apps/items`
- [SerializedInstalledApp](./serverdatastatus-definitions-serverinstalledappsdata-properties-apps-serializedinstalledapp.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/apps/items`
- [SerializedInstalledApp](./serializedapplogicaction-definitions-serializedinstalledapp.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedInstalledApp`
- [SerializedMarkTaskPendingAction](./serializedapplogicaction-anyof-serializedmarktaskpendingaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/4`
- [SerializedMarkTaskPendingAction](./serializedapplogicaction-definitions-serializedmarktaskpendingaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedMarkTaskPendingAction`
- [SerializedMarkTaskPendingAction](./serializedapplogicaction-anyof-serializedmarktaskpendingaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/4`
- [SerializedRemoveCategoryAppsAction](./serializedparentaction-definitions-serializedremovecategoryappsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedRemoveCategoryAppsAction`
- [SerializedRemoveCategoryAppsAction](./serializedparentaction-anyof-serializedremovecategoryappsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/11`
- [SerializedRemoveInstalledAppsAction](./serializedapplogicaction-anyof-serializedremoveinstalledappsaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/5`
- [SerializedRemoveInstalledAppsAction](./serializedapplogicaction-definitions-serializedremoveinstalledappsaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedRemoveInstalledAppsAction`
- [SerializedRemoveUserAction](./serializedparentaction-anyof-serializedremoveuseraction.md) `https://timelimit.io/SerializedParentAction#/anyOf/12`
- [SerializedRemoveUserAction](./serializedparentaction-definitions-serializedremoveuseraction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedRemoveUserAction`
- [SerializedRenameChildAction](./serializedparentaction-anyof-serializedrenamechildaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/13`
- [SerializedRemoveUserAction](./serializedparentaction-anyof-serializedremoveuseraction.md) `https://timelimit.io/SerializedParentAction#/anyOf/12`
- [SerializedRenameChildAction](./serializedparentaction-definitions-serializedrenamechildaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedRenameChildAction`
- [SerializedResetParentBlockedTimesAction](./serializedparentaction-definitions-serializedresetparentblockedtimesaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedResetParentBlockedTimesAction`
- [SerializedResetParentBlockedTimesAction](./serializedparentaction-anyof-serializedresetparentblockedtimesaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/15`
- [SerializedReviewChildTaskAction](./serializedparentaction-anyof-serializedreviewchildtaskaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/16`
- [SerializedRenameChildAction](./serializedparentaction-anyof-serializedrenamechildaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/13`
- [SerializedReviewChildTaskAction](./serializedparentaction-definitions-serializedreviewchildtaskaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedReviewChildTaskAction`
- [SerializedReviewChildTaskAction](./serializedparentaction-anyof-serializedreviewchildtaskaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/15`
- [SerializedSetCategoryExtraTimeAction](./serializedparentaction-anyof-serializedsetcategoryextratimeaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/16`
- [SerializedSetCategoryExtraTimeAction](./serializedparentaction-definitions-serializedsetcategoryextratimeaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetCategoryExtraTimeAction`
- [SerializedSetCategoryExtraTimeAction](./serializedparentaction-anyof-serializedsetcategoryextratimeaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/17`
- [SerializedSetCategoryForUnassignedAppsAction](./serializedparentaction-anyof-serializedsetcategoryforunassignedappsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/18`
- [SerializedSetCategoryForUnassignedAppsAction](./serializedparentaction-definitions-serializedsetcategoryforunassignedappsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetCategoryForUnassignedAppsAction`
- [SerializedSetChildPasswordAction](./serializedparentaction-anyof-serializedsetchildpasswordaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/19`
- [SerializedSetCategoryForUnassignedAppsAction](./serializedparentaction-anyof-serializedsetcategoryforunassignedappsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/17`
- [SerializedSetChildPasswordAction](./serializedparentaction-anyof-serializedsetchildpasswordaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/18`
- [SerializedSetChildPasswordAction](./serializedparentaction-definitions-serializedsetchildpasswordaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetChildPasswordAction`
- [SerializedSetConsiderRebootManipulationAction](./serializedparentaction-anyof-serializedsetconsiderrebootmanipulationaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/20`
- [SerializedSetConsiderRebootManipulationAction](./serializedparentaction-anyof-serializedsetconsiderrebootmanipulationaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/19`
- [SerializedSetConsiderRebootManipulationAction](./serializedparentaction-definitions-serializedsetconsiderrebootmanipulationaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetConsiderRebootManipulationAction`
- [SerializedSetDeviceDefaultUserAction](./serializedparentaction-anyof-serializedsetdevicedefaultuseraction.md) `https://timelimit.io/SerializedParentAction#/anyOf/21`
- [SerializedSetDeviceDefaultUserAction](./serializedparentaction-definitions-serializedsetdevicedefaultuseraction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetDeviceDefaultUserAction`
- [SerializedSetDeviceDefaultUserAction](./serializedparentaction-anyof-serializedsetdevicedefaultuseraction.md) `https://timelimit.io/SerializedParentAction#/anyOf/20`
- [SerializedSetDeviceDefaultUserTimeoutAction](./serializedparentaction-definitions-serializedsetdevicedefaultusertimeoutaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetDeviceDefaultUserTimeoutAction`
- [SerializedSetDeviceDefaultUserTimeoutAction](./serializedparentaction-anyof-serializedsetdevicedefaultusertimeoutaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/22`
- [SerializedSetDeviceUserAction](./serializedparentaction-anyof-serializedsetdeviceuseraction.md) `https://timelimit.io/SerializedParentAction#/anyOf/23`
- [SerializedSetDeviceDefaultUserTimeoutAction](./serializedparentaction-anyof-serializedsetdevicedefaultusertimeoutaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/21`
- [SerializedSetDeviceUserAction](./serializedparentaction-definitions-serializedsetdeviceuseraction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetDeviceUserAction`
- [SerializedSetKeepSignedInAction](./serializedparentaction-anyof-serializedsetkeepsignedinaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/24`
- [SerializedSetDeviceUserAction](./serializedparentaction-anyof-serializedsetdeviceuseraction.md) `https://timelimit.io/SerializedParentAction#/anyOf/22`
- [SerializedSetKeepSignedInAction](./serializedparentaction-definitions-serializedsetkeepsignedinaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetKeepSignedInAction`
- [SerializedSetParentCategoryAction](./serializedparentaction-anyof-serializedsetparentcategoryaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/25`
- [SerializedSetKeepSignedInAction](./serializedparentaction-anyof-serializedsetkeepsignedinaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/23`
- [SerializedSetParentCategoryAction](./serializedparentaction-definitions-serializedsetparentcategoryaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetParentCategoryAction`
- [SerializedSetRelaxPrimaryDeviceAction](./serializedparentaction-anyof-serializedsetrelaxprimarydeviceaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/26`
- [SerializedSetParentCategoryAction](./serializedparentaction-anyof-serializedsetparentcategoryaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/24`
- [SerializedSetRelaxPrimaryDeviceAction](./serializedparentaction-anyof-serializedsetrelaxprimarydeviceaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/25`
- [SerializedSetRelaxPrimaryDeviceAction](./serializedparentaction-definitions-serializedsetrelaxprimarydeviceaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetRelaxPrimaryDeviceAction`
- [SerializedSetSendDeviceConnected](./serializedparentaction-definitions-serializedsetsenddeviceconnected.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetSendDeviceConnected`
- [SerializedSetSendDeviceConnected](./serializedparentaction-anyof-serializedsetsenddeviceconnected.md) `https://timelimit.io/SerializedParentAction#/anyOf/27`
- [SerializedSetSendDeviceConnected](./serializedparentaction-anyof-serializedsetsenddeviceconnected.md) `https://timelimit.io/SerializedParentAction#/anyOf/26`
- [SerializedSetUserDisableLimitsUntilAction](./serializedparentaction-definitions-serializedsetuserdisablelimitsuntilaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetUserDisableLimitsUntilAction`
- [SerializedSetUserDisableLimitsUntilAction](./serializedparentaction-anyof-serializedsetuserdisablelimitsuntilaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/28`
- [SerializedSetUserTimezoneAction](./serializedparentaction-anyof-serializedsetusertimezoneaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/29`
- [SerializedSetUserDisableLimitsUntilAction](./serializedparentaction-anyof-serializedsetuserdisablelimitsuntilaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/27`
- [SerializedSetUserTimezoneAction](./serializedparentaction-anyof-serializedsetusertimezoneaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/28`
- [SerializedSetUserTimezoneAction](./serializedparentaction-definitions-serializedsetusertimezoneaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedSetUserTimezoneAction`
- [SerializedSignOutAtDeviceAction](./serializedapplogicaction-anyof-serializedsignoutatdeviceaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/6`
- [SerializedSignOutAtDeviceAction](./serializedapplogicaction-definitions-serializedsignoutatdeviceaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSignOutAtDeviceAction`
- [SerializedTimeLimitRule](./serializedparentaction-definitions-serializedcreatetimelimtruleaction-properties-serializedtimelimitrule.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedCreateTimelimtRuleAction/properties/rule`
- [SerializedTimeLimitRule](./serializedparentaction-definitions-serializedcreatetimelimtruleaction-properties-serializedtimelimitrule.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedCreateTimelimtRuleAction/properties/rule`
- [SerializedTimeLimitRule](./serializedparentaction-definitions-serializedtimelimitrule.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule`
- [SerializedTimeLimitRule](./serializedparentaction-definitions-serializedcreatetimelimtruleaction-properties-serializedtimelimitrule.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedCreateTimelimtRuleAction/properties/rule`
- [SerializedTimeLimitRule](./serializedparentaction-definitions-serializedcreatetimelimtruleaction-properties-serializedtimelimitrule.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedCreateTimelimtRuleAction/properties/rule`
- [SerializedUpdatCategoryDisableLimitsAction](./serializedparentaction-definitions-serializedupdatcategorydisablelimitsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdatCategoryDisableLimitsAction`
- [SerializedUpdatCategoryDisableLimitsAction](./serializedparentaction-anyof-serializedupdatcategorydisablelimitsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/33`
- [SerializedUpdatCategoryDisableLimitsAction](./serializedparentaction-anyof-serializedupdatcategorydisablelimitsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/32`
- [SerializedUpdateAppActivitiesAction](./serializedapplogicaction-definitions-serializedupdateappactivitiesaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction`
- [SerializedUpdateAppActivitiesAction](./serializedapplogicaction-anyof-serializedupdateappactivitiesaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/8`
- [SerializedUpdateCategoryBatteryLimitAction](./serializedparentaction-definitions-serializedupdatecategorybatterylimitaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategoryBatteryLimitAction`
- [SerializedUpdateCategoryBatteryLimitAction](./serializedparentaction-anyof-serializedupdatecategorybatterylimitaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/30`
- [SerializedUpdateCategoryBatteryLimitAction](./serializedparentaction-anyof-serializedupdatecategorybatterylimitaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/29`
- [SerializedUpdateCategoryBlockAllNotificationsAction](./serializedparentaction-definitions-serializedupdatecategoryblockallnotificationsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategoryBlockAllNotificationsAction`
- [SerializedUpdateCategoryBlockAllNotificationsAction](./serializedparentaction-anyof-serializedupdatecategoryblockallnotificationsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/31`
- [SerializedUpdateCategoryBlockAllNotificationsAction](./serializedparentaction-anyof-serializedupdatecategoryblockallnotificationsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/30`
- [SerializedUpdateCategoryBlockedTimesAction](./serializedparentaction-definitions-serializedupdatecategoryblockedtimesaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategoryBlockedTimesAction`
- [SerializedUpdateCategoryBlockedTimesAction](./serializedparentaction-anyof-serializedupdatecategoryblockedtimesaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/32`
- [SerializedUpdateCategorySortingAction](./serializedparentaction-anyof-serializedupdatecategorysortingaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/34`
- [SerializedUpdateCategoryBlockedTimesAction](./serializedparentaction-anyof-serializedupdatecategoryblockedtimesaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/31`
- [SerializedUpdateCategorySortingAction](./serializedparentaction-anyof-serializedupdatecategorysortingaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/33`
- [SerializedUpdateCategorySortingAction](./serializedparentaction-definitions-serializedupdatecategorysortingaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategorySortingAction`
- [SerializedUpdateCategoryTemporarilyBlockedAction](./serializedparentaction-anyof-serializedupdatecategorytemporarilyblockedaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/35`
- [SerializedUpdateCategoryTemporarilyBlockedAction](./serializedparentaction-anyof-serializedupdatecategorytemporarilyblockedaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/34`
- [SerializedUpdateCategoryTemporarilyBlockedAction](./serializedparentaction-definitions-serializedupdatecategorytemporarilyblockedaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategoryTemporarilyBlockedAction`
- [SerializedUpdateCategoryTimeWarningsAction](./serializedparentaction-anyof-serializedupdatecategorytimewarningsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/36`
- [SerializedUpdateCategoryTimeWarningsAction](./serializedparentaction-anyof-serializedupdatecategorytimewarningsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/35`
- [SerializedUpdateCategoryTimeWarningsAction](./serializedparentaction-definitions-serializedupdatecategorytimewarningsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategoryTimeWarningsAction`
- [SerializedUpdateCategoryTitleAction](./serializedparentaction-anyof-serializedupdatecategorytitleaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/37`
- [SerializedUpdateCategoryTitleAction](./serializedparentaction-anyof-serializedupdatecategorytitleaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/36`
- [SerializedUpdateCategoryTitleAction](./serializedparentaction-definitions-serializedupdatecategorytitleaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategoryTitleAction`
- [SerializedUpdateChildTaskAction](./serializedparentaction-anyof-serializedupdatechildtaskaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/38`
- [SerializedUpdateChildTaskAction](./serializedparentaction-anyof-serializedupdatechildtaskaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/37`
- [SerializedUpdateChildTaskAction](./serializedparentaction-definitions-serializedupdatechildtaskaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateChildTaskAction`
- [SerializedUpdateDeviceNameAction](./serializedparentaction-anyof-serializedupdatedevicenameaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/39`
- [SerializedUpdateDeviceNameAction](./serializedparentaction-anyof-serializedupdatedevicenameaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/38`
- [SerializedUpdateDeviceNameAction](./serializedparentaction-definitions-serializedupdatedevicenameaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateDeviceNameAction`
- [SerializedUpdateDeviceStatusAction](./serializedapplogicaction-anyof-serializedupdatedevicestatusaction.md) `https://timelimit.io/SerializedAppLogicAction#/anyOf/9`
- [SerializedUpdateDeviceStatusAction](./serializedapplogicaction-definitions-serializedupdatedevicestatusaction.md) `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction`
- [SerializedUpdateEnableActivityLevelBlockingAction](./serializedparentaction-anyof-serializedupdateenableactivitylevelblockingaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/40`
- [SerializedUpdateEnableActivityLevelBlockingAction](./serializedparentaction-anyof-serializedupdateenableactivitylevelblockingaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/39`
- [SerializedUpdateEnableActivityLevelBlockingAction](./serializedparentaction-definitions-serializedupdateenableactivitylevelblockingaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateEnableActivityLevelBlockingAction`
- [SerializedUpdateParentBlockedTimesAction](./serializedparentaction-anyof-serializedupdateparentblockedtimesaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/42`
- [SerializedUpdateParentBlockedTimesAction](./serializedparentaction-definitions-serializedupdateparentblockedtimesaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentBlockedTimesAction`
- [SerializedUpdateParentNotificationFlagsAction](./serializedparentaction-anyof-serializedupdateparentnotificationflagsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/43`
- [SerializedUpdateParentNotificationFlagsAction](./serializedparentaction-anyof-serializedupdateparentnotificationflagsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/41`
- [SerializedUpdateParentNotificationFlagsAction](./serializedparentaction-definitions-serializedupdateparentnotificationflagsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentNotificationFlagsAction`
- [SerializedUpdateTimelimitRuleAction](./serializedparentaction-anyof-serializedupdatetimelimitruleaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/42`
- [SerializedUpdateTimelimitRuleAction](./serializedparentaction-definitions-serializedupdatetimelimitruleaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction`
- [SerializedUpdateTimelimitRuleAction](./serializedparentaction-anyof-serializedupdatetimelimitruleaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/44`
- [SerializedUpdateUserFlagsAction](./serializedparentaction-anyof-serializedupdateuserflagsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/45`
- [SerializedUpdateUserFlagsAction](./serializedparentaction-definitions-serializedupdateuserflagsaction.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserFlagsAction`
- [SerializedUpdateUserLimitLoginCategory](./serializedparentaction-anyof-serializedupdateuserlimitlogincategory.md) `https://timelimit.io/SerializedParentAction#/anyOf/46`
- [SerializedUpdateUserFlagsAction](./serializedparentaction-anyof-serializedupdateuserflagsaction.md) `https://timelimit.io/SerializedParentAction#/anyOf/43`
- [SerializedUpdateUserLimitLoginCategory](./serializedparentaction-anyof-serializedupdateuserlimitlogincategory.md) `https://timelimit.io/SerializedParentAction#/anyOf/44`
- [SerializedUpdateUserLimitLoginCategory](./serializedparentaction-definitions-serializedupdateuserlimitlogincategory.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginCategory`
- [SerializedUpdateUserLimitLoginPreBlockDuration](./serializedparentaction-anyof-serializedupdateuserlimitloginpreblockduration.md) `https://timelimit.io/SerializedParentAction#/anyOf/45`
- [SerializedUpdateUserLimitLoginPreBlockDuration](./serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration.md) `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration`
- [ServerCategoryNetworkId](./serverdatastatus-definitions-servercategorynetworkid.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerCategoryNetworkId`
- [ServerCategoryNetworkId](./serverdatastatus-definitions-serverupdatedcategorybasedata-properties-networks-servercategorynetworkid.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedCategoryBaseData/properties/networks/items`
- [ServerCategoryNetworkId](./serverdatastatus-definitions-serverupdatedcategorybasedata-properties-networks-servercategorynetworkid.md) `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedCategoryBaseData/properties/networks/items`
+27 -50
View File
@@ -45,9 +45,6 @@
{
"$ref": "#/definitions/SerializeResetCategoryNetworkIdsAction"
},
{
"$ref": "#/definitions/SerializedResetParentBlockedTimesAction"
},
{
"$ref": "#/definitions/SerializedReviewChildTaskAction"
},
@@ -126,9 +123,6 @@
{
"$ref": "#/definitions/SerialiizedUpdateNetworkTimeVerificationAction"
},
{
"$ref": "#/definitions/SerializedUpdateParentBlockedTimesAction"
},
{
"$ref": "#/definitions/SerializedUpdateParentNotificationFlagsAction"
},
@@ -140,6 +134,9 @@
},
{
"$ref": "#/definitions/SerializedUpdateUserLimitLoginCategory"
},
{
"$ref": "#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration"
}
],
"definitions": {
@@ -623,26 +620,6 @@
],
"title": "SerializeResetCategoryNetworkIdsAction"
},
"SerializedResetParentBlockedTimesAction": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"RESET_PARENT_BLOCKED_TIMES"
]
},
"parentId": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"parentId",
"type"
],
"title": "SerializedResetParentBlockedTimesAction"
},
"SerializedReviewChildTaskAction": {
"type": "object",
"properties": {
@@ -1299,30 +1276,6 @@
],
"title": "SerialiizedUpdateNetworkTimeVerificationAction"
},
"SerializedUpdateParentBlockedTimesAction": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"UPDATE_PARENT_BLOCKED_TIMES"
]
},
"parentId": {
"type": "string"
},
"times": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"parentId",
"times",
"type"
],
"title": "SerializedUpdateParentBlockedTimesAction"
},
"SerializedUpdateParentNotificationFlagsAction": {
"type": "object",
"properties": {
@@ -1448,6 +1401,30 @@
"userId"
],
"title": "SerializedUpdateUserLimitLoginCategory"
},
"SerializedUpdateUserLimitLoginPreBlockDuration": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"UPDATE_USER_LIMIT_LOGIN_PRE_BLOCK_DURATION"
]
},
"userId": {
"type": "string"
},
"preBlockDuration": {
"type": "number"
}
},
"additionalProperties": false,
"required": [
"preBlockDuration",
"type",
"userId"
],
"title": "SerializedUpdateUserLimitLoginPreBlockDuration"
}
},
"$schema": "http://json-schema.org/draft-07/schema#",
+3
View File
@@ -738,6 +738,9 @@
},
"llc": {
"type": "string"
},
"pbd": {
"type": "number"
}
},
"additionalProperties": false,
@@ -0,0 +1,16 @@
# Untitled number in SerializedParentAction Schema
```txt
https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/preBlockDuration
```
| 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") |
## preBlockDuration Type
`number`
@@ -0,0 +1,24 @@
# Untitled string in SerializedParentAction Schema
```txt
https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/type
```
| 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") |
## type Type
`string`
## type Constraints
**enum**: the value of this property must be equal to one of the following values:
| Value | Explanation |
| :--------------------------------------------- | ----------- |
| `"UPDATE_USER_LIMIT_LOGIN_PRE_BLOCK_DURATION"` | |
@@ -0,0 +1,16 @@
# Untitled string in SerializedParentAction Schema
```txt
https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/userId
```
| 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") |
## userId Type
`string`
@@ -0,0 +1,16 @@
# Untitled undefined type in SerializedParentAction Schema
```txt
https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties
```
| 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") |
## properties Type
unknown
@@ -0,0 +1,80 @@
# SerializedUpdateUserLimitLoginPreBlockDuration Schema
```txt
https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration
```
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
| :------------------ | ---------- | -------------- | ------------ | :---------------- | --------------------- | ------------------- | ------------------------------------------------------------------------------------------------- |
| Can be instantiated | No | Unknown status | No | Forbidden | Forbidden | none | [SerializedParentAction.schema.json\*](SerializedParentAction.schema.json "open original schema") |
## SerializedUpdateUserLimitLoginPreBlockDuration Type
`object` ([SerializedUpdateUserLimitLoginPreBlockDuration](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration.md))
# SerializedUpdateUserLimitLoginPreBlockDuration Properties
| Property | Type | Required | Nullable | Defined by |
| :------------------------------------ | -------- | -------- | -------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [type](#type) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-type.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/type") |
| [userId](#userId) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-userid.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/userId") |
| [preBlockDuration](#preBlockDuration) | `number` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-preblockduration.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/preBlockDuration") |
## type
`type`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-type.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/type")
### type Type
`string`
### type Constraints
**enum**: the value of this property must be equal to one of the following values:
| Value | Explanation |
| :--------------------------------------------- | ----------- |
| `"UPDATE_USER_LIMIT_LOGIN_PRE_BLOCK_DURATION"` | |
## userId
`userId`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-userid.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/userId")
### userId Type
`string`
## preBlockDuration
`preBlockDuration`
- is required
- Type: `number`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-preblockduration.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/preBlockDuration")
### preBlockDuration Type
`number`
+71 -125
View File
@@ -32,7 +32,6 @@ any of
- [SerializedRemoveUserAction](serializedparentaction-definitions-serializedremoveuseraction.md "check type definition")
- [SerializedRenameChildAction](serializedparentaction-definitions-serializedrenamechildaction.md "check type definition")
- [SerializeResetCategoryNetworkIdsAction](serializedparentaction-definitions-serializeresetcategorynetworkidsaction.md "check type definition")
- [SerializedResetParentBlockedTimesAction](serializedparentaction-definitions-serializedresetparentblockedtimesaction.md "check type definition")
- [SerializedReviewChildTaskAction](serializedparentaction-definitions-serializedreviewchildtaskaction.md "check type definition")
- [SerializedSetCategoryExtraTimeAction](serializedparentaction-definitions-serializedsetcategoryextratimeaction.md "check type definition")
- [SerializedSetCategoryForUnassignedAppsAction](serializedparentaction-definitions-serializedsetcategoryforunassignedappsaction.md "check type definition")
@@ -59,11 +58,11 @@ any of
- [SerializedUpdateDeviceNameAction](serializedparentaction-definitions-serializedupdatedevicenameaction.md "check type definition")
- [SerializedUpdateEnableActivityLevelBlockingAction](serializedparentaction-definitions-serializedupdateenableactivitylevelblockingaction.md "check type definition")
- [SerialiizedUpdateNetworkTimeVerificationAction](serializedparentaction-definitions-serialiizedupdatenetworktimeverificationaction.md "check type definition")
- [SerializedUpdateParentBlockedTimesAction](serializedparentaction-definitions-serializedupdateparentblockedtimesaction.md "check type definition")
- [SerializedUpdateParentNotificationFlagsAction](serializedparentaction-definitions-serializedupdateparentnotificationflagsaction.md "check type definition")
- [SerializedUpdateTimelimitRuleAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction.md "check type definition")
- [SerializedUpdateUserFlagsAction](serializedparentaction-definitions-serializedupdateuserflagsaction.md "check type definition")
- [SerializedUpdateUserLimitLoginCategory](serializedparentaction-definitions-serializedupdateuserlimitlogincategory.md "check type definition")
- [SerializedUpdateUserLimitLoginPreBlockDuration](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration.md "check type definition")
# SerializedParentAction Definitions
@@ -1590,59 +1589,6 @@ Reference this group by using
`string`
## Definitions group SerializedResetParentBlockedTimesAction
Reference this group by using
```json
{"$ref":"https://timelimit.io/SerializedParentAction#/definitions/SerializedResetParentBlockedTimesAction"}
```
| Property | Type | Required | Nullable | Defined by |
| :-------------------- | -------- | -------- | -------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [type](#type) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedresetparentblockedtimesaction-properties-type.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedResetParentBlockedTimesAction/properties/type") |
| [parentId](#parentId) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedresetparentblockedtimesaction-properties-parentid.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedResetParentBlockedTimesAction/properties/parentId") |
### type
`type`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedresetparentblockedtimesaction-properties-type.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedResetParentBlockedTimesAction/properties/type")
#### type Type
`string`
#### type Constraints
**enum**: the value of this property must be equal to one of the following values:
| Value | Explanation |
| :----------------------------- | ----------- |
| `"RESET_PARENT_BLOCKED_TIMES"` | |
### parentId
`parentId`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedresetparentblockedtimesaction-properties-parentid.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedResetParentBlockedTimesAction/properties/parentId")
#### parentId Type
`string`
## Definitions group SerializedReviewChildTaskAction
Reference this group by using
@@ -3592,76 +3538,6 @@ Reference this group by using
| `"enabled"` | |
| `"if possible"` | |
## Definitions group SerializedUpdateParentBlockedTimesAction
Reference this group by using
```json
{"$ref":"https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentBlockedTimesAction"}
```
| Property | Type | Required | Nullable | Defined by |
| :-------------------- | -------- | -------- | -------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [type](#type) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateparentblockedtimesaction-properties-type.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentBlockedTimesAction/properties/type") |
| [parentId](#parentId) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateparentblockedtimesaction-properties-parentid.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentBlockedTimesAction/properties/parentId") |
| [times](#times) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateparentblockedtimesaction-properties-times.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentBlockedTimesAction/properties/times") |
### type
`type`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateparentblockedtimesaction-properties-type.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentBlockedTimesAction/properties/type")
#### type Type
`string`
#### type Constraints
**enum**: the value of this property must be equal to one of the following values:
| Value | Explanation |
| :------------------------------ | ----------- |
| `"UPDATE_PARENT_BLOCKED_TIMES"` | |
### parentId
`parentId`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateparentblockedtimesaction-properties-parentid.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentBlockedTimesAction/properties/parentId")
#### parentId Type
`string`
### times
`times`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateparentblockedtimesaction-properties-times.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateParentBlockedTimesAction/properties/times")
#### times Type
`string`
## Definitions group SerializedUpdateParentNotificationFlagsAction
Reference this group by using
@@ -4094,3 +3970,73 @@ Reference this group by using
#### categoryId Type
`string`
## Definitions group SerializedUpdateUserLimitLoginPreBlockDuration
Reference this group by using
```json
{"$ref":"https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration"}
```
| Property | Type | Required | Nullable | Defined by |
| :------------------------------------ | -------- | -------- | -------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [type](#type) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-type.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/type") |
| [userId](#userId) | `string` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-userid.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/userId") |
| [preBlockDuration](#preBlockDuration) | `number` | Required | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-preblockduration.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/preBlockDuration") |
### type
`type`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-type.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/type")
#### type Type
`string`
#### type Constraints
**enum**: the value of this property must be equal to one of the following values:
| Value | Explanation |
| :--------------------------------------------- | ----------- |
| `"UPDATE_USER_LIMIT_LOGIN_PRE_BLOCK_DURATION"` | |
### userId
`userId`
- is required
- Type: `string`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-userid.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/userId")
#### userId Type
`string`
### preBlockDuration
`preBlockDuration`
- is required
- Type: `number`
- cannot be null
- defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdateuserlimitloginpreblockduration-properties-preblockduration.md "https&#x3A;//timelimit.io/SerializedParentAction#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration/properties/preBlockDuration")
#### preBlockDuration Type
`number`
@@ -0,0 +1,16 @@
# Untitled number in ServerDataStatus Schema
```txt
https://timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/pbd
```
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
| :------------------ | ---------- | -------------- | ----------------------- | :---------------- | --------------------- | ------------------- | ------------------------------------------------------------------------------------- |
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [ServerDataStatus.schema.json\*](ServerDataStatus.schema.json "open original schema") |
## pbd Type
`number`
@@ -34,6 +34,7 @@ https://timelimit.io/ServerDataStatus#/definitions/ServerUserEntry
| [blockedTimes](#blockedTimes) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-blockedtimes.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/blockedTimes") |
| [flags](#flags) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-flags.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/flags") |
| [llc](#llc) | `string` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-llc.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/llc") |
| [pbd](#pbd) | `number` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-pbd.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/pbd") |
## id
@@ -283,3 +284,19 @@ https://timelimit.io/ServerDataStatus#/definitions/ServerUserEntry
### llc Type
`string`
## pbd
`pbd`
- is optional
- Type: `number`
- cannot be null
- defined in: [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-pbd.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/pbd")
### pbd Type
`number`
+17
View File
@@ -2083,6 +2083,7 @@ Reference this group by using
| [blockedTimes](#blockedTimes) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-blockedtimes.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/blockedTimes") |
| [flags](#flags) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-flags.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/flags") |
| [llc](#llc) | `string` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-llc.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/llc") |
| [pbd](#pbd) | `number` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-pbd.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/pbd") |
### id
@@ -2333,6 +2334,22 @@ Reference this group by using
`string`
### pbd
`pbd`
- is optional
- Type: `number`
- cannot be null
- defined in: [ServerDataStatus](serverdatastatus-definitions-serveruserentry-properties-pbd.md "https&#x3A;//timelimit.io/ServerDataStatus#/definitions/ServerUserEntry/properties/pbd")
#### pbd Type
`number`
# ServerDataStatus Properties
| Property | Type | Required | Nullable | Defined by |
+287
View File
@@ -0,0 +1,287 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<title> </title>
<!--[if !mso]><!-- -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!--<![endif]-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
#outlook a {
padding: 0;
}
body {
margin: 0;
padding: 0;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table,
td {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
p {
display: block;
margin: 13px 0;
}
</style>
<!--[if mso]>
<xml>
<o:OfficeDocumentSettings>
<o:AllowPNG/>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
<![endif]-->
<!--[if lte mso 11]>
<style type="text/css">
.mj-outlook-group-fix { width:100% !important; }
</style>
<![endif]-->
<!--[if !mso]><!-->
<!--<![endif]-->
<style type="text/css">
@media only screen and (min-width:480px) {
.mj-column-per-100 {
width: 100% !important;
max-width: 100%;
}
}
</style>
<style type="text/css">
</style>
</head>
<body>
<div style="">
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="background:#009688;background-color:#009688;margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="background:#009688;background-color:#009688;width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:20px;line-height:1;text-align:left;color:#ffffff;">TimeLimit</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;">
<p>
<%= child %> hat angegeben, dass die Aufgabe
<%= task %> erledigt wurde. Die angeblich erledigten Aufgaben werden auf der Startseite der TimeLimit-App angezeigt. Dort kann die Erledigung bestätigt werden. </p>
<p> Da die Anzahl der Benachrichtigungs-E-Mails begrenzt ist erhalten Sie möglicherweise nicht bei jeder Aufgabenerledigung eine derartige E-Mail. </p>
<p>
<%= child %> reported that
<%= task %> was finished. You can see the tasks which are marked as finished at the overview screen of the TimeLimit application. You can confirm the task completion there. </p>
<p> There are limits for the notifications mails so that it can happen that you do not get a mail for each completed task. </p>
</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td style="font-size:0px;padding:10px 25px;word-break:break-word;">
<p style="border-top:dashed 1px lightgrey;font-size:1px;margin:0px auto;width:100%;"> </p>
<!--[if mso | IE]>
<table
align="center" border="0" cellpadding="0" cellspacing="0" style="border-top:dashed 1px lightgrey;font-size:1px;margin:0px auto;width:550px;" role="presentation" width="550px"
>
<tr>
<td style="height:0;line-height:0;">
&nbsp;
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
>
<tr>
<td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
<![endif]-->
<div style="margin:0px auto;max-width:600px;">
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="width:100%;">
<tbody>
<tr>
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td
class="" style="vertical-align:top;width:600px;"
>
<![endif]-->
<div class="mj-column-per-100 mj-outlook-group-fix" style="font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;">
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="vertical-align:top;" width="100%">
<tr>
<td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;">
<div style="font-family:Ubuntu, Helvetica, Arial, sans-serif;font-size:13px;line-height:1;text-align:left;color:#000000;">
<p> Sie erhalten diese Nachricht, weil Sie E-Mail-Benachrichtigungen in TimeLimit aktiviert haben. Sie können die Nachrichten in der TimeLimit-App abbestellen. Falls Sie Fragen haben können Sie einfach auf diese E-Mail antworten. </p>
<p> You got this mail because you enable mail notifications for this in TimeLimit. You can disable getting these messages in the TimeLimit App. If you have got any questions, then you can reply to this messagge. </p>
<p> &copy;
<%= mailimprint %>
</p>
</div>
</td>
</tr>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
</tbody>
</table>
</div>
<!--[if mso | IE]>
</td>
</tr>
</table>
<![endif]-->
</div>
</body>
</html>
+57
View File
@@ -0,0 +1,57 @@
<mjml>
<mj-body>
<mj-section background-color="#009688">
<mj-column>
<mj-text font-size="20px" color="#ffffff">TimeLimit</mj-text>
</mj-column>
</mj-section>
<mj-section>
<mj-column>
<mj-text>
<p>
<%= child %> hat angegeben, dass die Aufgabe <%= task %> erledigt wurde.
Die angeblich erledigten Aufgaben werden auf der Startseite der TimeLimit-App
angezeigt. Dort kann die Erledigung bestätigt werden.
</p>
<p>
Da die Anzahl der Benachrichtigungs-E-Mails begrenzt ist erhalten Sie
möglicherweise nicht bei jeder Aufgabenerledigung eine derartige E-Mail.
</p>
<p>
<%= child %> reported that <%= task %> was finished.
You can see the tasks which are marked as finished at the overview screen
of the TimeLimit application. You can confirm the task completion there.
</p>
<p>
There are limits for the notifications mails so that it can happen that
you do not get a mail for each completed task.
</p>
</mj-text>
</mj-column>
</mj-section>
<mj-section>
<mj-column>
<mj-divider border-width="1px" border-style="dashed" border-color="lightgrey" />
</mj-column>
</mj-section>
<mj-section>
<mj-column>
<mj-text>
<p>
Sie erhalten diese Nachricht, weil Sie E-Mail-Benachrichtigungen in TimeLimit aktiviert haben.
Sie können die Nachrichten in der TimeLimit-App abbestellen.
Falls Sie Fragen haben können Sie einfach auf diese E-Mail antworten.
</p>
<p>
You got this mail because you enable mail notifications for this in TimeLimit.
You can disable getting these messages in the TimeLimit App.
If you have got any questions, then you can reply to this messagge.
</p>
<p>
&copy; <%= mailimprint %>
</p>
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
+1
View File
@@ -0,0 +1 @@
<%= child %>/<%= task %>
+25
View File
@@ -0,0 +1,25 @@
<%= child %> hat angegeben, dass die Aufgabe <%= task %> erledigt wurde.
Die angeblich erledigten Aufgaben werden auf der Startseite der TimeLimit-App
angezeigt. Dort kann die Erledigung bestätigt werden.
Da die Anzahl der Benachrichtigungs-E-Mails begrenzt ist erhalten Sie
möglicherweise nicht bei jeder Aufgabenerledigung eine derartige E-Mail.
<%= child %> reported that <%= task %> was finished.
You can see the tasks which are marked as finished at the overview screen
of the TimeLimit application. You can confirm the task completion there.
There are limits for the notifications mails so that it can happen that
you do not get a mail for each completed task.
----------------------
Sie erhalten diese Nachricht, weil Sie E-Mail-Benachrichtigungen in TimeLimit aktiviert haben.
Sie können die Nachrichten in der TimeLimit-App abbestellen.
Falls Sie Fragen haben können Sie einfach auf diese E-Mail antworten.
You got this mail because you enable mail notifications for this in TimeLimit.
You can disable getting these messages in the TimeLimit App.
If you have got any questions, then you can reply to this messagge.
<C> <%= mailimprint %>
+1 -2
View File
@@ -38,7 +38,6 @@ export { RemoveInstalledAppsAction } from './removeinstalledapps'
export { RemoveUserAction } from './removeuser'
export { ResetCategoryNetworkIdsAction } from './resetcategorynetworkids'
export { RenameChildAction } from './renamechild'
export { ResetParentBlockedTimesAction } from './resetparentblockedtimes'
export { SetCategoryExtraTimeAction } from './setcategoryextratime'
export { SetCategoryForUnassignedAppsAction } from './setcategoryforunassignedapps'
export { SetChildPasswordAction } from './setchildpassword'
@@ -67,7 +66,6 @@ export { UpdateDeviceNameAction } from './updatedevicename'
export { UpdateDeviceStatusAction } from './updatedevicestatus'
export { UpdateEnableActivityLevelBlockingAction } from './updateenableactivitylevelblocking'
export { UpdateNetworkTimeVerificationAction } from './updatenetworktimeverification'
export { UpdateParentBlockedTimesAction } from './updateparentblockedtimes'
export { UpdateParentNotificationFlagsAction } from './updateparentnotificationflags'
export { UpdateTimelimitRuleAction } from './updatetimelimitrule'
export { UpdateUserFlagsAction } from './updateuserflags'
@@ -76,3 +74,4 @@ export { MarkTaskPendingAction } from './marktaskpendingaction'
export { DeleteChildTaskAction } from './deletechildtaskaction'
export { UpdateChildTaskAction } from './updatechildtaskaction'
export { ReviewChildTaskAction } from './reviewchildtaskaction'
export { UpdateUserLimitLoginPreBlockDuration } from './updateuserlimitloginpreblockduration'
-46
View File
@@ -1,46 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { ParentAction } from './basetypes'
import { assertIdWithinFamily } from './meta/util'
const actionType = 'ResetParentBlockedTimesAction'
export class ResetParentBlockedTimesAction extends ParentAction {
readonly parentId: string
constructor ({ parentId }: {
parentId: string
}) {
super()
assertIdWithinFamily({ actionType, field: 'parentId', value: parentId })
this.parentId = parentId
}
static parse = ({ parentId }: SerializedResetParentBlockedTimesAction) => (
new ResetParentBlockedTimesAction({
parentId
})
)
}
export interface SerializedResetParentBlockedTimesAction {
type: 'RESET_PARENT_BLOCKED_TIMES'
parentId: string
}
+5 -9
View File
@@ -32,7 +32,6 @@ import { RemoveCategoryAppsAction, SerializedRemoveCategoryAppsAction } from '..
import { RemoveUserAction, SerializedRemoveUserAction } from '../removeuser'
import { RenameChildAction, SerializedRenameChildAction } from '../renamechild'
import { ResetCategoryNetworkIdsAction, SerializeResetCategoryNetworkIdsAction } from '../resetcategorynetworkids'
import { ResetParentBlockedTimesAction, SerializedResetParentBlockedTimesAction } from '../resetparentblockedtimes'
import { ReviewChildTaskAction, SerializedReviewChildTaskAction } from '../reviewchildtaskaction'
import { SerializedSetCategoryExtraTimeAction, SetCategoryExtraTimeAction } from '../setcategoryextratime'
import { SerializedSetCategoryForUnassignedAppsAction, SetCategoryForUnassignedAppsAction } from '../setcategoryforunassignedapps'
@@ -59,11 +58,11 @@ import { SerializedUpdateChildTaskAction, UpdateChildTaskAction } from '../updat
import { SerializedUpdateDeviceNameAction, UpdateDeviceNameAction } from '../updatedevicename'
import { SerializedUpdateEnableActivityLevelBlockingAction, UpdateEnableActivityLevelBlockingAction } from '../updateenableactivitylevelblocking'
import { SerialiizedUpdateNetworkTimeVerificationAction, UpdateNetworkTimeVerificationAction } from '../updatenetworktimeverification'
import { SerializedUpdateParentBlockedTimesAction, UpdateParentBlockedTimesAction } from '../updateparentblockedtimes'
import { SerializedUpdateParentNotificationFlagsAction, UpdateParentNotificationFlagsAction } from '../updateparentnotificationflags'
import { SerializedUpdateTimelimitRuleAction, UpdateTimelimitRuleAction } from '../updatetimelimitrule'
import { SerializedUpdateUserFlagsAction, UpdateUserFlagsAction } from '../updateuserflags'
import { SerializedUpdateUserLimitLoginCategory, UpdateUserLimitLoginCategory } from '../updateuserlimitlogincategory'
import { SerializedUpdateUserLimitLoginPreBlockDuration, UpdateUserLimitLoginPreBlockDuration } from '../updateuserlimitloginpreblockduration'
export type SerializedParentAction =
SerializedAddCategoryAppsAction |
@@ -81,7 +80,6 @@ export type SerializedParentAction =
SerializedRemoveUserAction |
SerializedRenameChildAction |
SerializeResetCategoryNetworkIdsAction |
SerializedResetParentBlockedTimesAction |
SerializedReviewChildTaskAction |
SerializedSetCategoryForUnassignedAppsAction |
SerializedSetChildPasswordAction |
@@ -108,11 +106,11 @@ export type SerializedParentAction =
SerializedUpdateDeviceNameAction |
SerializedUpdateEnableActivityLevelBlockingAction |
SerialiizedUpdateNetworkTimeVerificationAction |
SerializedUpdateParentBlockedTimesAction |
SerializedUpdateParentNotificationFlagsAction |
SerializedUpdateTimelimitRuleAction |
SerializedUpdateUserFlagsAction |
SerializedUpdateUserLimitLoginCategory
SerializedUpdateUserLimitLoginCategory |
SerializedUpdateUserLimitLoginPreBlockDuration
export const parseParentAction = (action: SerializedParentAction): ParentAction => {
if (action.type === 'ADD_CATEGORY_APPS') {
@@ -145,8 +143,6 @@ export const parseParentAction = (action: SerializedParentAction): ParentAction
return RenameChildAction.parse(action)
} else if (action.type === 'RESET_CATEGORY_NETWORK_IDS') {
return ResetCategoryNetworkIdsAction.parse(action)
} else if (action.type === 'RESET_PARENT_BLOCKED_TIMES') {
return ResetParentBlockedTimesAction.parse(action)
} else if (action.type === 'REVIEW_CHILD_TASK') {
return ReviewChildTaskAction.parse(action)
} else if (action.type === 'SET_CATEGORY_EXTRA_TIME') {
@@ -199,8 +195,6 @@ export const parseParentAction = (action: SerializedParentAction): ParentAction
return UpdateEnableActivityLevelBlockingAction.parse(action)
} else if (action.type === 'UPDATE_NETWORK_TIME_VERIFICATION') {
return UpdateNetworkTimeVerificationAction.parse(action)
} else if (action.type === 'UPDATE_PARENT_BLOCKED_TIMES') {
return UpdateParentBlockedTimesAction.parse(action)
} else if (action.type === 'UPDATE_PARENT_NOTIFICATION_FLAGS') {
return UpdateParentNotificationFlagsAction.parse(action)
} else if (action.type === 'UPDATE_TIMELIMIT_RULE') {
@@ -209,6 +203,8 @@ export const parseParentAction = (action: SerializedParentAction): ParentAction
return UpdateUserFlagsAction.parse(action)
} else if (action.type === 'UPDATE_USER_LIMIT_LOGIN_CATEGORY') {
return UpdateUserLimitLoginCategory.parse(action)
} else if (action.type === 'UPDATE_USER_LIMIT_LOGIN_PRE_BLOCK_DURATION') {
return UpdateUserLimitLoginPreBlockDuration.parse(action)
} else {
throw new UnknownActionTypeException({ group: 'parent' })
}
-81
View File
@@ -1,81 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { BitmapValidationException, validateAndParseBitmask } from '../util/bitmask'
import { ParentAction } from './basetypes'
import { InvalidActionParameterException } from './meta/exception'
import { assertIdWithinFamily } from './meta/util'
const actionType = 'UpdateParentBlockedTimesAction'
export class UpdateParentBlockedTimesAction extends ParentAction {
readonly parentId: string
readonly blockedTimes: string
constructor ({ parentId, blockedTimes }: {
parentId: string
blockedTimes: string
}) {
super()
assertIdWithinFamily({ actionType, field: 'parentId', value: parentId })
try {
const parsedBlockedTimes = validateAndParseBitmask(blockedTimes, 60 * 24 * 7 /* number of minutes per week */)
for (let day = 0; day < 7; day++) {
let blockedMinutes = 0
for (let minute = 0; minute < 60 * 24 /* 1 day */; minute++) {
if (parsedBlockedTimes[day * 60 * 24 + minute]) {
blockedMinutes++
}
}
if (blockedMinutes > 60 * 18 /* 18 hours */) {
throw new InvalidActionParameterException({
actionType,
staticMessage: 'too much blocked minutes per day'
})
}
}
} catch (ex) {
if (ex instanceof BitmapValidationException) {
throw new InvalidActionParameterException({
actionType,
staticMessage: 'invalid bitmask'
})
} else throw ex
}
this.parentId = parentId
this.blockedTimes = blockedTimes
}
static parse = ({ parentId, times }: SerializedUpdateParentBlockedTimesAction) => (
new UpdateParentBlockedTimesAction({
parentId,
blockedTimes: times
})
)
}
export interface SerializedUpdateParentBlockedTimesAction {
type: 'UPDATE_PARENT_BLOCKED_TIMES'
parentId: string
times: string
}
+2 -1
View File
@@ -15,6 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { maxMailNotificationFlags } from '../database/user'
import { ParentAction } from './basetypes'
import { assertIdWithinFamily, assertSafeInteger, throwOutOfRange } from './meta/util'
@@ -36,7 +37,7 @@ export class UpdateParentNotificationFlagsAction extends ParentAction {
assertSafeInteger({ actionType, field: 'flags', value: flags })
if (flags < 0 || flags > 1) {
if (flags < 0 || flags > maxMailNotificationFlags) {
throwOutOfRange({ actionType, field: 'flags', value: flags })
}
@@ -0,0 +1,57 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { maxPreBlockDuration } from '../database/userlimitlogincategory'
import { ParentAction } from './basetypes'
import { assertIdWithinFamily, assertSafeInteger, throwOutOfRange } from './meta/util'
const actionType = 'UpdateUserLimitLoginPreBlockDuration'
export class UpdateUserLimitLoginPreBlockDuration extends ParentAction {
readonly userId: string
readonly preBlockDuration: number
constructor ({ userId, preBlockDuration }: {
userId: string,
preBlockDuration: number
}) {
super()
assertIdWithinFamily({ actionType, field: 'userId', value: userId })
assertSafeInteger({ actionType, field: 'preBlockDuration', value: preBlockDuration })
if (preBlockDuration < 0 || preBlockDuration > maxPreBlockDuration) {
throwOutOfRange({ actionType, field: 'preBlockDuration', value: preBlockDuration })
}
this.userId = userId
this.preBlockDuration = preBlockDuration
}
static parse = ({ userId, preBlockDuration }: SerializedUpdateUserLimitLoginPreBlockDuration) => (
new UpdateUserLimitLoginPreBlockDuration({
userId,
preBlockDuration
})
)
}
export interface SerializedUpdateUserLimitLoginPreBlockDuration {
type: 'UPDATE_USER_LIMIT_LOGIN_PRE_BLOCK_DURATION'
userId: string
preBlockDuration: number
}
+29 -48
View File
@@ -572,25 +572,6 @@ const definitions = {
"type"
]
},
"SerializedResetParentBlockedTimesAction": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"RESET_PARENT_BLOCKED_TIMES"
]
},
"parentId": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"parentId",
"type"
]
},
"SerializedReviewChildTaskAction": {
"type": "object",
"properties": {
@@ -1221,29 +1202,6 @@ const definitions = {
"type"
]
},
"SerializedUpdateParentBlockedTimesAction": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"UPDATE_PARENT_BLOCKED_TIMES"
]
},
"parentId": {
"type": "string"
},
"times": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"parentId",
"times",
"type"
]
},
"SerializedUpdateParentNotificationFlagsAction": {
"type": "object",
"properties": {
@@ -1366,6 +1324,29 @@ const definitions = {
"userId"
]
},
"SerializedUpdateUserLimitLoginPreBlockDuration": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"UPDATE_USER_LIMIT_LOGIN_PRE_BLOCK_DURATION"
]
},
"userId": {
"type": "string"
},
"preBlockDuration": {
"type": "number"
}
},
"additionalProperties": false,
"required": [
"preBlockDuration",
"type",
"userId"
]
},
"SerializedAddInstalledAppsAction": {
"type": "object",
"properties": {
@@ -2412,6 +2393,9 @@ const definitions = {
},
"llc": {
"type": "string"
},
"pbd": {
"type": "number"
}
},
"additionalProperties": false,
@@ -2648,9 +2632,6 @@ export const isSerializedParentAction: (value: object) => value is SerializedPar
{
"$ref": "#/definitions/SerializeResetCategoryNetworkIdsAction"
},
{
"$ref": "#/definitions/SerializedResetParentBlockedTimesAction"
},
{
"$ref": "#/definitions/SerializedReviewChildTaskAction"
},
@@ -2729,9 +2710,6 @@ export const isSerializedParentAction: (value: object) => value is SerializedPar
{
"$ref": "#/definitions/SerialiizedUpdateNetworkTimeVerificationAction"
},
{
"$ref": "#/definitions/SerializedUpdateParentBlockedTimesAction"
},
{
"$ref": "#/definitions/SerializedUpdateParentNotificationFlagsAction"
},
@@ -2743,6 +2721,9 @@ export const isSerializedParentAction: (value: object) => value is SerializedPar
},
{
"$ref": "#/definitions/SerializedUpdateUserLimitLoginCategory"
},
{
"$ref": "#/definitions/SerializedUpdateUserLimitLoginPreBlockDuration"
}
],
"definitions": definitions,
@@ -0,0 +1,38 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { QueryInterface, Sequelize, Transaction } from 'sequelize'
import { attributesVersion2 as limitLoginCategoryAttributes } from '../../userlimitlogincategory'
export async function up (queryInterface: QueryInterface, sequelize: Sequelize) {
await sequelize.transaction({
type: Transaction.TYPES.EXCLUSIVE
}, async (transaction) => {
// timelimit rule table
await queryInterface.addColumn('UserLimitLoginCategories', 'preBlockDuration', {
...limitLoginCategoryAttributes.preBlockDuration
}, { transaction })
})
}
export async function down (queryInterface: QueryInterface, sequelize: Sequelize) {
await sequelize.transaction({
type: Transaction.TYPES.EXCLUSIVE
}, async (transaction) => {
await queryInterface.removeColumn('UserLimitLoginCategories', 'preBlockDuration', { transaction })
})
}
+9 -1
View File
@@ -22,6 +22,13 @@ import { optionalPasswordRegex, optionalSaltRegex } from '../util/password'
import { booleanColumn, createEnumColumn, familyIdColumn, idWithinFamilyColumn, labelColumn, optionalIdWithinFamilyColumn, timestampColumn } from './columns'
import { SequelizeAttributes } from './types'
export const maxMailNotificationFlags = 1 | 2
export const mailNotificationFlags = {
warnings: 1,
tasks: 2
}
export interface UserAttributesVersion1 {
familyId: string
userId: string
@@ -52,6 +59,7 @@ export interface UserAttributesVersion4 {
}
export interface UserAttributesVersion5 {
// currently unused
blockedTimes: string
}
@@ -128,7 +136,7 @@ export const attributesVersion4: SequelizeAttributes<UserAttributesVersion4> = {
defaultValue: 0,
validate: {
min: 0,
max: 1
max: maxMailNotificationFlags
}
}
}
+27 -2
View File
@@ -19,21 +19,46 @@ import * as Sequelize from 'sequelize'
import { familyIdColumn, idWithinFamilyColumn } from './columns'
import { SequelizeAttributes } from './types'
export interface UserLimitLoginCategoryAttributes {
export const maxPreBlockDuration = 1000 * 60 * 60 * 24 // 1 day
export interface UserLimitLoginCategoryAttributesVersion1 {
familyId: string
userId: string
categoryId: string
}
export interface UserLimitLoginCategoryAttributesVersion2 {
preBlockDuration: number
}
export type UserLimitLoginCategoryAttributes = UserLimitLoginCategoryAttributesVersion1 & UserLimitLoginCategoryAttributesVersion2
export type UserLimitLoginCategoryModel = Sequelize.Model & UserLimitLoginCategoryAttributes
export type UserLimitLoginCategoryModelStatic = typeof Sequelize.Model & {
new (values?: object, options?: Sequelize.BuildOptions): UserLimitLoginCategoryModel;
}
export const attributes: SequelizeAttributes<UserLimitLoginCategoryAttributes> = {
export const attributesVersion1: SequelizeAttributes<UserLimitLoginCategoryAttributesVersion1> = {
familyId: { ...familyIdColumn, primaryKey: true },
userId: { ...idWithinFamilyColumn, primaryKey: true },
categoryId: { ...idWithinFamilyColumn }
}
export const attributesVersion2: SequelizeAttributes<UserLimitLoginCategoryAttributesVersion2> = {
preBlockDuration: {
type: Sequelize.INTEGER,
validate: {
min: 0,
max: maxPreBlockDuration
},
allowNull: false,
defaultValue: 0
}
}
export const attributes: SequelizeAttributes<UserLimitLoginCategoryAttributes> = {
...attributesVersion1,
...attributesVersion2
}
export const createUserLimitLoginCategoryModel = (sequelize: Sequelize.Sequelize): UserLimitLoginCategoryModelStatic => sequelize.define('UserLimitLoginCategory', attributes) as UserLimitLoginCategoryModelStatic
+2 -1
View File
@@ -52,7 +52,8 @@ export const addChildDevice = async ({ database, websocket, request }: {
deviceAuthToken,
deviceName: request.deviceName,
newDeviceInfo: request.childDevice,
userId: ''
userId: '',
isUserKeptSignedIn: false
}), { transaction })
await database.family.update({
+3 -2
View File
@@ -19,13 +19,14 @@ import { NewDeviceInfo } from '../../api/schema'
import { DeviceAttributes } from '../../database/device'
import { generateVersionId } from '../../util/token'
export const prepareDeviceEntry = ({ familyId, userId, deviceAuthToken, deviceId, deviceName, newDeviceInfo }: {
export const prepareDeviceEntry = ({ familyId, userId, deviceAuthToken, deviceId, deviceName, newDeviceInfo, isUserKeptSignedIn }: {
familyId: string
userId: string
deviceAuthToken: string
deviceId: string
deviceName: string
newDeviceInfo: NewDeviceInfo
isUserKeptSignedIn: boolean
}): DeviceAttributes => ({
familyId,
deviceId,
@@ -52,7 +53,7 @@ export const prepareDeviceEntry = ({ familyId, userId, deviceAuthToken, deviceId
lastConnectivity: '0',
notSeenForLongTime: false,
didDeviceReportUninstall: false,
isUserKeptSignedIn: false,
isUserKeptSignedIn,
showDeviceConnected: false,
defaultUserId: '',
defaultUserTimeout: 0,
+4 -2
View File
@@ -18,6 +18,7 @@
import { Conflict } from 'http-errors'
import { NewDeviceInfo, ParentPassword } from '../../api/schema'
import { Database } from '../../database'
import { maxMailNotificationFlags } from '../../database/user'
import {
generateAuthToken, generateFamilyId, generateIdWithinFamily, generateVersionId
} from '../../util/token'
@@ -82,7 +83,7 @@ export const createFamily = async ({ database, mailAuthToken, firstParentDevice,
currentDevice: '',
categoryForNotAssignedApps: '',
relaxPrimaryDeviceRule: false,
mailNotificationFlags: 1, // enable warning notifications
mailNotificationFlags: maxMailNotificationFlags,
blockedTimes: '',
flags: '0'
}, { transaction })
@@ -94,7 +95,8 @@ export const createFamily = async ({ database, mailAuthToken, firstParentDevice,
deviceName,
newDeviceInfo: firstParentDevice,
userId,
deviceAuthToken
deviceAuthToken,
isUserKeptSignedIn: true
}), { transaction })
return {
+2 -1
View File
@@ -61,7 +61,8 @@ export const signInIntoFamily = async ({ database, mailAuthToken, newDeviceInfo,
userId: userEntry.userId,
deviceName,
deviceAuthToken,
newDeviceInfo
newDeviceInfo,
isUserKeptSignedIn: true
}), { transaction })
// notify about changes
@@ -16,8 +16,9 @@
*/
import { MarkTaskPendingAction } from '../../../../action'
import { sendTaskDoneMails } from '../../../warningmail/taskdone'
import { Cache } from '../cache'
import { IllegalStateException, SourceDeviceNotFoundException } from '../exception/illegal-state'
import { IllegalStateException, SourceDeviceNotFoundException, SourceUserNotFoundException } from '../exception/illegal-state'
import { MissingTaskException } from '../exception/missing-item'
export async function dispatchMarkTaskPendingAction ({ action, cache, deviceId }: {
@@ -31,14 +32,15 @@ export async function dispatchMarkTaskPendingAction ({ action, cache, deviceId }
taskId: action.taskId
},
transaction: cache.transaction,
attributes: ['categoryId', 'pendingRequest']
attributes: ['categoryId', 'pendingRequest', 'taskTitle']
})
if (taskInfoUnsafe === null) throw new MissingTaskException()
const taskInfo = {
categoryId: taskInfoUnsafe.categoryId,
pendingRequest: taskInfoUnsafe.pendingRequest
pendingRequest: taskInfoUnsafe.pendingRequest,
taskTitle: taskInfoUnsafe.taskTitle
}
if (taskInfo.pendingRequest !== 0) return // review already requested
@@ -75,6 +77,19 @@ export async function dispatchMarkTaskPendingAction ({ action, cache, deviceId }
throw new IllegalStateException({ staticMessage: 'Can not mark task pending for other user than the current user' })
}
const childInfoUnsafe = await cache.database.user.findOne({
where: {
familyId: cache.familyId,
userId: categoryInfo.childId
},
attributes: ['name'],
transaction: cache.transaction
})
if (childInfoUnsafe === null) throw new SourceUserNotFoundException()
const childInfo = { name: childInfoUnsafe.name }
await cache.database.childTask.update({ pendingRequest: true }, {
where: {
familyId: cache.familyId,
@@ -84,4 +99,12 @@ export async function dispatchMarkTaskPendingAction ({ action, cache, deviceId }
})
cache.categoriesWithModifiedTasks.add(taskInfo.categoryId)
await sendTaskDoneMails({
database: cache.database,
transaction: cache.transaction,
familyId: cache.familyId,
childName: childInfo.name,
taskTitle: taskInfo.taskTitle
})
}
@@ -32,7 +32,6 @@ import {
RemoveUserAction,
RenameChildAction,
ResetCategoryNetworkIdsAction,
ResetParentBlockedTimesAction,
ReviewChildTaskAction,
SetCategoryExtraTimeAction,
SetCategoryForUnassignedAppsAction,
@@ -59,11 +58,11 @@ import {
UpdateDeviceNameAction,
UpdateEnableActivityLevelBlockingAction,
UpdateNetworkTimeVerificationAction,
UpdateParentBlockedTimesAction,
UpdateParentNotificationFlagsAction,
UpdateTimelimitRuleAction,
UpdateUserFlagsAction,
UpdateUserLimitLoginCategory
UpdateUserLimitLoginCategory,
UpdateUserLimitLoginPreBlockDuration
} from '../../../../action'
import { Cache } from '../cache'
import { ActionObjectTypeNotHandledException } from '../exception/illegal-state'
@@ -83,7 +82,6 @@ import { dispatchRemoveCategoryApps } from './removecategoryapps'
import { dispatchRemoveUser } from './removeuser'
import { dispatchRenameChild } from './renamechild'
import { dispatchResetCategoryNetworkIds } from './resetcategorynetworkids'
import { dispatchResetParentBlockedTimes } from './resetparentblockedtimes'
import { dispatchReviewChildTaskAction } from './reviewchildtaskaction'
import { dispatchSetCategoryExtraTime } from './setcategoryextratime'
import { dispatchSetCategoryForUnassignedApps } from './setcategoryforunassignedapps'
@@ -110,11 +108,11 @@ import { dispatchUpdateChildTaskAction } from './updatechildtaskaction'
import { dispatchUpdateDeviceName } from './updatedevicename'
import { dispatchUpdateEnableActivityLevelBlocking } from './updateenableactivitylevelblocking'
import { dispatchUpdateNetworkTimeVerification } from './updatenetworktimeverification'
import { dispatchUpdateParentBlockedTimes } from './updateparentblockedtimes'
import { dispatchUpdateParentNotificationFlags } from './updateparentnotificationflags'
import { dispatchUpdateTimelimitRule } from './updatetimelimitrule'
import { dispatchUpdateUserFlagsAction } from './updateuserflags'
import { dispatchUpdateUserLimitLoginCategoryAction } from './updateuserlimitlogincategory'
import { dispatchUpdateUserLimitPreBlockDuration } from './updateuserlimitloginpreblockduration'
export const dispatchParentAction = async ({ action, cache, parentUserId, sourceDeviceId, fromChildSelfLimitAddChildUserId }: {
action: ParentAction
@@ -208,10 +206,6 @@ export const dispatchParentAction = async ({ action, cache, parentUserId, source
return dispatchIgnoreManipulation({ action, cache })
} else if (action instanceof UpdateCategoryTimeWarningsAction) {
return dispatchUpdateCategoryTimeWarnings({ action, cache })
} else if (action instanceof ResetParentBlockedTimesAction) {
return dispatchResetParentBlockedTimes({ action, cache })
} else if (action instanceof UpdateParentBlockedTimesAction) {
return dispatchUpdateParentBlockedTimes({ action, cache, parentUserId })
} else if (action instanceof UpdateUserFlagsAction) {
return dispatchUpdateUserFlagsAction({ action, cache })
} else if (action instanceof UpdateUserLimitLoginCategory) {
@@ -222,6 +216,8 @@ export const dispatchParentAction = async ({ action, cache, parentUserId, source
await dispatchReviewChildTaskAction({ action, cache })
} else if (action instanceof UpdateChildTaskAction) {
await dispatchUpdateChildTaskAction({ action, cache })
} else if (action instanceof UpdateUserLimitLoginPreBlockDuration) {
await dispatchUpdateUserLimitPreBlockDuration({ action, cache, parentUserId })
} else {
throw new ActionObjectTypeNotHandledException()
}
@@ -1,52 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { ResetParentBlockedTimesAction } from '../../../../action'
import { Cache } from '../cache'
import { MissingUserException } from '../exception/missing-item'
export async function dispatchResetParentBlockedTimes ({ action, cache }: {
action: ResetParentBlockedTimesAction
cache: Cache
}) {
const oldItem = await cache.database.user.findOne({
where: {
familyId: cache.familyId,
userId: action.parentId,
type: 'parent'
},
transaction: cache.transaction
})
if (!oldItem) {
throw new MissingUserException()
}
await cache.database.user.update({
blockedTimes: ''
}, {
where: {
familyId: cache.familyId,
userId: action.parentId,
type: 'parent'
},
transaction: cache.transaction
})
cache.invalidiateUserList = true
cache.areChangesImportant = true
}
@@ -1,58 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { UpdateParentBlockedTimesAction } from '../../../../action'
import { Cache } from '../cache'
import { ApplyActionException } from '../exception/index'
import { MissingUserException } from '../exception/missing-item'
export async function dispatchUpdateParentBlockedTimes ({ action, cache, parentUserId }: {
action: UpdateParentBlockedTimesAction
cache: Cache
parentUserId: string
}) {
if (parentUserId !== action.parentId && action.blockedTimes !== '') {
throw new ApplyActionException({ staticMessage: 'only a parent itself can add limits' })
}
const oldUser = await cache.database.user.findOne({
where: {
familyId: cache.familyId,
userId: action.parentId,
type: 'parent'
},
transaction: cache.transaction
})
if (!oldUser) {
throw new MissingUserException()
}
await cache.database.user.update({
blockedTimes: action.blockedTimes
}, {
where: {
familyId: cache.familyId,
userId: action.parentId,
type: 'parent'
},
transaction: cache.transaction
})
cache.invalidiateUserList = true
cache.areChangesImportant = true
}
@@ -68,7 +68,8 @@ export async function dispatchUpdateUserLimitLoginCategoryAction ({ action, cach
await cache.database.userLimitLoginCategory.create({
familyId: cache.familyId,
userId: action.userId,
categoryId: action.categoryId
categoryId: action.categoryId,
preBlockDuration: 0
}, {
transaction: cache.transaction
})
@@ -0,0 +1,72 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { UpdateUserLimitLoginPreBlockDuration } from '../../../../action'
import { Cache } from '../cache'
import { ApplyActionException } from '../exception/index'
import { MissingItemException, MissingUserException } from '../exception/missing-item'
export async function dispatchUpdateUserLimitPreBlockDuration ({ action, cache, parentUserId }: {
action: UpdateUserLimitLoginPreBlockDuration
cache: Cache
parentUserId: string
}) {
const userEntry = await cache.database.user.findOne({
where: {
familyId: cache.familyId,
userId: action.userId,
type: 'parent'
},
transaction: cache.transaction
})
if (!userEntry) {
throw new MissingUserException()
}
if (action.preBlockDuration !== 0 && parentUserId !== action.userId) {
throw new ApplyActionException({
staticMessage: 'only the parent user itself can add a limit login pre block duration'
})
}
const preBlockItem = await cache.database.userLimitLoginCategory.findOne({
transaction: cache.transaction,
where: {
familyId: cache.familyId,
userId: action.userId
}
})
if (preBlockItem === null) {
throw new MissingItemException({
staticMessage: 'you can not set a pre block duration if there is no pre block item'
})
}
await cache.database.userLimitLoginCategory.update({
preBlockDuration: action.preBlockDuration
}, {
transaction: cache.transaction,
where: {
familyId: cache.familyId,
userId: action.userId
}
})
cache.invalidiateUserList = true
}
@@ -42,7 +42,6 @@ export async function getUserList ({ database, transaction, familyEntry }: {
'categoryForNotAssignedApps',
'relaxPrimaryDeviceRule',
'mailNotificationFlags',
'blockedTimes',
'flags'
],
transaction
@@ -59,7 +58,6 @@ export async function getUserList ({ database, transaction, familyEntry }: {
categoryForNotAssignedApps: item.categoryForNotAssignedApps,
relaxPrimaryDeviceRule: item.relaxPrimaryDeviceRule,
mailNotificationFlags: item.mailNotificationFlags,
blockedTimes: item.blockedTimes,
flags: item.flags
}))
@@ -69,19 +67,21 @@ export async function getUserList ({ database, transaction, familyEntry }: {
},
attributes: [
'userId',
'categoryId'
'categoryId',
'preBlockDuration'
],
transaction
})).map((item) => ({
userId: item.userId,
categoryId: item.categoryId
categoryId: item.categoryId,
preBlockDuration: item.preBlockDuration
}))
const getLimitLoginCategory = (userId: string) => {
const item = limitLoginCategories.find((item) => item.userId === userId)
if (item) {
return item.categoryId
return item
} else {
return undefined
}
@@ -89,22 +89,27 @@ export async function getUserList ({ database, transaction, familyEntry }: {
return {
version: familyEntry.userListVersion,
data: users.map((item) => ({
id: item.userId,
name: item.name,
password: item.passwordHash,
secondPasswordSalt: item.secondPasswordSalt,
type: item.type,
timeZone: item.timeZone,
disableLimitsUntil: parseInt(item.disableTimelimitsUntil, 10),
mail: item.mail,
currentDevice: item.currentDevice,
categoryForNotAssignedApps: item.categoryForNotAssignedApps,
relaxPrimaryDevice: item.relaxPrimaryDeviceRule,
mailNotificationFlags: item.mailNotificationFlags,
blockedTimes: item.blockedTimes,
flags: parseInt(item.flags, 10),
llc: getLimitLoginCategory(item.userId)
}))
data: users.map((item) => {
const limitLoginCategory = getLimitLoginCategory(item.userId)
return {
id: item.userId,
name: item.name,
password: item.passwordHash,
secondPasswordSalt: item.secondPasswordSalt,
type: item.type,
timeZone: item.timeZone,
disableLimitsUntil: parseInt(item.disableTimelimitsUntil, 10),
mail: item.mail,
currentDevice: item.currentDevice,
categoryForNotAssignedApps: item.categoryForNotAssignedApps,
relaxPrimaryDevice: item.relaxPrimaryDeviceRule,
mailNotificationFlags: item.mailNotificationFlags,
blockedTimes: '',
flags: parseInt(item.flags, 10),
llc: limitLoginCategory?.categoryId,
pbd: limitLoginCategory?.preBlockDuration
}
})
}
}
+2 -1
View File
@@ -16,6 +16,7 @@
*/
import { Database, Transaction, warpPromiseReturner } from '../../database'
import { mailNotificationFlags } from '../../database/user'
import { sendManipulationWarningMail } from '../../util/mail'
import { canSendWarningMail } from '../../util/ratelimit-warningmail'
@@ -35,7 +36,7 @@ export const sendManipulationWarnings = async ({ database, familyId, deviceName,
const targetMailAddresses = parentEntries
.filter((item) => item.mail !== '')
.filter((item) => (item.mailNotificationFlags & 1) === 1)
.filter((item) => (item.mailNotificationFlags & mailNotificationFlags.warnings) === mailNotificationFlags.warnings)
.map((item) => item.mail)
transaction.afterCommit(warpPromiseReturner(async () => {
+52
View File
@@ -0,0 +1,52 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { Database, Transaction, warpPromiseReturner } from '../../database'
import { mailNotificationFlags } from '../../database/user'
import { sendTaskDoneMail } from '../../util/mail'
import { canSendTaskDoneMail } from '../../util/ratelimit-taskdonemail'
export const sendTaskDoneMails = async ({ database, familyId, childName, taskTitle, transaction }: {
database: Database
familyId: string
childName: string
taskTitle: string
transaction: Transaction
}) => {
const parentEntries = await database.user.findAll({
where: {
familyId,
type: 'parent'
},
transaction
})
const targetMailAddresses = parentEntries
.filter((item) => item.mail !== '')
.filter((item) => (item.mailNotificationFlags & mailNotificationFlags.tasks) === mailNotificationFlags.tasks)
.map((item) => item.mail)
transaction.afterCommit(warpPromiseReturner(async () => {
await Promise.all(
targetMailAddresses.map(async (receiver) => {
if (await canSendTaskDoneMail(receiver)) {
await sendTaskDoneMail({ receiver, child: childName, task: taskTitle })
}
})
)
}))
}
+2 -1
View File
@@ -16,6 +16,7 @@
*/
import { Database, Transaction, warpPromiseReturner } from '../../database'
import { mailNotificationFlags } from '../../database/user'
import { sendUninstallWarningMail } from '../../util/mail'
import { canSendWarningMail } from '../../util/ratelimit-warningmail'
@@ -35,7 +36,7 @@ export const sendUninstallWarnings = async ({ database, familyId, deviceName, tr
const targetMailAddresses = parentEntries
.filter((item) => item.mail !== '')
.filter((item) => (item.mailNotificationFlags & 1) === 1)
.filter((item) => (item.mailNotificationFlags & mailNotificationFlags.warnings) === mailNotificationFlags.warnings)
.map((item) => item.mail)
transaction.afterCommit(warpPromiseReturner(async () => {
+1
View File
@@ -61,6 +61,7 @@ export interface ServerUserEntry {
blockedTimes: string
flags: number
llc?: string // limit login category
pbd?: number // pre block duration, default is zero
}
export interface ServerDeviceData {
+14
View File
@@ -86,6 +86,20 @@ export const sendUninstallWarningMail = async ({ receiver, deviceName }: {
})
}
export const sendTaskDoneMail = async ({ receiver, child, task }: {
receiver: string
child: string
task: string
}) => {
await email.send({
template: join(__dirname, '../../other/mail/taskdone'),
message: {
to: receiver
},
locals: { child, task, mailimprint }
})
}
export function isMailServerBlacklisted (mail: string): boolean {
const parts = mail.split('@')
const domain = parts[parts.length - 1]
+63
View File
@@ -0,0 +1,63 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
import { RateLimiterAbstract, RateLimiterMemory } from 'rate-limiter-flexible'
const individualMailLimitMinute: RateLimiterAbstract = new RateLimiterMemory({
keyPrefix: 'timelimit:sendmail-taskdone:individual:minute',
points: 1,
duration: 60 // 1 minute
})
const individualMailLimitFiveMinutes: RateLimiterAbstract = new RateLimiterMemory({
keyPrefix: 'timelimit:sendmail-taskdone:individual:fiveminutes',
points: 3,
duration: 60 * 5 // 5 minutes
})
const individualMailLimitHourly: RateLimiterAbstract = new RateLimiterMemory({
keyPrefix: 'timelimit:sendmail-taskdone:individual:hourly',
points: 5,
duration: 60 * 60 // 1 hour
})
const individualMailLimitDay: RateLimiterAbstract = new RateLimiterMemory({
keyPrefix: 'timelimit:sendmail-taskdone:individual:day',
points: 10,
duration: 60 * 60 * 24 // 1 day
})
const checkIndividualMailSendLimit = async (receiver: string) => {
await individualMailLimitMinute.consume(receiver)
await individualMailLimitFiveMinutes.consume(receiver)
await individualMailLimitHourly.consume(receiver)
await individualMailLimitDay.consume(receiver)
}
const checkMailSendLimit = async (receiver: string) => {
await checkIndividualMailSendLimit(receiver)
}
export const canSendTaskDoneMail = async (receiver: string) => {
try {
await checkMailSendLimit(receiver)
return true
} catch (ex) {
return false
}
}