add login, register, and auth

This commit is contained in:
riqo 2021-02-08 09:43:29 -06:00
commit 29f6b759f8
17 changed files with 436 additions and 55 deletions

49
src/background/audio.ts Normal file
View file

@ -0,0 +1,49 @@
const portAudio = require('naudiodon');
let audioInput: string[] = [];
function processAudio(audioInput: Array<string>): Buffer {
let audio = '';
audioInput.forEach(chunk => audio += chunk);
return Buffer.from(audio, "base64");
}
const updateRecorder = async (Event: any, record: boolean): void => {
if (record) {
ia.resume();
} else {
ia.pause();
const audio = processAudio(audioInput);
// emmit ws event with audio
// sendAudio(audio);
audioInput = [];
}
}
let ia = new portAudio.AudioIO({
inOptions: {
channelCount: 1,
sampleFormat: 16,
sampleRate: 16000,
deviceId: -1,
closeOnError: false,
}
});
ia.setEncoding('base64');
ia.start();
ia.pause();
ia.on('error', (e: Error) => {
console.log('Error recording audio', + e);
});
ia.on('data', (chunk: string) => {
audioInput.push(chunk);
});
export function useIA() {
return {
ia,
processAudio
}
}

View file

@ -1,6 +1,5 @@
import { createWindow } from './createWindow';
import { Recorder } from './recorder';
import { ipcMain, BrowserWindow } from "electron";
import { ipcMain } from "electron";
import WebSocket from 'ws';
import { windowEmitter } from './windowEmitter';
const portAudio = require('naudiodon');
@ -12,6 +11,27 @@ export function main(): void {
let audioInput: string[] = [];
const authUser = (event: any, arg: any) => {
let reply;
reply = {
id: "2",
email: "hernandeze@xavier.edu",
firstName: "Enrique",
lastName: "Hernandez",
access_token: "test-token"
}
if (arg === ['undefined']) {
reply = new Error('AUTH-FAILED');
}
event.reply('auth-user-reply', reply)
}
ipcMain.on('auth-user', authUser);
const authLogin = (event: any, arg: any) => {
console.log(arg)
event.reply('auth-login-reply', true)
}
// create main window.
const win = createWindow({ width: 350, height: 525, resizable: false });
@ -44,19 +64,16 @@ export function main(): void {
ia.resume();
} else {
ia.pause();
const audio = processAudio();
const audio = processAudio(audioInput);
sendAudio(audio);
audioInput = [];
}
}
function processAudio(): Buffer {
function processAudio(audioInput: Array<string>): Buffer {
let audio = '';
audioInput.forEach(s => {
audio += s;
});
const buffer = Buffer.from(audio, "base64");
return buffer;
audioInput.forEach(chunk => audio += chunk);
return Buffer.from(audio, "base64");
}
const windowMount = (): void => {
@ -64,13 +81,16 @@ export function main(): void {
// ipc event handlers
ipcMain.on('update-recorder', updateRecorder);
ipcMain.on('send-message', sendMessage);
ipcMain.on('auth-login', authLogin);
}
const windowDismount = (): void => {
windowEmitter.emit('window-active', false);
// TODO: Gracefully close socket connection
ipcMain.removeListener('update-recorder', updateRecorder);
ipcMain.removeListener('send-message', sendMessage);
ipcMain.removeAllListeners('update-recorder');
ipcMain.removeAllListeners('send-message');
ipcMain.removeAllListeners('auth-login');
ipcMain.removeAllListeners('auth-user');
}
// socket handlers
@ -92,12 +112,11 @@ export function main(): void {
});
ia.setEncoding('base64');
ia.start();
ia.on('error', (e: Error) => {
console.log('error recording audio', + e);
});
ia.pause();
ia.on('error', (e: Error) => {
console.log('Error recording audio', + e);
});
ia.on('data', (chunk: string) => {
audioInput.push(chunk);
console.log('Got %d characters of string data:', chunk.length);
});
}

22
src/background/user.ts Normal file
View file

@ -0,0 +1,22 @@
const authUser = (event: any, arg: any) => {
let reply;
reply = {
id: "2",
email: "hernandeze@xavier.edu",
firstName: "Enrique",
lastName: "Hernandez",
access_token: "test-token"
}
if (arg === ['undefined']) {
reply = new Error('AUTH-FAILED');
}
event.reply('auth-user-reply', reply)
}
ipcMain.on('auth-user', authUser);
const authLogin = (event: any, arg: any) => {
console.log(arg)
event.reply('auth-login-reply', true)
}

View file

@ -31,7 +31,7 @@ import useComputedBubble from "./bubbleDetails/computed";
import useBubbleDrawer from "./bubbleDetails/drawer";
// text wrap composition
import useTextWrap from "@/composables/textWrap";
import useTextWrap from "@/modules/textWrap";
import { defineComponent, onMounted, ref, reactive } from "vue";
export default defineComponent({

View file

@ -28,15 +28,12 @@
<script lang="ts">
import useMessageVisualizer from "./viewDetails/visualizer";
import useScrollView from "@/composables/scrollView";
import useScrollView from "@/modules/scrollView";
import MessageItem from "../messageBubble/index.vue";
import { Message } from "@/types/message/index";
import { Mitt } from "@/types/mitt/index";
import { defineComponent, reactive, inject } from "vue";
export default defineComponent({
name: "MessageVisualizer",
components: { MessageItem },

View file

@ -1,11 +1,7 @@
import { ref, watch, onUnmounted, onMounted } from "vue";
import useKeyDownHandler from "@/composables/keyDownHandler/useKeyDownHandler";
import useMediaStream from "@/composables/mediaStream";
import useKeyDownHandler from "@/modules/keyDownHandler/useKeyDownHandler";
import useMediaStream from "@/modules/mediaStream";
import useAudioVisualizer from './audioDetails/audioVisualizer';
import useTextVisualizer from './textDetails/textVisualizer';
/*

70
src/modules/auth.ts Normal file
View file

@ -0,0 +1,70 @@
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;
error?: Error;
}
const state = reactive<AuthState>({
authenticating: false,
user: undefined,
error: undefined,
});
const AUTH_KEY = 'crimata_token';
const token = window.localStorage.getItem(AUTH_KEY);
if (token) {
const { loading, error, data, send } = useIpc('auth-user');
state.authenticating = true;
// authenticate token against crimata-platform
send([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;
})
}
export const useAuth = () => {
const setUser = (payload: User, remember: boolean) => {
if (remember) {
// Save
window.localStorage.setItem(AUTH_KEY, payload.access_token);
}
state.user = payload;
state.error = undefined;
}
const logout = (): Promise<void> => {
window.localStorage.removeItem(AUTH_KEY);
return Promise.resolve(state.user = undefined);
}
return {
setUser,
logout,
...toRefs(state), // authenticating, user, error
}
}

54
src/modules/ipc.ts Normal file
View file

@ -0,0 +1,54 @@
import { ref, computed } from 'vue'
export const useIpc = (endpoint: string) => {
const data = ref();
const loading = ref(false);
const error = ref();
const listener = ref(false);
const errorMessage = computed(() => {
console.log('ERROR', error.value);
if (error.value) {
return error.value.message
}
})
const send = (payload?: Record<string, any>, callback?: (arg: any) => void) => {
loading.value = true;
error.value = undefined;
window.ipcRenderer.on(endpoint + '-reply', (event: any, arg: any | Error) => {
if (arg instanceof Error) {
error.value = arg;
throw arg;
} else {
if (callback) {
callback(arg);
}
data.value = arg;
loading.value = false;
}
});
window.ipcRenderer.send(endpoint, payload);
};
const onEvent = (callback: (event: any, arg: any) => void) => {
listener.value = true;
window.ipcRenderer.on(endpoint, callback);
};
const post = (payload?: Record<string, any>) => {
window.postMessage({
myTypeField: endpoint,
message: payload
}, '*')
};
return {
loading,
data,
error,
errorMessage,
send
}
}

View file

@ -1,35 +1,32 @@
import {
createRouter,
createWebHistory,
createWebHashHistory,
RouteRecordRaw
import {
createRouter,
createWebHistory,
createWebHashHistory,
RouteRecordRaw
} from "vue-router";
import Home from "./views/home.vue";
import Login from "./views/login.vue";
import Splash from "./views/splash.vue";
import Home from "@/views/home.vue";
import { useAuth } from '@/modules/auth';
// Define the routes (/*) for the app here.
const routes: Array<RouteRecordRaw> = [
{
path: "/sdf",
name: "Splash",
component: Splash
},
{
path: "/sdf",
name: "Home",
component: Home
},
{
path: "/",
name: "Login",
component: Login
name: "home",
component: Home,
meta: { requiresAuth: true },
},
{
path: "/login",
name: "login",
component: () => import("@/views/login.vue"),
meta: { requiresAuth: false },
},
{
path: "/register",
name: "register",
component: () => import("@/views/register.vue"),
meta: { requiresAuth: false },
},
];
const router = createRouter({
@ -37,4 +34,17 @@ const router = createRouter({
routes
});
export default router;
router.beforeEach((to, from, next) => {
const { user } = useAuth();
// Not logged into a guarded route?
if (to.meta.requiresAuth && !user?.value) next({ name: 'login' });
// Logged in for an auth route
else if ((to.name == 'login' || to.name == 'register') && user!.value) next({ name: 'home' });
// Carry On...
else next();
})
export default router;

View file

@ -1,17 +1,110 @@
<template>
<LoginComponent />
<form id="login" @submit.prevent="submit">
<!-- login title -->
<div id="loginTitle">Crimata Messenger</div>
<!-- username and password forms -->
<div id="loginBox">
<!-- username -->
<input class="input" type="text" v-model="email" placeholder="username" />
<!-- password -->
<input class="input" type="password" v-model="password" placeholder="Password" />
</div>
<!-- submit button -->
<button class="button" type="submit">Login</button>
</form>
</template>
<script lang="ts">
import { defineComponent, toRefs, reactive, watch } from "vue";
import { useAuth } from "@/modules/auth";
import { useIpc } from "@/modules/ipc";
import { useRouter } from "vue-router";
import { defineComponent } from "vue";
import LoginComponent from "@/components/login/index.vue";
interface LoginPayload {
email: string;
password: string;
rememberMe: boolean;
}
export default defineComponent({
name: "Login",
components: { LoginComponent },
setup() {
const { setUser, user } = useAuth();
const router = useRouter();
const payload = reactive<LoginPayload>({
email: "",
password: "",
rememberMe: true,
});
const { loading, data, send, errorMessage } = useIpc("auth-login");
const submit = async () => {
// console.log(toRefs(payload));
send({
email: payload.email,
password: payload.password,
});
console.log(data.value, "login");
// setUser(data.value, payload.rememberMe);
// router.push({ name: "home" });
};
watch(loading, () => {
console.log("loading changed");
console.log(data.value, "post laoding");
});
return {
loading,
submit,
errorMessage,
...toRefs(payload),
};
},
});
</script>
</script>
<style lang="scss" scoped>
#login {
width: 350px;
height: 500px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #e6e6e6;
}
#loginBox {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.input {
background-color: #B9B9B9;
border: none;
color: white;
padding: 16px;
text-decoration: none;
margin: 4px 2px;
cursor: pointer;
border-radius: 10px;
}
.button {
background-color: #58C4FD;
border: none;
color: white;
padding: 10px 20px;
text-decoration: none;
border-radius: 20px;
font-weight: bold;
}
</style>

View file

@ -0,0 +1,71 @@
<template>
<div id="login">
<!-- login title -->
<div id="loginTitle">Login</div>
<!-- username and password forms -->
<div id="loginBox">
<!-- username -->
<input class="input" type="text" v-model="login.username" placeholder="username" />
<!-- password -->
<input class="input" type="password" v-model="login.password" placeholder="Password" />
</div>
<!-- submit button -->
<button class="button" @click="submitCreds">Submit</button>
</div>
</template>
<script lang="ts">
import {
computed,
defineComponent,
onErrorCaptured,
reactive,
ref,
toRefs,
} from "vue";
import { useRouter } from "vue-router";
import { useIpc } from "@/modules/ipc";
import { useAuth } from "@/modules/auth";
interface RegisterPayload {
email?: string;
password?: string;
firstName?: string;
lastName?: string;
}
export default defineComponent({
name: "Register",
setup() {
const payload = reactive<RegisterPayload>({
email: undefined,
password: undefined,
firstName: undefined,
lastName: undefined,
});
const { error, loading, send, data, errorMessage } = useIpc(
"auth-register"
);
const { setUser } = useAuth();
const router = useRouter();
const submit = async () => {
send(payload);
setUser(data.value, true);
router.push({ name: "home" });
};
return {
...toRefs(payload),
submit,
loading,
errorMessage,
};
},
});
</script>