Add more robust error handling to server

Changes:
- Use the proper RESTful HTTP status codes for all endpoints (e.g. 204 rather than 200 when the response body is empty)
- Add consistent and more helpful error messages
- Handle invalid route parameters by checking if jamid returns empty objects (e.g. invalid contact IDs)
- Use res.send() rather than res.json() for consistency
- Handle three new signals

GitLab: #111
Change-Id: I1d48dc4629995ab9a96bb2086a9aa91f81889598
diff --git a/server/src/routers/auth-router.ts b/server/src/routers/auth-router.ts
index 086f640..f04529e 100644
--- a/server/src/routers/auth-router.ts
+++ b/server/src/routers/auth-router.ts
@@ -42,8 +42,13 @@
   '/new-account',
   asyncHandler(async (req: Request<ParamsDictionary, string, Credentials>, res, _next) => {
     const { username, password } = req.body;
-    if (!username || !password) {
-      res.status(HttpStatusCode.BadRequest).send('Missing username or password');
+    if (username === undefined || password === undefined) {
+      res.status(HttpStatusCode.BadRequest).send('Missing username or password in body');
+      return;
+    }
+
+    if (password === '') {
+      res.status(HttpStatusCode.BadRequest).send('Password may not be empty');
       return;
     }
 
@@ -82,8 +87,8 @@
   '/login',
   asyncHandler(async (req: Request<ParamsDictionary, { accessToken: string } | string, Credentials>, res, _next) => {
     const { username, password } = req.body;
-    if (!username || !password) {
-      res.status(HttpStatusCode.BadRequest).send('Missing username or password');
+    if (username === undefined || password === undefined) {
+      res.status(HttpStatusCode.BadRequest).send('Missing username or password in body');
       return;
     }
 
@@ -99,13 +104,15 @@
     // TODO: load the password from Jami
     const hashedPassword = creds.get(username);
     if (!hashedPassword) {
-      res.status(HttpStatusCode.NotFound).send('Password not found');
+      res
+        .status(HttpStatusCode.NotFound)
+        .send('Password not found (the account does not have a password set on the server)');
       return;
     }
 
     const isPasswordVerified = await argon2.verify(hashedPassword, password);
     if (!isPasswordVerified) {
-      res.sendStatus(HttpStatusCode.Unauthorized);
+      res.status(HttpStatusCode.Unauthorized).send('Incorrect password');
       return;
     }