Create new enums to type state strings and numbers on server
New enums:
- RegisteredNameFoundState (for NS lookups which emit a RegisteredNameFound signal)
- This enum is in common/ since it is used by the common LookupResult interface
- NameRegistrationEndedState (for the NameRegistrationEnded signal)
- RegistrationState (for the RegistrationStateChanged signal)
- MessageState (for the AccountMessageStatusChanged signal)
- ConversationMemberEventType (for the ConversationMemberEvent signal)
Other changes:
- Update jamid.ts and jami-signal-interfaces.ts to use these new enums
- Update routers to use the enum members rather than magic constants
GitLab: #89
Change-Id: Ief38df0d4a35c6ecf96375bba01773e60e07b888
diff --git a/common/src/index.ts b/common/src/index.ts
index a7c0b1c..0dde015 100644
--- a/common/src/index.ts
+++ b/common/src/index.ts
@@ -16,7 +16,6 @@
* <https://www.gnu.org/licenses/>.
*/
export * from './enums/http-status-code.js';
-export * from './enums/registration-state.js';
export * from './enums/websocket-message-type.js';
export * from './interfaces/account.js';
export * from './interfaces/auth-interfaces.js';
diff --git a/common/src/interfaces/lookup-result.ts b/common/src/interfaces/lookup-result.ts
index 1d18a14..b3c21bd 100644
--- a/common/src/interfaces/lookup-result.ts
+++ b/common/src/interfaces/lookup-result.ts
@@ -16,7 +16,14 @@
* <https://www.gnu.org/licenses/>.
*/
export interface LookupResult {
- state: number; // TODO: Create enum for state
+ state: RegisteredNameFoundState;
address: string;
username: string;
}
+
+export enum RegisteredNameFoundState {
+ Found,
+ InvalidResponse,
+ NotFound,
+ Error,
+}
diff --git a/server/src/jamid/jami-signal-interfaces.ts b/server/src/jamid/jami-signal-interfaces.ts
index 960034b..851239b 100644
--- a/server/src/jamid/jami-signal-interfaces.ts
+++ b/server/src/jamid/jami-signal-interfaces.ts
@@ -16,8 +16,15 @@
* <https://www.gnu.org/licenses/>.
*/
import { AccountDetails, Devices, Message, VolatileDetails } from 'jami-web-common';
+import { RegisteredNameFoundState } from 'jami-web-common';
import { ConversationRequestMetadata } from './conversation-request-metadata.js';
+import {
+ ConversationMemberEventType,
+ MessageState,
+ NameRegistrationEndedState,
+ RegistrationState,
+} from './state-enums.js';
// These interfaces are used to hold all the parameters for signal handlers
// These parameters' names and types can be found in daemon/bin/nodejs/callback.h
@@ -35,20 +42,20 @@
export interface RegistrationStateChanged {
accountId: string;
- state: string;
+ state: RegistrationState;
code: number;
details: string;
}
export interface NameRegistrationEnded {
accountId: string;
- state: number;
+ state: NameRegistrationEndedState;
username: string;
}
export interface RegisteredNameFound {
accountId: string;
- state: number;
+ state: RegisteredNameFoundState;
address: string;
username: string;
}
@@ -68,7 +75,7 @@
accountId: string;
messageId: string;
peer: string;
- state: number; // TODO: Replace state number with enum (see account_const.h)
+ state: MessageState;
}
export interface IncomingTrustRequest {
@@ -118,7 +125,7 @@
accountId: string;
conversationId: string;
memberUri: string;
- event: number;
+ event: ConversationMemberEventType;
}
export interface MessageReceived {
diff --git a/server/src/jamid/jamid.ts b/server/src/jamid/jamid.ts
index bb47b4e..b6a728b 100644
--- a/server/src/jamid/jamid.ts
+++ b/server/src/jamid/jamid.ts
@@ -25,6 +25,7 @@
Devices,
LookupResult,
Message,
+ RegisteredNameFoundState,
VolatileDetails,
WebSocketMessage,
WebSocketMessageType,
@@ -56,6 +57,12 @@
VolatileDetailsChanged,
} from './jami-signal-interfaces.js';
import { JamiSwig, StringMap, stringMapToRecord, stringVectToArray, vectMapToRecordArray } from './jami-swig.js';
+import {
+ ConversationMemberEventType,
+ MessageState,
+ NameRegistrationEndedState,
+ RegistrationState,
+} from './state-enums.js';
const require = createRequire(import.meta.url);
@@ -92,16 +99,20 @@
onVolatileDetailsChanged.next({ accountId, details });
const onRegistrationStateChanged = new Subject<RegistrationStateChanged>();
- handlers.RegistrationStateChanged = (accountId: string, state: string, code: number, details: string) =>
+ handlers.RegistrationStateChanged = (accountId: string, state: RegistrationState, code: number, details: string) =>
onRegistrationStateChanged.next({ accountId, state, code, details });
const onNameRegistrationEnded = new Subject<NameRegistrationEnded>();
- handlers.NameRegistrationEnded = (accountId: string, state: number, username: string) =>
+ handlers.NameRegistrationEnded = (accountId: string, state: NameRegistrationEndedState, username: string) =>
onNameRegistrationEnded.next({ accountId, state, username });
const onRegisteredNameFound = new Subject<RegisteredNameFound>();
- handlers.RegisteredNameFound = (accountId: string, state: number, address: string, username: string) =>
- onRegisteredNameFound.next({ accountId, state, address, username });
+ handlers.RegisteredNameFound = (
+ accountId: string,
+ state: RegisteredNameFoundState,
+ address: string,
+ username: string
+ ) => onRegisteredNameFound.next({ accountId, state, address, username });
const onKnownDevicesChanged = new Subject<KnownDevicesChanged>();
handlers.KnownDevicesChanged = (accountId: string, devices: Devices) =>
@@ -112,7 +123,7 @@
onIncomingAccountMessage.next({ accountId, from, payload });
const onAccountMessageStatusChanged = new Subject<AccountMessageStatusChanged>();
- handlers.AccountMessageStatusChanged = (accountId: string, messageId: string, peer: string, state: number) =>
+ handlers.AccountMessageStatusChanged = (accountId: string, messageId: string, peer: string, state: MessageState) =>
onAccountMessageStatusChanged.next({ accountId, messageId, peer, state });
const onContactAdded = new Subject<ContactAdded>();
@@ -147,7 +158,7 @@
accountId: string,
conversationId: string,
memberUri: string,
- event: number
+ event: ConversationMemberEventType
) => {
onConversationMemberEvent.next({ accountId, conversationId, memberUri, event });
};
@@ -209,18 +220,18 @@
async addAccount(accountDetails: Partial<AccountDetails>): Promise<RegistrationStateChanged> {
accountDetails['Account.type'] = 'RING';
- const detailsStringMap: StringMap = new this.jamiSwig.StringMap();
+ const accountDetailsStringMap: StringMap = new this.jamiSwig.StringMap();
for (const [key, value] of Object.entries(accountDetails)) {
- detailsStringMap.set(key, value.toString());
+ accountDetailsStringMap.set(key, value.toString());
}
- const accountId = this.jamiSwig.addAccount(detailsStringMap);
+ const accountId = this.jamiSwig.addAccount(accountDetailsStringMap);
return firstValueFrom(
this.events.onRegistrationStateChanged.pipe(
filter((value) => value.accountId === accountId),
- // TODO: is it the only state?
- // TODO: Replace with string enum in common/
- filter((value) => value.state === 'REGISTERED' || value.state === 'ERROR_GENERIC')
+ filter(
+ (value) => value.state === RegistrationState.Registered || value.state === RegistrationState.ErrorGeneric
+ )
)
);
}
@@ -242,7 +253,7 @@
async lookupUsername(username: string, accountId?: string): Promise<LookupResult> {
const hasRingNs = this.jamiSwig.lookupName(accountId || '', '', username);
if (!hasRingNs) {
- throw new Error('Jami does not have NS');
+ throw new Error('Jami does not have a nameserver');
}
return firstValueFrom(
this.events.onRegisteredNameFound.pipe(
@@ -255,7 +266,7 @@
async lookupAddress(address: string, accountId?: string): Promise<LookupResult> {
const hasRingNs = this.jamiSwig.lookupAddress(accountId || '', '', address);
if (!hasRingNs) {
- throw new Error('Jami does not have NS');
+ throw new Error('Jami does not have a nameserver');
}
return firstValueFrom(
this.events.onRegisteredNameFound.pipe(
@@ -265,11 +276,10 @@
);
}
- // TODO: Create enum for state and return that rather than a number
- async registerUsername(accountId: string, username: string, password: string): Promise<number> {
+ async registerUsername(accountId: string, username: string, password: string): Promise<NameRegistrationEndedState> {
const hasRingNs = this.jamiSwig.registerName(accountId, password, username);
if (!hasRingNs) {
- throw new Error('Jami does not have NS');
+ throw new Error('Jami does not have a nameserver');
}
return firstValueFrom(
this.events.onNameRegistrationEnded.pipe(
@@ -409,10 +419,10 @@
this.events.onIncomingAccountMessage.subscribe(<T extends WebSocketMessageType>(signal: IncomingAccountMessage) => {
log.debug('Received IncomingAccountMessage:', JSON.stringify(signal));
- const message: WebSocketMessage<T> = JSON.parse(signal.payload['application/json']);
+ const message: Partial<WebSocketMessage<T>> = JSON.parse(signal.payload['application/json']);
- if (message === undefined) {
- log.warn('Undefined account message');
+ if (typeof message !== 'object' || message === null) {
+ log.warn('Account message is not an object');
return;
}
diff --git a/common/src/enums/registration-state.ts b/server/src/jamid/state-enums.ts
similarity index 77%
rename from common/src/enums/registration-state.ts
rename to server/src/jamid/state-enums.ts
index 591a6a3..08b75da 100644
--- a/common/src/enums/registration-state.ts
+++ b/server/src/jamid/state-enums.ts
@@ -27,3 +27,28 @@
ErrorNeedMigration = 'ERROR_NEED_MIGRATION',
Initializing = 'INITIALIZING',
}
+
+export enum NameRegistrationEndedState {
+ Success,
+ InvalidCredentials,
+ InvalidName,
+ AlreadyTaken,
+ Error,
+}
+
+export enum MessageState {
+ Unknown,
+ Sending,
+ Sent,
+ Displayed,
+ Failure,
+ Cancelled,
+}
+
+export enum ConversationMemberEventType {
+ Add,
+ Join,
+ Remove,
+ Ban,
+ Unban,
+}
diff --git a/server/src/routers/auth-router.ts b/server/src/routers/auth-router.ts
index 21ffefc..74fc1f5 100644
--- a/server/src/routers/auth-router.ts
+++ b/server/src/routers/auth-router.ts
@@ -23,6 +23,7 @@
import { Container } from 'typedi';
import { Jamid } from '../jamid/jamid.js';
+import { NameRegistrationEndedState, RegistrationState } from '../jamid/state-enums.js';
import { Accounts } from '../storage/accounts.js';
import { signJwt } from '../utils/jwt.js';
@@ -64,21 +65,24 @@
const { accountId, state } = await jamid.addAccount(accountDetails);
if (isJams) {
- if (state === 'ERROR_GENERIC') {
+ if (state === RegistrationState.ErrorGeneric) {
jamid.removeAccount(accountId);
res.status(HttpStatusCode.Unauthorized).send('Invalid JAMS credentials');
return;
}
} else {
const state = await jamid.registerUsername(accountId, username, '');
- if (state !== 0) {
+ if (state !== NameRegistrationEndedState.Success) {
jamid.removeAccount(accountId);
- if (state === 2) {
- res.status(HttpStatusCode.BadRequest).send('Invalid username or password');
- } else if (state === 3) {
- res.status(HttpStatusCode.Conflict).send('Username already exists');
- } else {
- throw new Error(`Unhandled state ${state}`);
+ switch (state) {
+ case NameRegistrationEndedState.InvalidName:
+ res.status(HttpStatusCode.BadRequest).send('Invalid username or password');
+ break;
+ case NameRegistrationEndedState.AlreadyTaken:
+ res.status(HttpStatusCode.Conflict).send('Username already exists');
+ break;
+ default:
+ throw new Error(`Unhandled state ${state}`);
}
return;
}
diff --git a/server/src/routers/nameserver-router.ts b/server/src/routers/nameserver-router.ts
index 2ead8ee..415c2d1 100644
--- a/server/src/routers/nameserver-router.ts
+++ b/server/src/routers/nameserver-router.ts
@@ -17,7 +17,7 @@
*/
import { Router } from 'express';
import asyncHandler from 'express-async-handler';
-import { HttpStatusCode } from 'jami-web-common';
+import { HttpStatusCode, RegisteredNameFoundState } from 'jami-web-common';
import { Container } from 'typedi';
import { Jamid } from '../jamid/jamid.js';
@@ -34,10 +34,10 @@
asyncHandler(async (req, res) => {
const result = await jamid.lookupUsername(req.params.username, res.locals.accountId);
switch (result.state) {
- case 0:
+ case RegisteredNameFoundState.Found:
res.send(result);
break;
- case 1:
+ case RegisteredNameFoundState.InvalidResponse:
res.status(HttpStatusCode.BadRequest).send('Invalid username');
break;
default:
@@ -52,10 +52,10 @@
asyncHandler(async (req, res) => {
const result = await jamid.lookupAddress(req.params.address, res.locals.accountId);
switch (result.state) {
- case 0:
+ case RegisteredNameFoundState.Found:
res.send(result);
break;
- case 1:
+ case RegisteredNameFoundState.InvalidResponse:
res.status(HttpStatusCode.BadRequest).send('Invalid address');
break;
default: