BBIO-46 WIP
This commit is contained in:
parent
be1e94ee06
commit
b387643068
@ -1,5 +1,5 @@
|
||||
--
|
||||
-- Generated by basebox compiler (bbc) version 0.1.0-beta.23 at 2023-11-01 03:18:33+01:00
|
||||
-- Generated by basebox compiler (bbc) version 0.1.0-beta.23 at 2023-11-01 10:35:59+01:00
|
||||
--
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
@ -23,6 +23,12 @@ CREATE TABLE "User" (
|
||||
"name" VARCHAR
|
||||
);
|
||||
|
||||
ALTER TABLE "List" ADD COLUMN ".ownerId" VARCHAR NOT NULL;
|
||||
|
||||
ALTER TABLE "Task" ADD COLUMN ".ownerId" VARCHAR NOT NULL;
|
||||
|
||||
ALTER TABLE "User" ADD COLUMN ".ownerId" VARCHAR NOT NULL;
|
||||
|
||||
ALTER TABLE "List" ADD PRIMARY KEY ("id");
|
||||
|
||||
ALTER TABLE "Task" ADD PRIMARY KEY ("id");
|
||||
@ -37,9 +43,3 @@ ALTER TABLE "Task" ADD CONSTRAINT fk_task_3 FOREIGN KEY ("list_id") REFERENCES "
|
||||
|
||||
ALTER TABLE "User" ADD CONSTRAINT uq_user_4 UNIQUE (".ownerId");
|
||||
|
||||
ALTER TABLE "List" ADD COLUMN ".ownerId" VARCHAR NOT NULL;
|
||||
|
||||
ALTER TABLE "Task" ADD COLUMN ".ownerId" VARCHAR NOT NULL;
|
||||
|
||||
ALTER TABLE "User" ADD COLUMN ".ownerId" VARCHAR NOT NULL;
|
||||
|
||||
|
@ -1,6 +1,31 @@
|
||||
#
|
||||
# Generated by bbc (basebox compiler) version 0.1.0-beta.23 at 2023-11-01 03:18:33+01:00
|
||||
# Generated by bbc (basebox compiler) version 0.1.0-beta.23 at 2023-11-01 10:35:59+01:00
|
||||
#
|
||||
[resolvers._bb_user_User]
|
||||
operation_name = "_bb_user_User"
|
||||
|
||||
[resolvers._bb_user_User.resolver.InternalQueryBuilder]
|
||||
command_type = "SQLSelect"
|
||||
|
||||
[resolvers._bb_user_User.resolver.InternalQueryBuilder.command]
|
||||
table = "User"
|
||||
command_type = "SQLSelect"
|
||||
modify_values = []
|
||||
nested_modify_tables = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers._bb_user_User.resolver.InternalQueryBuilder.command.columns]]
|
||||
|
||||
[resolvers._bb_user_User.resolver.InternalQueryBuilder.command.columns.Column]
|
||||
table = "User"
|
||||
column = "username"
|
||||
|
||||
[[resolvers._bb_user_User.resolver.InternalQueryBuilder.command.where_clauses]]
|
||||
table = "User"
|
||||
column = ".ownerId"
|
||||
condition_str = "= $1"
|
||||
index = ""
|
||||
|
||||
[resolvers.updateTask]
|
||||
operation_name = "updateTask"
|
||||
|
||||
@ -36,45 +61,39 @@ column = "id"
|
||||
condition_str = "= '$id'"
|
||||
index = ""
|
||||
|
||||
[resolvers.getUser]
|
||||
operation_name = "getUser"
|
||||
[resolvers.createTask]
|
||||
operation_name = "createTask"
|
||||
|
||||
[resolvers.getUser.resolver.QueryBuilder]
|
||||
command_type = "SQLSelect"
|
||||
[resolvers.createTask.resolver.QueryBuilder]
|
||||
command_type = "SQLInsert"
|
||||
|
||||
[resolvers.getUser.resolver.QueryBuilder.command]
|
||||
table = "User"
|
||||
command_type = "SQLSelect"
|
||||
columns = []
|
||||
modify_values = []
|
||||
nested_modify_tables = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.getUser.resolver.QueryBuilder.command.where_clauses]]
|
||||
table = "User"
|
||||
column = "username"
|
||||
condition_str = "= '$username'"
|
||||
index = ""
|
||||
|
||||
[resolvers.deleteTask]
|
||||
operation_name = "deleteTask"
|
||||
|
||||
[resolvers.deleteTask.resolver.QueryBuilder]
|
||||
command_type = "SQLDelete"
|
||||
|
||||
[resolvers.deleteTask.resolver.QueryBuilder.command]
|
||||
[resolvers.createTask.resolver.QueryBuilder.command]
|
||||
table = "Task"
|
||||
command_type = "SQLSelect"
|
||||
columns = []
|
||||
modify_values = []
|
||||
nested_modify_tables = []
|
||||
where_clauses = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.deleteTask.resolver.QueryBuilder.command.where_clauses]]
|
||||
table = "Task"
|
||||
column = "id"
|
||||
condition_str = "= '$id'"
|
||||
index = ""
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "title"
|
||||
value = "'$title'"
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "description"
|
||||
value = "'$description'"
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "completed"
|
||||
value = "'$completed'"
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "list_id"
|
||||
value = "'$list.$id'"
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "user_username"
|
||||
value = "'$user.$username'"
|
||||
|
||||
[resolvers.createUser]
|
||||
operation_name = "createUser"
|
||||
@ -98,6 +117,46 @@ value = "'$username'"
|
||||
column = "name"
|
||||
value = "'$name'"
|
||||
|
||||
[resolvers.deleteTask]
|
||||
operation_name = "deleteTask"
|
||||
|
||||
[resolvers.deleteTask.resolver.QueryBuilder]
|
||||
command_type = "SQLDelete"
|
||||
|
||||
[resolvers.deleteTask.resolver.QueryBuilder.command]
|
||||
table = "Task"
|
||||
command_type = "SQLSelect"
|
||||
columns = []
|
||||
modify_values = []
|
||||
nested_modify_tables = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.deleteTask.resolver.QueryBuilder.command.where_clauses]]
|
||||
table = "Task"
|
||||
column = "id"
|
||||
condition_str = "= '$id'"
|
||||
index = ""
|
||||
|
||||
[resolvers.getUser]
|
||||
operation_name = "getUser"
|
||||
|
||||
[resolvers.getUser.resolver.QueryBuilder]
|
||||
command_type = "SQLSelect"
|
||||
|
||||
[resolvers.getUser.resolver.QueryBuilder.command]
|
||||
table = "User"
|
||||
command_type = "SQLSelect"
|
||||
columns = []
|
||||
modify_values = []
|
||||
nested_modify_tables = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.getUser.resolver.QueryBuilder.command.where_clauses]]
|
||||
table = "User"
|
||||
column = "username"
|
||||
condition_str = "= '$username'"
|
||||
index = ""
|
||||
|
||||
[resolvers.createList]
|
||||
operation_name = "createList"
|
||||
|
||||
@ -143,65 +202,6 @@ column = "id"
|
||||
condition_str = "= '$id'"
|
||||
index = ""
|
||||
|
||||
[resolvers._bb_user_User]
|
||||
operation_name = "_bb_user_User"
|
||||
|
||||
[resolvers._bb_user_User.resolver.InternalQueryBuilder]
|
||||
command_type = "SQLSelect"
|
||||
|
||||
[resolvers._bb_user_User.resolver.InternalQueryBuilder.command]
|
||||
table = "User"
|
||||
command_type = "SQLSelect"
|
||||
modify_values = []
|
||||
nested_modify_tables = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers._bb_user_User.resolver.InternalQueryBuilder.command.columns]]
|
||||
|
||||
[resolvers._bb_user_User.resolver.InternalQueryBuilder.command.columns.Column]
|
||||
table = "User"
|
||||
column = "username"
|
||||
|
||||
[[resolvers._bb_user_User.resolver.InternalQueryBuilder.command.where_clauses]]
|
||||
table = "User"
|
||||
column = ".ownerId"
|
||||
condition_str = "= $1"
|
||||
index = ""
|
||||
|
||||
[resolvers.createTask]
|
||||
operation_name = "createTask"
|
||||
|
||||
[resolvers.createTask.resolver.QueryBuilder]
|
||||
command_type = "SQLInsert"
|
||||
|
||||
[resolvers.createTask.resolver.QueryBuilder.command]
|
||||
table = "Task"
|
||||
command_type = "SQLSelect"
|
||||
columns = []
|
||||
nested_modify_tables = []
|
||||
where_clauses = []
|
||||
aggregate_result = true
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "title"
|
||||
value = "'$title'"
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "description"
|
||||
value = "'$description'"
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "completed"
|
||||
value = "'$completed'"
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "list_id"
|
||||
value = "'$list.$id'"
|
||||
|
||||
[[resolvers.createTask.resolver.QueryBuilder.command.modify_values]]
|
||||
column = "user_username"
|
||||
value = "'$user.$username'"
|
||||
|
||||
[resolvers.deleteList]
|
||||
operation_name = "deleteList"
|
||||
|
||||
|
@ -3,13 +3,14 @@ import { RouterLink, RouterView } from 'vue-router'
|
||||
import { store, loggedIn } from './store.js'
|
||||
import {clearSession} from "./store.js";
|
||||
import {Modal} from "bootstrap";
|
||||
import { getOidcUserManager } from './util/oidc';
|
||||
|
||||
/**
|
||||
* Logout the user.
|
||||
*/
|
||||
function logOut() {
|
||||
clearSession();
|
||||
location.href = "/";
|
||||
getOidcUserManager().signoutRedirect();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,7 +49,7 @@ function dismissError() {
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="navbar-text">Hello, {{ store.userDisplayName }}!</li>
|
||||
<li class="nav-item ms-2">
|
||||
<button class="nav-link btn btn-sm btn-secondary" @click="$oidc.signOut()">Logout</button>
|
||||
<button class="nav-link btn btn-sm btn-secondary" @click="logOut()">Logout</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -53,9 +53,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {gqlQuery} from "../util/net";
|
||||
import {showError, store} from "../store";
|
||||
import {showModal} from "../util/misc";
|
||||
import { gqlRequest } from "../util/net";
|
||||
import { showError, store } from "../store";
|
||||
import { showModal } from "../util/misc";
|
||||
|
||||
const NEW_LIST_ID = "new-list-id";
|
||||
|
||||
@ -96,12 +96,17 @@ export default {
|
||||
}`;
|
||||
}
|
||||
/* send query */
|
||||
gqlQuery(
|
||||
gqlRequest(
|
||||
gql
|
||||
).then(data => {
|
||||
/* Save the list's id in case it was just created */
|
||||
if (!list.id) {
|
||||
if (list.id === NEW_LIST_ID) {
|
||||
list.id = data.createList.id;
|
||||
/* Update list id in data store */
|
||||
const idx = store.lists.findIndex(item => item.id === NEW_LIST_ID);
|
||||
if (idx !== -1) {
|
||||
store.lists[idx].id = list.id;
|
||||
}
|
||||
}
|
||||
}).catch(e => {
|
||||
const errMsg = `Failed to save list: ${e}`;
|
||||
@ -122,7 +127,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
/* List must be also deleted from the server */
|
||||
gqlQuery(`mutation {
|
||||
gqlRequest(`mutation {
|
||||
deleteList(id: "${list.id}") {
|
||||
id
|
||||
}
|
||||
|
@ -73,9 +73,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {gqlQuery} from "../util/net";
|
||||
import {showError, store} from "../store";
|
||||
import {showModal} from "../util/misc";
|
||||
import { gqlRequest } from "../util/net";
|
||||
import { removeTask, showError, store } from "../store";
|
||||
import { showModal } from "../util/misc";
|
||||
|
||||
const NEW_TASK_ID = "new-task-id";
|
||||
|
||||
@ -137,7 +137,7 @@ export default {
|
||||
}
|
||||
|
||||
/* send query */
|
||||
gqlQuery(
|
||||
gqlRequest(
|
||||
request
|
||||
).then(data => {
|
||||
/* Save the task's id in case it was just created */
|
||||
@ -158,18 +158,24 @@ export default {
|
||||
deleteTask(task) {
|
||||
if (task.id !== NEW_TASK_ID) {
|
||||
/* Task must be also deleted from the server */
|
||||
gqlQuery(`mutation {
|
||||
gqlRequest(`mutation {
|
||||
deleteTask(id: "${task.id}") {
|
||||
id
|
||||
}
|
||||
}`);
|
||||
}`).then(data => {
|
||||
console.info(`Deleted task '${task.title}' with id ${task.id}`);
|
||||
/* Also remove task from the store */
|
||||
removeTask(task);
|
||||
}).catch(e => {
|
||||
const errMsg = `Failed to delete task: ${e}`;
|
||||
console.error(errMsg);
|
||||
showError(errMsg);
|
||||
});
|
||||
} else {
|
||||
/* Just delete task from the store */
|
||||
removeTask(task);
|
||||
}
|
||||
|
||||
/* delete task from the store. */
|
||||
const idx = store.tasks.findIndex(item => item.id === task.id);
|
||||
if (idx !== -1) {
|
||||
store.tasks.splice(idx, 1);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
onMounted(() => {
|
||||
console.log('Component is mounted!');
|
||||
});
|
||||
|
||||
</script>
|
@ -5,7 +5,7 @@
|
||||
* https://basebox.io
|
||||
*/
|
||||
|
||||
import {loggedIn, showError, store} from "../store";
|
||||
import {loggedIn, showError, storeInit } from "../store";
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import HomeView from '../views/HomeView.vue'
|
||||
import { objectToQueryString } from "../util/net";
|
||||
@ -39,7 +39,7 @@ router.beforeEach(async (to, from) => {
|
||||
|
||||
/* catch OIDC callback */
|
||||
if (to.path === callbackPath) {
|
||||
console.info("OIDC: got signin callback request to ", to);
|
||||
console.info("OIDC: got OIDC callback request to ", to);
|
||||
const userMgr = getOidcUserManager();
|
||||
try {
|
||||
const user = await userMgr.signinRedirectCallback(location.origin + to.fullPath);
|
||||
@ -47,6 +47,7 @@ router.beforeEach(async (to, from) => {
|
||||
storeInit(user);
|
||||
} catch (err) {
|
||||
console.error("OIDC: Error handling signin callback: ", err);
|
||||
showError("The login process failed: " + err);
|
||||
}
|
||||
/* redirect to home page */
|
||||
return {name: 'home'};
|
||||
|
26
src/store.js
26
src/store.js
@ -5,7 +5,7 @@
|
||||
* https://basebox.io
|
||||
*/
|
||||
import { reactive } from 'vue'
|
||||
import {gqlQuery} from "./util/net";
|
||||
import {gqlRequest} from "./util/net";
|
||||
|
||||
export const store = reactive({
|
||||
|
||||
@ -60,6 +60,18 @@ export function clearError() {
|
||||
store.fatalError = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a task from the store.
|
||||
*
|
||||
* This does not remove it from the database/server!
|
||||
*/
|
||||
export function removeTask(task) {
|
||||
const idx = store.tasks.findIndex(item => item.id === task.id);
|
||||
if (idx !== -1) {
|
||||
store.tasks.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize data store and database.
|
||||
*
|
||||
@ -88,7 +100,7 @@ export async function storeInit(user) {
|
||||
*/
|
||||
try {
|
||||
console.info("NOTE: If next request fails, it is probably because the user already exists. In this case, the error is ignored.");
|
||||
await gqlQuery(`mutation {
|
||||
await gqlRequest(`mutation {
|
||||
createUser(
|
||||
username: "${store.userId}",
|
||||
name: "${store.userDisplayName}"
|
||||
@ -108,7 +120,7 @@ export async function storeInit(user) {
|
||||
}
|
||||
|
||||
/* Load user info, lists and todos. */
|
||||
gqlQuery(`query {
|
||||
gqlRequest(`query {
|
||||
getUser(username: "${store.userId}") {
|
||||
name
|
||||
lists {
|
||||
@ -131,14 +143,18 @@ export async function storeInit(user) {
|
||||
/* create default list if necessary */
|
||||
if (store.lists.length === 0) {
|
||||
console.info("No lists found for current user; creating default list.");
|
||||
gqlQuery(`mutation {
|
||||
gqlRequest(`mutation {
|
||||
createList(
|
||||
title: "Default",
|
||||
user: { username: "${store.userId}" }
|
||||
) {
|
||||
title
|
||||
id
|
||||
}
|
||||
}`);
|
||||
}`).then(data => {
|
||||
/* Save new default list in store */
|
||||
store.lists.push(data.createList);
|
||||
});
|
||||
}
|
||||
|
||||
/* fix for basebox bug: task.list is returned as an array of List objects, where we expect just a single object */
|
||||
|
@ -8,7 +8,7 @@
|
||||
import {clearSession, store} from "../store";
|
||||
|
||||
/**
|
||||
* GqlError - custom error thrown by the gqlQuery function.
|
||||
* GqlError - custom error thrown by the gqlRequest function.
|
||||
*
|
||||
* Since the GraphQL server might through multiple errors at once,
|
||||
* this error class uses a message array.
|
||||
@ -102,7 +102,7 @@ class GqlError extends Error {
|
||||
* Error with error message array on failure
|
||||
*/
|
||||
|
||||
export function gqlQuery(query)
|
||||
export function gqlRequest(query)
|
||||
{
|
||||
/* prepare fetch options */
|
||||
const fetchOpt = {
|
||||
@ -113,9 +113,9 @@ export function gqlQuery(query)
|
||||
body: JSON.stringify({ query: query }),
|
||||
};
|
||||
|
||||
/* if we're logged in, we add the authorization header */
|
||||
if (store.session) {
|
||||
fetchOpt.headers["Authorization"] = `Bearer ${store.session.token}`;
|
||||
/* if we're logged in, we add the authorization header with the access token */
|
||||
if (store.user) {
|
||||
fetchOpt.headers["Authorization"] = `Bearer ${store.user.access_token}`;
|
||||
}
|
||||
|
||||
console.info(`Sending request:\n${query}`);
|
||||
|
@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Configure oidc-client-ts library and retrieve UserManager instance for authentication.
|
||||
*
|
||||
* The documentation of oidc-client-ts is very...thin; this might be helpful:
|
||||
* <https://gist.github.com/davidamidon/24c8a6980e116e62f781be4d6239d10d>
|
||||
*
|
||||
*/
|
||||
|
||||
import { Log, UserManager, WebStorageStateStore } from 'oidc-client-ts';
|
||||
@ -11,13 +14,18 @@ Log.level = (process.env.NODE_ENV === 'production') ? Log.ERROR : Log.DEBUG;
|
||||
// OIDC configuration
|
||||
const oidcProviderDomain = 'https://basebox-test-1.eu.auth0.com';
|
||||
const clientId = '5wl8hQV1thh07rScSoJ3aN56ETuXWprg';
|
||||
const clientSecret = 'QlHMvIffKLRviCcSu_bPQcf8e4dc6WeS3BwZE1r1F-9R30AFoeYEwaOazAuFenI5';
|
||||
const scopes = "openid profile email name nickname";
|
||||
export const callbackPath = "/auth/callback"
|
||||
|
||||
/* OIDC UserManager singleton */
|
||||
let userMgr = null;
|
||||
|
||||
// OIDC Client
|
||||
/**
|
||||
* Get OIDC UserManager singleton.
|
||||
*
|
||||
* @returns OIDC UserManager singleton.
|
||||
*/
|
||||
export const getOidcUserManager = () => {
|
||||
if (userMgr) {
|
||||
return userMgr;
|
||||
@ -27,11 +35,12 @@ export const getOidcUserManager = () => {
|
||||
userStore: new WebStorageStateStore(),
|
||||
authority: oidcProviderDomain,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
redirect_uri: window.location.origin + callbackPath,
|
||||
response_type: 'code',
|
||||
response_mode: 'query',
|
||||
scope: scopes,
|
||||
post_logout_redirect_uri: window.location.origin + '/home?action=logout',
|
||||
post_logout_redirect_uri: window.location.origin,
|
||||
accessTokenExpiringNotificationTime: 10,
|
||||
automaticSilentRenew: false,
|
||||
filterProtocolClaims: false,
|
||||
|
Loading…
Reference in New Issue
Block a user