diff --git a/lib/types/tunnelbroker/connection-initialization-response-types.js b/lib/types/tunnelbroker/connection-initialization-response-types.js new file mode 100644 --- /dev/null +++ b/lib/types/tunnelbroker/connection-initialization-response-types.js @@ -0,0 +1,26 @@ +// @flow + +import type { TInterface } from 'tcomb'; +import t from 'tcomb'; + +import { tShape, tString } from '../../utils/validation-utils.js'; + +export type ConnectionInitializationStatus = + | { +type: 'Success' } + | { +type: 'Error', +data: string }; + +const connectionInitializationStatusValidator = t.union([ + tShape({ type: tString('Success') }), + tShape({ type: tString('Error'), data: t.String }), +]); + +export type ConnectionInitializationResponse = { + +type: 'ConnectionInitializationResponse', + +status: ConnectionInitializationStatus, +}; + +export const connectionInitializationResponseValidator: TInterface = + tShape({ + type: tString('ConnectionInitializationResponse'), + status: connectionInitializationStatusValidator, + }); diff --git a/lib/types/tunnelbroker/keys-types.js b/lib/types/tunnelbroker/keys-types.js new file mode 100644 --- /dev/null +++ b/lib/types/tunnelbroker/keys-types.js @@ -0,0 +1,19 @@ +// @flow + +import type { TInterface } from 'tcomb'; +import t from 'tcomb'; + +import { tShape, tString } from '../../utils/validation-utils.js'; + +export type RefreshKeyRequest = { + +type: 'RefreshKeyRequest', + +deviceID: string, + +numberOfKeys: number, +}; + +export const refreshKeysRequestValidator: TInterface = + tShape({ + type: tString('RefreshKeyRequest'), + deviceID: t.String, + numberOfKeys: t.Number, + }); diff --git a/lib/types/tunnelbroker/message-receive-confirmation-types.js b/lib/types/tunnelbroker/message-receive-confirmation-types.js new file mode 100644 --- /dev/null +++ b/lib/types/tunnelbroker/message-receive-confirmation-types.js @@ -0,0 +1,17 @@ +// @flow + +import type { TInterface } from 'tcomb'; +import t from 'tcomb'; + +import { tShape, tString } from '../../utils/validation-utils.js'; + +export type MessageReceiveConfirmation = { + +type: 'MessageReceiveConfirmation', + +messageIDs: $ReadOnlyArray, +}; + +export const messageReceiveConfirmationValidator: TInterface = + tShape({ + type: tString('MessageReceiveConfirmation'), + messageIDs: t.list(t.String), + }); diff --git a/lib/types/tunnelbroker/message-to-device-request-status-types.js b/lib/types/tunnelbroker/message-to-device-request-status-types.js new file mode 100644 --- /dev/null +++ b/lib/types/tunnelbroker/message-to-device-request-status-types.js @@ -0,0 +1,40 @@ +// @flow + +import type { TInterface } from 'tcomb'; +import t from 'tcomb'; + +import { tShape, tString } from '../../utils/validation-utils.js'; + +export type Failure = { + +id: string, + +error: string, +}; + +const failureValidator: TInterface = tShape({ + id: t.String, + error: t.String, +}); + +export type MessageSentStatus = + | { +type: 'Success', +data: string } + | { +type: 'Error', +data: Failure } + | { +type: 'InvalidRequest' } + | { +type: 'SerializationError', +data: string }; + +const messageSentStatusValidator = t.union([ + tShape({ type: tString('Success'), data: t.String }), + tShape({ type: tString('Error'), data: failureValidator }), + tShape({ type: tString('InvalidRequest') }), + tShape({ type: tString('SerializationError'), data: t.String }), +]); + +export type MessageToDeviceRequestStatus = { + +type: 'MessageToDeviceRequestStatus', + +clientMessageIDs: $ReadOnlyArray, +}; + +export const messageToDeviceRequestStatusValidator: TInterface = + tShape({ + type: tString('MessageToDeviceRequestStatus'), + clientMessageIDs: t.list(messageSentStatusValidator), + }); diff --git a/lib/types/tunnelbroker/message-to-device-request-types.js b/lib/types/tunnelbroker/message-to-device-request-types.js new file mode 100644 --- /dev/null +++ b/lib/types/tunnelbroker/message-to-device-request-types.js @@ -0,0 +1,21 @@ +// @flow + +import type { TInterface } from 'tcomb'; +import t from 'tcomb'; + +import { tShape, tString } from '../../utils/validation-utils.js'; + +export type MessageToDeviceRequest = { + +type: 'MessageToDeviceRequest', + +clientMessageID: string, + +deviceID: string, + +payload: string, +}; + +export const messageToDeviceRequestValidator: TInterface = + tShape({ + type: tString('MessageToDeviceRequest'), + clientMessageID: t.String, + deviceID: t.String, + payload: t.String, + }); diff --git a/lib/types/tunnelbroker/message-to-device-types.js b/lib/types/tunnelbroker/message-to-device-types.js new file mode 100644 --- /dev/null +++ b/lib/types/tunnelbroker/message-to-device-types.js @@ -0,0 +1,21 @@ +// @flow + +import type { TInterface } from 'tcomb'; +import t from 'tcomb'; + +import { tShape, tString } from '../../utils/validation-utils.js'; + +export type MessageToDevice = { + +type: 'MessageToDevice', + +messageID: string, + +deviceID: string, + +payload: string, +}; + +export const messageToDeviceValidator: TInterface = + tShape({ + type: tString('MessageToDevice'), + messageID: t.String, + deviceID: t.String, + payload: t.String, + }); diff --git a/lib/types/tunnelbroker/messages.js b/lib/types/tunnelbroker/messages.js new file mode 100644 --- /dev/null +++ b/lib/types/tunnelbroker/messages.js @@ -0,0 +1,74 @@ +// @flow + +import type { TUnion } from 'tcomb'; +import t from 'tcomb'; + +import { + type ConnectionInitializationResponse, + connectionInitializationResponseValidator, +} from './connection-initialization-response-types.js'; +import { + type RefreshKeyRequest, + refreshKeysRequestValidator, +} from './keys-types.js'; +import { + type MessageReceiveConfirmation, + messageReceiveConfirmationValidator, +} from './message-receive-confirmation-types.js'; +import { + type MessageToDeviceRequestStatus, + messageToDeviceRequestStatusValidator, +} from './message-to-device-request-status-types.js'; +import { + type MessageToDeviceRequest, + messageToDeviceRequestValidator, +} from './message-to-device-request-types.js'; +import { + type MessageToDevice, + messageToDeviceValidator, +} from './message-to-device-types.js'; +import { + type ConnectionInitializationMessage, + connectionInitializationMessageValidator, +} from './session-types.js'; + +/* + * This file defines types and validation for messages exchanged + * with the Tunnelbroker. The definitions in this file should remain in sync + * with the structures defined in the corresponding + * Rust file at `shared/tunnelbroker_messages/src/messages/mod.rs`. + * + * If you edit the definitions in one file, + * please make sure to update the corresponding definitions in the other. + * + */ + +export const tunnelbrokerMessageTypes = Object.freeze({ + REFRESH_KEYS_REQUEST: 'RefreshKeyRequest', + CONNECTION_INITIALIZATION_MESSAGE: 'ConnectionInitializationMessage', + CONNECTION_INITIALIZATION_RESPONSE: 'ConnectionInitializationResponse', + MESSAGE_TO_DEVICE_REQUEST_STATUS: 'MessageToDeviceRequestStatus', + MESSAGE_TO_DEVICE_REQUEST: 'MessageToDeviceRequest', + MESSAGE_TO_DEVICE: 'MessageToDevice', + MESSAGE_RECEIVE_CONFIRMATION: 'MessageReceiveConfirmation', +}); + +export const tunnelbrokerMessageValidator: TUnion = + t.union([ + refreshKeysRequestValidator, + connectionInitializationMessageValidator, + connectionInitializationResponseValidator, + messageToDeviceRequestStatusValidator, + messageToDeviceRequestValidator, + messageToDeviceValidator, + messageReceiveConfirmationValidator, + ]); + +export type TunnelbrokerMessage = + | RefreshKeyRequest + | ConnectionInitializationMessage + | ConnectionInitializationResponse + | MessageToDeviceRequestStatus + | MessageToDeviceRequest + | MessageToDevice + | MessageReceiveConfirmation; diff --git a/lib/types/tunnelbroker/session-types.js b/lib/types/tunnelbroker/session-types.js new file mode 100644 --- /dev/null +++ b/lib/types/tunnelbroker/session-types.js @@ -0,0 +1,31 @@ +// @flow + +import type { TInterface } from 'tcomb'; +import t from 'tcomb'; + +import { tShape, tString } from '../../utils/validation-utils.js'; + +export type DeviceTypes = 'mobile' | 'web' | 'keyserver'; + +export type ConnectionInitializationMessage = { + +type: 'ConnectionInitializationMessage', + +deviceID: string, + +accessToken: string, + +userID: string, + +notifyToken?: ?string, + +deviceType: DeviceTypes, + +deviceAppVersion?: ?string, + +deviceOS?: ?string, +}; + +export const connectionInitializationMessageValidator: TInterface = + tShape({ + type: tString('ConnectionInitializationMessage'), + deviceID: t.String, + accessToken: t.String, + userID: t.String, + notifyToken: t.maybe(t.String), + deviceType: t.enums.of(['Mobile', 'Web', 'Keyserver']), + deviceAppVersion: t.maybe(t.String), + deviceOS: t.maybe(t.String), + }); diff --git a/shared/tunnelbroker_messages/src/messages/mod.rs b/shared/tunnelbroker_messages/src/messages/mod.rs --- a/shared/tunnelbroker_messages/src/messages/mod.rs +++ b/shared/tunnelbroker_messages/src/messages/mod.rs @@ -18,6 +18,14 @@ use serde::{Deserialize, Serialize}; +// This file defines types and validation for messages exchanged +// with the Tunnelbroker. The definitions in this file should remain in sync +// with the structures defined in the corresponding +// JavaScript file at `lib/types/tunnelbroker/messages.js`. + +// If you edit the definitions in one file, +// please make sure to update the corresponding definitions in the other. + #[derive(Serialize, Deserialize, Debug)] #[serde(untagged)] pub enum Messages {