mirror of
https://codeberg.org/timelimit/timelimit-server.git
synced 2026-08-31 19:03:45 +02:00
Compare commits
71
Commits
2022-11-01
...
2026-05-23
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b6ece0d28 | ||
|
|
271b27ffe9 | ||
|
|
b80b74b072 | ||
|
|
190ae54602 | ||
|
|
eb87d331b3 | ||
|
|
5a6f37e4c7 | ||
|
|
bd4b5b206b | ||
|
|
a8db1ec1a9 | ||
|
|
3aed2010c7 | ||
|
|
510c61bafd | ||
|
|
6fefd4cf18 | ||
|
|
bedaa955b5 | ||
|
|
a13656b27d | ||
|
|
abb2d1657e | ||
|
|
47c4e866bf | ||
|
|
65f1f8a410 | ||
|
|
c6c0051f82 | ||
|
|
6935c0811c | ||
|
|
66001b547f | ||
|
|
c574fccda7 | ||
|
|
2cfa0babe1 | ||
|
|
2f2d932d10 | ||
|
|
1215c0c8a2 | ||
|
|
93337e5e08 | ||
|
|
e871188661 | ||
|
|
ac9f655c44 | ||
|
|
717d8f243a | ||
|
|
6189601459 | ||
|
|
569e5ce62d | ||
|
|
6220cc6bb9 | ||
|
|
33d9fd732f | ||
|
|
764f240707 | ||
|
|
b392ca295a | ||
|
|
f5fc8e6cd6 | ||
|
|
9c2048af64 | ||
|
|
b69271f7df | ||
|
|
97d2730b20 | ||
|
|
0346197c23 | ||
|
|
a7ed01af74 | ||
|
|
f77d91ff56 | ||
|
|
2d035da0da | ||
|
|
2d73cba90e | ||
|
|
1918c74277 | ||
|
|
e55d1fd1a9 | ||
|
|
f10b79a023 | ||
|
|
2c401288a3 | ||
|
|
89f3325a18 | ||
|
|
7aaad00881 | ||
|
|
c7e4cfc9f9 | ||
|
|
12ed5d73cd | ||
|
|
4df809a306 | ||
|
|
8ec0781859 | ||
|
|
376a2cc624 | ||
|
|
e14237be7d | ||
|
|
4183ea615a | ||
|
|
e46f5bea3f | ||
|
|
05fac79849 | ||
|
|
1e5da1b95e | ||
|
|
dc5e2baebd | ||
|
|
73465ebe6e | ||
|
|
98ee0fe94e | ||
|
|
d9a032823e | ||
|
|
ae044c19d6 | ||
|
|
41758c32f2 | ||
|
|
38b113c9e8 | ||
|
|
83619eb98e | ||
|
|
89e9b85bda | ||
|
|
f5198c7c0b | ||
|
|
9b8caccfbd | ||
|
|
747be7cf7d | ||
|
|
fe1ce74ff3 |
@@ -1,3 +0,0 @@
|
||||
node_modules
|
||||
build
|
||||
scripts
|
||||
@@ -1,14 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
],
|
||||
env: {
|
||||
node: true
|
||||
}
|
||||
};
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
FROM node:16-alpine
|
||||
FROM node:24-alpine
|
||||
|
||||
# Create app directories
|
||||
RUN mkdir -p /usr/src/app
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Install app dependencies
|
||||
COPY package.json package-lock.json tsconfig.json .eslintignore .eslintrc.js Readme.md /usr/src/app/
|
||||
COPY package.json package-lock.json tsconfig.json eslint.config.mjs Readme.md /usr/src/app/
|
||||
COPY src/ /usr/src/app/src/
|
||||
COPY scripts/ /usr/src/app/scripts/
|
||||
COPY other/ /usr/src/app/other/
|
||||
|
||||
+2
-1
@@ -96,10 +96,11 @@ Use this to unlock all features for one user for a specified duration.
|
||||
|
||||
### request
|
||||
|
||||
request properties: ``purchaseToken`` and ``purchaseId``
|
||||
request properties: ``purchaseToken``, ``purchaseId`` and ``dryRun``
|
||||
|
||||
- ``purchasetoken`` is a string which the client shows at the purchase screen
|
||||
- ``purchaseId`` is the ID that is used at the bill
|
||||
- ``dryRun`` is a boolean; setting true will skip the actual unlocking
|
||||
|
||||
### response
|
||||
|
||||
|
||||
@@ -41,6 +41,10 @@ If a whitelist was configured and the mail address is not within it: ``{"mailAdd
|
||||
|
||||
If a blacklist was configured and the mail server is within it: ``{"mailServerBlacklisted": true}``
|
||||
|
||||
If a temporarily blacklist was configured and the mail server is within it (used in case of known mail delivery issues): ``{"mailServerBlacklistedTemporarily": true}``
|
||||
|
||||
If the client is suspicious: ``{"blockedForIntegrityReasons": true}``
|
||||
|
||||
On success: a object with a ``mailLoginToken`` of the type string
|
||||
|
||||
#### example response
|
||||
|
||||
+1
-2
@@ -16,8 +16,7 @@ On a invalid request body: HTTP status code 400 Bad request
|
||||
|
||||
On a invalid add device token: HTTP status code 401 Unauthorized
|
||||
|
||||
On success: a JSON object with the properties ``deviceAuthToken`` and ``ownDeviceId``,
|
||||
both of the type string
|
||||
On success: object with ``deviceAuthToken`` (string), ``ownDeviceId`` (string) and ``data`` (like a ``/sync/pull-status`` response)
|
||||
|
||||
## POST /child/update-primary-device
|
||||
|
||||
|
||||
+26
-2
@@ -44,7 +44,7 @@ If the mail auth token is invalid/ expired: HTTP status code 401 Unauthorized
|
||||
|
||||
If there is already a user with the mail address of the mail auth token: HTTP status code 409 Conflict
|
||||
|
||||
On success: object with ``deviceAuthToken`` (string) and ``ownDeviceId`` (string)
|
||||
On success: object with ``deviceAuthToken`` (string), ``ownDeviceId`` (string) and ``data`` (like a ``/sync/pull-status`` response)
|
||||
|
||||
## POST /parent/sign-in-into-family
|
||||
|
||||
@@ -60,7 +60,7 @@ On a invalid request body: HTTP status code 400 Bad Request
|
||||
|
||||
If there is no user with the mail address of the mail auth token: HTTP status code 409 Conflict
|
||||
|
||||
On success: object with ``deviceAuthToken`` (string) and ``ownDeviceId`` (string)
|
||||
On success: object with ``deviceAuthToken`` (string), ``ownDeviceId`` (string) and ``data`` (like a ``/sync/pull-status`` response)
|
||||
|
||||
## POST /parent/can-recover-password
|
||||
|
||||
@@ -194,3 +194,27 @@ If the ``secondPasswordHash`` is invalid: HTTP status code 401 Unauthorized
|
||||
If the server does not support this request: HTTP status code 404
|
||||
|
||||
On success: ``{"token": "some string"}``; you should not make any assumptions about the token string
|
||||
|
||||
## POST /parent/delete-account
|
||||
|
||||
Use this to delete an account. This includes the complete family registration
|
||||
with users and devices. Due to that, all parents with a linked mail address
|
||||
have to authenticate this action.
|
||||
|
||||
## request
|
||||
|
||||
see [this JSON schema](../schema/deleteaccountpayload.md)
|
||||
|
||||
## response
|
||||
|
||||
On success: HTTP status code 200
|
||||
|
||||
On a invalid request body: HTTP status code 400 Bad Request
|
||||
|
||||
On unknown device auth token: HTTP status code 401 Unauthorized
|
||||
|
||||
On missing parent authentication: HTTP status code 401 Unauthorized
|
||||
|
||||
On unrelated parent authentication: HTTP status code 401 Unauthorized
|
||||
|
||||
If a newer endpoint must be used/the client is too old: HTTP status code 410 Gone
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
},
|
||||
"parentName": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deviceAuthToken": {
|
||||
"type": "string"
|
||||
},
|
||||
"mailAuthTokens": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"deviceAuthToken",
|
||||
"mailAuthTokens"
|
||||
],
|
||||
"definitions": {},
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "DeleteAccountPayload",
|
||||
"$id": "https://timelimit.io/DeleteAccountPayload"
|
||||
}
|
||||
+8
-56
@@ -14,6 +14,8 @@
|
||||
|
||||
* [CreateRegisterDeviceTokenRequest](./createregisterdevicetokenrequest.md) – `https://timelimit.io/CreateRegisterDeviceTokenRequest`
|
||||
|
||||
* [DeleteAccountPayload](./deleteaccountpayload.md) – `https://timelimit.io/DeleteAccountPayload`
|
||||
|
||||
* [FinishPurchaseByGooglePlayRequest](./finishpurchasebygoogleplayrequest.md) – `https://timelimit.io/FinishPurchaseByGooglePlayRequest`
|
||||
|
||||
* [IdentityTokenPayload](./identitytokenpayload.md) – `https://timelimit.io/IdentityTokenPayload`
|
||||
@@ -128,6 +130,8 @@
|
||||
|
||||
* [SerializedMarkTaskPendingAction](./serializedapplogicaction-definitions-serializedmarktaskpendingaction.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedMarkTaskPendingAction`
|
||||
|
||||
* [SerializedPingAction](./serializedapplogicaction-definitions-serializedpingaction.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction`
|
||||
|
||||
* [SerializedRemoveCategoryAppsAction](./serializedparentaction-definitions-serializedremovecategoryappsaction.md) – `https://timelimit.io/SerializedParentAction#/definitions/SerializedRemoveCategoryAppsAction`
|
||||
|
||||
* [SerializedRemoveInstalledAppsAction](./serializedapplogicaction-definitions-serializedremoveinstalledappsaction.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedRemoveInstalledAppsAction`
|
||||
@@ -236,6 +240,8 @@
|
||||
|
||||
* [ServerKeyResponse](./serverdatastatus-definitions-serverkeyresponse.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerKeyResponse`
|
||||
|
||||
* [ServerPing](./serverdatastatus-definitions-serverping.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerPing`
|
||||
|
||||
* [ServerSessionDurationItem](./serverdatastatus-definitions-serversessiondurationitem.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerSessionDurationItem`
|
||||
|
||||
* [ServerTimeLimitRule](./serverdatastatus-definitions-servertimelimitrule.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerTimeLimitRule`
|
||||
@@ -268,39 +274,13 @@
|
||||
|
||||
* [Untitled object in ClientPullChangesRequest](./clientpullchangesrequest-definitions-clientdatastatus-properties-devicesdetail.md) – `https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/devicesDetail`
|
||||
|
||||
* [Untitled object in ClientPullChangesRequest](./clientpullchangesrequest-definitions-clientdatastatus-properties-apps.md) – `https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/apps`
|
||||
|
||||
* [Untitled object in ClientPullChangesRequest](./clientpullchangesrequest-definitions-clientdatastatus-properties-categories.md) – `https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/categories`
|
||||
|
||||
* [Untitled object in ClientPullChangesRequest](./clientpullchangesrequest-definitions-clientdatastatus-properties-devicesdetail.md) – `https://timelimit.io/ClientPullChangesRequest#/definitions/ClientDataStatus/properties/devicesDetail`
|
||||
|
||||
* [Untitled object in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddusedtimeactionversion2-properties-i-items.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeActionVersion2/properties/i/items`
|
||||
|
||||
* [Untitled object in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddusedtimeactionversion2-properties-i-items.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeActionVersion2/properties/i/items`
|
||||
|
||||
### Arrays
|
||||
|
||||
* [Untitled array in ClientPushChangesRequest](./clientpushchangesrequest-properties-actions.md) – `https://timelimit.io/ClientPushChangesRequest#/properties/actions`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddinstalledappsaction-properties-apps.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddInstalledAppsAction/properties/apps`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddusedtimeactionversion2-properties-i.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeActionVersion2/properties/i`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddusedtimeactionversion2-properties-i-items-properties-as.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeActionVersion2/properties/i/items/properties/as`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddusedtimeactionversion2-properties-i-items-properties-as-items.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeActionVersion2/properties/i/items/properties/as/items`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddusedtimeactionversion2-properties-i-items-properties-sdl.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeActionVersion2/properties/i/items/properties/sdl`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddusedtimeactionversion2-properties-i-items-properties-sdl-items.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddUsedTimeActionVersion2/properties/i/items/properties/sdl/items`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedremoveinstalledappsaction-properties-packagenames.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedRemoveInstalledAppsAction/properties/packageNames`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-removed.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/removed`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-removed-items.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/removed/items`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-updatedoradded.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/updatedOrAdded`
|
||||
* [Untitled array in DeleteAccountPayload](./deleteaccountpayload-properties-mailauthtokens.md) – `https://timelimit.io/DeleteAccountPayload#/properties/mailAuthTokens`
|
||||
|
||||
* [Untitled array in SerializedAppLogicAction](./serializedapplogicaction-definitions-serializedaddinstalledappsaction-properties-apps.md) – `https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedAddInstalledAppsAction/properties/apps`
|
||||
|
||||
@@ -328,12 +308,6 @@
|
||||
|
||||
* [Untitled array in SerializedParentAction](./serializedparentaction-definitions-serializedupdatecategorysortingaction-properties-categoryids.md) – `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategorySortingAction/properties/categoryIds`
|
||||
|
||||
* [Untitled array in SerializedParentAction](./serializedparentaction-definitions-serializedaddcategoryappsaction-properties-packagenames.md) – `https://timelimit.io/SerializedParentAction#/definitions/SerializedAddCategoryAppsAction/properties/packageNames`
|
||||
|
||||
* [Untitled array in SerializedParentAction](./serializedparentaction-definitions-serializedremovecategoryappsaction-properties-packagenames.md) – `https://timelimit.io/SerializedParentAction#/definitions/SerializedRemoveCategoryAppsAction/properties/packageNames`
|
||||
|
||||
* [Untitled array in SerializedParentAction](./serializedparentaction-definitions-serializedupdatecategorysortingaction-properties-categoryids.md) – `https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateCategorySortingAction/properties/categoryIds`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverdevicelist-properties-data.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceList/properties/data`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-properties-devices2.md) – `https://timelimit.io/ServerDataStatus#/properties/devices2`
|
||||
@@ -376,29 +350,7 @@
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-properties-kr.md) – `https://timelimit.io/ServerDataStatus#/properties/kr`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-u2fdata-properties-d.md) – `https://timelimit.io/ServerDataStatus#/definitions/U2fData/properties/d`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverdevicelist-properties-data.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceList/properties/data`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverinstalledappsdata-properties-apps.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/apps`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverinstalledappsdata-properties-activities.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerInstalledAppsData/properties/activities`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverupdatedcategorybasedata-properties-networks.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedCategoryBaseData/properties/networks`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverupdatedcategorybasedata-properties-atw.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedCategoryBaseData/properties/atw`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverupdatedcategoryassignedapps-properties-apps.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedCategoryAssignedApps/properties/apps`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverupdatedcategoryusedtimes-properties-times.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedCategoryUsedTimes/properties/times`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverupdatedcategoryusedtimes-properties-sessiondurations.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedCategoryUsedTimes/properties/sessionDurations`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverupdatedtimelimitrules-properties-rules.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedTimeLimitRules/properties/rules`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serverupdatedcategorytasks-properties-tasks.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerUpdatedCategoryTasks/properties/tasks`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-serveruserlist-properties-data.md) – `https://timelimit.io/ServerDataStatus#/definitions/ServerUserList/properties/data`
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-properties-pings.md) – `https://timelimit.io/ServerDataStatus#/properties/pings`
|
||||
|
||||
* [Untitled array in ServerDataStatus](./serverdatastatus-definitions-u2fdata-properties-d.md) – `https://timelimit.io/ServerDataStatus#/definitions/U2fData/properties/d`
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
},
|
||||
"deviceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
{
|
||||
"$ref": "#/definitions/SerializedMarkTaskPendingAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/SerializedPingAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/SerializedUpdateInstalledAppsAction"
|
||||
},
|
||||
@@ -309,6 +312,43 @@
|
||||
],
|
||||
"title": "SerializedMarkTaskPendingAction"
|
||||
},
|
||||
"SerializedPingAction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"PING"
|
||||
]
|
||||
},
|
||||
"deviceId": {
|
||||
"type": "string"
|
||||
},
|
||||
"event": {
|
||||
"$ref": "#/definitions/PingEvent"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"deviceId",
|
||||
"event",
|
||||
"token",
|
||||
"type"
|
||||
],
|
||||
"title": "SerializedPingAction"
|
||||
},
|
||||
"PingEvent": {
|
||||
"enum": [
|
||||
"clear",
|
||||
"ping",
|
||||
"pong"
|
||||
],
|
||||
"type": "string",
|
||||
"title": "PingEvent"
|
||||
},
|
||||
"SerializedUpdateInstalledAppsAction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -545,6 +585,12 @@
|
||||
},
|
||||
"addedManipulationFlags": {
|
||||
"type": "number"
|
||||
},
|
||||
"platformType": {
|
||||
"type": "string"
|
||||
},
|
||||
"platformLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -410,6 +410,9 @@
|
||||
},
|
||||
"perDay": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"e": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -1458,6 +1461,9 @@
|
||||
},
|
||||
"perDay": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"e": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -67,6 +67,12 @@
|
||||
"$ref": "#/definitions/ServerKeyResponse"
|
||||
}
|
||||
},
|
||||
"pings": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ServerPing"
|
||||
}
|
||||
},
|
||||
"dh": {
|
||||
"$ref": "#/definitions/ServerDhKey"
|
||||
},
|
||||
@@ -212,6 +218,12 @@
|
||||
},
|
||||
"pk": {
|
||||
"type": "string"
|
||||
},
|
||||
"pType": {
|
||||
"type": "string"
|
||||
},
|
||||
"pLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -240,6 +252,7 @@
|
||||
"model",
|
||||
"name",
|
||||
"networkTime",
|
||||
"pLevel",
|
||||
"qOrLater",
|
||||
"reboot",
|
||||
"rebootIsManipulation",
|
||||
@@ -920,6 +933,31 @@
|
||||
],
|
||||
"title": "ServerKeyResponse"
|
||||
},
|
||||
"ServerPing": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deviceId": {
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"ping",
|
||||
"pong"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"deviceId",
|
||||
"token",
|
||||
"type"
|
||||
],
|
||||
"title": "ServerPing"
|
||||
},
|
||||
"ServerDhKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
},
|
||||
"deviceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled number in CreateFamilyByMailTokenRequest Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/CreateFamilyByMailTokenRequest#/properties/clientLevel
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [CreateFamilyByMailTokenRequest.schema.json\*](CreateFamilyByMailTokenRequest.schema.json "open original schema") |
|
||||
|
||||
## clientLevel Type
|
||||
|
||||
`number`
|
||||
@@ -24,6 +24,7 @@ https://timelimit.io/CreateFamilyByMailTokenRequest
|
||||
| [deviceName](#devicename) | `string` | Required | cannot be null | [CreateFamilyByMailTokenRequest](createfamilybymailtokenrequest-properties-devicename.md "https://timelimit.io/CreateFamilyByMailTokenRequest#/properties/deviceName") |
|
||||
| [timeZone](#timezone) | `string` | Required | cannot be null | [CreateFamilyByMailTokenRequest](createfamilybymailtokenrequest-properties-timezone.md "https://timelimit.io/CreateFamilyByMailTokenRequest#/properties/timeZone") |
|
||||
| [parentName](#parentname) | `string` | Required | cannot be null | [CreateFamilyByMailTokenRequest](createfamilybymailtokenrequest-properties-parentname.md "https://timelimit.io/CreateFamilyByMailTokenRequest#/properties/parentName") |
|
||||
| [clientLevel](#clientlevel) | `number` | Optional | cannot be null | [CreateFamilyByMailTokenRequest](createfamilybymailtokenrequest-properties-clientlevel.md "https://timelimit.io/CreateFamilyByMailTokenRequest#/properties/clientLevel") |
|
||||
|
||||
## mailAuthToken
|
||||
|
||||
@@ -133,6 +134,24 @@ https://timelimit.io/CreateFamilyByMailTokenRequest
|
||||
|
||||
`string`
|
||||
|
||||
## clientLevel
|
||||
|
||||
|
||||
|
||||
`clientLevel`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [CreateFamilyByMailTokenRequest](createfamilybymailtokenrequest-properties-clientlevel.md "https://timelimit.io/CreateFamilyByMailTokenRequest#/properties/clientLevel")
|
||||
|
||||
### clientLevel Type
|
||||
|
||||
`number`
|
||||
|
||||
# CreateFamilyByMailTokenRequest Definitions
|
||||
|
||||
## Definitions group PlaintextParentPassword
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled undefined type in DeleteAccountPayload Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/DeleteAccountPayload#/definitions
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :-------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [DeleteAccountPayload.schema.json\*](DeleteAccountPayload.schema.json "open original schema") |
|
||||
|
||||
## definitions Type
|
||||
|
||||
unknown
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled string in DeleteAccountPayload Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/DeleteAccountPayload#/properties/deviceAuthToken
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :-------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [DeleteAccountPayload.schema.json\*](DeleteAccountPayload.schema.json "open original schema") |
|
||||
|
||||
## deviceAuthToken Type
|
||||
|
||||
`string`
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled string in DeleteAccountPayload Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/DeleteAccountPayload#/properties/mailAuthTokens/items
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :-------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [DeleteAccountPayload.schema.json\*](DeleteAccountPayload.schema.json "open original schema") |
|
||||
|
||||
## items Type
|
||||
|
||||
`string`
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled array in DeleteAccountPayload Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/DeleteAccountPayload#/properties/mailAuthTokens
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :-------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [DeleteAccountPayload.schema.json\*](DeleteAccountPayload.schema.json "open original schema") |
|
||||
|
||||
## mailAuthTokens Type
|
||||
|
||||
`string[]`
|
||||
@@ -0,0 +1,60 @@
|
||||
# DeleteAccountPayload Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/DeleteAccountPayload
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :----------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | Yes | Unknown status | No | Forbidden | Forbidden | none | [DeleteAccountPayload.schema.json](DeleteAccountPayload.schema.json "open original schema") |
|
||||
|
||||
## DeleteAccountPayload Type
|
||||
|
||||
`object` ([DeleteAccountPayload](deleteaccountpayload.md))
|
||||
|
||||
# DeleteAccountPayload Properties
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :---------------------------------- | :------- | :------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [deviceAuthToken](#deviceauthtoken) | `string` | Required | cannot be null | [DeleteAccountPayload](deleteaccountpayload-properties-deviceauthtoken.md "https://timelimit.io/DeleteAccountPayload#/properties/deviceAuthToken") |
|
||||
| [mailAuthTokens](#mailauthtokens) | `array` | Required | cannot be null | [DeleteAccountPayload](deleteaccountpayload-properties-mailauthtokens.md "https://timelimit.io/DeleteAccountPayload#/properties/mailAuthTokens") |
|
||||
|
||||
## deviceAuthToken
|
||||
|
||||
|
||||
|
||||
`deviceAuthToken`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [DeleteAccountPayload](deleteaccountpayload-properties-deviceauthtoken.md "https://timelimit.io/DeleteAccountPayload#/properties/deviceAuthToken")
|
||||
|
||||
### deviceAuthToken Type
|
||||
|
||||
`string`
|
||||
|
||||
## mailAuthTokens
|
||||
|
||||
|
||||
|
||||
`mailAuthTokens`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string[]`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [DeleteAccountPayload](deleteaccountpayload-properties-mailauthtokens.md "https://timelimit.io/DeleteAccountPayload#/properties/mailAuthTokens")
|
||||
|
||||
### mailAuthTokens Type
|
||||
|
||||
`string[]`
|
||||
|
||||
# DeleteAccountPayload Definitions
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled number in RegisterChildDeviceRequest Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/RegisterChildDeviceRequest#/properties/clientLevel
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :-------------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [RegisterChildDeviceRequest.schema.json\*](RegisterChildDeviceRequest.schema.json "open original schema") |
|
||||
|
||||
## clientLevel Type
|
||||
|
||||
`number`
|
||||
@@ -21,6 +21,7 @@ https://timelimit.io/RegisterChildDeviceRequest
|
||||
| [registerToken](#registertoken) | `string` | Required | cannot be null | [RegisterChildDeviceRequest](registerchilddevicerequest-properties-registertoken.md "https://timelimit.io/RegisterChildDeviceRequest#/properties/registerToken") |
|
||||
| [childDevice](#childdevice) | `object` | Required | cannot be null | [RegisterChildDeviceRequest](registerchilddevicerequest-definitions-newdeviceinfo.md "https://timelimit.io/RegisterChildDeviceRequest#/properties/childDevice") |
|
||||
| [deviceName](#devicename) | `string` | Required | cannot be null | [RegisterChildDeviceRequest](registerchilddevicerequest-properties-devicename.md "https://timelimit.io/RegisterChildDeviceRequest#/properties/deviceName") |
|
||||
| [clientLevel](#clientlevel) | `number` | Optional | cannot be null | [RegisterChildDeviceRequest](registerchilddevicerequest-properties-clientlevel.md "https://timelimit.io/RegisterChildDeviceRequest#/properties/clientLevel") |
|
||||
|
||||
## registerToken
|
||||
|
||||
@@ -76,6 +77,24 @@ https://timelimit.io/RegisterChildDeviceRequest
|
||||
|
||||
`string`
|
||||
|
||||
## clientLevel
|
||||
|
||||
|
||||
|
||||
`clientLevel`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [RegisterChildDeviceRequest](registerchilddevicerequest-properties-clientlevel.md "https://timelimit.io/RegisterChildDeviceRequest#/properties/clientLevel")
|
||||
|
||||
### clientLevel Type
|
||||
|
||||
`number`
|
||||
|
||||
# RegisterChildDeviceRequest Definitions
|
||||
|
||||
## Definitions group NewDeviceInfo
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# PingEvent Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedAppLogicAction#/definitions/PingEvent
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedAppLogicAction.schema.json\*](SerializedAppLogicAction.schema.json "open original schema") |
|
||||
|
||||
## PingEvent Type
|
||||
|
||||
`string` ([PingEvent](serializedapplogicaction-definitions-pingevent.md))
|
||||
|
||||
## PingEvent Constraints
|
||||
|
||||
**enum**: the value of this property must be equal to one of the following values:
|
||||
|
||||
| Value | Explanation |
|
||||
| :-------- | :---------- |
|
||||
| `"clear"` | |
|
||||
| `"ping"` | |
|
||||
| `"pong"` | |
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Untitled string in SerializedAppLogicAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/deviceId
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedAppLogicAction.schema.json\*](SerializedAppLogicAction.schema.json "open original schema") |
|
||||
|
||||
## deviceId Type
|
||||
|
||||
`string`
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
# PingEvent Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/event
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedAppLogicAction.schema.json\*](SerializedAppLogicAction.schema.json "open original schema") |
|
||||
|
||||
## event Type
|
||||
|
||||
`string` ([PingEvent](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md))
|
||||
|
||||
## event Constraints
|
||||
|
||||
**enum**: the value of this property must be equal to one of the following values:
|
||||
|
||||
| Value | Explanation |
|
||||
| :-------- | :---------- |
|
||||
| `"clear"` | |
|
||||
| `"ping"` | |
|
||||
| `"pong"` | |
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Untitled string in SerializedAppLogicAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/token
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedAppLogicAction.schema.json\*](SerializedAppLogicAction.schema.json "open original schema") |
|
||||
|
||||
## token Type
|
||||
|
||||
`string`
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
# Untitled string in SerializedAppLogicAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/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 | [SerializedAppLogicAction.schema.json\*](SerializedAppLogicAction.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 |
|
||||
| :------- | :---------- |
|
||||
| `"PING"` | |
|
||||
@@ -0,0 +1,114 @@
|
||||
# SerializedPingAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :----------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | No | Forbidden | Forbidden | none | [SerializedAppLogicAction.schema.json\*](SerializedAppLogicAction.schema.json "open original schema") |
|
||||
|
||||
## SerializedPingAction Type
|
||||
|
||||
`object` ([SerializedPingAction](serializedapplogicaction-definitions-serializedpingaction.md))
|
||||
|
||||
# SerializedPingAction Properties
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :-------------------- | :------- | :------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/type") |
|
||||
| [deviceId](#deviceid) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-deviceid.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/deviceId") |
|
||||
| [event](#event) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/event") |
|
||||
| [token](#token) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-token.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/token") |
|
||||
|
||||
## type
|
||||
|
||||
|
||||
|
||||
`type`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/type")
|
||||
|
||||
### type Type
|
||||
|
||||
`string`
|
||||
|
||||
### type Constraints
|
||||
|
||||
**enum**: the value of this property must be equal to one of the following values:
|
||||
|
||||
| Value | Explanation |
|
||||
| :------- | :---------- |
|
||||
| `"PING"` | |
|
||||
|
||||
## deviceId
|
||||
|
||||
|
||||
|
||||
`deviceId`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-deviceid.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/deviceId")
|
||||
|
||||
### deviceId Type
|
||||
|
||||
`string`
|
||||
|
||||
## event
|
||||
|
||||
|
||||
|
||||
`event`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string` ([PingEvent](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md))
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/event")
|
||||
|
||||
### event Type
|
||||
|
||||
`string` ([PingEvent](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md))
|
||||
|
||||
### event Constraints
|
||||
|
||||
**enum**: the value of this property must be equal to one of the following values:
|
||||
|
||||
| Value | Explanation |
|
||||
| :-------- | :---------- |
|
||||
| `"clear"` | |
|
||||
| `"ping"` | |
|
||||
| `"pong"` | |
|
||||
|
||||
## token
|
||||
|
||||
|
||||
|
||||
`token`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-token.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/token")
|
||||
|
||||
### token Type
|
||||
|
||||
`string`
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Untitled number in SerializedAppLogicAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformLevel
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedAppLogicAction.schema.json\*](SerializedAppLogicAction.schema.json "open original schema") |
|
||||
|
||||
## platformLevel Type
|
||||
|
||||
`number`
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Untitled string in SerializedAppLogicAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformType
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedAppLogicAction.schema.json\*](SerializedAppLogicAction.schema.json "open original schema") |
|
||||
|
||||
## platformType Type
|
||||
|
||||
`string`
|
||||
+38
@@ -28,6 +28,8 @@ https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDevic
|
||||
| [didReboot](#didreboot) | `boolean` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-didreboot.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/didReboot") |
|
||||
| [isQOrLaterNow](#isqorlaternow) | `boolean` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-isqorlaternow.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/isQOrLaterNow") |
|
||||
| [addedManipulationFlags](#addedmanipulationflags) | `number` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-addedmanipulationflags.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/addedManipulationFlags") |
|
||||
| [platformType](#platformtype) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-platformtype.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformType") |
|
||||
| [platformLevel](#platformlevel) | `number` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-platformlevel.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformLevel") |
|
||||
|
||||
## type
|
||||
|
||||
@@ -257,3 +259,39 @@ https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDevic
|
||||
### addedManipulationFlags Type
|
||||
|
||||
`number`
|
||||
|
||||
## platformType
|
||||
|
||||
|
||||
|
||||
`platformType`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-platformtype.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformType")
|
||||
|
||||
### platformType Type
|
||||
|
||||
`string`
|
||||
|
||||
## platformLevel
|
||||
|
||||
|
||||
|
||||
`platformLevel`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-platformlevel.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformLevel")
|
||||
|
||||
### platformLevel Type
|
||||
|
||||
`number`
|
||||
|
||||
@@ -30,6 +30,8 @@ any of
|
||||
|
||||
* [SerializedMarkTaskPendingAction](serializedapplogicaction-definitions-serializedmarktaskpendingaction.md "check type definition")
|
||||
|
||||
* [SerializedPingAction](serializedapplogicaction-definitions-serializedpingaction.md "check type definition")
|
||||
|
||||
* [SerializedUpdateInstalledAppsAction](serializedapplogicaction-definitions-serializedupdateinstalledappsaction.md "check type definition")
|
||||
|
||||
* [SerializedRemoveInstalledAppsAction](serializedapplogicaction-definitions-serializedremoveinstalledappsaction.md "check type definition")
|
||||
@@ -688,6 +690,122 @@ Reference this group by using
|
||||
|
||||
`string`
|
||||
|
||||
## Definitions group SerializedPingAction
|
||||
|
||||
Reference this group by using
|
||||
|
||||
```json
|
||||
{"$ref":"https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction"}
|
||||
```
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :-------------------- | :------- | :------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-7) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/type") |
|
||||
| [deviceId](#deviceid) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-deviceid.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/deviceId") |
|
||||
| [event](#event) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/event") |
|
||||
| [token](#token) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-token.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/token") |
|
||||
|
||||
### type
|
||||
|
||||
|
||||
|
||||
`type`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/type")
|
||||
|
||||
#### type Type
|
||||
|
||||
`string`
|
||||
|
||||
#### type Constraints
|
||||
|
||||
**enum**: the value of this property must be equal to one of the following values:
|
||||
|
||||
| Value | Explanation |
|
||||
| :------- | :---------- |
|
||||
| `"PING"` | |
|
||||
|
||||
### deviceId
|
||||
|
||||
|
||||
|
||||
`deviceId`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-deviceid.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/deviceId")
|
||||
|
||||
#### deviceId Type
|
||||
|
||||
`string`
|
||||
|
||||
### event
|
||||
|
||||
|
||||
|
||||
`event`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string` ([PingEvent](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md))
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/event")
|
||||
|
||||
#### event Type
|
||||
|
||||
`string` ([PingEvent](serializedapplogicaction-definitions-serializedpingaction-properties-pingevent.md))
|
||||
|
||||
#### event Constraints
|
||||
|
||||
**enum**: the value of this property must be equal to one of the following values:
|
||||
|
||||
| Value | Explanation |
|
||||
| :-------- | :---------- |
|
||||
| `"clear"` | |
|
||||
| `"ping"` | |
|
||||
| `"pong"` | |
|
||||
|
||||
### token
|
||||
|
||||
|
||||
|
||||
`token`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedpingaction-properties-token.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedPingAction/properties/token")
|
||||
|
||||
#### token Type
|
||||
|
||||
`string`
|
||||
|
||||
## Definitions group PingEvent
|
||||
|
||||
Reference this group by using
|
||||
|
||||
```json
|
||||
{"$ref":"https://timelimit.io/SerializedAppLogicAction#/definitions/PingEvent"}
|
||||
```
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :------- | :--- | :------- | :------- | :--------- |
|
||||
|
||||
## Definitions group SerializedUpdateInstalledAppsAction
|
||||
|
||||
Reference this group by using
|
||||
@@ -698,7 +816,7 @@ Reference this group by using
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :-------------- | :-------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-7) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateinstalledappsaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateInstalledAppsAction/properties/type") |
|
||||
| [type](#type-8) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateinstalledappsaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateInstalledAppsAction/properties/type") |
|
||||
| [b](#b) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateinstalledappsaction-properties-b.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateInstalledAppsAction/properties/b") |
|
||||
| [d](#d-1) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateinstalledappsaction-properties-d.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateInstalledAppsAction/properties/d") |
|
||||
| [w](#w) | `boolean` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateinstalledappsaction-properties-w.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateInstalledAppsAction/properties/w") |
|
||||
@@ -793,7 +911,7 @@ Reference this group by using
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :---------------------------- | :------- | :------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-8) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedremoveinstalledappsaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedRemoveInstalledAppsAction/properties/type") |
|
||||
| [type](#type-9) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedremoveinstalledappsaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedRemoveInstalledAppsAction/properties/type") |
|
||||
| [packageNames](#packagenames) | `array` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedremoveinstalledappsaction-properties-packagenames.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedRemoveInstalledAppsAction/properties/packageNames") |
|
||||
|
||||
### type
|
||||
@@ -850,9 +968,9 @@ Reference this group by using
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :-------------------------- | :------- | :------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-9) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsendkeyrequestaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSendKeyRequestAction/properties/type") |
|
||||
| [type](#type-10) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsendkeyrequestaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSendKeyRequestAction/properties/type") |
|
||||
| [dsn](#dsn-1) | `number` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsendkeyrequestaction-properties-dsn.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSendKeyRequestAction/properties/dsn") |
|
||||
| [deviceId](#deviceid) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsendkeyrequestaction-properties-deviceid.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSendKeyRequestAction/properties/deviceId") |
|
||||
| [deviceId](#deviceid-1) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsendkeyrequestaction-properties-deviceid.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSendKeyRequestAction/properties/deviceId") |
|
||||
| [categoryId](#categoryid-1) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsendkeyrequestaction-properties-categoryid.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSendKeyRequestAction/properties/categoryId") |
|
||||
| [dataType](#datatype) | `number` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsendkeyrequestaction-properties-datatype.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSendKeyRequestAction/properties/dataType") |
|
||||
| [tempKey](#tempkey-1) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsendkeyrequestaction-properties-tempkey.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSendKeyRequestAction/properties/tempKey") |
|
||||
@@ -1002,7 +1120,7 @@ Reference this group by using
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :--------------- | :------- | :------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-10) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsignoutatdeviceaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSignOutAtDeviceAction/properties/type") |
|
||||
| [type](#type-11) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedsignoutatdeviceaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedSignOutAtDeviceAction/properties/type") |
|
||||
|
||||
### type
|
||||
|
||||
@@ -1040,7 +1158,7 @@ Reference this group by using
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :--------------- | :------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-11) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serialiezdtrieddisablingdeviceadminaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerialiezdTriedDisablingDeviceAdminAction/properties/type") |
|
||||
| [type](#type-12) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serialiezdtrieddisablingdeviceadminaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerialiezdTriedDisablingDeviceAdminAction/properties/type") |
|
||||
|
||||
### type
|
||||
|
||||
@@ -1078,7 +1196,7 @@ Reference this group by using
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :-------------------------------- | :------- | :------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-12) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/type") |
|
||||
| [type](#type-13) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/type") |
|
||||
| [removed](#removed) | `array` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-removed.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/removed") |
|
||||
| [updatedOrAdded](#updatedoradded) | `array` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdateappactivitiesaction-properties-updatedoradded.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateAppActivitiesAction/properties/updatedOrAdded") |
|
||||
|
||||
@@ -1230,7 +1348,7 @@ Reference this group by using
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :---------------------------------------------------------- | :-------- | :------- | :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-13) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/type") |
|
||||
| [type](#type-14) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/type") |
|
||||
| [protectionLevel](#protectionlevel) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-protectionlevel.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/protectionLevel") |
|
||||
| [usageStats](#usagestats) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-usagestats.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/usageStats") |
|
||||
| [notificationAccess](#notificationaccess) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-notificationaccess.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/notificationAccess") |
|
||||
@@ -1240,6 +1358,8 @@ Reference this group by using
|
||||
| [didReboot](#didreboot) | `boolean` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-didreboot.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/didReboot") |
|
||||
| [isQOrLaterNow](#isqorlaternow) | `boolean` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-isqorlaternow.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/isQOrLaterNow") |
|
||||
| [addedManipulationFlags](#addedmanipulationflags) | `number` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-addedmanipulationflags.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/addedManipulationFlags") |
|
||||
| [platformType](#platformtype) | `string` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-platformtype.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformType") |
|
||||
| [platformLevel](#platformlevel) | `number` | Optional | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-platformlevel.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformLevel") |
|
||||
|
||||
### type
|
||||
|
||||
@@ -1470,6 +1590,42 @@ Reference this group by using
|
||||
|
||||
`number`
|
||||
|
||||
### platformType
|
||||
|
||||
|
||||
|
||||
`platformType`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-platformtype.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformType")
|
||||
|
||||
#### platformType Type
|
||||
|
||||
`string`
|
||||
|
||||
### platformLevel
|
||||
|
||||
|
||||
|
||||
`platformLevel`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedAppLogicAction](serializedapplogicaction-definitions-serializedupdatedevicestatusaction-properties-platformlevel.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUpdateDeviceStatusAction/properties/platformLevel")
|
||||
|
||||
#### platformLevel Type
|
||||
|
||||
`number`
|
||||
|
||||
## Definitions group SerializedUploadDevicePublicKeyAction
|
||||
|
||||
Reference this group by using
|
||||
@@ -1480,7 +1636,7 @@ Reference this group by using
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :--------------- | :------- | :------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [type](#type-14) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializeduploaddevicepublickeyaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUploadDevicePublicKeyAction/properties/type") |
|
||||
| [type](#type-15) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializeduploaddevicepublickeyaction-properties-type.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUploadDevicePublicKeyAction/properties/type") |
|
||||
| [key](#key) | `string` | Required | cannot be null | [SerializedAppLogicAction](serializedapplogicaction-definitions-serializeduploaddevicepublickeyaction-properties-key.md "https://timelimit.io/SerializedAppLogicAction#/definitions/SerializedUploadDevicePublicKeyAction/properties/key") |
|
||||
|
||||
### type
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# EncryptableParentPassword Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedParentAction#/definitions/SerializedSetChildPasswordAction/properties/newPassword
|
||||
https://timelimit.io/SerializedParentAction#/definitions/EncryptableParentPassword
|
||||
```
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedSetChildPassw
|
||||
| :------------------ | :--------- | :------------- | :----------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | No | Forbidden | Forbidden | none | [SerializedParentAction.schema.json\*](SerializedParentAction.schema.json "open original schema") |
|
||||
|
||||
## newPassword Type
|
||||
## EncryptableParentPassword Type
|
||||
|
||||
`object` ([EncryptableParentPassword](serializedparentaction-definitions-encryptableparentpassword.md))
|
||||
|
||||
# newPassword Properties
|
||||
# EncryptableParentPassword Properties
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :------------------------ | :-------- | :------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Untitled number in SerializedParentAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedParentAction.schema.json\*](SerializedParentAction.schema.json "open original schema") |
|
||||
|
||||
## e Type
|
||||
|
||||
`number`
|
||||
@@ -28,6 +28,7 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule
|
||||
| [dur](#dur) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-dur.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/dur") |
|
||||
| [pause](#pause) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-pause.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/pause") |
|
||||
| [perDay](#perday) | `boolean` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-perday.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/perDay") |
|
||||
| [e](#e) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e") |
|
||||
|
||||
## ruleId
|
||||
|
||||
@@ -208,3 +209,21 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule
|
||||
### perDay Type
|
||||
|
||||
`boolean`
|
||||
|
||||
## e
|
||||
|
||||
|
||||
|
||||
`e`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e")
|
||||
|
||||
### e Type
|
||||
|
||||
`number`
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Untitled number in SerializedParentAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedParentAction.schema.json\*](SerializedParentAction.schema.json "open original schema") |
|
||||
|
||||
## e Type
|
||||
|
||||
`number`
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
# Untitled number in SerializedParentAction Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/expiresAt
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SerializedParentAction.schema.json\*](SerializedParentAction.schema.json "open original schema") |
|
||||
|
||||
## expiresAt Type
|
||||
|
||||
`number`
|
||||
@@ -28,6 +28,7 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelim
|
||||
| [dur](#dur) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-dur.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/dur") |
|
||||
| [pause](#pause) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-pause.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/pause") |
|
||||
| [perDay](#perday) | `boolean` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-perday.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/perDay") |
|
||||
| [e](#e) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e") |
|
||||
|
||||
## type
|
||||
|
||||
@@ -216,3 +217,21 @@ https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelim
|
||||
### perDay Type
|
||||
|
||||
`boolean`
|
||||
|
||||
## e
|
||||
|
||||
|
||||
|
||||
`e`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e")
|
||||
|
||||
### e Type
|
||||
|
||||
`number`
|
||||
|
||||
@@ -899,6 +899,7 @@ Reference this group by using
|
||||
| [dur](#dur) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-dur.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/dur") |
|
||||
| [pause](#pause) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-pause.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/pause") |
|
||||
| [perDay](#perday) | `boolean` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-perday.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/perDay") |
|
||||
| [e](#e) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e") |
|
||||
|
||||
### ruleId
|
||||
|
||||
@@ -1080,6 +1081,24 @@ Reference this group by using
|
||||
|
||||
`boolean`
|
||||
|
||||
### e
|
||||
|
||||
|
||||
|
||||
`e`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedParentAction](serializedparentaction-definitions-serializedtimelimitrule-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedTimeLimitRule/properties/e")
|
||||
|
||||
#### e Type
|
||||
|
||||
`number`
|
||||
|
||||
## Definitions group SerializedDeleteCategoryAction
|
||||
|
||||
Reference this group by using
|
||||
@@ -4397,6 +4416,7 @@ Reference this group by using
|
||||
| [dur](#dur-1) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-dur.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/dur") |
|
||||
| [pause](#pause-1) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-pause.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/pause") |
|
||||
| [perDay](#perday-1) | `boolean` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-perday.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/perDay") |
|
||||
| [e](#e-1) | `number` | Optional | cannot be null | [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e") |
|
||||
|
||||
### type
|
||||
|
||||
@@ -4586,6 +4606,24 @@ Reference this group by using
|
||||
|
||||
`boolean`
|
||||
|
||||
### e
|
||||
|
||||
|
||||
|
||||
`e`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SerializedParentAction](serializedparentaction-definitions-serializedupdatetimelimitruleaction-properties-e.md "https://timelimit.io/SerializedParentAction#/definitions/SerializedUpdateTimelimitRuleAction/properties/e")
|
||||
|
||||
#### e Type
|
||||
|
||||
`number`
|
||||
|
||||
## Definitions group SerializedUpdateUserFlagsAction
|
||||
|
||||
Reference this group by using
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled number in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pLevel
|
||||
```
|
||||
|
||||
|
||||
|
||||
| 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") |
|
||||
|
||||
## pLevel Type
|
||||
|
||||
`number`
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled string in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pType
|
||||
```
|
||||
|
||||
|
||||
|
||||
| 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") |
|
||||
|
||||
## pType Type
|
||||
|
||||
`string`
|
||||
@@ -50,6 +50,8 @@ https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData
|
||||
| [qOrLater](#qorlater) | `boolean` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-qorlater.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/qOrLater") |
|
||||
| [mFlags](#mflags) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-mflags.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/mFlags") |
|
||||
| [pk](#pk) | `string` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-pk.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pk") |
|
||||
| [pType](#ptype) | `string` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-ptype.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pType") |
|
||||
| [pLevel](#plevel) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-plevel.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pLevel") |
|
||||
|
||||
## deviceId
|
||||
|
||||
@@ -718,3 +720,39 @@ https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData
|
||||
### pk Type
|
||||
|
||||
`string`
|
||||
|
||||
## pType
|
||||
|
||||
|
||||
|
||||
`pType`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-ptype.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pType")
|
||||
|
||||
### pType Type
|
||||
|
||||
`string`
|
||||
|
||||
## pLevel
|
||||
|
||||
|
||||
|
||||
`pLevel`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-plevel.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pLevel")
|
||||
|
||||
### pLevel Type
|
||||
|
||||
`number`
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled string in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/deviceId
|
||||
```
|
||||
|
||||
|
||||
|
||||
| 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") |
|
||||
|
||||
## deviceId Type
|
||||
|
||||
`string`
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled string in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/token
|
||||
```
|
||||
|
||||
|
||||
|
||||
| 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") |
|
||||
|
||||
## token Type
|
||||
|
||||
`string`
|
||||
@@ -0,0 +1,24 @@
|
||||
# Untitled string in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerPing/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 | [ServerDataStatus.schema.json\*](ServerDataStatus.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 |
|
||||
| :------- | :---------- |
|
||||
| `"ping"` | |
|
||||
| `"pong"` | |
|
||||
@@ -0,0 +1,86 @@
|
||||
# ServerPing Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/definitions/ServerPing
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :----------- | :---------------- | :-------------------- | :------------------ | :------------------------------------------------------------------------------------ |
|
||||
| Can be instantiated | No | Unknown status | No | Forbidden | Forbidden | none | [ServerDataStatus.schema.json\*](ServerDataStatus.schema.json "open original schema") |
|
||||
|
||||
## ServerPing Type
|
||||
|
||||
`object` ([ServerPing](serverdatastatus-definitions-serverping.md))
|
||||
|
||||
# ServerPing Properties
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :-------------------- | :------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [deviceId](#deviceid) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverping-properties-deviceid.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/deviceId") |
|
||||
| [token](#token) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverping-properties-token.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/token") |
|
||||
| [type](#type) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverping-properties-type.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/type") |
|
||||
|
||||
## deviceId
|
||||
|
||||
|
||||
|
||||
`deviceId`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverping-properties-deviceid.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/deviceId")
|
||||
|
||||
### deviceId Type
|
||||
|
||||
`string`
|
||||
|
||||
## token
|
||||
|
||||
|
||||
|
||||
`token`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverping-properties-token.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/token")
|
||||
|
||||
### token Type
|
||||
|
||||
`string`
|
||||
|
||||
## type
|
||||
|
||||
|
||||
|
||||
`type`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverping-properties-type.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/type")
|
||||
|
||||
### type Type
|
||||
|
||||
`string`
|
||||
|
||||
### type Constraints
|
||||
|
||||
**enum**: the value of this property must be equal to one of the following values:
|
||||
|
||||
| Value | Explanation |
|
||||
| :------- | :---------- |
|
||||
| `"ping"` | |
|
||||
| `"pong"` | |
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled array in ServerDataStatus Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/ServerDataStatus#/properties/pings
|
||||
```
|
||||
|
||||
|
||||
|
||||
| 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") |
|
||||
|
||||
## pings Type
|
||||
|
||||
`object[]` ([ServerPing](serverdatastatus-definitions-serverping.md))
|
||||
@@ -30,6 +30,7 @@ https://timelimit.io/ServerDataStatus
|
||||
| [users](#users) | `object` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serveruserlist.md "https://timelimit.io/ServerDataStatus#/properties/users") |
|
||||
| [krq](#krq) | `array` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-properties-krq.md "https://timelimit.io/ServerDataStatus#/properties/krq") |
|
||||
| [kr](#kr) | `array` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-properties-kr.md "https://timelimit.io/ServerDataStatus#/properties/kr") |
|
||||
| [pings](#pings) | `array` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-properties-pings.md "https://timelimit.io/ServerDataStatus#/properties/pings") |
|
||||
| [dh](#dh) | `object` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdhkey.md "https://timelimit.io/ServerDataStatus#/properties/dh") |
|
||||
| [u2f](#u2f) | `object` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-u2fdata.md "https://timelimit.io/ServerDataStatus#/properties/u2f") |
|
||||
| [fullVersion](#fullversion) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-properties-fullversion.md "https://timelimit.io/ServerDataStatus#/properties/fullVersion") |
|
||||
@@ -252,6 +253,24 @@ https://timelimit.io/ServerDataStatus
|
||||
|
||||
`object[]` ([ServerKeyResponse](serverdatastatus-definitions-serverkeyresponse.md))
|
||||
|
||||
## pings
|
||||
|
||||
|
||||
|
||||
`pings`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `object[]` ([ServerPing](serverdatastatus-definitions-serverping.md))
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-properties-pings.md "https://timelimit.io/ServerDataStatus#/properties/pings")
|
||||
|
||||
### pings Type
|
||||
|
||||
`object[]` ([ServerPing](serverdatastatus-definitions-serverping.md))
|
||||
|
||||
## dh
|
||||
|
||||
|
||||
@@ -435,6 +454,8 @@ Reference this group by using
|
||||
| [qOrLater](#qorlater) | `boolean` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-qorlater.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/qOrLater") |
|
||||
| [mFlags](#mflags) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-mflags.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/mFlags") |
|
||||
| [pk](#pk) | `string` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-pk.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pk") |
|
||||
| [pType](#ptype) | `string` | Optional | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-ptype.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pType") |
|
||||
| [pLevel](#plevel) | `number` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-plevel.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pLevel") |
|
||||
|
||||
### deviceId
|
||||
|
||||
@@ -1104,6 +1125,42 @@ Reference this group by using
|
||||
|
||||
`string`
|
||||
|
||||
### pType
|
||||
|
||||
|
||||
|
||||
`pType`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-ptype.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pType")
|
||||
|
||||
#### pType Type
|
||||
|
||||
`string`
|
||||
|
||||
### pLevel
|
||||
|
||||
|
||||
|
||||
`pLevel`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverdevicedata-properties-plevel.md "https://timelimit.io/ServerDataStatus#/definitions/ServerDeviceData/properties/pLevel")
|
||||
|
||||
#### pLevel Type
|
||||
|
||||
`number`
|
||||
|
||||
## Definitions group ProtectionLevel
|
||||
|
||||
Reference this group by using
|
||||
@@ -3411,6 +3468,83 @@ Reference this group by using
|
||||
|
||||
`string`
|
||||
|
||||
## Definitions group ServerPing
|
||||
|
||||
Reference this group by using
|
||||
|
||||
```json
|
||||
{"$ref":"https://timelimit.io/ServerDataStatus#/definitions/ServerPing"}
|
||||
```
|
||||
|
||||
| Property | Type | Required | Nullable | Defined by |
|
||||
| :---------------------- | :------- | :------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [deviceId](#deviceid-4) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverping-properties-deviceid.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/deviceId") |
|
||||
| [token](#token) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverping-properties-token.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/token") |
|
||||
| [type](#type-2) | `string` | Required | cannot be null | [ServerDataStatus](serverdatastatus-definitions-serverping-properties-type.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/type") |
|
||||
|
||||
### deviceId
|
||||
|
||||
|
||||
|
||||
`deviceId`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverping-properties-deviceid.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/deviceId")
|
||||
|
||||
#### deviceId Type
|
||||
|
||||
`string`
|
||||
|
||||
### token
|
||||
|
||||
|
||||
|
||||
`token`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverping-properties-token.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/token")
|
||||
|
||||
#### token Type
|
||||
|
||||
`string`
|
||||
|
||||
### type
|
||||
|
||||
|
||||
|
||||
`type`
|
||||
|
||||
* is required
|
||||
|
||||
* Type: `string`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [ServerDataStatus](serverdatastatus-definitions-serverping-properties-type.md "https://timelimit.io/ServerDataStatus#/definitions/ServerPing/properties/type")
|
||||
|
||||
#### type Type
|
||||
|
||||
`string`
|
||||
|
||||
#### type Constraints
|
||||
|
||||
**enum**: the value of this property must be equal to one of the following values:
|
||||
|
||||
| Value | Explanation |
|
||||
| :------- | :---------- |
|
||||
| `"ping"` | |
|
||||
| `"pong"` | |
|
||||
|
||||
## Definitions group ServerDhKey
|
||||
|
||||
Reference this group by using
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Untitled number in SignIntoFamilyRequest Schema
|
||||
|
||||
```txt
|
||||
https://timelimit.io/SignIntoFamilyRequest#/properties/clientLevel
|
||||
```
|
||||
|
||||
|
||||
|
||||
| Abstract | Extensible | Status | Identifiable | Custom Properties | Additional Properties | Access Restrictions | Defined In |
|
||||
| :------------------ | :--------- | :------------- | :---------------------- | :---------------- | :-------------------- | :------------------ | :---------------------------------------------------------------------------------------------- |
|
||||
| Can be instantiated | No | Unknown status | Unknown identifiability | Forbidden | Allowed | none | [SignIntoFamilyRequest.schema.json\*](SignIntoFamilyRequest.schema.json "open original schema") |
|
||||
|
||||
## clientLevel Type
|
||||
|
||||
`number`
|
||||
@@ -21,6 +21,7 @@ https://timelimit.io/SignIntoFamilyRequest
|
||||
| [mailAuthToken](#mailauthtoken) | `string` | Required | cannot be null | [SignIntoFamilyRequest](signintofamilyrequest-properties-mailauthtoken.md "https://timelimit.io/SignIntoFamilyRequest#/properties/mailAuthToken") |
|
||||
| [parentDevice](#parentdevice) | `object` | Required | cannot be null | [SignIntoFamilyRequest](signintofamilyrequest-definitions-newdeviceinfo.md "https://timelimit.io/SignIntoFamilyRequest#/properties/parentDevice") |
|
||||
| [deviceName](#devicename) | `string` | Required | cannot be null | [SignIntoFamilyRequest](signintofamilyrequest-properties-devicename.md "https://timelimit.io/SignIntoFamilyRequest#/properties/deviceName") |
|
||||
| [clientLevel](#clientlevel) | `number` | Optional | cannot be null | [SignIntoFamilyRequest](signintofamilyrequest-properties-clientlevel.md "https://timelimit.io/SignIntoFamilyRequest#/properties/clientLevel") |
|
||||
|
||||
## mailAuthToken
|
||||
|
||||
@@ -76,6 +77,24 @@ https://timelimit.io/SignIntoFamilyRequest
|
||||
|
||||
`string`
|
||||
|
||||
## clientLevel
|
||||
|
||||
|
||||
|
||||
`clientLevel`
|
||||
|
||||
* is optional
|
||||
|
||||
* Type: `number`
|
||||
|
||||
* cannot be null
|
||||
|
||||
* defined in: [SignIntoFamilyRequest](signintofamilyrequest-properties-clientlevel.md "https://timelimit.io/SignIntoFamilyRequest#/properties/clientLevel")
|
||||
|
||||
### clientLevel Type
|
||||
|
||||
`number`
|
||||
|
||||
# SignIntoFamilyRequest Definitions
|
||||
|
||||
## Definitions group NewDeviceInfo
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// @ts-check
|
||||
|
||||
import eslint from '@eslint/js';
|
||||
import { defineConfig } from 'eslint/config';
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
export default defineConfig(
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
{
|
||||
ignores: ['build', 'scripts']
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': ['warn', { caughtErrors: 'none' }]
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,192 @@
|
||||
<!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]>
|
||||
<noscript>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:AllowPNG/>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
</noscript>
|
||||
<![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 media="screen and (min-width:480px)">
|
||||
.moz-text-html .mj-column-per-100 {
|
||||
width: 100% !important;
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body style="word-spacing:normal;">
|
||||
<div style="">
|
||||
<!--[if mso | IE]><table align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" bgcolor="#009688" ><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%">
|
||||
<tbody>
|
||||
<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>
|
||||
</tbody>
|
||||
</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%">
|
||||
<tbody>
|
||||
<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 haben eine Löschung Ihres Benutzerkontos angefordert. Diese wurde soeben durchgeführt. </p>
|
||||
<p> You requested the deletion of your account. This deletion is finished now. </p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</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%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" 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;">
|
||||
</td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</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%">
|
||||
<tbody>
|
||||
<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 aufgrund Ihrer Anfrage. Falls Sie Fragen haben können Sie einfach auf diese E-Mail antworten. </p>
|
||||
<p> You got this mail due to your request. If you have got any questions, then you can reply to this message. </p>
|
||||
<p> © <%= mailimprint %> </p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!--[if mso | IE]></td></tr></table><![endif]-->
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,44 @@
|
||||
<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>
|
||||
Sie haben eine Löschung Ihres Benutzerkontos angefordert. Diese wurde soeben durchgeführt.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You requested the deletion of your account. This deletion is finished now.
|
||||
</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 aufgrund Ihrer Anfrage.
|
||||
Falls Sie Fragen haben können Sie einfach auf diese E-Mail antworten.
|
||||
</p>
|
||||
<p>
|
||||
You got this mail due to your request.
|
||||
If you have got any questions, then you can reply to this message.
|
||||
</p>
|
||||
<p>
|
||||
© <%= mailimprint %>
|
||||
</p>
|
||||
</mj-text>
|
||||
</mj-column>
|
||||
</mj-section>
|
||||
</mj-body>
|
||||
</mjml>
|
||||
@@ -0,0 +1 @@
|
||||
Konto gelöscht/Account deleted
|
||||
@@ -0,0 +1,13 @@
|
||||
Sie haben eine Löschung Ihres Benutzerkontos angefordert. Diese wurde soeben durchgeführt.
|
||||
|
||||
You requested the deletion of your account. This deletion is finished now.
|
||||
|
||||
----------------------
|
||||
|
||||
Sie erhalten diese Nachricht aufgrund Ihrer Anfrage.
|
||||
Falls Sie Fragen haben können Sie einfach auf diese E-Mail antworten.
|
||||
|
||||
You got this mail due to your request.
|
||||
If you have got any questions, then you can reply to this message.
|
||||
|
||||
<C> <%- mailimprint %>
|
||||
Generated
+4163
-4135
File diff suppressed because it is too large
Load Diff
+13
-16
@@ -6,10 +6,10 @@
|
||||
"scripts": {
|
||||
"start": "node ./build/index.js",
|
||||
"test": "node scripts/test-launch-with-different-databases.js",
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"build": "npm run build:clean && npm run build:json && npm run build:ts && npm run lint && npm run build:doc",
|
||||
"build:clean": "rimraf build",
|
||||
"build:clean": "rm -rf build",
|
||||
"build:json": "node ./scripts/build-schemas.js",
|
||||
"build:ts": "tsc",
|
||||
"build:doc": "npm run build:doc:json",
|
||||
@@ -29,7 +29,8 @@
|
||||
},
|
||||
"homepage": "https://gitlab.com/timelimit.io/timelimit-server-2018#README",
|
||||
"devDependencies": {
|
||||
"@adobe/jsonschema2md": "^7.0.0",
|
||||
"@adobe/jsonschema2md": "^8.0.8",
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@types/basic-auth": "^1.1.3",
|
||||
"@types/body-parser": "^1.19.0",
|
||||
"@types/ejs": "^3.1.0",
|
||||
@@ -38,16 +39,13 @@
|
||||
"@types/lodash": "^4.14.166",
|
||||
"@types/node": "^16.11.59",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/umzug": "^2.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||
"@typescript-eslint/parser": "^5.10.0",
|
||||
"eslint": "^8.7.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^4.4.4",
|
||||
"eslint": "^10.0.1",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript-eslint": "^8.56.0",
|
||||
"typescript-json-schema": "^0.52.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": "^7.0.2",
|
||||
"ajv": "^8.18.0",
|
||||
"basic-auth": "^2.0.1",
|
||||
"body-parser": "^1.19.0",
|
||||
"ejs": "^3.1.5",
|
||||
@@ -57,16 +55,15 @@
|
||||
"jose": "^4.9.3",
|
||||
"lodash": "^4.17.21",
|
||||
"mariadb": "^2.5.2",
|
||||
"nodemailer": "^6.7.2",
|
||||
"nodemailer": "^8.0.4",
|
||||
"pg": "^8.5.1",
|
||||
"pg-hstore": "^2.3.3",
|
||||
"rate-limiter-flexible": "^2.1.15",
|
||||
"sequelize": "^6.11.0",
|
||||
"sequelize": "^6.25.5",
|
||||
"socket.io": "^4.0.1",
|
||||
"sqlite3": "^4.0.0",
|
||||
"umzug": "^2.3.0"
|
||||
"umzug": "^3.8.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"sqlite3": "^4.0.0"
|
||||
"sqlite3": "npm:@vscode/sqlite3@^5.1.12-vscode"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2024 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@@ -43,7 +43,8 @@ const types = [
|
||||
'RequestWithAuthToken',
|
||||
'SendMailLoginCodeRequest',
|
||||
'SignInByMailCodeRequest',
|
||||
'IdentityTokenPayload'
|
||||
'IdentityTokenPayload',
|
||||
'DeleteAccountPayload',
|
||||
]
|
||||
|
||||
const docOnlyTypes = [
|
||||
@@ -57,7 +58,9 @@ const allTypes = [
|
||||
|
||||
const settings = {
|
||||
required: true,
|
||||
noExtraProps: true
|
||||
noExtraProps: true,
|
||||
// otherwise it finds errors in dependencies that we don't care about
|
||||
ignoreErrors: true
|
||||
};
|
||||
|
||||
const compilerOptions = {
|
||||
|
||||
@@ -24,6 +24,8 @@ const { spawnAsync } = require('../process.js')
|
||||
const { sleep } = require('../sleep.js')
|
||||
|
||||
async function startMariadb() {
|
||||
const osUsername = require('os').userInfo().username
|
||||
|
||||
try { await mkdirAsync(tempDir) } catch (ex) {/* ignore */}
|
||||
|
||||
const instanceDir = resolve(tempDir, generateShortToken())
|
||||
@@ -60,12 +62,12 @@ async function startMariadb() {
|
||||
|
||||
for (command of commands) {
|
||||
console.log(command)
|
||||
await spawnAsync('mysql', ['-S', socketPath, '-u', 'root', '-e', command], { stdio: 'inherit' })
|
||||
await spawnAsync('mysql', ['-S', socketPath, '-u', osUsername, '-e', command], { stdio: 'inherit' })
|
||||
}
|
||||
|
||||
return {
|
||||
shutdown: () => {
|
||||
spawnAsync('mysql', ['-S', socketPath, '-u', 'root', '-e', 'SHUTDOWN;'], { stdio: 'inherit' }).catch((ex) => {
|
||||
spawnAsync('mysql', ['-S', socketPath, '-u', osUsername, '-e', 'SHUTDOWN;'], { stdio: 'inherit' }).catch((ex) => {
|
||||
console.warn(ex)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -58,7 +58,7 @@ async function startPostgres() {
|
||||
const password = generateToken() // this database accepts anything
|
||||
|
||||
await spawnAsync('createuser', ['-h', socketDir, username], { stdio: 'inherit' })
|
||||
await spawnAsync('createdb', ['-h', socketDir, database], { stdio: 'inherit' })
|
||||
await spawnAsync('createdb', ['-h', socketDir, '--owner', username, database], { stdio: 'inherit' })
|
||||
|
||||
return {
|
||||
shutdown: () => task.kill('SIGINT'),
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2026 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
|
||||
@@ -78,6 +78,7 @@ export { UpdateTimelimitRuleAction } from './updatetimelimitrule'
|
||||
export { UpdateUserFlagsAction } from './updateuserflags'
|
||||
export { UpdateUserLimitLoginCategory } from './updateuserlimitlogincategory'
|
||||
export { MarkTaskPendingAction } from './marktaskpendingaction'
|
||||
export { PingAction } from './ping'
|
||||
export { DeleteChildTaskAction } from './deletechildtaskaction'
|
||||
export { UpdateChildTaskAction } from './updatechildtaskaction'
|
||||
export { ReviewChildTaskAction } from './reviewchildtaskaction'
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2026 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 { AppLogicAction } from './basetypes'
|
||||
import { assertIdWithinFamily } from './meta/util'
|
||||
|
||||
const actionType = 'PingAction'
|
||||
|
||||
export class PingAction extends AppLogicAction {
|
||||
readonly deviceId: string
|
||||
readonly event: PingEvent
|
||||
readonly token: string
|
||||
|
||||
constructor ({ deviceId, event, token }: {
|
||||
deviceId: string
|
||||
event: PingEvent
|
||||
token: string
|
||||
}) {
|
||||
super()
|
||||
|
||||
assertIdWithinFamily({ actionType, field: 'deviceId', value: deviceId })
|
||||
assertIdWithinFamily({ actionType, field: 'token', value: token })
|
||||
|
||||
this.deviceId = deviceId
|
||||
this.event = event
|
||||
this.token = token
|
||||
}
|
||||
|
||||
static parse = ({ deviceId, event, token }: SerializedPingAction) => (
|
||||
new PingAction({ deviceId, event, token })
|
||||
)
|
||||
}
|
||||
|
||||
export interface SerializedPingAction {
|
||||
type: 'PING'
|
||||
deviceId: string
|
||||
event: PingEvent
|
||||
token: string
|
||||
}
|
||||
|
||||
export type PingEvent = 'ping' | 'pong' | 'clear'
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2026 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
|
||||
@@ -24,6 +24,7 @@ import { ForceSyncAction, SerializedForceSyncAction } from '../forcesync'
|
||||
import { ReplyToKeyRequestAction, SerializedReplyToKeyRequestAction } from '../replytokeyrequest'
|
||||
import { MarkTaskPendingAction, SerializedMarkTaskPendingAction } from '../marktaskpendingaction'
|
||||
import { UnknownActionTypeException } from '../meta/exception'
|
||||
import { PingAction, SerializedPingAction } from '../ping'
|
||||
import { UpdateInstalledAppsAction, SerializedUpdateInstalledAppsAction } from '../updateinstalledapps'
|
||||
import { RemoveInstalledAppsAction, SerializedRemoveInstalledAppsAction } from '../removeinstalledapps'
|
||||
import { SendKeyRequestAction, SerializedSendKeyRequestAction } from '../sendkeyrequest'
|
||||
@@ -41,6 +42,7 @@ export type SerializedAppLogicAction =
|
||||
SerializedForceSyncAction |
|
||||
SerializedReplyToKeyRequestAction |
|
||||
SerializedMarkTaskPendingAction |
|
||||
SerializedPingAction |
|
||||
SerializedUpdateInstalledAppsAction |
|
||||
SerializedRemoveInstalledAppsAction |
|
||||
SerializedSendKeyRequestAction |
|
||||
@@ -65,6 +67,8 @@ export const parseAppLogicAction = (serialized: SerializedAppLogicAction): AppLo
|
||||
return ReplyToKeyRequestAction.parse(serialized)
|
||||
} else if (serialized.type === 'MARK_TASK_PENDING') {
|
||||
return MarkTaskPendingAction.parse(serialized)
|
||||
} else if (serialized.type === 'PING') {
|
||||
return PingAction.parse(serialized)
|
||||
} else if (serialized.type === 'UPDATE_INSTALLED_APPS') {
|
||||
return UpdateInstalledAppsAction.parse(serialized)
|
||||
} else if (serialized.type === 'REMOVE_INSTALLED_APPS') {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2023 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@@ -15,6 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { minPlatformLevel, maxPlatformLevel, minPlatformTypeLength, maxPlatformTypeLength } from '../database/device'
|
||||
import { NewPermissionStatus } from '../model/newpermissionstatus'
|
||||
import { ProtectionLevel } from '../model/protectionlevel'
|
||||
import { RuntimePermissionStatus } from '../model/runtimepermissionstatus'
|
||||
@@ -33,6 +34,8 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
|
||||
readonly didReboot: boolean
|
||||
readonly isQOrLaterNow: boolean
|
||||
readonly addedManipulationFlags: number
|
||||
readonly platformType?: string
|
||||
readonly platformLevel?: number
|
||||
|
||||
constructor ({
|
||||
newProtetionLevel,
|
||||
@@ -43,7 +46,9 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
|
||||
newAppVersion,
|
||||
didReboot,
|
||||
isQOrLaterNow,
|
||||
addedManipulationFlags
|
||||
addedManipulationFlags,
|
||||
platformType,
|
||||
platformLevel
|
||||
}: {
|
||||
newProtetionLevel?: ProtectionLevel
|
||||
newUsageStatsPermissionStatus?: RuntimePermissionStatus
|
||||
@@ -54,6 +59,8 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
|
||||
didReboot: boolean
|
||||
isQOrLaterNow: boolean
|
||||
addedManipulationFlags: number
|
||||
platformType?: string
|
||||
platformLevel?: number
|
||||
}) {
|
||||
super()
|
||||
|
||||
@@ -67,6 +74,20 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
|
||||
|
||||
assertSafeInteger({ actionType, field: 'addedManipulationFlags', value: addedManipulationFlags })
|
||||
|
||||
if (platformType !== undefined) {
|
||||
if (platformType.length < minPlatformTypeLength || platformType.length > maxPlatformTypeLength) {
|
||||
throwOutOfRange({ actionType, field: 'platformType.length', value: platformType.length })
|
||||
}
|
||||
}
|
||||
|
||||
if (platformLevel !== undefined) {
|
||||
assertSafeInteger({ actionType, field: 'platformLevel', value: platformLevel })
|
||||
|
||||
if (platformLevel < minPlatformLevel || platformLevel > maxPlatformLevel) {
|
||||
throwOutOfRange({ actionType, field: 'platformLevel', value: platformLevel })
|
||||
}
|
||||
}
|
||||
|
||||
this.newProtetionLevel = newProtetionLevel
|
||||
this.newUsageStatsPermissionStatus = newUsageStatsPermissionStatus
|
||||
this.newNotificationAccessPermission = newNotificationAccessPermission
|
||||
@@ -76,6 +97,8 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
|
||||
this.didReboot = didReboot
|
||||
this.isQOrLaterNow = isQOrLaterNow
|
||||
this.addedManipulationFlags = addedManipulationFlags
|
||||
this.platformType = platformType
|
||||
this.platformLevel = platformLevel
|
||||
}
|
||||
|
||||
static parse = ({
|
||||
@@ -87,7 +110,9 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
|
||||
appVersion,
|
||||
didReboot,
|
||||
isQOrLaterNow,
|
||||
addedManipulationFlags
|
||||
addedManipulationFlags,
|
||||
platformType,
|
||||
platformLevel
|
||||
}: SerializedUpdateDeviceStatusAction) => (
|
||||
new UpdateDeviceStatusAction({
|
||||
newProtetionLevel: protectionLevel,
|
||||
@@ -98,7 +123,9 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
|
||||
newAppVersion: appVersion,
|
||||
didReboot: !!didReboot,
|
||||
isQOrLaterNow: !!isQOrLaterNow,
|
||||
addedManipulationFlags: addedManipulationFlags || 0
|
||||
addedManipulationFlags: addedManipulationFlags || 0,
|
||||
platformType: platformType,
|
||||
platformLevel: platformLevel
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -114,4 +141,6 @@ export interface SerializedUpdateDeviceStatusAction {
|
||||
didReboot?: boolean
|
||||
isQOrLaterNow?: boolean
|
||||
addedManipulationFlags?: number
|
||||
platformType?: string
|
||||
platformLevel?: number
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2020 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2024 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@@ -32,11 +32,12 @@ export class UpdateTimelimitRuleAction extends ParentAction {
|
||||
readonly sessionDurationMilliseconds: number
|
||||
readonly sessionPauseMilliseconds: number
|
||||
readonly perDay: boolean
|
||||
readonly expiresAt?: number
|
||||
|
||||
constructor ({
|
||||
ruleId, maximumTimeInMillis, dayMask, applyToExtraTimeUsage,
|
||||
start, end, sessionDurationMilliseconds, sessionPauseMilliseconds,
|
||||
perDay
|
||||
perDay, expiresAt
|
||||
}: {
|
||||
ruleId: string
|
||||
maximumTimeInMillis: number
|
||||
@@ -47,6 +48,7 @@ export class UpdateTimelimitRuleAction extends ParentAction {
|
||||
sessionDurationMilliseconds: number
|
||||
sessionPauseMilliseconds: number
|
||||
perDay: boolean
|
||||
expiresAt?: number
|
||||
}) {
|
||||
super()
|
||||
|
||||
@@ -59,6 +61,7 @@ export class UpdateTimelimitRuleAction extends ParentAction {
|
||||
this.sessionDurationMilliseconds = sessionDurationMilliseconds
|
||||
this.sessionPauseMilliseconds = sessionPauseMilliseconds
|
||||
this.perDay = perDay
|
||||
this.expiresAt = expiresAt
|
||||
|
||||
assertIdWithinFamily({ actionType, field: 'ruleId', value: ruleId })
|
||||
|
||||
@@ -92,9 +95,17 @@ export class UpdateTimelimitRuleAction extends ParentAction {
|
||||
staticMessage: 'session duration lesser than zero'
|
||||
})
|
||||
}
|
||||
|
||||
if (expiresAt !== undefined) {
|
||||
assertSafeInteger({ actionType, field: 'expiresAt', value: expiresAt })
|
||||
|
||||
if (expiresAt <= 0) {
|
||||
throwOutOfRange({ actionType, field: 'expiresAt', value: expiresAt })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static parse = ({ ruleId, time, days, extraTime, start, end, dur, pause, perDay }: SerializedUpdateTimelimitRuleAction) => (
|
||||
static parse = ({ ruleId, time, days, extraTime, start, end, dur, pause, perDay, e }: SerializedUpdateTimelimitRuleAction) => (
|
||||
new UpdateTimelimitRuleAction({
|
||||
ruleId,
|
||||
maximumTimeInMillis: time,
|
||||
@@ -104,7 +115,8 @@ export class UpdateTimelimitRuleAction extends ParentAction {
|
||||
end: end ?? MinuteOfDay.MAX,
|
||||
sessionDurationMilliseconds: dur ?? 0,
|
||||
sessionPauseMilliseconds: pause ?? 0,
|
||||
perDay: perDay ?? false
|
||||
perDay: perDay ?? false,
|
||||
expiresAt: e
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -120,4 +132,5 @@ export interface SerializedUpdateTimelimitRuleAction {
|
||||
dur?: number
|
||||
pause?: number
|
||||
perDay?: boolean
|
||||
e?: number
|
||||
}
|
||||
|
||||
+5
-1
@@ -140,13 +140,15 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
|
||||
if (
|
||||
typeof req.body !== 'object' ||
|
||||
typeof req.body.purchaseToken !== 'string' ||
|
||||
typeof req.body.purchaseId !== 'string'
|
||||
typeof req.body.purchaseId !== 'string' ||
|
||||
typeof req.body.dryRun !== 'boolean'
|
||||
) {
|
||||
throw new BadRequest()
|
||||
}
|
||||
|
||||
const purchaseToken: string = req.body.purchaseToken
|
||||
const purchaseId: string = req.body.purchaseId
|
||||
const dryRun: boolean = req.body.dryRun
|
||||
|
||||
const tokenContent = await verifyIdentitifyToken(purchaseToken)
|
||||
|
||||
@@ -250,6 +252,7 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
|
||||
}
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
await addPurchase({
|
||||
database,
|
||||
familyId: tokenContent.familyId,
|
||||
@@ -260,6 +263,7 @@ export const createAdminRouter = ({ database, websocket, eventHandler }: {
|
||||
transaction
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
|
||||
+9
-5
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2022 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
|
||||
@@ -24,10 +24,12 @@ import { logoutAtPrimaryDevice } from '../function/child/logout-at-primary-devic
|
||||
import { setPrimaryDevice } from '../function/child/set-primary-device'
|
||||
import { WebsocketApi } from '../websocket'
|
||||
import { isRegisterChildDeviceRequest, isRequestWithAuthToken, isUpdatePrimaryDeviceRequest } from './validator'
|
||||
import { EventHandler } from '../monitoring/eventhandler'
|
||||
|
||||
export const createChildRouter = ({ database, websocket }: {
|
||||
database: Database,
|
||||
export const createChildRouter = ({ database, websocket, eventHandler }: {
|
||||
database: Database
|
||||
websocket: WebsocketApi
|
||||
eventHandler: EventHandler
|
||||
}) => {
|
||||
const router = Router()
|
||||
|
||||
@@ -37,15 +39,17 @@ export const createChildRouter = ({ database, websocket }: {
|
||||
throw new BadRequest()
|
||||
}
|
||||
|
||||
const { deviceAuthToken, deviceId } = await addChildDevice({
|
||||
const { deviceAuthToken, deviceId, data } = await addChildDevice({
|
||||
request: req.body,
|
||||
database,
|
||||
eventHandler,
|
||||
websocket
|
||||
})
|
||||
|
||||
res.json({
|
||||
deviceAuthToken,
|
||||
ownDeviceId: deviceId
|
||||
ownDeviceId: deviceId,
|
||||
data
|
||||
})
|
||||
} catch (ex) {
|
||||
next(ex)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2020 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2022 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
|
||||
@@ -47,8 +47,8 @@ export const createApi = ({ database, websocket, connectedDevicesManager, eventH
|
||||
})
|
||||
|
||||
app.use('/auth', createAuthRouter(database))
|
||||
app.use('/child', createChildRouter({ database, websocket }))
|
||||
app.use('/parent', createParentRouter({ database, websocket }))
|
||||
app.use('/child', createChildRouter({ database, websocket, eventHandler }))
|
||||
app.use('/parent', createParentRouter({ database, websocket, eventHandler }))
|
||||
app.use('/purchase', createPurchaseRouter({ database, websocket }))
|
||||
app.use('/sync', createSyncRouter({ database, websocket, connectedDevicesManager, eventHandler }))
|
||||
|
||||
|
||||
+35
-6
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2023 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
|
||||
@@ -21,6 +21,7 @@ import { Router } from 'express'
|
||||
import { BadRequest, Forbidden, Unauthorized } from 'http-errors'
|
||||
import { config } from '../config'
|
||||
import { Database, Transaction } from '../database'
|
||||
import { deleteAccount } from '../function/cleanup/account-deletion'
|
||||
import { removeDevice } from '../function/device/remove-device'
|
||||
import { createAddDeviceToken } from '../function/parent/create-add-device-token'
|
||||
import { createFamily } from '../function/parent/create-family'
|
||||
@@ -31,14 +32,22 @@ import { signInIntoFamily } from '../function/parent/sign-in-into-family'
|
||||
import { validateU2fIntegrity, U2fValidationError } from '../function/u2f'
|
||||
import { createIdentityToken, MissingSignSecretException } from '../util/identity-token'
|
||||
import { WebsocketApi } from '../websocket'
|
||||
import { EventHandler } from '../monitoring/eventhandler'
|
||||
import {
|
||||
isCreateFamilyByMailTokenRequest,
|
||||
isCreateRegisterDeviceTokenRequest, isLinkParentMailAddressRequest,
|
||||
isMailAuthTokenRequestBody, isRecoverParentPasswordRequest,
|
||||
isRemoveDeviceRequest, isSignIntoFamilyRequest, isRequestIdentityTokenRequest
|
||||
isRemoveDeviceRequest, isSignIntoFamilyRequest, isRequestIdentityTokenRequest,
|
||||
isDeleteAccountPayload
|
||||
} from './validator'
|
||||
|
||||
export const createParentRouter = ({ database, websocket }: {database: Database, websocket: WebsocketApi}) => {
|
||||
export const createParentRouter = ({
|
||||
database, websocket, eventHandler
|
||||
}: {
|
||||
database: Database
|
||||
websocket: WebsocketApi
|
||||
eventHandler: EventHandler
|
||||
}) => {
|
||||
const router = Router()
|
||||
|
||||
router.post('/get-status-by-mail-address', json(), async (req, res, next) => {
|
||||
@@ -75,17 +84,20 @@ export const createParentRouter = ({ database, websocket }: {database: Database,
|
||||
|
||||
const result = await createFamily({
|
||||
database,
|
||||
eventHandler,
|
||||
firstParentDevice: req.body.parentDevice,
|
||||
mailAuthToken: req.body.mailAuthToken,
|
||||
password: req.body.parentPassword,
|
||||
deviceName: req.body.deviceName,
|
||||
parentName: req.body.parentName,
|
||||
timeZone: req.body.timeZone
|
||||
timeZone: req.body.timeZone,
|
||||
clientLevel: req.body.clientLevel || null
|
||||
})
|
||||
|
||||
res.json({
|
||||
deviceAuthToken: result.deviceAuthToken,
|
||||
ownDeviceId: result.deviceId
|
||||
ownDeviceId: result.deviceId,
|
||||
data: result.data
|
||||
})
|
||||
} catch (ex) {
|
||||
next(ex)
|
||||
@@ -100,15 +112,18 @@ export const createParentRouter = ({ database, websocket }: {database: Database,
|
||||
|
||||
const result = await signInIntoFamily({
|
||||
database,
|
||||
eventHandler,
|
||||
newDeviceInfo: req.body.parentDevice,
|
||||
mailAuthToken: req.body.mailAuthToken,
|
||||
deviceName: req.body.deviceName,
|
||||
clientLevel: req.body.clientLevel || null,
|
||||
websocket
|
||||
})
|
||||
|
||||
res.json({
|
||||
deviceAuthToken: result.deviceAuthToken,
|
||||
ownDeviceId: result.deviceId
|
||||
ownDeviceId: result.deviceId,
|
||||
data: result.data
|
||||
})
|
||||
} catch (ex) {
|
||||
next(ex)
|
||||
@@ -343,5 +358,19 @@ export const createParentRouter = ({ database, websocket }: {database: Database,
|
||||
}
|
||||
})
|
||||
|
||||
router.post('/delete-account', json(), async (req, res, next) => {
|
||||
try {
|
||||
if (!isDeleteAccountPayload(req.body)) {
|
||||
throw new BadRequest()
|
||||
}
|
||||
|
||||
await deleteAccount({ database, request: req.body, websocket })
|
||||
|
||||
res.sendStatus(200)
|
||||
} catch (ex) {
|
||||
next(ex)
|
||||
}
|
||||
})
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
+9
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2023 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
|
||||
@@ -84,12 +84,14 @@ export interface CreateFamilyByMailTokenRequest {
|
||||
deviceName: string
|
||||
timeZone: string
|
||||
parentName: string
|
||||
clientLevel?: number
|
||||
}
|
||||
|
||||
export interface SignIntoFamilyRequest {
|
||||
mailAuthToken: string
|
||||
parentDevice: NewDeviceInfo
|
||||
deviceName: string
|
||||
clientLevel?: number
|
||||
}
|
||||
|
||||
export interface RecoverParentPasswordRequest {
|
||||
@@ -101,6 +103,7 @@ export interface RegisterChildDeviceRequest {
|
||||
registerToken: string
|
||||
childDevice: NewDeviceInfo
|
||||
deviceName: string
|
||||
clientLevel?: number
|
||||
}
|
||||
|
||||
export interface CreateRegisterDeviceTokenRequest {
|
||||
@@ -173,5 +176,10 @@ export type IdentityTokenPayload = IdentityTokenCreatePayload & {
|
||||
exp: number
|
||||
}
|
||||
|
||||
export interface DeleteAccountPayload {
|
||||
deviceAuthToken: string
|
||||
mailAuthTokens: Array<string>
|
||||
}
|
||||
|
||||
export { SerializedParentAction, SerializedChildAction, SerializedAppLogicAction } from '../action/serialization'
|
||||
export { ServerDataStatus } from '../object/serverdatastatus'
|
||||
|
||||
+112
-1
@@ -1,5 +1,5 @@
|
||||
// tslint:disable
|
||||
import { ClientPushChangesRequest, ClientPullChangesRequest, MailAuthTokenRequestBody, CreateFamilyByMailTokenRequest, SignIntoFamilyRequest, RecoverParentPasswordRequest, RegisterChildDeviceRequest, SerializedParentAction, SerializedAppLogicAction, SerializedChildAction, CreateRegisterDeviceTokenRequest, CanDoPurchaseRequest, FinishPurchaseByGooglePlayRequest, LinkParentMailAddressRequest, UpdatePrimaryDeviceRequest, RemoveDeviceRequest, RequestIdentityTokenRequest, RequestWithAuthToken, SendMailLoginCodeRequest, SignInByMailCodeRequest, IdentityTokenPayload } from './schema'
|
||||
import { ClientPushChangesRequest, ClientPullChangesRequest, MailAuthTokenRequestBody, CreateFamilyByMailTokenRequest, SignIntoFamilyRequest, RecoverParentPasswordRequest, RegisterChildDeviceRequest, SerializedParentAction, SerializedAppLogicAction, SerializedChildAction, CreateRegisterDeviceTokenRequest, CanDoPurchaseRequest, FinishPurchaseByGooglePlayRequest, LinkParentMailAddressRequest, UpdatePrimaryDeviceRequest, RemoveDeviceRequest, RequestIdentityTokenRequest, RequestWithAuthToken, SendMailLoginCodeRequest, SignInByMailCodeRequest, IdentityTokenPayload, DeleteAccountPayload } from './schema'
|
||||
import Ajv from 'ajv'
|
||||
const ajv = new Ajv()
|
||||
|
||||
@@ -409,6 +409,9 @@ const definitions = {
|
||||
},
|
||||
"perDay": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"e": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -1417,6 +1420,9 @@ const definitions = {
|
||||
},
|
||||
"perDay": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"e": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -1753,6 +1759,41 @@ const definitions = {
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"SerializedPingAction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"PING"
|
||||
]
|
||||
},
|
||||
"deviceId": {
|
||||
"type": "string"
|
||||
},
|
||||
"event": {
|
||||
"$ref": "#/definitions/PingEvent"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"deviceId",
|
||||
"event",
|
||||
"token",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"PingEvent": {
|
||||
"enum": [
|
||||
"clear",
|
||||
"ping",
|
||||
"pong"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"SerializedUpdateInstalledAppsAction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1982,6 +2023,12 @@ const definitions = {
|
||||
},
|
||||
"addedManipulationFlags": {
|
||||
"type": "number"
|
||||
},
|
||||
"platformType": {
|
||||
"type": "string"
|
||||
},
|
||||
"platformLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -2164,6 +2211,12 @@ const definitions = {
|
||||
},
|
||||
"pk": {
|
||||
"type": "string"
|
||||
},
|
||||
"pType": {
|
||||
"type": "string"
|
||||
},
|
||||
"pLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -2192,6 +2245,7 @@ const definitions = {
|
||||
"model",
|
||||
"name",
|
||||
"networkTime",
|
||||
"pLevel",
|
||||
"qOrLater",
|
||||
"reboot",
|
||||
"rebootIsManipulation",
|
||||
@@ -2796,6 +2850,30 @@ const definitions = {
|
||||
"tempKey"
|
||||
]
|
||||
},
|
||||
"ServerPing": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deviceId": {
|
||||
"type": "string"
|
||||
},
|
||||
"token": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"ping",
|
||||
"pong"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"deviceId",
|
||||
"token",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
"ServerDhKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -2930,6 +3008,9 @@ export const isCreateFamilyByMailTokenRequest: (value: unknown) => value is Crea
|
||||
},
|
||||
"parentName": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -2955,6 +3036,9 @@ export const isSignIntoFamilyRequest: (value: unknown) => value is SignIntoFamil
|
||||
},
|
||||
"deviceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -2995,6 +3079,9 @@ export const isRegisterChildDeviceRequest: (value: unknown) => value is Register
|
||||
},
|
||||
"deviceName": {
|
||||
"type": "string"
|
||||
},
|
||||
"clientLevel": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@@ -3185,6 +3272,9 @@ export const isSerializedAppLogicAction: (value: unknown) => value is Serialized
|
||||
{
|
||||
"$ref": "#/definitions/SerializedMarkTaskPendingAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/SerializedPingAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/SerializedUpdateInstalledAppsAction"
|
||||
},
|
||||
@@ -3484,3 +3574,24 @@ export const isIdentityTokenPayload: (value: unknown) => value is IdentityTokenP
|
||||
"definitions": definitions,
|
||||
"$schema": "http://json-schema.org/draft-07/schema#"
|
||||
})
|
||||
export const isDeleteAccountPayload: (value: unknown) => value is DeleteAccountPayload = ajv.compile({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deviceAuthToken": {
|
||||
"type": "string"
|
||||
},
|
||||
"mailAuthTokens": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"deviceAuthToken",
|
||||
"mailAuthTokens"
|
||||
],
|
||||
"definitions": definitions,
|
||||
"$schema": "http://json-schema.org/draft-07/schema#"
|
||||
})
|
||||
|
||||
+2
-2
@@ -34,6 +34,8 @@ function parseYesNo (value: string) {
|
||||
}
|
||||
}
|
||||
|
||||
class ParseYesNoException extends Error {}
|
||||
|
||||
export const config: Config = {
|
||||
mailWhitelist: (process.env.MAIL_WHITELIST || '').split(',').map((item) => item.trim()).filter((item) => item.length > 0),
|
||||
disableSignup: parseYesNo(process.env.DISABLE_SIGNUP || 'no'),
|
||||
@@ -41,5 +43,3 @@ export const config: Config = {
|
||||
alwaysPro: process.env.ALWAYS_PRO ? parseYesNo(process.env.ALWAYS_PRO) : false,
|
||||
signSecret: process.env.SIGN_SECRET || ''
|
||||
}
|
||||
|
||||
class ParseYesNoException extends Error {}
|
||||
|
||||
+36
-3
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2023 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
|
||||
@@ -37,6 +37,12 @@ export const DeviceManipulationFlags = {
|
||||
ALL: 1
|
||||
}
|
||||
|
||||
export const minPlatformTypeLength = 1
|
||||
export const maxPlatformTypeLength = 8
|
||||
|
||||
export const minPlatformLevel = 0
|
||||
export const maxPlatformLevel = 128
|
||||
|
||||
export interface DeviceAttributesVersion1 {
|
||||
familyId: string
|
||||
deviceId: string
|
||||
@@ -119,11 +125,17 @@ export interface DeviceAttributesVersion14 {
|
||||
nextKeyReplySequenceNumber: string
|
||||
}
|
||||
|
||||
export interface DeviceAttributesVersion15 {
|
||||
platformType: string | null
|
||||
platformLevel: number
|
||||
}
|
||||
|
||||
export type DeviceAttributes = DeviceAttributesVersion1 & DeviceAttributesVersion2 &
|
||||
DeviceAttributesVersion3 & DeviceAttributesVersion4 & DeviceAttributesVersion5 &
|
||||
DeviceAttributesVersion6 & DeviceAttributesVersion7 & DeviceAttributesVersion8 &
|
||||
DeviceAttributesVersion9 & DeviceAttributesVersion10 & DeviceAttributesVersion11 &
|
||||
DeviceAttributesVersion12 & DeviceAttributesVersion13 & DeviceAttributesVersion14
|
||||
DeviceAttributesVersion12 & DeviceAttributesVersion13 & DeviceAttributesVersion14 &
|
||||
DeviceAttributesVersion15
|
||||
|
||||
export type DeviceModel = Sequelize.Model<DeviceAttributes> & DeviceAttributes
|
||||
export type DeviceModelStatic = typeof Sequelize.Model & {
|
||||
@@ -305,6 +317,26 @@ export const attributesVersion14: SequelizeAttributes<DeviceAttributesVersion14>
|
||||
}
|
||||
}
|
||||
|
||||
export const attributesVersion15: SequelizeAttributes<DeviceAttributesVersion15> = {
|
||||
platformType: {
|
||||
type: Sequelize.STRING(maxPlatformTypeLength),
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
validate: {
|
||||
len: [minPlatformTypeLength, maxPlatformTypeLength]
|
||||
}
|
||||
},
|
||||
platformLevel: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: minPlatformLevel,
|
||||
validate: {
|
||||
min: minPlatformLevel,
|
||||
max: maxPlatformLevel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const attributes: SequelizeAttributes<DeviceAttributes> = {
|
||||
...attributesVersion1,
|
||||
...attributesVersion2,
|
||||
@@ -319,7 +351,8 @@ export const attributes: SequelizeAttributes<DeviceAttributes> = {
|
||||
...attributesVersion11,
|
||||
...attributesVersion12,
|
||||
...attributesVersion13,
|
||||
...attributesVersion14
|
||||
...attributesVersion14,
|
||||
...attributesVersion15
|
||||
}
|
||||
|
||||
export const createDeviceModel = (sequelize: Sequelize.Sequelize): DeviceModelStatic => sequelize.define('Device', attributes) as DeviceModelStatic
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2024 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@@ -26,7 +26,7 @@ export const config = {
|
||||
expireTimeRounding: 1000 * 60 * 15
|
||||
}
|
||||
|
||||
export function calculateExpireTime(now: bigint): BigInt {
|
||||
export function calculateExpireTime(now: bigint): bigint {
|
||||
const expireBaseTime = now + BigInt(config.expireDelay)
|
||||
const expireTime = expireBaseTime - expireBaseTime % BigInt(config.expireTimeRounding) + BigInt(config.expireTimeRounding)
|
||||
|
||||
|
||||
+45
-10
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2026 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
|
||||
@@ -17,8 +17,6 @@
|
||||
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { AddDeviceTokenModelStatic, createAddDeviceTokenModel } from './adddevicetoken'
|
||||
import { AppModelStatic, createAppModel } from './app'
|
||||
import { AppActivityModelStatic, createAppActivityModel } from './appactivity'
|
||||
import { AuthTokenModelStatic, createAuthtokenModel } from './authtoken'
|
||||
import { CategoryModelStatic, createCategoryModel } from './category'
|
||||
import { CategoryAppModelStatic, createCategoryAppModel } from './categoryapp'
|
||||
@@ -35,6 +33,7 @@ import { createKeyResponseModel, KeyResponseModelStatic } from './keyresponse'
|
||||
import { createMailLoginTokenModel, MailLoginTokenModelStatic } from './maillogintoken'
|
||||
import { createUmzug } from './migration/umzug'
|
||||
import { createOldDeviceModel, OldDeviceModelStatic } from './olddevice'
|
||||
import { createPingModel, PingModelStatic } from './ping'
|
||||
import { createPurchaseModel, PurchaseModelStatic } from './purchase'
|
||||
import { createSessionDurationModel, SessionDurationModelStatic } from './sessionduration'
|
||||
import { createTimelimitRuleModel, TimelimitRuleModelStatic } from './timelimitrule'
|
||||
@@ -42,14 +41,13 @@ import { createU2fKeyModel, U2fKeyModelStatic } from './u2fkey'
|
||||
import { createUsedTimeModel, UsedTimeModelStatic } from './usedtime'
|
||||
import { createUserModel, UserModelStatic } from './user'
|
||||
import { createUserLimitLoginCategoryModel, UserLimitLoginCategoryModelStatic } from './userlimitlogincategory'
|
||||
import { shouldRetryWithException } from './utils/serialized'
|
||||
|
||||
export type Transaction = Sequelize.Transaction
|
||||
|
||||
export interface Database {
|
||||
addDeviceToken: AddDeviceTokenModelStatic
|
||||
authtoken: AuthTokenModelStatic
|
||||
app: AppModelStatic
|
||||
appActivity: AppActivityModelStatic
|
||||
category: CategoryModelStatic
|
||||
categoryApp: CategoryAppModelStatic
|
||||
categoryNetworkId: CategoryNetworkIdModelStatic
|
||||
@@ -64,6 +62,7 @@ export interface Database {
|
||||
keyResponse: KeyResponseModelStatic
|
||||
mailLoginToken: MailLoginTokenModelStatic
|
||||
oldDevice: OldDeviceModelStatic
|
||||
ping: PingModelStatic
|
||||
purchase: PurchaseModelStatic
|
||||
sessionDuration: SessionDurationModelStatic
|
||||
timelimitRule: TimelimitRuleModelStatic
|
||||
@@ -71,15 +70,21 @@ export interface Database {
|
||||
usedTime: UsedTimeModelStatic
|
||||
user: UserModelStatic
|
||||
userLimitLoginCategory: UserLimitLoginCategoryModelStatic
|
||||
transaction: <T> (autoCallback: (t: Transaction) => Promise<T>, options?: { transaction: Transaction }) => Promise<T>
|
||||
transaction: <T> (
|
||||
autoCallback: (t: Transaction) => Promise<T>,
|
||||
options?: TransactionOptions
|
||||
) => Promise<T>
|
||||
dialect: string
|
||||
}
|
||||
|
||||
interface TransactionOptions {
|
||||
transaction?: Transaction
|
||||
disableRetry?: boolean
|
||||
}
|
||||
|
||||
const createDatabase = (sequelize: Sequelize.Sequelize): Database => ({
|
||||
addDeviceToken: createAddDeviceTokenModel(sequelize),
|
||||
authtoken: createAuthtokenModel(sequelize),
|
||||
app: createAppModel(sequelize),
|
||||
appActivity: createAppActivityModel(sequelize),
|
||||
category: createCategoryModel(sequelize),
|
||||
categoryApp: createCategoryAppModel(sequelize),
|
||||
childTask: createChildTaskModel(sequelize),
|
||||
@@ -94,6 +99,7 @@ const createDatabase = (sequelize: Sequelize.Sequelize): Database => ({
|
||||
keyResponse: createKeyResponseModel(sequelize),
|
||||
mailLoginToken: createMailLoginTokenModel(sequelize),
|
||||
oldDevice: createOldDeviceModel(sequelize),
|
||||
ping: createPingModel(sequelize),
|
||||
purchase: createPurchaseModel(sequelize),
|
||||
sessionDuration: createSessionDurationModel(sequelize),
|
||||
timelimitRule: createTimelimitRuleModel(sequelize),
|
||||
@@ -101,10 +107,39 @@ const createDatabase = (sequelize: Sequelize.Sequelize): Database => ({
|
||||
usedTime: createUsedTimeModel(sequelize),
|
||||
user: createUserModel(sequelize),
|
||||
userLimitLoginCategory: createUserLimitLoginCategoryModel(sequelize),
|
||||
transaction: <T> (autoCallback: (transaction: Transaction) => Promise<T>, options?: { transaction: Transaction }) => (sequelize.transaction({
|
||||
async transaction<T>(
|
||||
autoCallback: (transaction: Transaction) => Promise<T>,
|
||||
options?: TransactionOptions
|
||||
): Promise<T> {
|
||||
const runAttempt = () => sequelize.transaction({
|
||||
isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE,
|
||||
transaction: options?.transaction
|
||||
}, autoCallback)) as Promise<T>,
|
||||
}, autoCallback)
|
||||
|
||||
const delay = (time: number) => new Promise((resolve) => setTimeout(resolve, time))
|
||||
|
||||
try {
|
||||
return await runAttempt()
|
||||
} catch (ex) {
|
||||
if (
|
||||
options?.disableRetry ||
|
||||
options?.transaction ||
|
||||
!shouldRetryWithException(this, ex)
|
||||
) throw ex
|
||||
}
|
||||
|
||||
await delay(10 * (1 + Math.random()))
|
||||
|
||||
try {
|
||||
return await runAttempt()
|
||||
} catch (ex) {
|
||||
if (!shouldRetryWithException(this, ex)) throw ex
|
||||
}
|
||||
|
||||
await delay(100 * (1 + Math.random()))
|
||||
|
||||
return await runAttempt()
|
||||
},
|
||||
dialect: sequelize.getDialect()
|
||||
})
|
||||
|
||||
|
||||
+10
-19
@@ -15,26 +15,17 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { RemoveInstalledAppsAction } from '../../../../action'
|
||||
import { Cache } from '../cache'
|
||||
import { QueryInterface, Sequelize, Transaction } from 'sequelize'
|
||||
|
||||
export async function dispatchRemoveInstalledApps ({ deviceId, action, cache }: {
|
||||
deviceId: string
|
||||
action: RemoveInstalledAppsAction
|
||||
cache: Cache
|
||||
}) {
|
||||
await cache.database.app.destroy({
|
||||
where: {
|
||||
familyId: cache.familyId,
|
||||
deviceId,
|
||||
packageName: {
|
||||
[Sequelize.Op.in]: action.packageNames
|
||||
}
|
||||
},
|
||||
transaction: cache.transaction
|
||||
export async function up (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
await queryInterface.dropTable('Apps', { transaction })
|
||||
await queryInterface.dropTable('AppActivities', { transaction })
|
||||
})
|
||||
}
|
||||
|
||||
cache.devicesWithModifiedInstalledApps.add(deviceId)
|
||||
cache.incrementTriggeredSyncLevel(1)
|
||||
export async function down() {
|
||||
throw new Error('not possible')
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2023 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 { attributesVersion15 as deviceAttributes } from '../../device'
|
||||
|
||||
export async function up (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
await queryInterface.addColumn('Devices', 'platformType', {
|
||||
...deviceAttributes.platformType
|
||||
}, {
|
||||
transaction
|
||||
})
|
||||
|
||||
await queryInterface.addColumn('Devices', 'platformLevel', {
|
||||
...deviceAttributes.platformLevel
|
||||
}, {
|
||||
transaction
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function down (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
await queryInterface.removeColumn('Devices', 'platformLevel', { transaction })
|
||||
await queryInterface.removeColumn('Devices', 'platformType', { transaction })
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2024 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { QueryInterface, Sequelize, Transaction } from 'sequelize'
|
||||
import { attributesVersion4 as ruleAttributes } from '../../timelimitrule'
|
||||
|
||||
export async function up (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
await queryInterface.addColumn('TimelimitRules', 'expiresAt', {
|
||||
...ruleAttributes.expiresAt
|
||||
}, {
|
||||
transaction
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function down (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
await queryInterface.removeColumn('TimelimitRules', 'expiresAt', { transaction })
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2026 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'
|
||||
|
||||
export async function up (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
const dialect = sequelize.getDialect()
|
||||
const isMysql = dialect === 'mysql' || dialect === 'mariadb'
|
||||
|
||||
if (isMysql) {
|
||||
await sequelize.query(
|
||||
'CREATE TABLE `Pings` ' +
|
||||
'(`familyId` VARCHAR(10) NOT NULL,' +
|
||||
'`receiverDeviceId` VARCHAR(6) NOT NULL,' +
|
||||
'`senderDeviceId` VARCHAR(6) NOT NULL,' +
|
||||
'`type` INTEGER NOT NULL,' +
|
||||
'`token` VARCHAR(6) NOT NULL,' +
|
||||
'PRIMARY KEY (`familyId`, `receiverDeviceId`, `senderDeviceId`, `type`),' +
|
||||
'FOREIGN KEY (`familyId`, `receiverDeviceId`) REFERENCES `Devices` (`familyId`, `deviceId`) ON UPDATE CASCADE ON DELETE CASCADE,' +
|
||||
'FOREIGN KEY (`familyId`, `senderDeviceId`) REFERENCES `Devices` (`familyId`, `deviceId`) ON UPDATE CASCADE ON DELETE CASCADE' +
|
||||
')',
|
||||
{ transaction }
|
||||
)
|
||||
} else {
|
||||
await sequelize.query(
|
||||
'CREATE TABLE "Pings" ' +
|
||||
'("familyId" VARCHAR(10) NOT NULL,' +
|
||||
'"receiverDeviceId" VARCHAR(6) NOT NULL,' +
|
||||
'"senderDeviceId" VARCHAR(6) NOT NULL,' +
|
||||
'"type" INTEGER NOT NULL,' +
|
||||
'"token" VARCHAR(6) NOT NULL,' +
|
||||
'PRIMARY KEY ("familyId", "receiverDeviceId", "senderDeviceId", "type"),' +
|
||||
'FOREIGN KEY ("familyId", "receiverDeviceId") REFERENCES "Devices" ("familyId", "deviceId") ON UPDATE CASCADE ON DELETE CASCADE,' +
|
||||
'FOREIGN KEY ("familyId", "senderDeviceId") REFERENCES "Devices" ("familyId", "deviceId") ON UPDATE CASCADE ON DELETE CASCADE' +
|
||||
')',
|
||||
{ transaction }
|
||||
)
|
||||
}
|
||||
|
||||
await queryInterface.addIndex('Pings', ['familyId', 'senderDeviceId'], { transaction })
|
||||
})
|
||||
}
|
||||
|
||||
export async function down (queryInterface: QueryInterface, sequelize: Sequelize) {
|
||||
await sequelize.transaction({
|
||||
type: Transaction.TYPES.EXCLUSIVE
|
||||
}, async (transaction) => {
|
||||
await queryInterface.dropTable('Pings', { transaction })
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2026 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
|
||||
@@ -17,18 +17,26 @@
|
||||
|
||||
import { resolve } from 'path'
|
||||
import { Sequelize } from 'sequelize'
|
||||
import * as Umzug from 'umzug'
|
||||
import { Umzug, SequelizeStorage } from 'umzug'
|
||||
|
||||
export const createUmzug = (sequelize: Sequelize) => (
|
||||
new Umzug({
|
||||
storage: 'sequelize',
|
||||
storageOptions: {
|
||||
sequelize
|
||||
},
|
||||
storage: new SequelizeStorage({ sequelize }),
|
||||
migrations: {
|
||||
params: [sequelize.getQueryInterface(), sequelize],
|
||||
path: resolve(__dirname, '../../../build/database/migration/migrations'),
|
||||
pattern: /^\d+[\w-]+\.js$/
|
||||
glob: resolve(__dirname, '../../../build/database/migration/migrations/*.js'),
|
||||
resolve: ({ name, path }) => {
|
||||
if (!path) throw new Error()
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const migration = require(path)
|
||||
|
||||
return {
|
||||
name,
|
||||
up: async () => migration.up(sequelize.getQueryInterface(), sequelize),
|
||||
down: async () => migration.down(sequelize.getQueryInterface(), sequelize),
|
||||
}
|
||||
},
|
||||
},
|
||||
logger: console
|
||||
})
|
||||
)
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2026 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 * as Sequelize from 'sequelize'
|
||||
import { familyIdColumn, idWithinFamilyColumn } from './columns'
|
||||
import { SequelizeAttributes } from './types'
|
||||
|
||||
export interface PingAttributes {
|
||||
familyId: string
|
||||
receiverDeviceId: string
|
||||
senderDeviceId: string
|
||||
type: number
|
||||
token: string
|
||||
}
|
||||
|
||||
export const types = {
|
||||
ping: 1,
|
||||
pong: 2,
|
||||
all: [1, 2]
|
||||
}
|
||||
|
||||
export type PingModel = Sequelize.Model<PingAttributes> & PingAttributes
|
||||
export type PingModelStatic = typeof Sequelize.Model & {
|
||||
new (values?: object, options?: Sequelize.BuildOptions): PingModel;
|
||||
}
|
||||
|
||||
export const attributes: SequelizeAttributes<PingAttributes> = {
|
||||
familyId: {
|
||||
...familyIdColumn,
|
||||
primaryKey: true
|
||||
},
|
||||
receiverDeviceId: {
|
||||
...idWithinFamilyColumn,
|
||||
primaryKey: true
|
||||
},
|
||||
senderDeviceId: {
|
||||
...idWithinFamilyColumn,
|
||||
primaryKey: true
|
||||
},
|
||||
type: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
validate: {
|
||||
isIn: [types.all]
|
||||
},
|
||||
primaryKey: true
|
||||
},
|
||||
token: {
|
||||
...idWithinFamilyColumn
|
||||
}
|
||||
}
|
||||
|
||||
export const createPingModel = (sequelize: Sequelize.Sequelize): PingModelStatic => sequelize.define('Ping', attributes) as PingModelStatic
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2021 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2024 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@@ -41,8 +41,13 @@ interface TimelimitRuleAttributesVersion3 {
|
||||
perDay: number
|
||||
}
|
||||
|
||||
interface TimelimitRuleAttributesVersion4 {
|
||||
expiresAt: string | null
|
||||
}
|
||||
|
||||
type TimelimitRuleAttributes = TimelimitRuleAttributesVersion1 &
|
||||
TimelimitRuleAttributesVersion2 & TimelimitRuleAttributesVersion3
|
||||
TimelimitRuleAttributesVersion2 & TimelimitRuleAttributesVersion3 &
|
||||
TimelimitRuleAttributesVersion4
|
||||
|
||||
export type TimelimitRuleModel = Sequelize.Model<TimelimitRuleAttributes> & TimelimitRuleAttributes
|
||||
export type TimelimitRuleModelStatic = typeof Sequelize.Model & {
|
||||
@@ -137,10 +142,22 @@ export const attributesVersion3: SequelizeAttributes<TimelimitRuleAttributesVers
|
||||
}
|
||||
}
|
||||
|
||||
export const attributesVersion4: SequelizeAttributes<TimelimitRuleAttributesVersion4> = {
|
||||
expiresAt: {
|
||||
type: Sequelize.BIGINT,
|
||||
validate: {
|
||||
min: 1
|
||||
},
|
||||
allowNull: true,
|
||||
defaultValue: null
|
||||
}
|
||||
}
|
||||
|
||||
export const attributes: SequelizeAttributes<TimelimitRuleAttributes> = {
|
||||
...attributesVersion1,
|
||||
...attributesVersion2,
|
||||
...attributesVersion3
|
||||
...attributesVersion3,
|
||||
...attributesVersion4
|
||||
}
|
||||
|
||||
export const createTimelimitRuleModel = (sequelize: Sequelize.Sequelize): TimelimitRuleModelStatic => sequelize.define('TimelimitRule', attributes) as TimelimitRuleModelStatic
|
||||
|
||||
@@ -86,8 +86,8 @@ export async function assertSerializeableTransactionsAreWorking (database: Datab
|
||||
await database.config.update({ value: 'd' }, { where: { id: configItemIds.secondSelfTestData }, transaction: transactionTwo })
|
||||
})()
|
||||
])
|
||||
})
|
||||
})
|
||||
}, { disableRetry: true })
|
||||
}, { disableRetry: true })
|
||||
|
||||
throw new SerializationFeatureCheckException()
|
||||
} catch (ex) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2021 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2023 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
|
||||
@@ -109,7 +109,7 @@ export const signInByMailCode = async ({ mailLoginToken, receivedCode, database
|
||||
database: Database
|
||||
// no transaction here because this is directly called from an API endpoint
|
||||
}): Promise<{ mailAuthToken: string }> => {
|
||||
return database.transaction(async (transaction) => {
|
||||
const result = await database.transaction(async (transaction) => {
|
||||
const entry = await database.mailLoginToken.findOne({
|
||||
where: {
|
||||
mailLoginToken
|
||||
@@ -127,9 +127,9 @@ export const signInByMailCode = async ({ mailLoginToken, receivedCode, database
|
||||
await entry.save({ transaction })
|
||||
|
||||
if (entry.remainingAttempts === 0) {
|
||||
throw new Gone()
|
||||
return () => { throw new Gone() }
|
||||
} else {
|
||||
throw new Forbidden()
|
||||
return () => { throw new Forbidden() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +151,8 @@ export const signInByMailCode = async ({ mailLoginToken, receivedCode, database
|
||||
transaction
|
||||
})
|
||||
|
||||
return { mailAuthToken }
|
||||
return () => ({ mailAuthToken })
|
||||
})
|
||||
|
||||
return result()
|
||||
}
|
||||
|
||||
@@ -22,13 +22,22 @@ import { generateAuthToken, generateVersionId } from '../../util/token'
|
||||
import { WebsocketApi } from '../../websocket'
|
||||
import { prepareDeviceEntry } from '../device/prepare-device-entry'
|
||||
import { notifyClientsAboutChangesDelayed } from '../websocket'
|
||||
import { generateServerDataStatus } from '../sync/get-server-data-status'
|
||||
import { EventHandler } from '../../monitoring/eventhandler'
|
||||
import { ServerDataStatus } from '../../object/serverdatastatus'
|
||||
import { createEmptyClientDataStatus } from '../../object/clientdatastatus'
|
||||
|
||||
export const addChildDevice = async ({ database, websocket, request }: {
|
||||
export const addChildDevice = async ({ database, eventHandler, websocket, request }: {
|
||||
database: Database
|
||||
eventHandler: EventHandler
|
||||
websocket: WebsocketApi
|
||||
request: RegisterChildDeviceRequest
|
||||
// no transaction here because this is directly called from an API endpoint
|
||||
}) => {
|
||||
}): Promise<{
|
||||
deviceId: string
|
||||
deviceAuthToken: string
|
||||
data: ServerDataStatus
|
||||
}> => {
|
||||
return database.transaction(async (transaction) => {
|
||||
const entry = await database.addDeviceToken.findOne({
|
||||
where: {
|
||||
@@ -75,9 +84,19 @@ export const addChildDevice = async ({ database, websocket, request }: {
|
||||
transaction
|
||||
})
|
||||
|
||||
const data = await generateServerDataStatus({
|
||||
database,
|
||||
clientStatus: createEmptyClientDataStatus({ clientLevel: request.clientLevel || null }),
|
||||
familyId: entry.familyId,
|
||||
deviceId,
|
||||
transaction,
|
||||
eventHandler
|
||||
})
|
||||
|
||||
return {
|
||||
deviceId,
|
||||
deviceAuthToken
|
||||
deviceAuthToken,
|
||||
data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2023 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 { Unauthorized } from 'http-errors'
|
||||
import { DeleteAccountPayload } from '../../api/schema'
|
||||
import { Database } from '../../database'
|
||||
import { sendAccountDeletedMail } from '../../util/mail'
|
||||
import { WebsocketApi } from '../../websocket'
|
||||
import { requireMailAndLocaleByAuthToken } from '../authentication'
|
||||
import { deleteFamilies } from './delete-families'
|
||||
|
||||
export async function deleteAccount({ request, database, websocket }: {
|
||||
request: DeleteAccountPayload
|
||||
database: Database
|
||||
websocket: WebsocketApi
|
||||
}) {
|
||||
await database.transaction(async (transaction) => {
|
||||
const deviceEntryUnsafe = await database.device.findOne({
|
||||
where: { deviceAuthToken: request.deviceAuthToken },
|
||||
attributes: ['familyId'],
|
||||
transaction
|
||||
})
|
||||
|
||||
if (!deviceEntryUnsafe) {
|
||||
throw new Unauthorized()
|
||||
}
|
||||
|
||||
const deviceEntry = {
|
||||
familyId: deviceEntryUnsafe.familyId
|
||||
}
|
||||
|
||||
const userEntries = (await database.user.findAll({
|
||||
where: {
|
||||
familyId: deviceEntry.familyId,
|
||||
type: 'parent'
|
||||
},
|
||||
attributes: ['mail'],
|
||||
transaction
|
||||
})).map((item) => ({ mail: item.mail }))
|
||||
|
||||
const registeredMailAddresses = new Set<string>()
|
||||
|
||||
userEntries.forEach((item) => {
|
||||
if (item.mail !== '') registeredMailAddresses.add(item.mail)
|
||||
})
|
||||
|
||||
const authenticatedMailAddresses = new Set<string>()
|
||||
|
||||
for (const mailAuthToken of request.mailAuthTokens) {
|
||||
const info = await requireMailAndLocaleByAuthToken({
|
||||
mailAuthToken,
|
||||
database,
|
||||
transaction,
|
||||
invalidate: true
|
||||
})
|
||||
|
||||
if (!registeredMailAddresses.has(info.mail)) throw new Unauthorized()
|
||||
|
||||
authenticatedMailAddresses.add(info.mail)
|
||||
}
|
||||
|
||||
if (registeredMailAddresses.size !== authenticatedMailAddresses.size) throw new Unauthorized()
|
||||
|
||||
registeredMailAddresses.forEach((mail) => {
|
||||
if (!authenticatedMailAddresses.has(mail)) throw new Unauthorized()
|
||||
})
|
||||
|
||||
const deviceEntries = (await database.device.findAll({
|
||||
where: {
|
||||
familyId: deviceEntry.familyId
|
||||
},
|
||||
transaction,
|
||||
attributes: ['deviceAuthToken']
|
||||
})).map((item) => ({ deviceAuthToken: item.deviceAuthToken }))
|
||||
|
||||
await deleteFamilies({ database, transaction, familiyIds: [deviceEntry.familyId] })
|
||||
|
||||
transaction.afterCommit(() => {
|
||||
for (const device of deviceEntries) {
|
||||
websocket.triggerSyncByDeviceAuthToken({
|
||||
deviceAuthToken: device.deviceAuthToken,
|
||||
isImportant: true
|
||||
})
|
||||
}
|
||||
|
||||
registeredMailAddresses.forEach((receiver) => {
|
||||
sendAccountDeletedMail({ receiver }).catch((ex) => {
|
||||
console.warn('failure while sending account deletion confirmation', ex)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2020 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2023 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
|
||||
@@ -17,10 +17,11 @@
|
||||
|
||||
import { difference } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { Database } from '../../database'
|
||||
import { Database, Transaction } from '../../database'
|
||||
|
||||
export async function deleteFamilies ({ database, familiyIds }: {
|
||||
export async function deleteFamilies ({ database, transaction, familiyIds }: {
|
||||
database: Database
|
||||
transaction: Transaction
|
||||
familiyIds: Array<string>
|
||||
// no transaction here because this should run isolated
|
||||
}) {
|
||||
@@ -28,27 +29,6 @@ export async function deleteFamilies ({ database, familiyIds }: {
|
||||
return
|
||||
}
|
||||
|
||||
await database.transaction(async (transaction) => {
|
||||
// app
|
||||
await database.app.destroy({
|
||||
where: {
|
||||
familyId: {
|
||||
[Sequelize.Op.in]: familiyIds
|
||||
}
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
// app activity
|
||||
await database.appActivity.destroy({
|
||||
where: {
|
||||
familyId: {
|
||||
[Sequelize.Op.in]: familiyIds
|
||||
}
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
// category
|
||||
await database.category.destroy({
|
||||
where: {
|
||||
@@ -99,6 +79,16 @@ export async function deleteFamilies ({ database, familiyIds }: {
|
||||
transaction
|
||||
})
|
||||
|
||||
// session durations
|
||||
await database.sessionDuration.destroy({
|
||||
where: {
|
||||
familyId: {
|
||||
[Sequelize.Op.in]: familiyIds
|
||||
}
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
// user
|
||||
await database.user.destroy({
|
||||
where: {
|
||||
@@ -161,5 +151,4 @@ export async function deleteFamilies ({ database, familiyIds }: {
|
||||
},
|
||||
transaction
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2020 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2023 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
|
||||
@@ -26,10 +26,13 @@ export async function deleteOldFamilies (database: Database) {
|
||||
if (oldFamilyIds.length > 0) {
|
||||
const familyIdsToDelete = oldFamilyIds.slice(0, 256) /* limit to 256 families per execution */
|
||||
|
||||
await database.transaction(async (transaction) => {
|
||||
await deleteFamilies({
|
||||
database,
|
||||
transaction,
|
||||
familiyIds: familyIdsToDelete
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2023 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
|
||||
@@ -66,5 +66,7 @@ export const prepareDeviceEntry = ({ familyId, userId, deviceAuthToken, deviceId
|
||||
isQorLater: false,
|
||||
manipulationFlags: 0,
|
||||
publicKey: null,
|
||||
nextKeyReplySequenceNumber: '1'
|
||||
nextKeyReplySequenceNumber: '1',
|
||||
platformType: null,
|
||||
platformLevel: 0
|
||||
})
|
||||
|
||||
@@ -40,23 +40,6 @@ export async function removeDevice ({ database, familyId, deviceId, websocket, t
|
||||
throw new Conflict()
|
||||
}
|
||||
|
||||
// remove app entries
|
||||
await database.app.destroy({
|
||||
where: {
|
||||
familyId,
|
||||
deviceId
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
await database.appActivity.destroy({
|
||||
where: {
|
||||
familyId,
|
||||
deviceId
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
// remove as current device
|
||||
await database.user.update({
|
||||
currentDevice: ''
|
||||
|
||||
@@ -16,25 +16,38 @@
|
||||
*/
|
||||
|
||||
import { Conflict } from 'http-errors'
|
||||
import { generateServerDataStatus } from '../sync/get-server-data-status'
|
||||
import { NewDeviceInfo, PlaintextParentPassword, assertPlaintextParentPasswordValid } from '../../api/schema'
|
||||
import { Database } from '../../database'
|
||||
import { maxMailNotificationFlags } from '../../database/user'
|
||||
import { EventHandler } from '../../monitoring/eventhandler'
|
||||
import { ServerDataStatus } from '../../object/serverdatastatus'
|
||||
import { createEmptyClientDataStatus } from '../../object/clientdatastatus'
|
||||
import {
|
||||
generateAuthToken, generateFamilyId, generateIdWithinFamily, generateVersionId
|
||||
} from '../../util/token'
|
||||
import { requireMailAndLocaleByAuthToken } from '../authentication'
|
||||
import { prepareDeviceEntry } from '../device/prepare-device-entry'
|
||||
|
||||
export const createFamily = async ({ database, mailAuthToken, firstParentDevice, password, timeZone, parentName, deviceName }: {
|
||||
database: Database,
|
||||
mailAuthToken: string,
|
||||
firstParentDevice: NewDeviceInfo,
|
||||
password: PlaintextParentPassword,
|
||||
timeZone: string,
|
||||
parentName: string,
|
||||
export async function createFamily ({
|
||||
database, eventHandler, mailAuthToken, firstParentDevice,
|
||||
password, timeZone, parentName, deviceName, clientLevel
|
||||
}: {
|
||||
database: Database
|
||||
eventHandler: EventHandler
|
||||
mailAuthToken: string
|
||||
firstParentDevice: NewDeviceInfo
|
||||
password: PlaintextParentPassword
|
||||
timeZone: string
|
||||
parentName: string
|
||||
deviceName: string
|
||||
clientLevel: number | null
|
||||
// no transaction here because this is directly called from an API endpoint
|
||||
}) => {
|
||||
}): Promise<{
|
||||
deviceAuthToken: string
|
||||
deviceId: string
|
||||
data: ServerDataStatus
|
||||
}> {
|
||||
assertPlaintextParentPasswordValid(password)
|
||||
|
||||
return database.transaction(async (transaction) => {
|
||||
@@ -42,14 +55,14 @@ export const createFamily = async ({ database, mailAuthToken, firstParentDevice,
|
||||
const mailInfo = await requireMailAndLocaleByAuthToken({ database, mailAuthToken, transaction, invalidate: true })
|
||||
|
||||
// ensure that no family was created for this mail yet
|
||||
const exisitngUserEntry = await database.user.findOne({
|
||||
const existingUserEntry = await database.user.findOne({
|
||||
where: {
|
||||
mail: mailInfo.mail
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
if (exisitngUserEntry) {
|
||||
if (existingUserEntry) {
|
||||
throw new Conflict()
|
||||
}
|
||||
|
||||
@@ -103,9 +116,19 @@ export const createFamily = async ({ database, mailAuthToken, firstParentDevice,
|
||||
isUserKeptSignedIn: true
|
||||
}), { transaction })
|
||||
|
||||
const data = await generateServerDataStatus({
|
||||
database,
|
||||
clientStatus: createEmptyClientDataStatus({ clientLevel }),
|
||||
familyId,
|
||||
deviceId,
|
||||
transaction,
|
||||
eventHandler
|
||||
})
|
||||
|
||||
return {
|
||||
deviceAuthToken,
|
||||
deviceId
|
||||
deviceId,
|
||||
data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,15 +24,21 @@ import { WebsocketApi } from '../../websocket'
|
||||
import { requireMailAndLocaleByAuthToken } from '../authentication'
|
||||
import { prepareDeviceEntry } from '../device/prepare-device-entry'
|
||||
import { notifyClientsAboutChangesDelayed } from '../websocket'
|
||||
import { generateServerDataStatus } from '../sync/get-server-data-status'
|
||||
import { EventHandler } from '../../monitoring/eventhandler'
|
||||
import { ServerDataStatus } from '../../object/serverdatastatus'
|
||||
import { createEmptyClientDataStatus } from '../../object/clientdatastatus'
|
||||
|
||||
export const signInIntoFamily = async ({ database, mailAuthToken, newDeviceInfo, deviceName, websocket }: {
|
||||
export const signInIntoFamily = async ({ database, eventHandler, mailAuthToken, newDeviceInfo, deviceName, websocket, clientLevel }: {
|
||||
database: Database
|
||||
eventHandler: EventHandler
|
||||
mailAuthToken: string
|
||||
newDeviceInfo: NewDeviceInfo
|
||||
deviceName: string
|
||||
websocket: WebsocketApi
|
||||
clientLevel: number | null
|
||||
// no transaction here because this is directly called from an API endpoint
|
||||
}): Promise<{ deviceId: string; deviceAuthToken: string }> => {
|
||||
}): Promise<{ deviceId: string; deviceAuthToken: string; data: ServerDataStatus }> => {
|
||||
return database.transaction(async (transaction) => {
|
||||
const mailInfo = await requireMailAndLocaleByAuthToken({ database, mailAuthToken, transaction, invalidate: true })
|
||||
|
||||
@@ -94,9 +100,19 @@ export const signInIntoFamily = async ({ database, mailAuthToken, newDeviceInfo,
|
||||
})
|
||||
})
|
||||
|
||||
const data = await generateServerDataStatus({
|
||||
database,
|
||||
clientStatus: createEmptyClientDataStatus({ clientLevel }),
|
||||
familyId: userEntry.familyId,
|
||||
deviceId,
|
||||
transaction,
|
||||
eventHandler
|
||||
})
|
||||
|
||||
return {
|
||||
deviceId,
|
||||
deviceAuthToken
|
||||
deviceAuthToken,
|
||||
data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ export class Cache {
|
||||
categoriesWithModifiedUsedTimes = new Set<string>()
|
||||
categoriesWithModifiedTasks = new Set<string>()
|
||||
|
||||
devicesWithModifiedInstalledApps = new Set<string>()
|
||||
devicesWithModifiedShowDeviceConnected = new Map<string, boolean>()
|
||||
|
||||
invalidiateUserList = false
|
||||
@@ -241,22 +240,6 @@ export class Cache {
|
||||
this.categoriesWithModifiedUsedTimes.clear()
|
||||
}
|
||||
|
||||
if (this.devicesWithModifiedInstalledApps.size > 0) {
|
||||
await database.device.update({
|
||||
installedAppsVersion: generateVersionId()
|
||||
}, {
|
||||
where: {
|
||||
familyId,
|
||||
deviceId: {
|
||||
[Sequelize.Op.in]: setToList(this.devicesWithModifiedInstalledApps)
|
||||
}
|
||||
},
|
||||
transaction
|
||||
})
|
||||
|
||||
this.devicesWithModifiedInstalledApps.clear()
|
||||
}
|
||||
|
||||
if (this.invalidiateUserList) {
|
||||
await database.family.update({
|
||||
userListVersion: generateVersionId()
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 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 * as Sequelize from 'sequelize'
|
||||
import { AddInstalledAppsAction } from '../../../../action'
|
||||
import { AppAttributes, maxPackageNameLength } from '../../../../database/app'
|
||||
import { Cache } from '../cache'
|
||||
import { ApplyActionException } from '../exception'
|
||||
|
||||
export async function dispatchAddInstalledApps ({ deviceId, action, cache }: {
|
||||
deviceId: string
|
||||
action: AddInstalledAppsAction
|
||||
cache: Cache
|
||||
}) {
|
||||
action.apps.forEach((app) => {
|
||||
if (app.packageName.length > maxPackageNameLength) {
|
||||
throw new ApplyActionException({
|
||||
staticMessage: 'package name too long',
|
||||
dynamicMessage: 'package name too long: ' + app.packageName
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
await cache.database.app.destroy({
|
||||
where: {
|
||||
familyId: cache.familyId,
|
||||
deviceId,
|
||||
packageName: {
|
||||
[Sequelize.Op.in]: action.apps.map((app) => app.packageName)
|
||||
}
|
||||
},
|
||||
transaction: cache.transaction
|
||||
})
|
||||
|
||||
await cache.database.app.bulkCreate(
|
||||
action.apps.map((app): AppAttributes => ({
|
||||
familyId: cache.familyId,
|
||||
deviceId,
|
||||
packageName: app.packageName,
|
||||
title: app.title,
|
||||
isLaunchable: app.isLaunchable,
|
||||
recommendation: app.recommendation
|
||||
})),
|
||||
{ transaction: cache.transaction }
|
||||
)
|
||||
|
||||
cache.devicesWithModifiedInstalledApps.add(deviceId)
|
||||
cache.incrementTriggeredSyncLevel(1)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2026 Jonas Lochmann
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
@@ -15,6 +15,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { AddUsedTimeActionVersion2 } from '../../../../action'
|
||||
import { EventHandler } from '../../../../monitoring/eventhandler'
|
||||
import { MinuteOfDay } from '../../../../util/minuteofday'
|
||||
@@ -22,6 +23,8 @@ import { Cache } from '../cache'
|
||||
import { IllegalStateException, SourceDeviceNotFoundException } from '../exception/illegal-state'
|
||||
import { getRoundedTimestamp as getRoundedTimestampForUsedTime } from './addusedtime'
|
||||
|
||||
const tolerance = 5 * 1000 // 5 seconds
|
||||
|
||||
export const getRoundedTimestampForSessionDuration = () => {
|
||||
const now = Date.now()
|
||||
|
||||
@@ -86,7 +89,6 @@ export async function dispatchAddUsedTimeVersion2 ({ deviceId, action, cache, ev
|
||||
addUsedTimeForADifferentUserThanTheCurrentUserOfTheDevice = true
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-inner-declarations
|
||||
async function handle (start: number, end: number) {
|
||||
const lengthInMinutes = (end - start) + 1
|
||||
const lengthInMs = lengthInMinutes * 1000 * 60
|
||||
@@ -129,11 +131,32 @@ export async function dispatchAddUsedTimeVersion2 ({ deviceId, action, cache, ev
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const oldTime: number | null = await cache.database.usedTime.aggregate(
|
||||
'usedTime',
|
||||
'MAX',
|
||||
{
|
||||
where: {
|
||||
familyId: cache.familyId,
|
||||
categoryId: item.categoryId,
|
||||
dayOfEpoch: action.dayOfEpoch,
|
||||
startMinuteOfDay: {
|
||||
[Sequelize.Op.gte]: start
|
||||
},
|
||||
endMinuteOfDay: {
|
||||
[Sequelize.Op.lte]: end
|
||||
}
|
||||
},
|
||||
transaction: cache.transaction
|
||||
}
|
||||
) || 0
|
||||
|
||||
if (oldTime !== null && typeof oldTime !== 'number') throw new Error()
|
||||
|
||||
await cache.database.usedTime.create({
|
||||
familyId: cache.familyId,
|
||||
categoryId: item.categoryId,
|
||||
dayOfEpoch: action.dayOfEpoch,
|
||||
usedTime: Math.max(0, Math.min(item.timeToAdd, lengthInMs)),
|
||||
usedTime: Math.max(0, Math.min(oldTime + item.timeToAdd, lengthInMs)),
|
||||
lastUpdate: roundedTimestampForUsedTime,
|
||||
startMinuteOfDay: start,
|
||||
endMinuteOfDay: end
|
||||
@@ -168,6 +191,39 @@ export async function dispatchAddUsedTimeVersion2 ({ deviceId, action, cache, ev
|
||||
transaction: cache.transaction
|
||||
})
|
||||
|
||||
const oldDuration: () => Promise<number> = async () => {
|
||||
const fittingDurationItems = await cache.database.sessionDuration.findAll({
|
||||
where: {
|
||||
familyId: cache.familyId,
|
||||
categoryId: item.categoryId,
|
||||
startMinuteOfDay: {
|
||||
[Sequelize.Op.gte]: limit.start
|
||||
},
|
||||
endMinuteOfDay: {
|
||||
[Sequelize.Op.lte]: limit.end
|
||||
},
|
||||
maxSessionDuration: {
|
||||
[Sequelize.Op.gte]: limit.duration
|
||||
},
|
||||
sessionPauseDuration: {
|
||||
[Sequelize.Op.lte]: limit.pause
|
||||
}
|
||||
},
|
||||
transaction: cache.transaction
|
||||
})
|
||||
|
||||
const fittingDurationItemsLastUsageFiltered =
|
||||
hasTrustedTimestamp ?
|
||||
fittingDurationItems.filter((it) => (
|
||||
action.trustedTimestamp - item.timeToAdd <=
|
||||
parseInt(it.lastUsage, 10) + it.sessionPauseDuration - tolerance
|
||||
)) : fittingDurationItems
|
||||
|
||||
return fittingDurationItemsLastUsageFiltered
|
||||
.map((it) => it.lastSessionDuration)
|
||||
.reduce((a, b) => Math.max(a, b), 0)
|
||||
}
|
||||
|
||||
if (oldItem) {
|
||||
let extendSession: boolean
|
||||
|
||||
@@ -188,14 +244,13 @@ export async function dispatchAddUsedTimeVersion2 ({ deviceId, action, cache, ev
|
||||
* Due to this, a session is reset if it would be over in a few seconds, too.
|
||||
*/
|
||||
|
||||
const tolerance = 5 * 1000 // 5 seconds
|
||||
const timeWhenStartingCurrentUsage = action.trustedTimestamp - item.timeToAdd
|
||||
const nextSessionStart = parseInt(oldItem.lastUsage, 10) + oldItem.sessionPauseDuration - tolerance
|
||||
|
||||
extendSession = timeWhenStartingCurrentUsage <= nextSessionStart
|
||||
}
|
||||
|
||||
oldItem.lastSessionDuration = extendSession ? oldItem.lastSessionDuration + item.timeToAdd : item.timeToAdd
|
||||
oldItem.lastSessionDuration = extendSession ? oldItem.lastSessionDuration + item.timeToAdd : await oldDuration() + item.timeToAdd
|
||||
oldItem.roundedLastUpdate = roundedTimestampForSessionDuration
|
||||
|
||||
if (hasTrustedTimestamp) {
|
||||
@@ -215,7 +270,7 @@ export async function dispatchAddUsedTimeVersion2 ({ deviceId, action, cache, ev
|
||||
endMinuteOfDay: limit.end,
|
||||
// end of primary key
|
||||
lastUsage: action.trustedTimestamp.toString(10),
|
||||
lastSessionDuration: item.timeToAdd,
|
||||
lastSessionDuration: await oldDuration() + item.timeToAdd,
|
||||
roundedLastUpdate: roundedTimestampForSessionDuration
|
||||
}, { transaction: cache.transaction })
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 Jonas Lochmann
|
||||
* Copyright (C) 2019 - 2026 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
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
FinishKeyRequestAction,
|
||||
ForceSyncAction,
|
||||
MarkTaskPendingAction,
|
||||
PingAction,
|
||||
ReplyToKeyRequestAction,
|
||||
RemoveInstalledAppsAction,
|
||||
SendKeyRequestAction,
|
||||
@@ -36,18 +37,16 @@ import {
|
||||
import { EventHandler } from '../../../../monitoring/eventhandler'
|
||||
import { Cache } from '../cache'
|
||||
import { ActionObjectTypeNotHandledException } from '../exception/illegal-state'
|
||||
import { dispatchAddInstalledApps } from './addinstalledapps'
|
||||
import { dispatchAddUsedTime } from './addusedtime'
|
||||
import { dispatchAddUsedTimeVersion2 } from './addusedtime2'
|
||||
import { dispatchFinishKeyRequestAction } from './finishkeyrequest'
|
||||
import { dispatchForceSyncAction } from './forcesync'
|
||||
import { dispatchMarkTaskPendingAction } from './marktaskpendingaction'
|
||||
import { dispatchPingAction } from './ping'
|
||||
import { dispatchReplyToKeyRequestAction } from './replytokeyrequest'
|
||||
import { dispatchRemoveInstalledApps } from './removeinstalledapps'
|
||||
import { dispatchSendKeyRequestAction } from './sendkeyrequest'
|
||||
import { dispatchSignOutAtDevice } from './signoutatdevice'
|
||||
import { dispatchTriedDisablingDeviceAdmin } from './trieddisablingdeviceadmin'
|
||||
import { dispatchUpdateAppActivities } from './updateappactivities'
|
||||
import { dispatchUpdateDeviceStatus } from './updatedevicestatus'
|
||||
import { dispatchUpdateInstalledApps } from './updateinstalledapps'
|
||||
import { dispatchUploadDevicePublicKeyAction } from './uploaddevicepublickey'
|
||||
@@ -59,7 +58,7 @@ export const dispatchAppLogicAction = async ({ action, deviceId, cache, eventHan
|
||||
eventHandler: EventHandler
|
||||
}) => {
|
||||
if (action instanceof AddInstalledAppsAction) {
|
||||
await dispatchAddInstalledApps({ deviceId, action, cache })
|
||||
// do nothing
|
||||
} else if (action instanceof AddUsedTimeAction) {
|
||||
await dispatchAddUsedTime({ deviceId, action, cache })
|
||||
} else if (action instanceof AddUsedTimeActionVersion2) {
|
||||
@@ -70,10 +69,12 @@ export const dispatchAppLogicAction = async ({ action, deviceId, cache, eventHan
|
||||
await dispatchForceSyncAction({ deviceId, action, cache })
|
||||
} else if (action instanceof MarkTaskPendingAction) {
|
||||
await dispatchMarkTaskPendingAction({ deviceId, action, cache })
|
||||
} else if (action instanceof PingAction) {
|
||||
await dispatchPingAction({ deviceId, action, cache })
|
||||
} else if (action instanceof ReplyToKeyRequestAction) {
|
||||
await dispatchReplyToKeyRequestAction({ deviceId, action, cache, eventHandler })
|
||||
} else if (action instanceof RemoveInstalledAppsAction) {
|
||||
await dispatchRemoveInstalledApps({ deviceId, action, cache })
|
||||
// do nothing
|
||||
} else if (action instanceof SendKeyRequestAction) {
|
||||
await dispatchSendKeyRequestAction({ deviceId, action, cache })
|
||||
} else if (action instanceof SignOutAtDeviceAction) {
|
||||
@@ -81,7 +82,7 @@ export const dispatchAppLogicAction = async ({ action, deviceId, cache, eventHan
|
||||
} else if (action instanceof UpdateDeviceStatusAction) {
|
||||
await dispatchUpdateDeviceStatus({ deviceId, action, cache })
|
||||
} else if (action instanceof UpdateAppActivitiesAction) {
|
||||
await dispatchUpdateAppActivities({ deviceId, action, cache })
|
||||
// do nothing
|
||||
} else if (action instanceof TriedDisablingDeviceAdminAction) {
|
||||
await dispatchTriedDisablingDeviceAdmin({ deviceId, action, cache })
|
||||
} else if (action instanceof UpdateInstalledAppsAction) {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2026 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 { PingAction } from '../../../../action'
|
||||
import { types as pingTypes } from '../../../../database/ping'
|
||||
import { Cache } from '../cache'
|
||||
|
||||
export async function dispatchPingAction ({ action, cache, deviceId }: {
|
||||
deviceId: string
|
||||
action: PingAction
|
||||
cache: Cache
|
||||
}) {
|
||||
// handle insertion
|
||||
if (action.event === 'ping' || action.event === 'pong') {
|
||||
let type
|
||||
|
||||
if (action.event === 'ping') type = pingTypes.ping
|
||||
else if (action.event === 'pong') type = pingTypes.pong
|
||||
else throw new Error()
|
||||
|
||||
// delete any previous ping/pong
|
||||
await cache.database.ping.destroy({
|
||||
where: {
|
||||
familyId: cache.familyId,
|
||||
receiverDeviceId: action.deviceId,
|
||||
senderDeviceId: deviceId,
|
||||
type: type
|
||||
},
|
||||
transaction: cache.transaction
|
||||
})
|
||||
|
||||
// insert
|
||||
await cache.database.ping.create({
|
||||
familyId: cache.familyId,
|
||||
receiverDeviceId: action.deviceId,
|
||||
senderDeviceId: deviceId,
|
||||
type,
|
||||
token: action.token
|
||||
}, {
|
||||
transaction: cache.transaction
|
||||
})
|
||||
|
||||
// notify
|
||||
cache.incrementTargetedTriggeredSyncLevel(action.deviceId, 2)
|
||||
}
|
||||
|
||||
// handle deleting
|
||||
if (action.event === 'pong' || action.event === 'clear') {
|
||||
await cache.database.ping.destroy({
|
||||
where: {
|
||||
familyId: cache.familyId,
|
||||
receiverDeviceId: deviceId,
|
||||
senderDeviceId: action.deviceId,
|
||||
token: action.token
|
||||
},
|
||||
transaction: cache.transaction
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* server component for the TimeLimit App
|
||||
* Copyright (C) 2019 - 2022 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 { chunk } from 'lodash'
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { UpdateAppActivitiesAction } from '../../../../action'
|
||||
import { AppActivityAttributes, maxActivityNameLength, maxPackageNameLength } from '../../../../database/appactivity'
|
||||
import { Cache } from '../cache'
|
||||
import { ApplyActionException } from '../exception'
|
||||
|
||||
export async function dispatchUpdateAppActivities ({ deviceId, action, cache }: {
|
||||
deviceId: string
|
||||
action: UpdateAppActivitiesAction
|
||||
cache: Cache
|
||||
}) {
|
||||
action.updatedOrAdded.forEach((app) => {
|
||||
if (app.packageName.length > maxPackageNameLength) {
|
||||
throw new ApplyActionException({
|
||||
staticMessage: 'package name too long',
|
||||
dynamicMessage: 'package name too long: ' + app.packageName
|
||||
})
|
||||
}
|
||||
|
||||
if (app.activityName.length > maxActivityNameLength) {
|
||||
throw new ApplyActionException({
|
||||
staticMessage: 'activity name too long',
|
||||
dynamicMessage: 'activity name too long: ' + app.activityName
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (action.updatedOrAdded.length > 0) {
|
||||
const chuncks = chunk(action.updatedOrAdded, 500)
|
||||
|
||||
for (const items of chuncks) {
|
||||
await cache.database.appActivity.destroy({
|
||||
where: {
|
||||
familyId: cache.familyId,
|
||||
deviceId,
|
||||
[Sequelize.Op.or]: (
|
||||
items.map((item) => ({
|
||||
packageName: item.packageName,
|
||||
activityName: item.activityName
|
||||
}))
|
||||
)
|
||||
},
|
||||
transaction: cache.transaction
|
||||
})
|
||||
}
|
||||
|
||||
await cache.database.appActivity.bulkCreate(
|
||||
action.updatedOrAdded.map((item): AppActivityAttributes => ({
|
||||
familyId: cache.familyId,
|
||||
deviceId,
|
||||
packageName: item.packageName,
|
||||
activityName: item.activityName,
|
||||
title: item.title
|
||||
})),
|
||||
{ transaction: cache.transaction }
|
||||
)
|
||||
}
|
||||
|
||||
if (action.removed.length > 0) {
|
||||
const chunks = chunk(action.removed, 500)
|
||||
|
||||
for (const items of chunks) {
|
||||
await cache.database.appActivity.destroy({
|
||||
where: {
|
||||
familyId: cache.familyId,
|
||||
deviceId,
|
||||
[Sequelize.Op.or]: (
|
||||
items.map((item) => ({
|
||||
packageName: item.packageName,
|
||||
activityName: item.activityName
|
||||
}))
|
||||
)
|
||||
},
|
||||
transaction: cache.transaction
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
cache.devicesWithModifiedInstalledApps.add(deviceId)
|
||||
cache.incrementTriggeredSyncLevel(1)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user