add socket connect and reconnect to session code
This commit is contained in:
parent
e0da50eb27
commit
b05cb202b6
9 changed files with 140 additions and 166 deletions
|
|
@ -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")
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
resolve(win);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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('error', (e) => {
|
||||
console.log('ERROR: Failed to connect.');
|
||||
socket.removeAllListeners();
|
||||
socket.close();
|
||||
setTimeout(()=> {
|
||||
if (!success) {
|
||||
console.log('Attempting reconnect.');
|
||||
initSession();
|
||||
}
|
||||
}, reconnectTimeout);
|
||||
|
||||
})
|
||||
|
||||
socket.on('close', () => {
|
||||
console.log('Connection droped. Restarting.')
|
||||
initSession();
|
||||
})
|
||||
|
||||
socket.on("message", receiveMessage);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
export const sendMessage = (content: string | Buffer) => {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -12,13 +12,16 @@
|
|||
<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
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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" });
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const testMessage = {
|
|||
time: 'test'
|
||||
}
|
||||
const wss = new WebSocket.Server({
|
||||
port: 8080
|
||||
port: 8081
|
||||
});
|
||||
|
||||
wss.on("connection", function connection(ws, req) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue