diff --git a/frontend/src/components/Sidebar.vue b/frontend/src/components/Sidebar.vue
index 8643cbd..136556f 100644
--- a/frontend/src/components/Sidebar.vue
+++ b/frontend/src/components/Sidebar.vue
@@ -9,6 +9,12 @@
+
@@ -68,6 +74,19 @@ export default {
flex-grow: 1
}
+.sidebar-link, a.sidebar-link {
+ display: block;
+ padding: .625rem 1.625rem;
+ font-weight: 400;
+ transition: background .1s ease-in-out;
+ position: relative;
+ text-decoration: none;
+ cursor: pointer;
+ color: #e9ecef80;
+ background: #222e3c;
+ border-left: 3px solid transparent;
+}
+
.sidebar-link i, .sidebar-link svg, a.sidebar-link i, a.sidebar-link svg {
margin-right: .75rem;
color: rgba(233, 236, 239, .5)
diff --git a/frontend/src/router.js b/frontend/src/router.js
index 9d8f707..275216f 100644
--- a/frontend/src/router.js
+++ b/frontend/src/router.js
@@ -1,29 +1,27 @@
import {createRouter, createWebHistory} from 'vue-router'
-import Index from '@/views/Index.vue';
+import Dashboard from '@/views/Dashboard.vue';
import Login from '@/views/Login.vue';
import Register from '@/views/Register.vue';
import store from '@/store';
+import Friends from "@/views/Friends.vue";
const routes = [
- {path: '/', component: Index, meta: {requiresAuth: true}},
+ {path: '/', component: Dashboard, meta: {requiresAuth: true}},
+ {path: '/friends', component: Friends, meta: {requiresAuth: true}},
{path: '/login', component: Login, meta: {requiresAuth: false}},
{path: '/register', component: Register, meta: {requiresAuth: false}},
]
const router = createRouter({
- // 4. Provide the history implementation to use. We are using the hash history for simplicity here.
history: createWebHistory(),
linkActiveClass: "active",
- routes, // short for `routes: routes`
+ routes,
})
router.beforeEach((to/*, from*/) => {
- // instead of having to check every route record with
- // to.matched.some(record => record.meta.requiresAuth)
+ // if this route requires auth, check if logged in, if not, redirect to login page.
if (to.meta.requiresAuth && !store.getters.isLoggedIn) {
- // this route requires auth, check if logged in
- // if not, redirect to login page.
console.log("Not logged in, redirecting to login page")
return {
path: '/login',
diff --git a/frontend/src/store.js b/frontend/src/store.js
index 6d0dd73..071004d 100644
--- a/frontend/src/store.js
+++ b/frontend/src/store.js
@@ -14,6 +14,7 @@ export default createStore({
keypair: null,
remember: false,
home_servers: null,
+ all_friends_servers: null,
resolver: new FallBackResolver(),
unreachable_neighbors: new NeighborsCache(),
},
@@ -42,9 +43,15 @@ export default createStore({
}
localStorage.setItem('remember', remember);
},
+ setFriends(state, friends) {
+ state.friends = friends;
+ },
setHomeServers(state, home_servers) {
state.home_servers = home_servers;
},
+ setAllFriendsServers(state, servers) {
+ state.all_friends_servers = servers;
+ },
logout(state) {
state.user = null;
state.token = null;
@@ -101,9 +108,79 @@ export default createStore({
commit('setHomeServers', promise)
return promise
},
+ async getAllKnownServers({state, dispatch, commit}) {
+ const friends = await dispatch('fetchFriends')
+ if (state.all_friends_servers)
+ return state.all_friends_servers
+ const promise = (async () => {
+ const servers = new ServerSetUnion([])
+ const home = await dispatch('getHomeServers')
+ servers.add(home)
+ for (const friend of friends) {
+ const s = await dispatch('lookupServer', {username: friend.username})
+ servers.add(new ServerSet(s, state.unreachable_neighbors))
+ }
+ return servers
+ })()
+ commit('setAllFriendsServers', promise)
+ return promise
+ },
async getFriendServers({state, dispatch, commit}, {username}) {
return dispatch('lookupServer', {username}).then(servers => new ServerSet(servers, state.unreachable_neighbors))
},
+ async fetchFriends({commit, dispatch, getters, state}) {
+ const servers = await dispatch('getHomeServers')
+ const data = await servers.get(getters.signAuth, '/api/friends/')
+ commit('setFriends', data)
+ return data
+ },
+ async fetchFriendRequests({state, dispatch, getters}) {
+ const servers = await dispatch('getHomeServers')
+ return await servers.get(getters.signAuth, '/api/friendrequests/')
+ },
+ async requestFriend({state, dispatch, getters}, {username}) {
+ if (username in state.friends) {
+ return true;
+ }
+ const home_servers = await dispatch('getHomeServers')
+ const home_reply = await home_servers.post(getters.signAuth, '/api/friendrequests/', {
+ befriender: state.user,
+ befriendee: username
+ })
+ if (home_reply.status !== 'pending' || !home_reply.secret)
+ return false;
+
+ const befriendee_servers = await dispatch('getFriendServers', {username})
+ const ext_reply = await befriendee_servers.post(getters.signAuth, '/api/friendrequests/', {
+ befriender: state.user,
+ befriendee: username,
+ befriender_key: nacl.to_hex(state.keypair.signPk),
+ secret: home_reply.secret
+ })
+ return true;
+ },
+ async acceptFriend({state, dispatch, getters}, {id, secret, befriender}) {
+ const home_servers = await dispatch('getHomeServers')
+ const home_reply = await home_servers.post(getters.signAuth, '/api/friends/', {
+ friend_request_id: id, secret: secret
+ })
+ const ext_servers = await dispatch('getFriendServers', {username: befriender})
+ const ext_reply = await ext_servers.post(getters.signAuth, '/api/friendrequests/', {
+ befriender: state.user,
+ befriendee: befriender,
+ befriender_key: nacl.to_hex(state.keypair.signPk),
+ secret: secret
+ })
+ return true
+ },
+ async declineFriend({state, dispatch, getters}, {id}) {
+ const servers = await dispatch('getHomeServers')
+ return await servers.delete(getters.signAuth, '/api/friendrequests/' + id + '/')
+ },
+ async dropFriend({state, dispatch, getters}, {id}) {
+ const servers = await dispatch('getHomeServers')
+ return await servers.delete(getters.signAuth, '/api/friends/' + id + '/')
+ },
},
getters: {
isLoggedIn(state) {
diff --git a/frontend/src/views/Index.vue b/frontend/src/views/Dashboard.vue
similarity index 94%
rename from frontend/src/views/Index.vue
rename to frontend/src/views/Dashboard.vue
index 90fbeb1..6c19b16 100644
--- a/frontend/src/views/Index.vue
+++ b/frontend/src/views/Dashboard.vue
@@ -18,7 +18,7 @@ import * as BIcons from "bootstrap-icons-vue";
import BaseLayout from "@/components/BaseLayout.vue";
export default {
- name: 'Index',
+ name: 'Dashboard',
components: {
...BIcons,
BaseLayout
diff --git a/frontend/src/views/Friends.vue b/frontend/src/views/Friends.vue
new file mode 100644
index 0000000..7d49453
--- /dev/null
+++ b/frontend/src/views/Friends.vue
@@ -0,0 +1,190 @@
+
+
+
+
+
Friends
+
+
+
+
+
+
+
+
+ Name |
+ Key |
+
+
+
+ Refresh
+
+ |
+
+
+
+
+ {{ request.befriender }} |
+
+ {{ request.befriender_public_key.slice(0, 32) }}...
+ |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index f6a3db5..c199937 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -2,7 +2,6 @@ import {fileURLToPath, URL} from 'node:url'
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
-import * as fs from "fs";
export default defineConfig({
plugins: [vue()],