add login, register, and auth
This commit is contained in:
parent
9d64ffcb41
commit
29f6b759f8
17 changed files with 436 additions and 55 deletions
49
src/background/audio.ts
Normal file
49
src/background/audio.ts
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
22
src/background/user.ts
Normal 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)
|
||||
}
|
||||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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
70
src/modules/auth.ts
Normal 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
54
src/modules/ipc.ts
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
Loading…
Reference in a new issue