Skip to content

Commit

Permalink
✨ feat: add base pages and auth (#14)
Browse files Browse the repository at this point in the history
* 🚧 wip: add mongoose

* fix: 🐛 mongoose adapter/callback

* refactor: ♻️ use mongoose on client end

* chore: 🔨 remove unused code

* 🚧 wip: test permissions

* 🚧 wip: test permissions

* 🚧 wip: test permissions

* 🚧 wip: test permissions

* 🚧 wip: test permissions

* ✨ feat: add error sections

* 🧑‍💻 chore: remove console.logs

---------

Co-authored-by: slugb0t <wheresdorian@gmail.com>
  • Loading branch information
megasanjay and slugb0t authored May 8, 2024
1 parent 1f7b6bc commit 384e981
Show file tree
Hide file tree
Showing 21 changed files with 1,396 additions and 337 deletions.
897 changes: 878 additions & 19 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ui/composables/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { User } from "lucia";

export const useUser = () => {
const user = useState<User | null>("user", () => null);
console.log(unref(user));

return user;
};

Expand Down
26 changes: 26 additions & 0 deletions ui/error.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup lang="ts"></script>

<template>
<NuxtLayout name="default">
<main class="grid place-items-center px-6 lg:px-8">
<div class="text-center">
<img
src="/assets/images/error/404.svg"
alt="Page not found"
class="mx-auto w-96"
/>

<h1
class="mt-4 text-3xl font-bold tracking-tight text-gray-900 sm:text-5xl"
>
Something went wrong
</h1>

<p class="mt-6 text-base leading-7 text-gray-600">
The page you are looking for might have been removed or is temporarily
unavailable.
</p>
</div>
</main>
</NuxtLayout>
</template>
2 changes: 1 addition & 1 deletion ui/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const devMode = process.env.NODE_ENV === "development";
>
<div class="relative pb-10 sm:pb-8 lg:pb-12">
<div
class="ransform-gpu absolute inset-x-0 -top-40 z-0 overflow-hidden blur-3xl sm:-top-80"
class="absolute inset-x-0 -top-40 z-0 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true"
>
<div
Expand Down
2 changes: 1 addition & 1 deletion ui/middleware/protected.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default defineNuxtRouteMiddleware(async () => {
const user = useUser();

if (!user.value) {
return navigateTo("/login");
}
});

10 changes: 9 additions & 1 deletion ui/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default defineNuxtConfig({
script: [
{
async: true,
"data-website-id": "",
"data-website-id": "80e10200-5878-4adb-9a9e-ac0f23cb1f33",
src: "https://umami.fairdataihub.org/mushroom",
},
],
Expand All @@ -37,6 +37,14 @@ export default defineNuxtConfig({
"nuxt-icon",
],

nitro: {
esbuild: {
options: {
target: "esnext",
},
},
},

colorMode: {
preference: "light", // default value of $colorMode.preference
fallback: "light", // fallback value if not system preference found
Expand Down
2 changes: 2 additions & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
"lucia": "^3.2.0",
"md-editor-v3": "^4.13.5",
"mongodb": "^6.5.0",
"mongoose": "^8.3.3",
"notivue": "^2.4.4",
"nuxt": "3.11.1",
"nuxt-mongoose": "^1.0.5",
"oslo": "^1.2.0",
"probot": "^13.2.0",
"sanitize-html": "^2.13.0",
Expand Down
175 changes: 114 additions & 61 deletions ui/pages/add/license/[identifier].vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ config({
},
});
// definePageMeta({
// middleware: ["protected"],
// });
definePageMeta({
middleware: ["protected"],
});
const licenseOptions = licensesJSON.map((option) => ({
label: option.name,
Expand All @@ -41,19 +41,37 @@ const displayLicenseEditor = ref(false);
const getLicenseLoading = ref(false);
const submitLoading = ref(false);
const showNotAuthorizedError = ref(false);
const requestClosed = ref(false);
const { data, error } = await useFetch(`/api/license/${identifier}`, {
headers: useRequestHeaders(["cookie"]),
});
if (error.value) {
console.log(error.value);
const statusCode = error.value.statusCode ?? 500;
const message = error.value.data.message ?? "Something went wrong";
if (statusCode === 403) {
showNotAuthorizedError.value = true;
} else if (statusCode === 400) {
if (message === "request closed") {
requestClosed.value = true;
push.error({
title: "Request closed",
message: "This request has been closed. You can't edit it anymore.",
});
}
} else {
push.error({
title: "Something went wrong",
});
push.error({
title: "Something went wrong",
message: "Please contact support",
});
throw new Error("Something went wrong");
}
navigateTo("/");
// navigateTo("/");
}
if (data.value) {
Expand Down Expand Up @@ -111,8 +129,6 @@ const updateLicenseContent = async (value: string) => {
const saveLicenseDraft = async () => {
submitLoading.value = true;
console.log(licenseId.value, licenseContent.value);
const body = {
licenseId: licenseId.value,
licenseContent: licenseContent.value,
Expand Down Expand Up @@ -148,57 +164,94 @@ const saveLicenseAndPush = () => {

<template>
<main class="">
<n-flex vertical size="large" class="pb-5">
<n-select
v-model:value="licenseId"
placeholder="MIT License Modern Variant"
clearable
size="large"
filterable
@update:value="updateLicenseContent"
:options="licenseOptions"
/>

<div v-if="displayLicenseEditor" class="pb-5">
<MdEditor
v-model="licenseContent"
language="en-US"
preview-theme="github"
:show-code-row-number="true"
:sanitize="sanitize"
<div v-if="showNotAuthorizedError">
<div class="flex items-center space-x-4">
<img
src="https://www.svgrepo.com/show/406101/locked.svg"
alt="Not authorized"
class="h-20 w-20"
/>

<n-flex vertical>
<h1>You are not authorized to view this page.</h1>
<p>
Please contact the owner of the repository to get access to this
page.
</p>
</n-flex>
</div>
</n-flex>

<n-divider />

<n-flex>
<n-button
size="large"
color="black"
@click="saveLicenseDraft"
:loading="submitLoading"
:disabled="!licenseId || !licenseContent"
>
<template #icon>
<Icon name="material-symbols:save" />
</template>

Save draft
</n-button>

<n-button
size="large"
color="black"
@click="saveLicenseAndPush"
:disabled="!licenseId || !licenseContent"
:loading="submitLoading"
>
<template #icon>
<Icon name="ion:push" />
</template>
Save and push license to repository
</n-button>
</n-flex>
</div>
<div v-else-if="requestClosed">
<div class="flex items-center space-x-4">
<img
src="https://www.svgrepo.com/show/235034/close-sign.svg"
alt="Not authorized"
class="h-20 w-20"
/>

<n-flex vertical>
<h1>This request has been closed</h1>
<p>
This request has been marked as closed. This is due to the fact that
the request has been completed or the request has been closed by the
owner of the repository.
</p>
</n-flex>
</div>
</div>
<div v-else>
<n-flex vertical size="large" class="pb-5">
<n-select
v-model:value="licenseId"
placeholder="MIT License Modern Variant"
clearable
size="large"
filterable
@update:value="updateLicenseContent"
:options="licenseOptions"
/>

<div v-if="displayLicenseEditor" class="pb-5">
<MdEditor
v-model="licenseContent"
language="en-US"
preview-theme="github"
:show-code-row-number="true"
:sanitize="sanitize"
/>
</div>
</n-flex>

<n-divider />

<n-flex>
<n-button
size="large"
color="black"
@click="saveLicenseDraft"
:loading="submitLoading"
:disabled="!licenseId || !licenseContent"
>
<template #icon>
<Icon name="material-symbols:save" />
</template>

Save draft
</n-button>

<n-button
size="large"
color="black"
@click="saveLicenseAndPush"
:disabled="!licenseId || !licenseContent"
:loading="submitLoading"
>
<template #icon>
<Icon name="ion:push" />
</template>
Save and push license to repository
</n-button>
</n-flex>
</div>
</main>
</template>
1 change: 1 addition & 0 deletions ui/public/assets/images/error/404.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion ui/server/api/license/[identifier]/index.get.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { MongoClient } from "mongodb";
import type { User } from "lucia";

export default defineEventHandler(async (event) => {
await protectRoute(event);

const { identifier } = event.context.params as { identifier: string };

const client = new MongoClient(process.env.MONGODB_URI as string, {});
Expand All @@ -21,11 +24,14 @@ export default defineEventHandler(async (event) => {
});
}

// Check if the user is authorized to access the license request
await repoWritePermissions(event, licenseRequest.owner, licenseRequest.repo);

// Check if the license request is still open
if (!licenseRequest.open) {
throw createError({
statusCode: 400,
message: "License request is not open",
message: "request closed",
});
}

Expand Down
2 changes: 2 additions & 0 deletions ui/server/api/license/[identifier]/index.put.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { MongoClient } from "mongodb";
import { z } from "zod";

export default defineEventHandler(async (event) => {
await protectRoute(event);

const bodySchema = z.object({
licenseId: z.string(),
licenseContent: z.string(),
Expand Down
20 changes: 13 additions & 7 deletions ui/server/api/logout.post.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
export default eventHandler(async (event) => {
if (!event.context.session) {
throw createError({
statusCode: 403
});
}
await lucia.invalidateSession(event.context.session.id);
appendHeader(event, "Set-Cookie", lucia.createBlankSessionCookie().serialize());
if (!event.context.session) {
throw createError({
statusCode: 403,
});
}

await lucia.invalidateSession(event.context.session.id);

appendHeader(
event,
"Set-Cookie",
lucia.createBlankSessionCookie().serialize(),
);
});
14 changes: 12 additions & 2 deletions ui/server/api/user.get.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
export default defineEventHandler((event) => {
return event.context.user;
import type { User } from "lucia";

export default defineEventHandler(async (event) => {
const user = event.context.user as User | null;

return user
? {
username: user?.username,
githubId: user?.github_id,
id: user?.id,
}
: null;
});
Loading

0 comments on commit 384e981

Please sign in to comment.