Add suport for accessibility service permission

This commit is contained in:
Jonas L 2019-03-25 00:00:00 +00:00
parent b6f5edc976
commit 0e601995ec
10 changed files with 117 additions and 9 deletions

View file

@ -26,13 +26,14 @@ export class IgnoreManipulationAction extends ParentAction {
readonly ignoreNotificationAccessManipulation: boolean readonly ignoreNotificationAccessManipulation: boolean
readonly ignoreUsageStatsAccessManipulation: boolean readonly ignoreUsageStatsAccessManipulation: boolean
readonly ignoreOverlayPermissionManipulation: boolean readonly ignoreOverlayPermissionManipulation: boolean
readonly ignoreAccessibilityServiceManipulation: boolean
readonly ignoreDidReboot: boolean readonly ignoreDidReboot: boolean
readonly ignoreHadManipulation: boolean readonly ignoreHadManipulation: boolean
constructor ({ constructor ({
deviceId, ignoreDeviceAdminManipulation, ignoreDeviceAdminManipulationAttempt, deviceId, ignoreDeviceAdminManipulation, ignoreDeviceAdminManipulationAttempt,
ignoreAppDowngrade, ignoreNotificationAccessManipulation, ignoreUsageStatsAccessManipulation, ignoreAppDowngrade, ignoreNotificationAccessManipulation, ignoreUsageStatsAccessManipulation,
ignoreOverlayPermissionManipulation, ignoreDidReboot, ignoreHadManipulation ignoreOverlayPermissionManipulation, ignoreAccessibilityServiceManipulation, ignoreDidReboot, ignoreHadManipulation
}: { }: {
deviceId: string deviceId: string
ignoreDeviceAdminManipulation: boolean ignoreDeviceAdminManipulation: boolean
@ -41,6 +42,7 @@ export class IgnoreManipulationAction extends ParentAction {
ignoreNotificationAccessManipulation: boolean ignoreNotificationAccessManipulation: boolean
ignoreUsageStatsAccessManipulation: boolean ignoreUsageStatsAccessManipulation: boolean
ignoreOverlayPermissionManipulation: boolean ignoreOverlayPermissionManipulation: boolean
ignoreAccessibilityServiceManipulation: boolean
ignoreDidReboot: boolean ignoreDidReboot: boolean
ignoreHadManipulation: boolean ignoreHadManipulation: boolean
}) { }) {
@ -55,6 +57,7 @@ export class IgnoreManipulationAction extends ParentAction {
this.ignoreNotificationAccessManipulation = ignoreNotificationAccessManipulation this.ignoreNotificationAccessManipulation = ignoreNotificationAccessManipulation
this.ignoreUsageStatsAccessManipulation = ignoreUsageStatsAccessManipulation this.ignoreUsageStatsAccessManipulation = ignoreUsageStatsAccessManipulation
this.ignoreOverlayPermissionManipulation = ignoreOverlayPermissionManipulation this.ignoreOverlayPermissionManipulation = ignoreOverlayPermissionManipulation
this.ignoreAccessibilityServiceManipulation = ignoreAccessibilityServiceManipulation
this.ignoreDidReboot = ignoreDidReboot this.ignoreDidReboot = ignoreDidReboot
this.ignoreHadManipulation = ignoreHadManipulation this.ignoreHadManipulation = ignoreHadManipulation
} }
@ -67,11 +70,12 @@ export class IgnoreManipulationAction extends ParentAction {
downgrade: this.ignoreAppDowngrade, downgrade: this.ignoreAppDowngrade,
notification: this.ignoreNotificationAccessManipulation, notification: this.ignoreNotificationAccessManipulation,
overlay: this.ignoreOverlayPermissionManipulation, overlay: this.ignoreOverlayPermissionManipulation,
accessibilityService: this.ignoreAccessibilityServiceManipulation,
usageStats: this.ignoreUsageStatsAccessManipulation, usageStats: this.ignoreUsageStatsAccessManipulation,
hadManipulation: this.ignoreHadManipulation hadManipulation: this.ignoreHadManipulation
}) })
static parse = ({ deviceId, admin, adminA, downgrade, notification, usageStats, overlay, reboot, hadManipulation }: SerializedIgnoreManipulationAction) => ( static parse = ({ deviceId, admin, adminA, downgrade, notification, usageStats, overlay, accessibilityService, reboot, hadManipulation }: SerializedIgnoreManipulationAction) => (
new IgnoreManipulationAction({ new IgnoreManipulationAction({
deviceId, deviceId,
ignoreDeviceAdminManipulation: admin, ignoreDeviceAdminManipulation: admin,
@ -80,6 +84,7 @@ export class IgnoreManipulationAction extends ParentAction {
ignoreUsageStatsAccessManipulation: usageStats, ignoreUsageStatsAccessManipulation: usageStats,
ignoreNotificationAccessManipulation: notification, ignoreNotificationAccessManipulation: notification,
ignoreOverlayPermissionManipulation: !!overlay, ignoreOverlayPermissionManipulation: !!overlay,
ignoreAccessibilityServiceManipulation: !!accessibilityService,
ignoreDidReboot: !!reboot, ignoreDidReboot: !!reboot,
ignoreHadManipulation: hadManipulation ignoreHadManipulation: hadManipulation
}) })
@ -98,4 +103,5 @@ export interface SerializedIgnoreManipulationAction {
// was added at a later version // was added at a later version
reboot?: boolean reboot?: boolean
overlay?: boolean overlay?: boolean
accessibilityService?: boolean
} }

View file

@ -25,14 +25,16 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
readonly newUsageStatsPermissionStatus?: RuntimePermissionStatus readonly newUsageStatsPermissionStatus?: RuntimePermissionStatus
readonly newNotificationAccessPermission?: NewPermissionStatus readonly newNotificationAccessPermission?: NewPermissionStatus
readonly newOverlayPermission?: RuntimePermissionStatus readonly newOverlayPermission?: RuntimePermissionStatus
readonly newAccessibilityServiceEnabled?: boolean
readonly newAppVersion?: number readonly newAppVersion?: number
readonly didReboot: boolean readonly didReboot: boolean
constructor ({ newProtetionLevel, newUsageStatsPermissionStatus, newNotificationAccessPermission, newOverlayPermission, newAppVersion, didReboot }: { constructor ({ newProtetionLevel, newUsageStatsPermissionStatus, newNotificationAccessPermission, newOverlayPermission, newAccessibilityServiceEnabled, newAppVersion, didReboot }: {
newProtetionLevel?: ProtectionLevel newProtetionLevel?: ProtectionLevel
newUsageStatsPermissionStatus?: RuntimePermissionStatus newUsageStatsPermissionStatus?: RuntimePermissionStatus
newNotificationAccessPermission?: NewPermissionStatus newNotificationAccessPermission?: NewPermissionStatus
newOverlayPermission?: RuntimePermissionStatus newOverlayPermission?: RuntimePermissionStatus
newAccessibilityServiceEnabled?: boolean
newAppVersion?: number newAppVersion?: number
didReboot: boolean didReboot: boolean
}) { }) {
@ -48,6 +50,7 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
this.newUsageStatsPermissionStatus = newUsageStatsPermissionStatus this.newUsageStatsPermissionStatus = newUsageStatsPermissionStatus
this.newNotificationAccessPermission = newNotificationAccessPermission this.newNotificationAccessPermission = newNotificationAccessPermission
this.newOverlayPermission = newOverlayPermission this.newOverlayPermission = newOverlayPermission
this.newAccessibilityServiceEnabled = newAccessibilityServiceEnabled
this.newAppVersion = newAppVersion this.newAppVersion = newAppVersion
this.didReboot = didReboot this.didReboot = didReboot
} }
@ -58,16 +61,18 @@ export class UpdateDeviceStatusAction extends AppLogicAction {
usageStats: this.newUsageStatsPermissionStatus, usageStats: this.newUsageStatsPermissionStatus,
notificationAccess: this.newNotificationAccessPermission, notificationAccess: this.newNotificationAccessPermission,
overlayPermission: this.newOverlayPermission, overlayPermission: this.newOverlayPermission,
accessibilityServiceEnabled: this.newAccessibilityServiceEnabled,
appVersion: this.newAppVersion, appVersion: this.newAppVersion,
didReboot: this.didReboot didReboot: this.didReboot
}) })
static parse = ({ protectionLevel, usageStats, notificationAccess, overlayPermission, appVersion, didReboot }: SerializedUpdateDeviceStatusAction) => ( static parse = ({ protectionLevel, usageStats, notificationAccess, overlayPermission, accessibilityServiceEnabled, appVersion, didReboot }: SerializedUpdateDeviceStatusAction) => (
new UpdateDeviceStatusAction({ new UpdateDeviceStatusAction({
newProtetionLevel: protectionLevel, newProtetionLevel: protectionLevel,
newUsageStatsPermissionStatus: usageStats, newUsageStatsPermissionStatus: usageStats,
newNotificationAccessPermission: notificationAccess, newNotificationAccessPermission: notificationAccess,
newOverlayPermission: overlayPermission, newOverlayPermission: overlayPermission,
newAccessibilityServiceEnabled: accessibilityServiceEnabled,
newAppVersion: appVersion, newAppVersion: appVersion,
didReboot: !!didReboot didReboot: !!didReboot
}) })
@ -80,6 +85,7 @@ export interface SerializedUpdateDeviceStatusAction {
usageStats?: RuntimePermissionStatus usageStats?: RuntimePermissionStatus
notificationAccess?: NewPermissionStatus notificationAccess?: NewPermissionStatus
overlayPermission?: RuntimePermissionStatus overlayPermission?: RuntimePermissionStatus
accessibilityServiceEnabled?: boolean
appVersion?: number appVersion?: number
didReboot?: boolean didReboot?: boolean
} }

View file

@ -336,6 +336,9 @@ const definitions = {
}, },
"overlay": { "overlay": {
"type": "boolean" "type": "boolean"
},
"accessibilityService": {
"type": "boolean"
} }
}, },
"additionalProperties": false, "additionalProperties": false,
@ -1123,6 +1126,9 @@ const definitions = {
], ],
"type": "string" "type": "string"
}, },
"accessibilityServiceEnabled": {
"type": "boolean"
},
"appVersion": { "appVersion": {
"type": "number" "type": "number"
}, },

View file

@ -74,9 +74,15 @@ export interface DeviceAttributesVersion7 {
highestOverlayPermission: RuntimePermissionStatus highestOverlayPermission: RuntimePermissionStatus
} }
export interface DeviceAttributesVersion8 {
// as = accessibility service
asEnabled: boolean
wasAsEnabled: boolean
}
export type DeviceAttributes = DeviceAttributesVersion1 & DeviceAttributesVersion2 & export type DeviceAttributes = DeviceAttributesVersion1 & DeviceAttributesVersion2 &
DeviceAttributesVersion3 & DeviceAttributesVersion4 & DeviceAttributesVersion5 & DeviceAttributesVersion3 & DeviceAttributesVersion4 & DeviceAttributesVersion5 &
DeviceAttributesVersion6 & DeviceAttributesVersion7 DeviceAttributesVersion6 & DeviceAttributesVersion7 & DeviceAttributesVersion8
export type DeviceInstance = Sequelize.Instance<DeviceAttributes> & DeviceAttributes export type DeviceInstance = Sequelize.Instance<DeviceAttributes> & DeviceAttributes
export type DeviceModel = Sequelize.Model<DeviceInstance, DeviceAttributes> export type DeviceModel = Sequelize.Model<DeviceInstance, DeviceAttributes>
@ -191,6 +197,17 @@ export const attributesVersion7: SequelizeAttributes<DeviceAttributesVersion7> =
} }
} }
export const attributesVersion8: SequelizeAttributes<DeviceAttributesVersion8> = {
asEnabled: {
...booleanColumn,
defaultValue: false
},
wasAsEnabled: {
...booleanColumn,
defaultValue: false
}
}
export const attributes: SequelizeAttributes<DeviceAttributes> = { export const attributes: SequelizeAttributes<DeviceAttributes> = {
...attributesVersion1, ...attributesVersion1,
...attributesVersion2, ...attributesVersion2,
@ -198,7 +215,8 @@ export const attributes: SequelizeAttributes<DeviceAttributes> = {
...attributesVersion4, ...attributesVersion4,
...attributesVersion5, ...attributesVersion5,
...attributesVersion6, ...attributesVersion6,
...attributesVersion7 ...attributesVersion7,
...attributesVersion8
} }
export const createDeviceModel = (sequelize: Sequelize.Sequelize): DeviceModel => sequelize.define<DeviceInstance, DeviceAttributes>('Device', attributes) export const createDeviceModel = (sequelize: Sequelize.Sequelize): DeviceModel => sequelize.define<DeviceInstance, DeviceAttributes>('Device', attributes)
@ -208,6 +226,7 @@ export const hasDeviceManipulation = (device: DeviceAttributes) => {
const manipulationOfNotificationAccess = device.currentNotificationAccessPermission !== device.highestNotificationAccessPermission const manipulationOfNotificationAccess = device.currentNotificationAccessPermission !== device.highestNotificationAccessPermission
const manipulationOfAppVersion = device.currentAppVersion !== device.highestAppVersion const manipulationOfAppVersion = device.currentAppVersion !== device.highestAppVersion
const manipulationOfOverlayPermission = device.currentOverlayPermission !== device.highestOverlayPermission const manipulationOfOverlayPermission = device.currentOverlayPermission !== device.highestOverlayPermission
const manipulationOfAsPermission = device.asEnabled !== device.wasAsEnabled
const hasActiveManipulationWarning = manipulationOfProtectionLevel || const hasActiveManipulationWarning = manipulationOfProtectionLevel ||
manipulationOfUsageStats || manipulationOfUsageStats ||
@ -215,7 +234,8 @@ export const hasDeviceManipulation = (device: DeviceAttributes) => {
manipulationOfAppVersion || manipulationOfAppVersion ||
device.triedDisablingDeviceAdmin || device.triedDisablingDeviceAdmin ||
device.didReboot || device.didReboot ||
manipulationOfOverlayPermission manipulationOfOverlayPermission ||
manipulationOfAsPermission
const hasAnyManipulation = hasActiveManipulationWarning || device.hadManipulation const hasAnyManipulation = hasActiveManipulationWarning || device.hadManipulation

View file

@ -0,0 +1,46 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 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 } from 'sequelize'
import { attributesVersion8 } from '../../device'
export async function up (queryInterface: QueryInterface, sequelize: Sequelize) {
await sequelize.transaction({
type: 'EXCLUSIVE'
}, async (transaction) => {
await queryInterface.addColumn('Devices', 'asEnabled', {
...attributesVersion8.asEnabled
}, {
transaction
})
await queryInterface.addColumn('Devices', 'wasAsEnabled', {
...attributesVersion8.wasAsEnabled
}, {
transaction
})
})
}
export async function down (queryInterface: QueryInterface, sequelize: Sequelize) {
await sequelize.transaction({
type: 'EXCLUSIVE'
}, async (transaction) => {
await queryInterface.removeColumn('Devices', 'asEnabled', { transaction })
await queryInterface.removeColumn('Devices', 'wasAsEnabled', { transaction })
})
}

View file

@ -57,5 +57,7 @@ export const prepareDeviceEntry = ({ familyId, userId, deviceAuthToken, deviceId
defaultUserTimeout: 0, defaultUserTimeout: 0,
considerRebootManipulation: false, considerRebootManipulation: false,
currentOverlayPermission: 'not granted', currentOverlayPermission: 'not granted',
highestOverlayPermission: 'not granted' highestOverlayPermission: 'not granted',
asEnabled: false,
wasAsEnabled: false
}) })

View file

@ -107,6 +107,20 @@ export async function dispatchUpdateDeviceStatus ({ deviceId, action, cache }: {
} }
} }
if (action.newAccessibilityServiceEnabled !== undefined) {
const hasChanged = deviceEntry.asEnabled !== action.newAccessibilityServiceEnabled
deviceEntry.asEnabled = action.newAccessibilityServiceEnabled
if (action.newAccessibilityServiceEnabled) {
deviceEntry.wasAsEnabled = true
}
if (hasChanged && (deviceEntry.asEnabled !== deviceEntry.wasAsEnabled)) {
deviceEntry.hadManipulation = true
}
}
if (action.newAppVersion !== undefined) { if (action.newAppVersion !== undefined) {
const hasChanged = deviceEntry.currentAppVersion !== action.newAppVersion const hasChanged = deviceEntry.currentAppVersion !== action.newAppVersion

View file

@ -58,6 +58,10 @@ export async function dispatchIgnoreManipulation ({ action, cache }: {
deviceEntry.highestOverlayPermission = deviceEntry.currentOverlayPermission deviceEntry.highestOverlayPermission = deviceEntry.currentOverlayPermission
} }
if (action.ignoreAccessibilityServiceManipulation) {
deviceEntry.wasAsEnabled = deviceEntry.asEnabled
}
if (action.ignoreDidReboot) { if (action.ignoreDidReboot) {
deviceEntry.didReboot = false deviceEntry.didReboot = false
} }

View file

@ -95,7 +95,9 @@ export const generateServerDataStatus = async ({ database, clientStatus, familyI
defUserTimeout: item.defaultUserTimeout, defUserTimeout: item.defaultUserTimeout,
rebootIsManipulation: item.considerRebootManipulation, rebootIsManipulation: item.considerRebootManipulation,
cOverlay: item.currentOverlayPermission, cOverlay: item.currentOverlayPermission,
hOverlay: item.highestOverlayPermission hOverlay: item.highestOverlayPermission,
asEnabled: item.asEnabled,
wasAsEnabled: item.wasAsEnabled
})) }))
} }
} }

View file

@ -84,6 +84,8 @@ export interface ServerDeviceData {
rebootIsManipulation: boolean rebootIsManipulation: boolean
cOverlay: RuntimePermissionStatus cOverlay: RuntimePermissionStatus
hOverlay: RuntimePermissionStatus hOverlay: RuntimePermissionStatus
asEnabled: boolean
wasAsEnabled: boolean
} }
export interface ServerUpdatedCategoryBaseData { export interface ServerUpdatedCategoryBaseData {