Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datamob sdk methods #177

Merged
merged 9 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,19 @@ await doExpensiveTask();
await hideLoadingOverlay();
```

#### Error cases
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated. Just update missing doc


If `showLoadingOverlay` is called while the loading overlay is already being
shown, the promise will be rejected with an error object with the following
type:

```ts
{
code: 503;
description: 'Loading screen already showing';
}
```

### getInstallationId

<kbd>App version >=24.11</kbd>
Expand Down Expand Up @@ -1381,6 +1394,91 @@ app using the `setUnseenNotificationsBadge`. This way, the next time the webview
use the getter, it will know if the `lastUpdated` matches with the one persisted
in `localStorage`.

### requestDatamobDeviceAdmin

<kbd>App version >=25.x</kbd>

Datamob is a native library that offer developers a way to integrate security
and remote device control features into their applications.

The application that implements the Datamob library must be registered as a
system management application (Device Admin). This configuration is essential to
allow the application to have sufficient permissions to execute security
commands, such as screen lock and factory reset.

This method opens a setting screen asking the user to accept system management
permissions for the application.

```ts
requestDatamobDeviceAdmin: () => Promise<{isAdmin: boolean}>;
```

`isAdmin` is true if the permission was granted.

#### Demo

https://github.com/user-attachments/assets/28095f42-76db-4ac2-9586-e350acef7e1d

### registerDatamobUser

<kbd>App version >=25.x</kbd>

The application that implements the Datamob should have an user registered. This
method is used to register one.

```ts
registerDatamobUser: ({phoneNumber: string, tokenPassword: string}) => Promise<void>;
```

- `phoneNumber`: The phone number of the user.
- `tokenPassword`: When registering the device, datamob generate an accessKey
that is recorded in the Datamob device registry. By combining this attribute
with a hash that we keep in a password vault, generate this token.

#### Error cases

If the registration fails, the promise will be rejected with an error object
with the following type:

```ts
{
code: 500;
reason: `Registration error: ${errorDescription}`;
}
```

### validateDatamobRequirements

<kbd>App version >=25.x</kbd>

Datamob sdk allows to send remote commands to the user device. These remote
commands include actions such as locking the device screen (lock screen) or even
forcing a wipe (factory reset) of the device, providing additional security
control for the end user.

This method returns a map with the requirements. Each requirement is a boolean
value where true is valid, false is not valid.

```ts
validateDatamobRequirements: ({phoneNumber: string, tokenPassword: string}) => Promise<{
requirements: {
deviceAdmin: boolean;
googleAccount: boolean;
lockPassword: boolean;
accessibilityOption: boolean;
invalidPassword: boolean;
invalidToken: boolean;
}
}>
```

- `phoneNumber`: The phone number of the user.
- `tokenPassword`: When registering the device, datamob generate an accessKey
that is recorded in the Datamob device registry. By combining this attribute
with a hash that we keep in a password vault, generate this token.

- `requirements`: A map with the requirements.

## Error handling

If an uncontrolled error occurs, promise will be rejected with an error object:
Expand Down
6 changes: 6 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,9 @@ export {
getUnseenNotificationsBadge,
setUnseenNotificationsBadge,
} from './src/inbox-notifications';

export {
registerDatamobUser,
requestDatamobDeviceAdmin,
validateDatamobRequirements,
} from './src/datamob';
106 changes: 106 additions & 0 deletions src/__tests__/datamob-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import {
registerDatamobUser,
requestDatamobDeviceAdmin,
validateDatamobRequirements,
} from '../datamob';
import {createFakeAndroidPostMessage} from './fake-post-message';

test('requestDatamobDeviceAdmin', async () => {
createFakeAndroidPostMessage({
checkMessage: (msg) => {
expect(msg.type).toBe('REQUEST_DATAMOB_DEVICE_ADMIN');
},
getResponse: (msg) => ({
type: 'REQUEST_DATAMOB_DEVICE_ADMIN',
id: msg.id,
payload: {
isAdmin: true,
},
}),
});

const res = await requestDatamobDeviceAdmin();
expect(res).toEqual({isAdmin: true});
});

test('registerDatamobUser', async () => {
const phoneNumber = '666112233';
const tokenPassword = 'sometoken';
createFakeAndroidPostMessage({
checkMessage: (msg) => {
expect(msg.type).toBe('REGISTER_DATAMOB_USER');
expect(msg.payload).toEqual({phoneNumber, tokenPassword});
},
getResponse: (msg) => ({
type: 'REGISTER_DATAMOB_USER',
id: msg.id,
}),
});

const res = await registerDatamobUser({phoneNumber, tokenPassword});
expect(res).toBeUndefined();
});

test('registerDatamobUser error', async () => {
const phoneNumber = '666112233';
const tokenPassword = 'sometoken';
createFakeAndroidPostMessage({
checkMessage: (msg) => {
expect(msg.type).toBe('REGISTER_DATAMOB_USER');
expect(msg.payload).toEqual({phoneNumber, tokenPassword});
},
getResponse: (msg) => ({
type: 'ERROR',
id: msg.id,
payload: {
code: 500,
reason: 'Registration error',
},
}),
});

await expect(
registerDatamobUser({phoneNumber, tokenPassword}),
).rejects.toEqual({
code: 500,
reason: 'Registration error',
});
});

test('validateDatamobRequirements', async () => {
const phoneNumber = '666112233';
const tokenPassword = 'sometoken';
createFakeAndroidPostMessage({
checkMessage: (msg) => {
expect(msg.type).toBe('VALIDATE_DATAMOB_REQUIREMENTS');
expect(msg.payload).toEqual({phoneNumber, tokenPassword});
},
getResponse: (msg) => ({
type: 'VALIDATE_DATAMOB_REQUIREMENTS',
id: msg.id,
payload: {
requirements: {
deviceAdmin: true,
googleAccount: true,
lockPassword: true,
accessibilityOption: true,
invalidPhoneNumber: true,
invalidToken: true,
},
},
}),
});

const res = await validateDatamobRequirements({phoneNumber, tokenPassword});

expect(res).toEqual({
requirements: {
deviceAdmin: true,
googleAccount: true,
lockPassword: true,
accessibilityOption: true,
invalidPhoneNumber: true,
invalidToken: true,
},
});
});
40 changes: 40 additions & 0 deletions src/datamob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {postMessageToNativeApp} from './post-message';

export const requestDatamobDeviceAdmin = (): Promise<{isAdmin: boolean}> =>
postMessageToNativeApp({
type: 'REQUEST_DATAMOB_DEVICE_ADMIN',
payload: {},
}).then(({isAdmin}) => ({isAdmin}));

export const registerDatamobUser = ({
phoneNumber,
tokenPassword,
}: {
phoneNumber: string;
tokenPassword: string;
}): Promise<void> =>
postMessageToNativeApp({
type: 'REGISTER_DATAMOB_USER',
payload: {phoneNumber, tokenPassword},
});

export const validateDatamobRequirements = ({
phoneNumber,
tokenPassword,
}: {
phoneNumber: string;
tokenPassword: string;
}): Promise<{
requirements: {
deviceAdmin: boolean;
googleAccount: boolean;
lockPassword: boolean;
accessibilityOption: boolean;
invalidPhoneNumber: boolean;
invalidToken: boolean;
};
}> =>
postMessageToNativeApp({
type: 'VALIDATE_DATAMOB_REQUIREMENTS',
payload: {phoneNumber, tokenPassword},
}).then(({requirements}) => ({requirements}));
29 changes: 28 additions & 1 deletion src/post-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,13 +379,40 @@ export type ResponsesFromNativeApp = {
GET_UNSEEN_NOTIFICATIONS_BADGE: {
type: 'GET_UNSEEN_NOTIFICATIONS_BADGE';
id: string;
payload: {unseenNotificationCounter: number; lastUpdated: number};
payload: {
unseenNotificationCounter: number;
lastUpdated: number;
};
};
SET_UNSEEN_NOTIFICATIONS_BADGE: {
type: 'SET_UNSEEN_NOTIFICATIONS_BADGE';
id: string;
payload: void;
};
REQUEST_DATAMOB_DEVICE_ADMIN: {
type: 'REQUEST_DATAMOB_DEVICE_ADMIN';
id: string;
payload: {isAdmin: boolean};
};
REGISTER_DATAMOB_USER: {
type: 'REGISTER_DATAMOB_USER';
id: string;
payload: void;
};
VALIDATE_DATAMOB_REQUIREMENTS: {
type: 'VALIDATE_DATAMOB_REQUIREMENTS';
id: string;
payload: {
requirements: {
deviceAdmin: boolean;
googleAccount: boolean;
lockPassword: boolean;
accessibilityOption: boolean;
invalidPhoneNumber: boolean;
invalidToken: boolean;
};
};
};
};

export type NativeAppResponsePayload<
Expand Down
Loading