]> Repos - mime-chat/commitdiff
add socket connect and reconnect to session code
authorEnrique Hernandez <hernandeze2@xavier.edu>
Wed, 10 Feb 2021 15:00:42 +0000 (09:00 -0600)
committerriqo <hernandeze2@xavier.edu>
Wed, 10 Feb 2021 22:41:03 +0000 (16:41 -0600)
src/background/createWindow.ts
src/background/run.ts
src/background/session.ts
src/background/windowEmitter.ts
src/modules/auth.ts
src/router.ts
src/views/login.vue
src/views/register.vue
testServer.js

index 02aadf9aa57ed10111f7087bcc373e9d1912dec3..22b1cd50005982b1bf49eec44b71e32e322cf1aa 100644 (file)
@@ -4,35 +4,39 @@ import { BrowserWindow } from "electron";
 import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
 import * as path from "path";
 
-export function createWindow(options: {
+interface WindowSettings {
     width: number;
     height: number;
     resizable: boolean;
-}): BrowserWindow {
+}
 
-  const win: BrowserWindow = new BrowserWindow({
-    width: options.width,
-    height: options.height,
-    resizable: options.resizable,
-    webPreferences: {
-      // Use pluginOptions.nodeIntegration, leave this alone
-      // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
-      nodeIntegration: (process.env
-        .ELECTRON_NODE_INTEGRATION as unknown) as boolean,
-      preload: path.join(__dirname, "preload.js")
-    }
-  });
+export const createWindow = async (options: WindowSettings): Promise<BrowserWindow> => {
+    return new Promise((resolve, reject) => {
+      const win: BrowserWindow = new BrowserWindow({
+        width: options.width,
+        height: options.height,
+        resizable: options.resizable,
+        webPreferences: {
+          // Use pluginOptions.nodeIntegration, leave this alone
+          // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
+          nodeIntegration: (process.env
+            .ELECTRON_NODE_INTEGRATION as unknown) as boolean,
+          preload: path.join(__dirname, "preload.js")
+        }
+      });
 
-  if (process.env.WEBPACK_DEV_SERVER_URL) {
-    // Load the url of the dev server if in development mode
-    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string);
-  } else {
-    createProtocol("app");
-    // Load the index.html when not in development
-    win.loadURL("app://./index.html");
-  }
+      if (process.env.WEBPACK_DEV_SERVER_URL) {
+        // Load the url of the dev server if in development mode
+        win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string);
+      } else {
+        createProtocol("app");
+        // Load the index.html when not in development
+        win.loadURL("app://./index.html");
+      }
 
-  return win;
+        win.webContents.on('did-finish-load', () => {
+            resolve(win);
+        });
+    })
 }
 
-
index b8af00290b1e5d08fa74a22732e233aca734a508..63d7b3d8c55132635d5fedd16b48ae58d3d2dea0 100644 (file)
@@ -1,6 +1,6 @@
 import { createWindow } from './createWindow';
 import { ipcMain  } from "electron";
-import { initSession, sendMessage, authUser, authLogin} from './session';
+import { initSession, sendMessage } from './session';
 import { windowEmitter } from './windowEmitter';
 const portAudio = require('naudiodon');
 
@@ -9,13 +9,15 @@ interface ipcRendererPayload {
     message: any;
 }
 
+let activeSession = false;
+
 /*
  * The main function will be run after electron app is ready.
  */
-export function main(): void {
+export async function main() {
 
     // create main window.
-    const win = createWindow({ width: 350, height: 525, resizable: false });
+    const win = await createWindow({ width: 350, height: 525, resizable: false });
 
     windowEmitter.on('ipc-renderer', (payload: ipcRendererPayload) => {
         win.webContents.send(payload.endpoint, {
@@ -23,22 +25,24 @@ export function main(): void {
         });
     });
 
+    // Instantiate socket session with crimata-platorm.
+    if (!activeSession) {
+        initSession();
+    }
+    activeSession = true;
+
     const handleMessage = (event: any, arg: any) => {
         sendMessage(arg);
     }
 
     const windowMount = (): void => {
-        // Instantiate socket session with crimata-platorm.
-        initSession();
         windowEmitter.emit('window-active', true);
         ipcMain.on('send-message', handleMessage);
-        ipcMain.on('auth-login', authLogin);
     }
 
     const windowDismount = (): void => {
          windowEmitter.emit('window-active', false);
          ipcMain.removeAllListeners('send-message');
-         ipcMain.removeAllListeners('auth-login');
     }
 
     // Handle window mount and dismount.
index 4612757592cb82d2f21ebbc23bda0c3c2dc29d90..8902281f09b1d855ae170714f3ab0972887d40ca 100644 (file)
@@ -2,77 +2,84 @@ import WebSocket from 'ws';
 import { windowEmitter } from './windowEmitter';
 import { ipcMain  } from "electron";
 
-type Message = {
-    type: string;
-    id: string;
-}
-
-interface RenderMessage  extends Message  {
+interface RenderMessage  {
+  type: 'render';
   content: string;
   context: string;
   subContext: string;
   modifiers: string;
   time: string;
+  id: string;
 }
 
-interface AuthUser extends Message  {
+interface UserCreds {
     email: string;
-    firstName: string;
-    lastName: string;
-    access_token: string;
+    password: string;
 }
 
 const ip = 'ws://localhost';
-const port = 8080;
+const port = 8081;
 const reconnectTimeout = 3000; //ms
 let socket: WebSocket;
 let success = false;
+let auth = false;
 
 const receiveMessage = (message: string): void => {
-  // NOTE assuming message is JSON string
-  if (message === 'locked') {
-      windowEmitter.emit('auth-resp', message);
-      return;
-  }
-  const parsed: RenderMessage | AuthUser  = JSON.parse(message);
-  if (parsed.type === "render") {
-    windowEmitter.emit('ipc-renderer', {
-        endpoint: 'render-message',
-        message: parsed
-    });
-  }
+
+    while(!auth) {
+        windowEmitter.emit('auth-res', message);
+        return;
+    }
+
+    const parsed: RenderMessage  = JSON.parse(message);
+      if (parsed.type === "render") {
+        windowEmitter.emit('ipc-renderer', {
+            endpoint: 'render-message',
+            message: parsed
+        });
+      }
 }
 
-const authToken = async (event: any, token: string): Promise<string | AuthUser > => {
+const authUser = async (event: any, payload: string | UserCreds | null): Promise<string> => {
     return new Promise((resolve, reject) => {
         console.log('authenticating...');
-        windowEmitter.on('auth-resp', (arg: string | AuthUser) => {
-            if (arg === 'locked') {
-                reject(arg);
+        windowEmitter.on('auth-res', (res: string) => {
+            if (res === 'locked') {
+                reject(res);
+            } else {
+                auth = true;
+                resolve(res);
             }
-            resolve(arg);
         });
-        if (token) {
-            socket.send(token);
-        } else {
+        if (!payload) {
             socket.send('no-token');
+        } else if (typeof payload === 'string' || payload instanceof String) {
+            socket.send(payload);
+        } else {
+            socket.send(JSON.stringify(payload));
         }
     });
 };
 
-// Connect and authenticate
-export function initSession() {
+export const initSession = () => {
+    if (socket) {
+        socket.removeAllListeners();
+        socket.terminate();
+        socket.close();
+        success = false;
+    }
+
+    console.log('Connecting to Crimata Servers...');
 
     socket = new WebSocket(`${ip}:${port}`);
     socket.binaryType = 'arraybuffer';
 
     socket.on('open', () => {
-        console.log('Connected to crimata-platform');
-        success = true;
+        console.log('Success! Connected to Crimata.');
 
         // handle renderer auth-token event
-        ipcMain.removeHandler('auth-token'); // avoid setting duplicate handlers
-        ipcMain.handle('auth-token', authToken);
+        ipcMain.removeHandler('auth-user'); // avoid setting duplicate handlers
+        ipcMain.handle('auth-user', authUser);
 
         // fetch token from renderer
         windowEmitter.emit('ipc-renderer', {
@@ -80,28 +87,28 @@ export function initSession() {
             message: null
         });
 
-    })
+        success = true;
+    });
 
-    socket.on("message", receiveMessage);
+    socket.on('error', (e) => {
+        console.log('ERROR: Failed to connect.');
+        socket.removeAllListeners();
+        socket.close();
+        setTimeout(()=> {
+            if (!success) {
+                console.log('Attempting reconnect.');
+                initSession();
+            }
+        }, reconnectTimeout);
 
-    setTimeout(()=> {
-        if (!success) {
-            // initSession();
-            throw new Error('Unable to connect to crimata-platform');
-        }
-    }, reconnectTimeout);
-}
+    })
 
-export const authLogin = (event: any, arg: any) => {
-    try {
-        sendMessage(arg)
-        windowEmitter.on('auth-resp', (payload: AuthUser) => {
-            event.reply('auth-login-reply', payload);
-        })
-    } catch(e) {
-        console.log('Error loging in' + e);
-        event.reply('auth-login-reply', e);
-    }
+    socket.on('close', () => {
+        console.log('Connection droped. Restarting.')
+        initSession();
+    })
+
+    socket.on("message", receiveMessage);
 }
 
 export const sendMessage = (content: string | Buffer) => {
index a56c7dff7e8572571a7e04214234ffe829f15522..65bf9ae11fbcad6db2e8e616e1ae3223392bce4d 100644 (file)
@@ -3,9 +3,3 @@ const EventEmitter = require('events');
 class WindowEmitter extends EventEmitter {}
 
 export const windowEmitter = new WindowEmitter();
-
-const ipcRend = (endpoint: string, message: any) => {
-    win.webContents.send(endpoint, {
-      message: message
-    })
-}
index ec8e4447a7bbd1342966ac5a0caed4ec92a5930b..ae908f178ff4d7fee36627c0b75cb77162d19cf6 100644 (file)
@@ -1,23 +1,13 @@
 import { reactive, watch, toRefs } from 'vue';
 import { useIpc } from './ipc';
 
-interface User {
-    id: string;
-    email: string;
-    firstName: string;
-    lastName: string;
-    access_token: string;
-}
-
 interface AuthState {
-    authenticating: boolean;
-    user?: User;
+    access_token?: string | null;
     error?: Error;
 }
 
 const state = reactive<AuthState>({
-    authenticating: false,
-    user: undefined,
+    access_token: undefined,
     error: undefined,
 });
 
@@ -26,11 +16,11 @@ const AUTH_KEY = 'crimata_token';
 const token = window.localStorage.getItem(AUTH_KEY);
 
 // authenticate on socket connect
-window.ipcRenderer.on("fetch-token", async (event, payload) => {
-    const { data, invoke  } = useIpc('auth-token');
+window.ipcRenderer.on("fetch-token", async (event, payload: null) => {
+    const { data, invoke  } = useIpc('auth-user');
     try {
         await invoke(token);
-        state.user = data.value;
+        state.access_token = data.value;
     }
     catch(e) {
         state.error = e;
@@ -39,51 +29,25 @@ window.ipcRenderer.on("fetch-token", async (event, payload) => {
     }
 });
 
-if (token) {
-    const { loading, error, data, send, invoke  } = useIpc('auth-user');
-
-    state.authenticating = true;
-
-    // authenticate token against crimata-platform
-    console.log('sending token to main')
-    send({
-        token: token
-    });
-
-    watch(loading, () => {
-        if (error.value) {
-            console.log('ERROR: failed authentication')
-            window.localStorage.removeItem(AUTH_KEY);
-        }
-        else if (data.value) {
-            state.user = data.value;
-        }
-
-        state.authenticating = false;
-    })
-} else {
-    console.log('no token to send')
-}
-
 export const useAuth = () => {
-    const setUser = (payload: User, remember: boolean) => {
+    const setToken = (token: string, remember: boolean) => {
         if (remember) {
             // Save
-            window.localStorage.setItem(AUTH_KEY, payload.access_token);
+            window.localStorage.setItem(AUTH_KEY, token);
         }
 
-        state.user = payload;
+        state.access_token = token;
         state.error = undefined;
     }
 
     const logout = (): Promise<void> => {
         window.localStorage.removeItem(AUTH_KEY);
-        return Promise.resolve(state.user = undefined);
+        return Promise.resolve(state.access_token = undefined);
     }
 
     return {
-        setUser,
+        setToken,
         logout,
-        ...toRefs(state), // authenticating, user, error
+        ...toRefs(state), // access_token, error
     }
 }
index 30c92b2f5206827ba4733381c97045841eac8a33..a0602abd491a9b521349e9c5089e212306e1489a 100644 (file)
@@ -35,13 +35,13 @@ const router = createRouter({
 });
 
 router.beforeEach((to, from, next) => {
-  const { user } = useAuth();
+  const { access_token } = useAuth();
 
   // Not logged into a guarded route?
-  if (to.meta.requiresAuth && !user?.value) next({ name: 'login' });
+  if (to.meta.requiresAuth && !access_token?.value) next({ name: 'login' });
 
   // Logged in for an auth route
-  else if ((to.name == 'login' || to.name == 'register') && user!.value) next({ name: 'home' });
+  else if ((to.name == 'login' || to.name == 'register') && access_token!.value) next({ name: 'home' });
 
   // Carry On...
   else next();
index 185b2311f38cae781ad94af8b3529237d5d69a27..38b96b6f3fd0125719a3be9f056a114db26a1278 100644 (file)
       <input class="input" type="password" v-model="password" placeholder="Password" />
     </div>
 
+    <input type="checkbox" id="checkbox" v-model="rememberMe" />
+    <label for="checkbox">Remember Me</label>
+
     <!-- submit button -->
     <button class="button" type="submit">Login</button>
   </form>
 </template>
 
 <script lang="ts">
-import { defineComponent, toRefs, reactive, watch } from "vue";
+import { defineComponent, toRefs, reactive, watch, ref } from "vue";
 import { useAuth } from "@/modules/auth";
 import { useIpc } from "@/modules/ipc";
 import { useRouter } from "vue-router";
@@ -32,27 +35,23 @@ interface LoginPayload {
 export default defineComponent({
   name: "Login",
   setup() {
-    const { setUser, user } = useAuth();
+    const { setToken, access_token } = useAuth();
     const router = useRouter();
 
-    const payload = reactive<LoginPayload>({
-      email: "",
-      password: "",
-      rememberMe: true,
-    });
+    const email = ref("");
+    const password = ref("");
+    const rememberMe = ref(false);
 
-    //const { loading, data, send, errorMessage } = useIpc("auth-login");
+    const { loading, error, data,  invoke, errorMessage  } = useIpc('auth-user');
 
-    const { loading, error, data,  invoke, errorMessage  } = useIpc('test');
     const submit = async () => {
-      // console.log(toRefs(payload));
-        await invoke({
-            request: "register",
-            email: payload.email,
-            password: payload.password,
-            })
-        console.log('testing incoke', data.value.test)
-        // setUser(data.value, payload.rememberMe);
+        const payload = {
+          email: email.value,
+          password: password.value
+        };
+        await invoke(payload);
+        console.log('testing incoke', data.value)
+        setToken(data.value, rememberMe.value);
         router.push({ name: "home" });
     };
 
@@ -60,7 +59,9 @@ export default defineComponent({
       loading,
       submit,
       errorMessage,
-      ...toRefs(payload),
+      email,
+      password,
+      rememberMe
     };
   },
 });
index 7fed6b699ecd3f949f2716e54b53251ccdf70c7d..a4a3a15a3ba0ed06e8678d64756285f25fd4c36a 100644 (file)
@@ -47,16 +47,16 @@ export default defineComponent({
       lastName: undefined,
     });
 
-    const { error, loading, send, data, errorMessage } = useIpc(
+    const { error, loading, invoke, data, errorMessage } = useIpc(
       "auth-register"
     );
 
-    const { setUser } = useAuth();
+    const { setToken } = useAuth();
     const router = useRouter();
 
     const submit = async () => {
-      send(payload);
-      setUser(data.value, true);
+      await invoke(payload);
+      setToken(data.value, true);
       router.push({ name: "home" });
     };
 
index 3d9864f4547c33b76a3b3c1802767b337d6214a3..e5066250bd2fc202084a3fd2895441a4ea9c4483 100644 (file)
@@ -9,7 +9,7 @@ const testMessage = {
   time: 'test'
 }
 const wss = new WebSocket.Server({
-  port: 8080
+  port: 8081
 });
 
 wss.on("connection", function connection(ws, req) {