From 368d4199a5426bfb65b4af5afe376b45d33ea310 Mon Sep 17 00:00:00 2001
From: Dessalines <tyhou13@gmx.com>
Date: Thu, 24 Dec 2020 17:05:57 -0500
Subject: [PATCH] Actually sending ws requests, some other fixes.

---
 Dockerfile                                    |  4 +-
 src/server/index.tsx                          |  4 +-
 src/shared/components/admin-settings.tsx      | 18 ++++---
 src/shared/components/app.tsx                 |  2 +-
 src/shared/components/comment-form.tsx        | 18 ++++---
 src/shared/components/comment-node.tsx        | 54 ++++++++++---------
 src/shared/components/communities.tsx         | 21 +++++---
 src/shared/components/community-form.tsx      | 14 +++--
 src/shared/components/community.tsx           | 41 ++++++++------
 src/shared/components/create-community.tsx    |  3 +-
 src/shared/components/create-post.tsx         | 11 ++--
 .../components/create-private-message.tsx     |  6 ++-
 src/shared/components/inbox.tsx               | 24 +++++----
 src/shared/components/login.tsx               | 30 ++++++-----
 src/shared/components/main.tsx                | 35 +++++++-----
 src/shared/components/modlog.tsx              |  3 +-
 src/shared/components/navbar.tsx              | 41 +++++++++-----
 src/shared/components/password_change.tsx     |  5 +-
 src/shared/components/post-form.tsx           | 18 ++++---
 src/shared/components/post-listing.tsx        | 54 ++++++++++---------
 src/shared/components/post.tsx                | 37 +++++++------
 .../components/private-message-form.tsx       | 14 ++---
 src/shared/components/private-message.tsx     | 10 ++--
 src/shared/components/search.tsx              | 11 ++--
 src/shared/components/setup.tsx               |  4 +-
 src/shared/components/sidebar.tsx             | 22 ++++----
 src/shared/components/site-form.tsx           | 17 +++---
 src/shared/components/user.tsx                | 21 +++++---
 src/shared/env.ts                             |  4 +-
 src/shared/services/UserService.ts            | 11 ----
 src/shared/services/WebSocketService.ts       | 25 +++++----
 src/shared/utils.ts                           | 30 +++++++++--
 32 files changed, 362 insertions(+), 250 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index 745651b..2781422 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
 FROM node:14-alpine as builder
-RUN apk update && apk add yarn curl bash && rm -rf /var/cache/apk/*
+RUN apk add yarn curl bash --no-cache
 
 RUN curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | bash -s -- -b /usr/local/bin
 
@@ -24,7 +24,7 @@ RUN yarn build:prod
 
 # Pruning
 # RUN npm prune --production
-RUN /usr/local/bin/node-prune
+RUN node-prune
 
 FROM node:14-alpine as runner
 COPY --from=builder /usr/src/app/dist /app/dist
diff --git a/src/server/index.tsx b/src/server/index.tsx
index a2bcd4a..10e935d 100644
--- a/src/server/index.tsx
+++ b/src/server/index.tsx
@@ -14,6 +14,7 @@ import { Helmet } from 'inferno-helmet';
 import { initializeSite } from '../shared/initialize';
 import { httpUri } from '../shared/env';
 import { IncomingHttpHeaders } from 'http';
+import { setOptionalAuth } from '../shared/utils';
 
 const server = express();
 const port = 1234;
@@ -29,7 +30,8 @@ server.get('/*', async (req, res) => {
   const context = {} as any;
   let auth: string = IsomorphicCookie.load('jwt', req);
 
-  let getSiteForm: GetSite = { auth };
+  let getSiteForm: GetSite = {};
+  setOptionalAuth(getSiteForm, auth);
 
   let promises: Promise<any>[] = [];
 
diff --git a/src/shared/components/admin-settings.tsx b/src/shared/components/admin-settings.tsx
index b9f93f4..6b985a4 100644
--- a/src/shared/components/admin-settings.tsx
+++ b/src/shared/components/admin-settings.tsx
@@ -8,7 +8,7 @@ import {
   GetSiteConfigResponse,
   GetSiteConfig,
 } from 'lemmy-js-client';
-import { UserService, WebSocketService } from '../services';
+import { WebSocketService } from '../services';
 import {
   wsJsonToRes,
   capitalizeFirstLetter,
@@ -18,6 +18,8 @@ import {
   wsSubscribe,
   isBrowser,
   wsUserOp,
+  wsClient,
+  authField,
 } from '../utils';
 import autosize from 'autosize';
 import { SiteForm } from './site-form';
@@ -42,7 +44,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
     siteRes: this.isoData.site_res,
     siteConfigForm: {
       config_hjson: null,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     },
     siteConfigRes: {
       config_hjson: null,
@@ -66,9 +68,11 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
       this.state.siteConfigLoading = false;
       this.state.loading = false;
     } else {
-      WebSocketService.Instance.client.getSiteConfig({
-        auth: UserService.Instance.authField(),
-      });
+      WebSocketService.Instance.send(
+        wsClient.getSiteConfig({
+          auth: authField(),
+        })
+      );
     }
   }
 
@@ -198,7 +202,9 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
   handleSiteConfigSubmit(i: AdminSettings, event: any) {
     event.preventDefault();
     i.state.siteConfigLoading = true;
-    WebSocketService.Instance.client.saveSiteConfig(i.state.siteConfigForm);
+    WebSocketService.Instance.send(
+      wsClient.saveSiteConfig(i.state.siteConfigForm)
+    );
     i.setState(i.state);
   }
 
diff --git a/src/shared/components/app.tsx b/src/shared/components/app.tsx
index 26a2886..8c9fa9f 100644
--- a/src/shared/components/app.tsx
+++ b/src/shared/components/app.tsx
@@ -28,7 +28,7 @@ export class App extends Component<AppProps, any> {
           <div>
             <Theme user={siteRes.my_user} />
             {siteRes &&
-              siteRes.site_view.site &&
+              siteRes.site_view &&
               this.props.siteRes.site_view.site.icon && (
                 <Helmet>
                   <link
diff --git a/src/shared/components/comment-form.tsx b/src/shared/components/comment-form.tsx
index 5a0d404..3e81d77 100644
--- a/src/shared/components/comment-form.tsx
+++ b/src/shared/components/comment-form.tsx
@@ -9,7 +9,9 @@ import {
 } from 'lemmy-js-client';
 import { CommentNode as CommentNodeI } from '../interfaces';
 import {
+  authField,
   capitalizeFirstLetter,
+  wsClient,
   wsJsonToRes,
   wsSubscribe,
   wsUserOp,
@@ -21,11 +23,11 @@ import { MarkdownTextArea } from './markdown-textarea';
 
 interface CommentFormProps {
   postId?: number;
-  node?: CommentNodeI;
-  onReplyCancel?(): any;
+  node?: CommentNodeI; // Can either be the parent, or the editable comment
   edit?: boolean;
   disabled?: boolean;
   focus?: boolean;
+  onReplyCancel?(): any;
 }
 
 interface CommentFormState {
@@ -68,7 +70,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
         {UserService.Instance.user ? (
           <MarkdownTextArea
             initialContent={
-              this.props.node
+              this.props.edit
                 ? this.props.node.comment_view.comment.content
                 : null
             }
@@ -108,18 +110,18 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
         content,
         form_id: this.state.formId,
         edit_id: node.comment_view.comment.id,
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.editComment(form);
+      WebSocketService.Instance.send(wsClient.editComment(form));
     } else {
       let form: CreateComment = {
         content,
         form_id: this.state.formId,
         post_id: node ? node.comment_view.post.id : this.props.postId,
-        parent_id: node ? node.comment_view.comment.parent_id : null,
-        auth: UserService.Instance.authField(),
+        parent_id: node ? node.comment_view.comment.id : null,
+        auth: authField(),
       };
-      WebSocketService.Instance.client.createComment(form);
+      WebSocketService.Instance.send(wsClient.createComment(form));
     }
     this.setState(this.state);
   }
diff --git a/src/shared/components/comment-node.tsx b/src/shared/components/comment-node.tsx
index 3d69812..c08edc3 100644
--- a/src/shared/components/comment-node.tsx
+++ b/src/shared/components/comment-node.tsx
@@ -32,6 +32,8 @@ import {
   isMod,
   setupTippy,
   colorList,
+  wsClient,
+  authField,
 } from '../utils';
 import moment from 'moment';
 import { MomentTime } from './moment-time';
@@ -849,9 +851,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     let deleteForm: DeleteComment = {
       edit_id: comment.id,
       deleted: !comment.deleted,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.deleteComment(deleteForm);
+    WebSocketService.Instance.send(wsClient.deleteComment(deleteForm));
   }
 
   handleSaveCommentClick(i: CommentNode) {
@@ -860,10 +862,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     let form: SaveComment = {
       comment_id: cv.comment.id,
       save,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
-    WebSocketService.Instance.client.saveComment(form);
+    WebSocketService.Instance.send(wsClient.saveComment(form));
 
     i.state.saveLoading = true;
     i.setState(this.state);
@@ -895,10 +897,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     let form: CreateCommentLike = {
       comment_id: i.comment_view.comment.id,
       score: this.state.my_vote,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
-    WebSocketService.Instance.client.likeComment(form);
+    WebSocketService.Instance.send(wsClient.likeComment(form));
     this.setState(this.state);
     setupTippy();
   }
@@ -923,10 +925,10 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     let form: CreateCommentLike = {
       comment_id: i.comment_view.comment.id,
       score: this.state.my_vote,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
-    WebSocketService.Instance.client.likeComment(form);
+    WebSocketService.Instance.send(wsClient.likeComment(form));
     this.setState(this.state);
     setupTippy();
   }
@@ -952,9 +954,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
       edit_id: comment.id,
       removed: !comment.removed,
       reason: i.state.removeReason,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.removeComment(form);
+    WebSocketService.Instance.send(wsClient.removeComment(form));
 
     i.state.showRemoveDialog = false;
     i.setState(i.state);
@@ -971,16 +973,16 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
       let form: MarkUserMentionAsRead = {
         user_mention_id: i.props.node.comment_view.user_mention.id,
         read: !i.props.node.comment_view.user_mention.read,
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.markUserMentionAsRead(form);
+      WebSocketService.Instance.send(wsClient.markUserMentionAsRead(form));
     } else {
       let form: MarkCommentAsRead = {
         comment_id: i.props.node.comment_view.comment.id,
         read: !i.props.node.comment_view.comment.read,
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.markCommentAsRead(form);
+      WebSocketService.Instance.send(wsClient.markCommentAsRead(form));
     }
 
     i.state.readLoading = true;
@@ -1037,9 +1039,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
         remove_data: i.state.removeData,
         reason: i.state.banReason,
         expires: getUnixTime(i.state.banExpires),
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.banFromCommunity(form);
+      WebSocketService.Instance.send(wsClient.banFromCommunity(form));
     } else {
       // If its an unban, restore all their data
       let ban = !cv.creator.banned;
@@ -1052,9 +1054,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
         remove_data: i.state.removeData,
         reason: i.state.banReason,
         expires: getUnixTime(i.state.banExpires),
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.banUser(form);
+      WebSocketService.Instance.send(wsClient.banUser(form));
     }
 
     i.state.showBanDialog = false;
@@ -1077,9 +1079,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
       user_id: cv.creator.id,
       community_id: cv.community.id,
       added: !i.isMod,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.addModToCommunity(form);
+    WebSocketService.Instance.send(wsClient.addModToCommunity(form));
     i.state.showConfirmAppointAsMod = false;
     i.setState(i.state);
   }
@@ -1098,9 +1100,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     let form: AddAdmin = {
       user_id: i.props.node.comment_view.creator.id,
       added: !i.isAdmin,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.addAdmin(form);
+    WebSocketService.Instance.send(wsClient.addAdmin(form));
     i.state.showConfirmAppointAsAdmin = false;
     i.setState(i.state);
   }
@@ -1120,9 +1122,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
     let form: TransferCommunity = {
       community_id: cv.community.id,
       user_id: cv.creator.id,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.transferCommunity(form);
+    WebSocketService.Instance.send(wsClient.transferCommunity(form));
     i.state.showConfirmTransferCommunity = false;
     i.setState(i.state);
   }
@@ -1140,9 +1142,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
   handleTransferSite(i: CommentNode) {
     let form: TransferSite = {
       user_id: i.props.node.comment_view.creator.id,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.transferSite(form);
+    WebSocketService.Instance.send(wsClient.transferSite(form));
     i.state.showConfirmTransferSite = false;
     i.setState(i.state);
   }
diff --git a/src/shared/components/communities.tsx b/src/shared/components/communities.tsx
index 148a413..236f777 100644
--- a/src/shared/components/communities.tsx
+++ b/src/shared/components/communities.tsx
@@ -11,7 +11,7 @@ import {
   SortType,
   SiteView,
 } from 'lemmy-js-client';
-import { UserService, WebSocketService } from '../services';
+import { WebSocketService } from '../services';
 import {
   wsJsonToRes,
   toast,
@@ -20,6 +20,9 @@ import {
   setIsoData,
   wsSubscribe,
   wsUserOp,
+  wsClient,
+  authField,
+  setOptionalAuth,
 } from '../utils';
 import { CommunityLink } from './community-link';
 import { i18n } from '../i18next';
@@ -212,18 +215,18 @@ export class Communities extends Component<any, CommunitiesState> {
     let form: FollowCommunity = {
       community_id: communityId,
       follow: false,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.followCommunity(form);
+    WebSocketService.Instance.send(wsClient.followCommunity(form));
   }
 
   handleSubscribe(communityId: number) {
     let form: FollowCommunity = {
       community_id: communityId,
       follow: true,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.followCommunity(form);
+    WebSocketService.Instance.send(wsClient.followCommunity(form));
   }
 
   refetch() {
@@ -231,10 +234,12 @@ export class Communities extends Component<any, CommunitiesState> {
       sort: SortType.TopAll,
       limit: communityLimit,
       page: this.state.page,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
 
-    WebSocketService.Instance.client.listCommunities(listCommunitiesForm);
+    WebSocketService.Instance.send(
+      wsClient.listCommunities(listCommunitiesForm)
+    );
   }
 
   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
@@ -244,8 +249,8 @@ export class Communities extends Component<any, CommunitiesState> {
       sort: SortType.TopAll,
       limit: communityLimit,
       page,
-      auth: req.auth,
     };
+    setOptionalAuth(listCommunitiesForm, req.auth);
 
     return [req.client.listCommunities(listCommunitiesForm)];
   }
diff --git a/src/shared/components/community-form.tsx b/src/shared/components/community-form.tsx
index 4a3dad4..b40899a 100644
--- a/src/shared/components/community-form.tsx
+++ b/src/shared/components/community-form.tsx
@@ -9,7 +9,7 @@ import {
   CommunityResponse,
   CommunityView,
 } from 'lemmy-js-client';
-import { UserService, WebSocketService } from '../services';
+import { WebSocketService } from '../services';
 import {
   wsJsonToRes,
   capitalizeFirstLetter,
@@ -17,6 +17,8 @@ import {
   randomStr,
   wsSubscribe,
   wsUserOp,
+  wsClient,
+  authField,
 } from '../utils';
 import { i18n } from '../i18next';
 
@@ -52,7 +54,7 @@ export class CommunityForm extends Component<
       nsfw: false,
       icon: null,
       banner: null,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     },
     loading: false,
   };
@@ -82,7 +84,7 @@ export class CommunityForm extends Component<
         nsfw: cv.community.nsfw,
         icon: cv.community.icon,
         banner: cv.community.banner,
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
     }
 
@@ -283,9 +285,11 @@ export class CommunityForm extends Component<
         ...i.state.communityForm,
         edit_id: i.props.community_view.community.id,
       };
-      WebSocketService.Instance.client.editCommunity(form);
+      WebSocketService.Instance.send(wsClient.editCommunity(form));
     } else {
-      WebSocketService.Instance.client.createCommunity(i.state.communityForm);
+      WebSocketService.Instance.send(
+        wsClient.createCommunity(i.state.communityForm)
+      );
     }
     i.setState(i.state);
   }
diff --git a/src/shared/components/community.tsx b/src/shared/components/community.tsx
index aa0cbf0..6025e91 100644
--- a/src/shared/components/community.tsx
+++ b/src/shared/components/community.tsx
@@ -51,6 +51,9 @@ import {
   isBrowser,
   communityRSSUrl,
   wsUserOp,
+  wsClient,
+  authField,
+  setOptionalAuth,
 } from '../utils';
 import { i18n } from '../i18next';
 
@@ -126,7 +129,7 @@ export class Community extends Component<any, State> {
     } else {
       this.fetchCommunity();
       this.fetchData();
-      WebSocketService.Instance.client.listCategories();
+      WebSocketService.Instance.send(wsClient.listCategories());
     }
     setupTippy();
   }
@@ -135,9 +138,9 @@ export class Community extends Component<any, State> {
     let form: GetCommunity = {
       id: this.state.communityId ? this.state.communityId : null,
       name: this.state.communityName ? this.state.communityName : null,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
-    WebSocketService.Instance.client.getCommunity(form);
+    WebSocketService.Instance.send(wsClient.getCommunity(form));
   }
 
   componentWillUnmount() {
@@ -170,7 +173,7 @@ export class Community extends Component<any, State> {
     }
 
     let communityForm: GetCommunity = id ? { id } : { name: name_ };
-    communityForm.auth = req.auth;
+    setOptionalAuth(communityForm, req.auth);
     promises.push(req.client.getCommunity(communityForm));
 
     let dataType: DataType = pathSplit[4]
@@ -191,8 +194,8 @@ export class Community extends Component<any, State> {
         limit: fetchLimit,
         sort,
         type_: ListingType.Community,
-        auth: req.auth,
       };
+      setOptionalAuth(getPostsForm, req.auth);
       this.setIdOrName(getPostsForm, id, name_);
       promises.push(req.client.getPosts(getPostsForm));
     } else {
@@ -201,8 +204,8 @@ export class Community extends Component<any, State> {
         limit: fetchLimit,
         sort,
         type_: ListingType.Community,
-        auth: req.auth,
       };
+      setOptionalAuth(getCommentsForm, req.auth);
       this.setIdOrName(getCommentsForm, id, name_);
       promises.push(req.client.getComments(getCommentsForm));
     }
@@ -236,7 +239,7 @@ export class Community extends Component<any, State> {
   }
 
   render() {
-    let cv = this.state.communityRes.community_view;
+    let cv = this.state.communityRes?.community_view;
     return (
       <div class="container">
         {this.state.communityLoading ? (
@@ -418,9 +421,9 @@ export class Community extends Component<any, State> {
         type_: ListingType.Community,
         community_id: this.state.communityId,
         community_name: this.state.communityName,
-        auth: UserService.Instance.authField(false),
+        auth: authField(false),
       };
-      WebSocketService.Instance.client.getPosts(form);
+      WebSocketService.Instance.send(wsClient.getPosts(form));
     } else {
       let form: GetComments = {
         page: this.state.page,
@@ -429,9 +432,9 @@ export class Community extends Component<any, State> {
         type_: ListingType.Community,
         community_id: this.state.communityId,
         community_name: this.state.communityName,
-        auth: UserService.Instance.authField(false),
+        auth: authField(false),
       };
-      WebSocketService.Instance.client.getComments(form);
+      WebSocketService.Instance.send(wsClient.getComments(form));
     }
   }
 
@@ -442,9 +445,11 @@ export class Community extends Component<any, State> {
       this.context.router.history.push('/');
       return;
     } else if (msg.reconnect) {
-      WebSocketService.Instance.client.communityJoin({
-        community_id: this.state.communityRes.community_view.community.id,
-      });
+      WebSocketService.Instance.send(
+        wsClient.communityJoin({
+          community_id: this.state.communityRes.community_view.community.id,
+        })
+      );
       this.fetchData();
     } else if (op == UserOperation.GetCommunity) {
       let data = wsJsonToRes<GetCommunityResponse>(msg).data;
@@ -452,9 +457,11 @@ export class Community extends Component<any, State> {
       this.state.communityLoading = false;
       this.setState(this.state);
       // TODO why is there no auth in this form?
-      WebSocketService.Instance.client.communityJoin({
-        community_id: data.community_view.community.id,
-      });
+      WebSocketService.Instance.send(
+        wsClient.communityJoin({
+          community_id: data.community_view.community.id,
+        })
+      );
     } else if (
       op == UserOperation.EditCommunity ||
       op == UserOperation.DeleteCommunity ||
diff --git a/src/shared/components/create-community.tsx b/src/shared/components/create-community.tsx
index b989183..aab5480 100644
--- a/src/shared/components/create-community.tsx
+++ b/src/shared/components/create-community.tsx
@@ -16,6 +16,7 @@ import {
   wsSubscribe,
   isBrowser,
   wsUserOp,
+  wsClient,
 } from '../utils';
 import { WebSocketService, UserService } from '../services';
 import { i18n } from '../i18next';
@@ -53,7 +54,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
       this.state.categories = this.isoData.routeData[0].categories;
       this.state.loading = false;
     } else {
-      WebSocketService.Instance.client.listCategories();
+      WebSocketService.Instance.send(wsClient.listCategories());
     }
   }
 
diff --git a/src/shared/components/create-post.tsx b/src/shared/components/create-post.tsx
index 35fd6a8..edb2f05 100644
--- a/src/shared/components/create-post.tsx
+++ b/src/shared/components/create-post.tsx
@@ -3,9 +3,12 @@ import { Subscription } from 'rxjs';
 import { PostForm } from './post-form';
 import { HtmlTags } from './html-tags';
 import {
+  authField,
   isBrowser,
   setIsoData,
+  setOptionalAuth,
   toast,
+  wsClient,
   wsJsonToRes,
   wsSubscribe,
   wsUserOp,
@@ -64,9 +67,11 @@ export class CreatePost extends Component<any, CreatePostState> {
     let listCommunitiesForm: ListCommunities = {
       sort: SortType.TopAll,
       limit: 9999,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
-    WebSocketService.Instance.client.listCommunities(listCommunitiesForm);
+    WebSocketService.Instance.send(
+      wsClient.listCommunities(listCommunitiesForm)
+    );
   }
 
   componentWillUnmount() {
@@ -157,8 +162,8 @@ export class CreatePost extends Component<any, CreatePostState> {
     let listCommunitiesForm: ListCommunities = {
       sort: SortType.TopAll,
       limit: 9999,
-      auth: req.auth,
     };
+    setOptionalAuth(listCommunitiesForm, req.auth);
     return [req.client.listCommunities(listCommunitiesForm)];
   }
 
diff --git a/src/shared/components/create-private-message.tsx b/src/shared/components/create-private-message.tsx
index 90e17c9..506e3ee 100644
--- a/src/shared/components/create-private-message.tsx
+++ b/src/shared/components/create-private-message.tsx
@@ -12,10 +12,12 @@ import {
   GetUserDetails,
 } from 'lemmy-js-client';
 import {
+  authField,
   getRecipientIdFromProps,
   isBrowser,
   setIsoData,
   toast,
+  wsClient,
   wsJsonToRes,
   wsSubscribe,
   wsUserOp,
@@ -73,9 +75,9 @@ export class CreatePrivateMessage extends Component<
       user_id: this.state.recipient_id,
       sort: SortType.New,
       saved_only: false,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
-    WebSocketService.Instance.client.getUserDetails(form);
+    WebSocketService.Instance.send(wsClient.getUserDetails(form));
   }
 
   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
diff --git a/src/shared/components/inbox.tsx b/src/shared/components/inbox.tsx
index 5d01fef..0a4c11c 100644
--- a/src/shared/components/inbox.tsx
+++ b/src/shared/components/inbox.tsx
@@ -31,6 +31,8 @@ import {
   wsSubscribe,
   isBrowser,
   wsUserOp,
+  wsClient,
+  authField,
 } from '../utils';
 import { CommentNodes } from './comment-nodes';
 import { PrivateMessage } from './private-message';
@@ -498,26 +500,28 @@ export class Inbox extends Component<any, InboxState> {
       unread_only: this.state.unreadOrAll == UnreadOrAll.Unread,
       page: this.state.page,
       limit: fetchLimit,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.getReplies(repliesForm);
+    WebSocketService.Instance.send(wsClient.getReplies(repliesForm));
 
     let userMentionsForm: GetUserMentions = {
       sort: this.state.sort,
       unread_only: this.state.unreadOrAll == UnreadOrAll.Unread,
       page: this.state.page,
       limit: fetchLimit,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.getUserMentions(userMentionsForm);
+    WebSocketService.Instance.send(wsClient.getUserMentions(userMentionsForm));
 
     let privateMessagesForm: GetPrivateMessages = {
       unread_only: this.state.unreadOrAll == UnreadOrAll.Unread,
       page: this.state.page,
       limit: fetchLimit,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.getPrivateMessages(privateMessagesForm);
+    WebSocketService.Instance.send(
+      wsClient.getPrivateMessages(privateMessagesForm)
+    );
   }
 
   handleSortChange(val: SortType) {
@@ -528,9 +532,11 @@ export class Inbox extends Component<any, InboxState> {
   }
 
   markAllAsRead(i: Inbox) {
-    WebSocketService.Instance.client.markAllAsRead({
-      auth: UserService.Instance.authField(),
-    });
+    WebSocketService.Instance.send(
+      wsClient.markAllAsRead({
+        auth: authField(),
+      })
+    );
     i.state.replies = [];
     i.state.mentions = [];
     i.state.messages = [];
diff --git a/src/shared/components/login.tsx b/src/shared/components/login.tsx
index 8ca9396..c650c38 100644
--- a/src/shared/components/login.tsx
+++ b/src/shared/components/login.tsx
@@ -19,6 +19,8 @@ import {
   isBrowser,
   setIsoData,
   wsUserOp,
+  wsClient,
+  authField,
 } from '../utils';
 import { i18n } from '../i18next';
 import { HtmlTags } from './html-tags';
@@ -67,7 +69,7 @@ export class Login extends Component<any, State> {
     this.subscription = wsSubscribe(this.parseMessage);
 
     if (isBrowser()) {
-      WebSocketService.Instance.client.getCaptcha();
+      WebSocketService.Instance.send(wsClient.getCaptcha());
     }
   }
 
@@ -349,7 +351,7 @@ export class Login extends Component<any, State> {
     event.preventDefault();
     i.state.loginLoading = true;
     i.setState(i.state);
-    WebSocketService.Instance.client.login(i.state.loginForm);
+    WebSocketService.Instance.send(wsClient.login(i.state.loginForm));
   }
 
   handleLoginUsernameChange(i: Login, event: any) {
@@ -366,7 +368,7 @@ export class Login extends Component<any, State> {
     event.preventDefault();
     i.state.registerLoading = true;
     i.setState(i.state);
-    WebSocketService.Instance.client.register(i.state.registerForm);
+    WebSocketService.Instance.send(wsClient.register(i.state.registerForm));
   }
 
   handleRegisterUsernameChange(i: Login, event: any) {
@@ -404,7 +406,7 @@ export class Login extends Component<any, State> {
 
   handleRegenCaptcha(_i: Login, event: any) {
     event.preventDefault();
-    WebSocketService.Instance.client.getCaptcha();
+    WebSocketService.Instance.send(wsClient.getCaptcha());
   }
 
   handlePasswordReset(i: Login, event: any) {
@@ -412,7 +414,7 @@ export class Login extends Component<any, State> {
     let resetForm: PasswordReset = {
       email: i.state.loginForm.username_or_email,
     };
-    WebSocketService.Instance.client.passwordReset(resetForm);
+    WebSocketService.Instance.send(wsClient.passwordReset(resetForm));
   }
 
   handleCaptchaPlay(i: Login, event: any) {
@@ -439,7 +441,7 @@ export class Login extends Component<any, State> {
       this.state = this.emptyState;
       this.state.registerForm.captcha_answer = undefined;
       // Refetch another captcha
-      WebSocketService.Instance.client.getCaptcha();
+      WebSocketService.Instance.send(wsClient.getCaptcha());
       this.setState(this.state);
       return;
     } else {
@@ -448,9 +450,11 @@ export class Login extends Component<any, State> {
         this.state = this.emptyState;
         this.setState(this.state);
         UserService.Instance.login(data);
-        WebSocketService.Instance.client.userJoin({
-          auth: UserService.Instance.authField(),
-        });
+        WebSocketService.Instance.send(
+          wsClient.userJoin({
+            auth: authField(),
+          })
+        );
         toast(i18n.t('logged_in'));
         this.props.history.push('/');
       } else if (op == UserOperation.Register) {
@@ -458,9 +462,11 @@ export class Login extends Component<any, State> {
         this.state = this.emptyState;
         this.setState(this.state);
         UserService.Instance.login(data);
-        WebSocketService.Instance.client.userJoin({
-          auth: UserService.Instance.authField(),
-        });
+        WebSocketService.Instance.send(
+          wsClient.userJoin({
+            auth: authField(),
+          })
+        );
         this.props.history.push('/communities');
       } else if (op == UserOperation.GetCaptcha) {
         let data = wsJsonToRes<GetCaptchaResponse>(msg).data;
diff --git a/src/shared/components/main.tsx b/src/shared/components/main.tsx
index 0bfe08d..fbccf51 100644
--- a/src/shared/components/main.tsx
+++ b/src/shared/components/main.tsx
@@ -55,6 +55,9 @@ import {
   wsSubscribe,
   isBrowser,
   wsUserOp,
+  setOptionalAuth,
+  wsClient,
+  authField,
 } from '../utils';
 import { i18n } from '../i18next';
 import { T } from 'inferno-i18next';
@@ -133,9 +136,11 @@ export class Main extends Component<any, MainState> {
       this.fetchTrendingCommunities();
       this.fetchData();
       if (UserService.Instance.user) {
-        WebSocketService.Instance.client.getFollowedCommunities({
-          auth: UserService.Instance.authField(),
-        });
+        WebSocketService.Instance.send(
+          wsClient.getFollowedCommunities({
+            auth: authField(),
+          })
+        );
       }
     }
 
@@ -146,9 +151,11 @@ export class Main extends Component<any, MainState> {
     let listCommunitiesForm: ListCommunities = {
       sort: SortType.Hot,
       limit: 6,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
-    WebSocketService.Instance.client.listCommunities(listCommunitiesForm);
+    WebSocketService.Instance.send(
+      wsClient.listCommunities(listCommunitiesForm)
+    );
   }
 
   componentDidMount() {
@@ -157,7 +164,7 @@ export class Main extends Component<any, MainState> {
       this.context.router.history.push('/setup');
     }
 
-    WebSocketService.Instance.client.communityJoin({ community_id: 0 });
+    WebSocketService.Instance.send(wsClient.communityJoin({ community_id: 0 }));
   }
 
   componentWillUnmount() {
@@ -206,8 +213,8 @@ export class Main extends Component<any, MainState> {
         limit: fetchLimit,
         sort,
         type_,
-        auth: req.auth,
       };
+      setOptionalAuth(getPostsForm, req.auth);
       promises.push(req.client.getPosts(getPostsForm));
     } else {
       let getCommentsForm: GetComments = {
@@ -215,8 +222,8 @@ export class Main extends Component<any, MainState> {
         limit: fetchLimit,
         sort,
         type_,
-        auth: req.auth,
       };
+      setOptionalAuth(getCommentsForm, req.auth);
       promises.push(req.client.getComments(getCommentsForm));
     }
 
@@ -661,18 +668,18 @@ export class Main extends Component<any, MainState> {
         limit: fetchLimit,
         sort: this.state.sort,
         type_: this.state.listingType,
-        auth: UserService.Instance.authField(false),
+        auth: authField(false),
       };
-      WebSocketService.Instance.client.getPosts(getPostsForm);
+      WebSocketService.Instance.send(wsClient.getPosts(getPostsForm));
     } else {
       let getCommentsForm: GetComments = {
         page: this.state.page,
         limit: fetchLimit,
         sort: this.state.sort,
         type_: this.state.listingType,
-        auth: UserService.Instance.authField(false),
+        auth: authField(false),
       };
-      WebSocketService.Instance.client.getComments(getCommentsForm);
+      WebSocketService.Instance.send(wsClient.getComments(getCommentsForm));
     }
   }
 
@@ -682,7 +689,9 @@ export class Main extends Component<any, MainState> {
       toast(i18n.t(msg.error), 'danger');
       return;
     } else if (msg.reconnect) {
-      WebSocketService.Instance.client.communityJoin({ community_id: 0 });
+      WebSocketService.Instance.send(
+        wsClient.communityJoin({ community_id: 0 })
+      );
       this.fetchData();
     } else if (op == UserOperation.GetFollowedCommunities) {
       let data = wsJsonToRes<GetFollowedCommunitiesResponse>(msg).data;
diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx
index fcd18e5..cfdaef7 100644
--- a/src/shared/components/modlog.tsx
+++ b/src/shared/components/modlog.tsx
@@ -25,6 +25,7 @@ import {
   wsSubscribe,
   isBrowser,
   wsUserOp,
+  wsClient,
 } from '../utils';
 import { MomentTime } from './moment-time';
 import { HtmlTags } from './html-tags';
@@ -439,7 +440,7 @@ export class Modlog extends Component<any, ModlogState> {
       page: this.state.page,
       limit: fetchLimit,
     };
-    WebSocketService.Instance.client.getModlog(modlogForm);
+    WebSocketService.Instance.send(wsClient.getModlog(modlogForm));
   }
 
   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
diff --git a/src/shared/components/navbar.tsx b/src/shared/components/navbar.tsx
index e31d0d5..ea191b8 100644
--- a/src/shared/components/navbar.tsx
+++ b/src/shared/components/navbar.tsx
@@ -30,6 +30,8 @@ import {
   wsSubscribe,
   supportLemmyUrl,
   wsUserOp,
+  wsClient,
+  authField,
 } from '../utils';
 import { i18n } from '../i18next';
 import { PictrsImage } from './pictrs-image';
@@ -88,9 +90,11 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
         // i18n.changeLanguage('de');
       } else {
         this.requestNotificationPermission();
-        WebSocketService.Instance.client.userJoin({
-          auth: UserService.Instance.authField(),
-        });
+        WebSocketService.Instance.send(
+          wsClient.userJoin({
+            auth: authField(),
+          })
+        );
         this.fetchUnreads();
       }
 
@@ -98,7 +102,9 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
         // A login
         if (res !== undefined) {
           this.requestNotificationPermission();
-          WebSocketService.Instance.client.getSite();
+          WebSocketService.Instance.send(
+            wsClient.getSite({ auth: authField() })
+          );
         } else {
           this.setState({ isLoggedIn: false });
         }
@@ -167,7 +173,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
 
   // TODO class active corresponding to current page
   navbar() {
-    let user = this.props.site_res.my_user;
+    let user = this.props.site_res.my_user || UserService.Instance.user;
     return (
       <nav class="navbar navbar-expand-lg navbar-light shadow-sm p-0 px-3">
         <div class="container">
@@ -376,9 +382,11 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
       }
       return;
     } else if (msg.reconnect) {
-      WebSocketService.Instance.client.userJoin({
-        auth: UserService.Instance.authField(),
-      });
+      WebSocketService.Instance.send(
+        wsClient.userJoin({
+          auth: authField(),
+        })
+      );
       this.fetchUnreads();
     } else if (op == UserOperation.GetReplies) {
       let data = wsJsonToRes<GetRepliesResponse>(msg).data;
@@ -409,6 +417,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
     } else if (op == UserOperation.GetSite) {
       // This is only called on a successful login
       let data = wsJsonToRes<GetSiteResponse>(msg).data;
+      console.log(data.my_user);
       UserService.Instance.user = data.my_user;
       setTheme(UserService.Instance.user.theme);
       i18n.changeLanguage(getLanguage());
@@ -450,7 +459,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
       unread_only: true,
       page: 1,
       limit: fetchLimit,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
     let userMentionsForm: GetUserMentions = {
@@ -458,20 +467,24 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
       unread_only: true,
       page: 1,
       limit: fetchLimit,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
     let privateMessagesForm: GetPrivateMessages = {
       unread_only: true,
       page: 1,
       limit: fetchLimit,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
     if (this.currentLocation !== '/inbox') {
-      WebSocketService.Instance.client.getReplies(repliesForm);
-      WebSocketService.Instance.client.getUserMentions(userMentionsForm);
-      WebSocketService.Instance.client.getPrivateMessages(privateMessagesForm);
+      WebSocketService.Instance.send(wsClient.getReplies(repliesForm));
+      WebSocketService.Instance.send(
+        wsClient.getUserMentions(userMentionsForm)
+      );
+      WebSocketService.Instance.send(
+        wsClient.getPrivateMessages(privateMessagesForm)
+      );
     }
   }
 
diff --git a/src/shared/components/password_change.tsx b/src/shared/components/password_change.tsx
index 4dcd6c6..6ffa3e0 100644
--- a/src/shared/components/password_change.tsx
+++ b/src/shared/components/password_change.tsx
@@ -15,6 +15,7 @@ import {
   isBrowser,
   wsSubscribe,
   wsUserOp,
+  wsClient,
 } from '../utils';
 import { i18n } from '../i18next';
 import { HtmlTags } from './html-tags';
@@ -138,7 +139,9 @@ export class PasswordChange extends Component<any, State> {
     i.state.loading = true;
     i.setState(i.state);
 
-    WebSocketService.Instance.client.passwordChange(i.state.passwordChangeForm);
+    WebSocketService.Instance.send(
+      wsClient.passwordChange(i.state.passwordChangeForm)
+    );
   }
 
   parseMessage(msg: any) {
diff --git a/src/shared/components/post-form.tsx b/src/shared/components/post-form.tsx
index c64104b..f4ff5ea 100644
--- a/src/shared/components/post-form.tsx
+++ b/src/shared/components/post-form.tsx
@@ -34,6 +34,8 @@ import {
   wsSubscribe,
   isBrowser,
   wsUserOp,
+  wsClient,
+  authField,
 } from '../utils';
 
 var Choices;
@@ -76,7 +78,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       community_id: null,
       name: null,
       nsfw: false,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     },
     loading: false,
     imageLoading: false,
@@ -102,7 +104,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
         community_id: this.props.post_view.community.id,
         url: this.props.post_view.post.url,
         nsfw: this.props.post_view.post.nsfw,
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
     }
 
@@ -377,9 +379,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
         ...i.state.postForm,
         edit_id: i.props.post_view.post.id,
       };
-      WebSocketService.Instance.client.editPost(form);
+      WebSocketService.Instance.send(wsClient.editPost(form));
     } else {
-      WebSocketService.Instance.client.createPost(i.state.postForm);
+      WebSocketService.Instance.send(wsClient.createPost(i.state.postForm));
     }
     i.state.loading = true;
     i.setState(i.state);
@@ -408,10 +410,10 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
         sort: SortType.TopAll,
         page: 1,
         limit: 6,
-        auth: UserService.Instance.authField(false),
+        auth: authField(false),
       };
 
-      WebSocketService.Instance.client.search(form);
+      WebSocketService.Instance.send(wsClient.search(form));
 
       // Fetch the page title
       getPageTitle(this.state.postForm.url).then(d => {
@@ -438,11 +440,11 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
       community_id: this.state.postForm.community_id,
       page: 1,
       limit: 6,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
 
     if (this.state.postForm.name !== '') {
-      WebSocketService.Instance.client.search(form);
+      WebSocketService.Instance.send(wsClient.search(form));
     } else {
       this.state.suggestedPosts = [];
     }
diff --git a/src/shared/components/post-listing.tsx b/src/shared/components/post-listing.tsx
index 881b9b0..7bf2174 100644
--- a/src/shared/components/post-listing.tsx
+++ b/src/shared/components/post-listing.tsx
@@ -36,6 +36,8 @@ import {
   setupTippy,
   hostname,
   previewLines,
+  wsClient,
+  authField,
 } from '../utils';
 import { i18n } from '../i18next';
 import { externalHost } from '../env';
@@ -1175,10 +1177,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     let form: CreatePostLike = {
       post_id: i.props.post_view.post.id,
       score: i.state.my_vote,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
-    WebSocketService.Instance.client.likePost(form);
+    WebSocketService.Instance.send(wsClient.likePost(form));
     i.setState(i.state);
     setupTippy();
   }
@@ -1207,10 +1209,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     let form: CreatePostLike = {
       post_id: i.props.post_view.post.id,
       score: i.state.my_vote,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
-    WebSocketService.Instance.client.likePost(form);
+    WebSocketService.Instance.send(wsClient.likePost(form));
     i.setState(i.state);
     setupTippy();
   }
@@ -1235,9 +1237,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     let deleteForm: DeletePost = {
       edit_id: i.props.post_view.post.id,
       deleted: !i.props.post_view.post.deleted,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.deletePost(deleteForm);
+    WebSocketService.Instance.send(wsClient.deletePost(deleteForm));
   }
 
   handleSavePostClick(i: PostListing) {
@@ -1246,10 +1248,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     let form: SavePost = {
       post_id: i.props.post_view.post.id,
       save: saved,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
 
-    WebSocketService.Instance.client.savePost(form);
+    WebSocketService.Instance.send(wsClient.savePost(form));
   }
 
   get crossPostParams(): string {
@@ -1286,9 +1288,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
       edit_id: i.props.post_view.post.id,
       removed: !i.props.post_view.post.removed,
       reason: i.state.removeReason,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.removePost(form);
+    WebSocketService.Instance.send(wsClient.removePost(form));
 
     i.state.showRemoveDialog = false;
     i.setState(i.state);
@@ -1298,18 +1300,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     let form: LockPost = {
       edit_id: i.props.post_view.post.id,
       locked: !i.props.post_view.post.locked,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.lockPost(form);
+    WebSocketService.Instance.send(wsClient.lockPost(form));
   }
 
   handleModSticky(i: PostListing) {
     let form: StickyPost = {
       edit_id: i.props.post_view.post.id,
       stickied: !i.props.post_view.post.stickied,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.stickyPost(form);
+    WebSocketService.Instance.send(wsClient.stickyPost(form));
   }
 
   handleModBanFromCommunityShow(i: PostListing) {
@@ -1362,9 +1364,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
         remove_data: i.state.removeData,
         reason: i.state.banReason,
         expires: getUnixTime(i.state.banExpires),
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.banFromCommunity(form);
+      WebSocketService.Instance.send(wsClient.banFromCommunity(form));
     } else {
       // If its an unban, restore all their data
       let ban = !i.props.post_view.creator.banned;
@@ -1377,9 +1379,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
         remove_data: i.state.removeData,
         reason: i.state.banReason,
         expires: getUnixTime(i.state.banExpires),
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.banUser(form);
+      WebSocketService.Instance.send(wsClient.banUser(form));
     }
 
     i.state.showBanDialog = false;
@@ -1391,9 +1393,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
       user_id: i.props.post_view.creator.id,
       community_id: i.props.post_view.community.id,
       added: !i.isMod,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.addModToCommunity(form);
+    WebSocketService.Instance.send(wsClient.addModToCommunity(form));
     i.setState(i.state);
   }
 
@@ -1401,9 +1403,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     let form: AddAdmin = {
       user_id: i.props.post_view.creator.id,
       added: !i.isAdmin,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.addAdmin(form);
+    WebSocketService.Instance.send(wsClient.addAdmin(form));
     i.setState(i.state);
   }
 
@@ -1421,9 +1423,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
     let form: TransferCommunity = {
       community_id: i.props.post_view.community.id,
       user_id: i.props.post_view.creator.id,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.transferCommunity(form);
+    WebSocketService.Instance.send(wsClient.transferCommunity(form));
     i.state.showConfirmTransferCommunity = false;
     i.setState(i.state);
   }
@@ -1441,9 +1443,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
   handleTransferSite(i: PostListing) {
     let form: TransferSite = {
       user_id: i.props.post_view.creator.id,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.transferSite(form);
+    WebSocketService.Instance.send(wsClient.transferSite(form));
     i.state.showConfirmTransferSite = false;
     i.setState(i.state);
   }
diff --git a/src/shared/components/post.tsx b/src/shared/components/post.tsx
index 1d800fc..160dfcc 100644
--- a/src/shared/components/post.tsx
+++ b/src/shared/components/post.tsx
@@ -47,6 +47,9 @@ import {
   previewLines,
   isImage,
   wsUserOp,
+  wsClient,
+  authField,
+  setOptionalAuth,
 } from '../utils';
 import { PostListing } from './post-listing';
 import { Sidebar } from './sidebar';
@@ -103,16 +106,16 @@ export class Post extends Component<any, PostState> {
       }
     } else {
       this.fetchPost();
-      WebSocketService.Instance.client.listCategories();
+      WebSocketService.Instance.send(wsClient.listCategories());
     }
   }
 
   fetchPost() {
     let form: GetPost = {
       id: this.state.postId,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
-    WebSocketService.Instance.client.getPost(form);
+    WebSocketService.Instance.send(wsClient.getPost(form));
   }
 
   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
@@ -123,8 +126,8 @@ export class Post extends Component<any, PostState> {
 
     let postForm: GetPost = {
       id,
-      auth: req.auth,
     };
+    setOptionalAuth(postForm, req.auth);
 
     promises.push(req.client.getPost(postForm));
     promises.push(req.client.listCategories());
@@ -138,7 +141,9 @@ export class Post extends Component<any, PostState> {
   }
 
   componentDidMount() {
-    WebSocketService.Instance.client.postJoin({ post_id: this.state.postId });
+    WebSocketService.Instance.send(
+      wsClient.postJoin({ post_id: this.state.postId })
+    );
     autosize(document.querySelectorAll('textarea'));
   }
 
@@ -191,9 +196,9 @@ export class Post extends Component<any, PostState> {
       let form: MarkCommentAsRead = {
         comment_id: found.creator.id,
         read: true,
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.markCommentAsRead(form);
+      WebSocketService.Instance.send(wsClient.markCommentAsRead(form));
       UserService.Instance.unreadCountSub.next(
         UserService.Instance.unreadCountSub.value - 1
       );
@@ -218,7 +223,7 @@ export class Post extends Component<any, PostState> {
   }
 
   render() {
-    let pv = this.state.postRes.post_view;
+    let pv = this.state.postRes?.post_view;
     return (
       <div class="container">
         {this.state.loading ? (
@@ -444,11 +449,13 @@ export class Post extends Component<any, PostState> {
       return;
     } else if (msg.reconnect) {
       let postId = Number(this.props.match.params.id);
-      WebSocketService.Instance.client.postJoin({ post_id: postId });
-      WebSocketService.Instance.client.getPost({
-        id: postId,
-        auth: UserService.Instance.authField(false),
-      });
+      WebSocketService.Instance.send(wsClient.postJoin({ post_id: postId }));
+      WebSocketService.Instance.send(
+        wsClient.getPost({
+          id: postId,
+          auth: authField(false),
+        })
+      );
     } else if (op == UserOperation.GetPost) {
       let data = wsJsonToRes<GetPostResponse>(msg).data;
       this.state.postRes = data;
@@ -462,9 +469,9 @@ export class Post extends Component<any, PostState> {
           sort: SortType.TopAll,
           page: 1,
           limit: 6,
-          auth: UserService.Instance.authField(false),
+          auth: authField(false),
         };
-        WebSocketService.Instance.client.search(form);
+        WebSocketService.Instance.send(wsClient.search(form));
       }
 
       this.setState(this.state);
diff --git a/src/shared/components/private-message-form.tsx b/src/shared/components/private-message-form.tsx
index a49f6ed..9c518aa 100644
--- a/src/shared/components/private-message-form.tsx
+++ b/src/shared/components/private-message-form.tsx
@@ -9,7 +9,7 @@ import {
   UserSafe,
   UserOperation,
 } from 'lemmy-js-client';
-import { UserService, WebSocketService } from '../services';
+import { WebSocketService } from '../services';
 import {
   capitalizeFirstLetter,
   wsJsonToRes,
@@ -18,6 +18,8 @@ import {
   wsSubscribe,
   isBrowser,
   wsUserOp,
+  wsClient,
+  authField,
 } from '../utils';
 import { UserListing } from './user-listing';
 import { MarkdownTextArea } from './markdown-textarea';
@@ -48,7 +50,7 @@ export class PrivateMessageForm extends Component<
     privateMessageForm: {
       content: null,
       recipient_id: this.props.recipient.id,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     },
     loading: false,
     previewMode: false,
@@ -191,12 +193,12 @@ export class PrivateMessageForm extends Component<
       let form: EditPrivateMessage = {
         edit_id: i.props.privateMessage.private_message.id,
         content: i.state.privateMessageForm.content,
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
-      WebSocketService.Instance.client.editPrivateMessage(form);
+      WebSocketService.Instance.send(wsClient.editPrivateMessage(form));
     } else {
-      WebSocketService.Instance.client.createPrivateMessage(
-        i.state.privateMessageForm
+      WebSocketService.Instance.send(
+        wsClient.createPrivateMessage(i.state.privateMessageForm)
       );
     }
     i.state.loading = true;
diff --git a/src/shared/components/private-message.tsx b/src/shared/components/private-message.tsx
index ffad47f..9e2fd76 100644
--- a/src/shared/components/private-message.tsx
+++ b/src/shared/components/private-message.tsx
@@ -6,7 +6,7 @@ import {
   UserSafe,
 } from 'lemmy-js-client';
 import { WebSocketService, UserService } from '../services';
-import { mdToHtml, toast } from '../utils';
+import { authField, mdToHtml, toast, wsClient } from '../utils';
 import { MomentTime } from './moment-time';
 import { PrivateMessageForm } from './private-message-form';
 import { UserListing } from './user-listing';
@@ -231,9 +231,9 @@ export class PrivateMessage extends Component<
     let form: DeletePrivateMessage = {
       edit_id: i.props.private_message_view.private_message.id,
       deleted: !i.props.private_message_view.private_message.deleted,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.deletePrivateMessage(form);
+    WebSocketService.Instance.send(wsClient.deletePrivateMessage(form));
   }
 
   handleReplyCancel() {
@@ -246,9 +246,9 @@ export class PrivateMessage extends Component<
     let form: MarkPrivateMessageAsRead = {
       edit_id: i.props.private_message_view.private_message.id,
       read: !i.props.private_message_view.private_message.read,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.markPrivateMessageAsRead(form);
+    WebSocketService.Instance.send(wsClient.markPrivateMessageAsRead(form));
   }
 
   handleMessageCollapse(i: PrivateMessage) {
diff --git a/src/shared/components/search.tsx b/src/shared/components/search.tsx
index b4196f7..9af800e 100644
--- a/src/shared/components/search.tsx
+++ b/src/shared/components/search.tsx
@@ -14,7 +14,7 @@ import {
   CommentResponse,
   Site,
 } from 'lemmy-js-client';
-import { UserService, WebSocketService } from '../services';
+import { WebSocketService } from '../services';
 import {
   wsJsonToRes,
   fetchLimit,
@@ -27,6 +27,9 @@ import {
   setIsoData,
   wsSubscribe,
   wsUserOp,
+  wsClient,
+  authField,
+  setOptionalAuth,
 } from '../utils';
 import { PostListing } from './post-listing';
 import { HtmlTags } from './html-tags';
@@ -141,8 +144,8 @@ export class Search extends Component<any, SearchState> {
       sort: this.getSortTypeFromProps(pathSplit[7]),
       page: this.getPageFromProps(pathSplit[9]),
       limit: fetchLimit,
-      auth: req.auth,
     };
+    setOptionalAuth(form, req.auth);
 
     if (form.q != '') {
       promises.push(req.client.search(form));
@@ -456,11 +459,11 @@ export class Search extends Component<any, SearchState> {
       sort: this.state.sort,
       page: this.state.page,
       limit: fetchLimit,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
 
     if (this.state.q != '') {
-      WebSocketService.Instance.client.search(form);
+      WebSocketService.Instance.send(wsClient.search(form));
     }
   }
 
diff --git a/src/shared/components/setup.tsx b/src/shared/components/setup.tsx
index c139988..bb30bc2 100644
--- a/src/shared/components/setup.tsx
+++ b/src/shared/components/setup.tsx
@@ -4,7 +4,7 @@ import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
 import { Register, LoginResponse, UserOperation } from 'lemmy-js-client';
 import { WebSocketService, UserService } from '../services';
-import { wsUserOp, wsJsonToRes, toast } from '../utils';
+import { wsUserOp, wsJsonToRes, toast, wsClient } from '../utils';
 import { SiteForm } from './site-form';
 import { i18n } from '../i18next';
 
@@ -163,7 +163,7 @@ export class Setup extends Component<any, State> {
     i.state.userLoading = true;
     i.setState(i.state);
     event.preventDefault();
-    WebSocketService.Instance.client.register(i.state.userForm);
+    WebSocketService.Instance.send(wsClient.register(i.state.userForm));
   }
 
   handleRegisterUsernameChange(i: Setup, event: any) {
diff --git a/src/shared/components/sidebar.tsx b/src/shared/components/sidebar.tsx
index 0934535..d44eb14 100644
--- a/src/shared/components/sidebar.tsx
+++ b/src/shared/components/sidebar.tsx
@@ -11,7 +11,7 @@ import {
   Category,
 } from 'lemmy-js-client';
 import { WebSocketService, UserService } from '../services';
-import { mdToHtml, getUnixTime } from '../utils';
+import { mdToHtml, getUnixTime, wsClient, authField } from '../utils';
 import { CommunityForm } from './community-form';
 import { UserListing } from './user-listing';
 import { CommunityLink } from './community-link';
@@ -394,9 +394,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
     let deleteForm: DeleteCommunity = {
       edit_id: i.props.community_view.community.id,
       deleted: !i.props.community_view.community.deleted,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.deleteCommunity(deleteForm);
+    WebSocketService.Instance.send(wsClient.deleteCommunity(deleteForm));
   }
 
   handleShowConfirmLeaveModTeamClick(i: Sidebar) {
@@ -409,9 +409,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
       user_id: UserService.Instance.user.id,
       community_id: i.props.community_view.community.id,
       added: false,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.addModToCommunity(form);
+    WebSocketService.Instance.send(wsClient.addModToCommunity(form));
     i.state.showConfirmLeaveModTeam = false;
     i.setState(i.state);
   }
@@ -426,9 +426,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
     let form: FollowCommunity = {
       community_id: communityId,
       follow: false,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.followCommunity(form);
+    WebSocketService.Instance.send(wsClient.followCommunity(form));
   }
 
   handleSubscribe(communityId: number, event: any) {
@@ -436,9 +436,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
     let form: FollowCommunity = {
       community_id: communityId,
       follow: true,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.followCommunity(form);
+    WebSocketService.Instance.send(wsClient.followCommunity(form));
   }
 
   private get amCreator(): boolean {
@@ -486,9 +486,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
       removed: !i.props.community_view.community.removed,
       reason: i.state.removeReason,
       expires: getUnixTime(i.state.removeExpires),
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     };
-    WebSocketService.Instance.client.removeCommunity(removeForm);
+    WebSocketService.Instance.send(wsClient.removeCommunity(removeForm));
 
     i.state.showRemoveDialog = false;
     i.setState(i.state);
diff --git a/src/shared/components/site-form.tsx b/src/shared/components/site-form.tsx
index 6547edd..2446b05 100644
--- a/src/shared/components/site-form.tsx
+++ b/src/shared/components/site-form.tsx
@@ -3,8 +3,13 @@ import { Prompt } from 'inferno-router';
 import { MarkdownTextArea } from './markdown-textarea';
 import { ImageUploadForm } from './image-upload-form';
 import { Site, EditSite } from 'lemmy-js-client';
-import { UserService, WebSocketService } from '../services';
-import { capitalizeFirstLetter, randomStr } from '../utils';
+import { WebSocketService } from '../services';
+import {
+  authField,
+  capitalizeFirstLetter,
+  randomStr,
+  wsClient,
+} from '../utils';
 import { i18n } from '../i18next';
 
 interface SiteFormProps {
@@ -27,7 +32,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
       name: null,
       icon: null,
       banner: null,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     },
     loading: false,
   };
@@ -55,7 +60,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
         enable_nsfw: this.props.site.enable_nsfw,
         icon: this.props.site.icon,
         banner: this.props.site.banner,
-        auth: UserService.Instance.authField(),
+        auth: authField(),
       };
     }
   }
@@ -244,9 +249,9 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
     event.preventDefault();
     i.state.loading = true;
     if (i.props.site) {
-      WebSocketService.Instance.client.editSite(i.state.siteForm);
+      WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
     } else {
-      WebSocketService.Instance.client.createSite(i.state.siteForm);
+      WebSocketService.Instance.send(wsClient.createSite(i.state.siteForm));
     }
     i.setState(i.state);
   }
diff --git a/src/shared/components/user.tsx b/src/shared/components/user.tsx
index 814e789..9cf7d66 100644
--- a/src/shared/components/user.tsx
+++ b/src/shared/components/user.tsx
@@ -42,6 +42,9 @@ import {
   previewLines,
   editPostFindRes,
   wsUserOp,
+  wsClient,
+  authField,
+  setOptionalAuth,
 } from '../utils';
 import { UserListing } from './user-listing';
 import { HtmlTags } from './html-tags';
@@ -107,14 +110,14 @@ export class User extends Component<any, UserState> {
       send_notifications_to_email: null,
       bio: null,
       preferred_username: null,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     },
     userSettingsLoading: null,
     deleteAccountLoading: null,
     deleteAccountShowConfirm: false,
     deleteAccountForm: {
       password: null,
-      auth: UserService.Instance.authField(),
+      auth: authField(),
     },
     siteRes: this.isoData.site_res,
   };
@@ -164,9 +167,9 @@ export class User extends Component<any, UserState> {
       saved_only: this.state.view === UserDetailsView.Saved,
       page: this.state.page,
       limit: fetchLimit,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
-    WebSocketService.Instance.client.getUserDetails(form);
+    WebSocketService.Instance.send(wsClient.getUserDetails(form));
   }
 
   get isCurrentUser() {
@@ -211,8 +214,8 @@ export class User extends Component<any, UserState> {
       saved_only: view === UserDetailsView.Saved,
       page,
       limit: fetchLimit,
-      auth: req.auth,
     };
+    setOptionalAuth(form, req.auth);
     this.setIdOrName(form, user_id, username);
     promises.push(req.client.getUserDetails(form));
     return promises;
@@ -1018,7 +1021,9 @@ export class User extends Component<any, UserState> {
     i.state.userSettingsLoading = true;
     i.setState(i.state);
 
-    WebSocketService.Instance.client.saveUserSettings(i.state.userSettingsForm);
+    WebSocketService.Instance.send(
+      wsClient.saveUserSettings(i.state.userSettingsForm)
+    );
   }
 
   handleDeleteAccountShowConfirmToggle(i: User, event: any) {
@@ -1042,7 +1047,9 @@ export class User extends Component<any, UserState> {
     i.state.deleteAccountLoading = true;
     i.setState(i.state);
 
-    WebSocketService.Instance.client.deleteAccount(i.state.deleteAccountForm);
+    WebSocketService.Instance.send(
+      wsClient.deleteAccount(i.state.deleteAccountForm)
+    );
     i.handleLogoutClick(i);
   }
 
diff --git a/src/shared/env.ts b/src/shared/env.ts
index 59566a1..02d66e8 100644
--- a/src/shared/env.ts
+++ b/src/shared/env.ts
@@ -25,8 +25,8 @@ const secure = isBrowser()
 const host = isBrowser() ? externalHost : internalHost;
 
 const httpBase = `http://${host}`; // Don't use secure here
-export const wsUri = `ws${secure}://${host}/api/v1/ws`;
-export const httpUri = `${httpBase}/api/v1`;
+export const wsUri = `ws${secure}://${host}/api/v2/ws`;
+export const httpUri = `${httpBase}/api/v2`;
 export const pictrsUri = `http${secure}://${host}/pictrs/image`;
 
 console.log(`httpbase: ${httpBase}`);
diff --git a/src/shared/services/UserService.ts b/src/shared/services/UserService.ts
index 391a5ef..cdcd63f 100644
--- a/src/shared/services/UserService.ts
+++ b/src/shared/services/UserService.ts
@@ -3,8 +3,6 @@ import IsomorphicCookie from 'isomorphic-cookie';
 import { User_, LoginResponse } from 'lemmy-js-client';
 import jwt_decode from 'jwt-decode';
 import { Subject, BehaviorSubject } from 'rxjs';
-import { i18n } from '../i18next';
-import { toast } from '../utils';
 
 interface Claims {
   id: number;
@@ -50,15 +48,6 @@ export class UserService {
     return IsomorphicCookie.load('jwt');
   }
 
-  public authField(throwErr: boolean = true): string {
-    if (this.auth == null && throwErr) {
-      toast(i18n.t('not_logged_in'), 'danger');
-      throw 'Not logged in';
-    } else {
-      return this.auth;
-    }
-  }
-
   private setClaims(jwt: string) {
     this.claims = jwt_decode(jwt);
     this.jwtSub.next(jwt);
diff --git a/src/shared/services/WebSocketService.ts b/src/shared/services/WebSocketService.ts
index 868bd40..3aab0e2 100644
--- a/src/shared/services/WebSocketService.ts
+++ b/src/shared/services/WebSocketService.ts
@@ -1,9 +1,5 @@
 import { wsUri } from '../env';
-import {
-  LemmyWebsocket,
-  UserViewSafe,
-  WebSocketJsonResponse,
-} from 'lemmy-js-client';
+import { UserViewSafe, WebSocketJsonResponse } from 'lemmy-js-client';
 import { isBrowser } from '../utils';
 import { Observable } from 'rxjs';
 import { share } from 'rxjs/operators';
@@ -14,7 +10,7 @@ import {
 
 export class WebSocketService {
   private static _instance: WebSocketService;
-  public ws: ReconnectingWebSocket;
+  private ws: ReconnectingWebSocket;
   public wsOptions: WSOptions = {
     connectionTimeout: 5000,
     maxRetries: 10,
@@ -23,7 +19,6 @@ export class WebSocketService {
 
   public admins: UserViewSafe[];
   public banned: UserViewSafe[];
-  public client = new LemmyWebsocket();
 
   private constructor() {
     this.ws = new ReconnectingWebSocket(wsUri, [], this.wsOptions);
@@ -46,15 +41,19 @@ export class WebSocketService {
         firstConnect = false;
       };
     }).pipe(share());
+
+    if (isBrowser()) {
+      window.onbeforeunload = () => {
+        this.ws.close();
+      };
+    }
+  }
+
+  public send(data: string) {
+    this.ws.send(data);
   }
 
   public static get Instance() {
     return this._instance || (this._instance = new this());
   }
 }
-
-if (isBrowser()) {
-  window.onbeforeunload = () => {
-    WebSocketService.Instance.ws.close();
-  };
-}
diff --git a/src/shared/utils.ts b/src/shared/utils.ts
index 603512b..5585681 100644
--- a/src/shared/utils.ts
+++ b/src/shared/utils.ts
@@ -41,6 +41,7 @@ import {
   SearchResponse,
   PostView,
   PrivateMessageView,
+  LemmyWebsocket,
 } from 'lemmy-js-client';
 
 import {
@@ -66,6 +67,9 @@ import tippy from 'tippy.js';
 import moment from 'moment';
 import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
+import { i18n } from './i18next';
+
+export const wsClient = new LemmyWebsocket();
 
 export const favIconUrl = '/static/assets/favicon.svg';
 export const favIconPngUrl = '/static/assets/apple-touch-icon.png';
@@ -719,10 +723,10 @@ function userSearch(text: string, cb: any) {
       sort: SortType.TopAll,
       page: 1,
       limit: mentionDropdownFetchLimit,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
 
-    WebSocketService.Instance.client.search(form);
+    WebSocketService.Instance.send(wsClient.search(form));
 
     let userSub = WebSocketService.Instance.subject.subscribe(
       msg => {
@@ -757,10 +761,10 @@ function communitySearch(text: string, cb: any) {
       sort: SortType.TopAll,
       page: 1,
       limit: mentionDropdownFetchLimit,
-      auth: UserService.Instance.authField(false),
+      auth: authField(false),
     };
 
-    WebSocketService.Instance.client.search(form);
+    WebSocketService.Instance.send(wsClient.search(form));
 
     let communitySub = WebSocketService.Instance.subject.subscribe(
       msg => {
@@ -1111,6 +1115,24 @@ export function wsSubscribe(parseMessage: any): Subscription {
   }
 }
 
+export function setOptionalAuth(obj: any, auth = UserService.Instance.auth) {
+  if (auth) {
+    obj.auth = auth;
+  }
+}
+
+export function authField(
+  throwErr: boolean = true,
+  auth = UserService.Instance.auth
+): string {
+  if (auth == null && throwErr) {
+    toast(i18n.t('not_logged_in'), 'danger');
+    throw 'Not logged in';
+  } else {
+    return auth;
+  }
+}
+
 moment.updateLocale('en', {
   relativeTime: {
     future: 'in %s',
-- 
2.44.1