Skip to content

Commit

Permalink
add forge
Browse files Browse the repository at this point in the history
  • Loading branch information
anbraten committed Aug 29, 2023
1 parent dc00249 commit 545f160
Show file tree
Hide file tree
Showing 17 changed files with 498 additions and 24 deletions.
4 changes: 2 additions & 2 deletions components/Menu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
<MenuItem
v-for="forge in forges"
:key="forge.id"
to="/"
:title="forge.name"
:to="forge.owner === user?.id ? `/forges/${forge.id}` : '/'"
:title="forge.host"
:icon="forge.isConnected ? 'i-ion-code' : 'i-ion-ios-repeat'"
@click="!forge.isConnected && login(forge.id)"
/>
Expand Down
5 changes: 3 additions & 2 deletions contrib/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async function main() {
.insert(forgeSchema)
.values({
id: forge?.id,
name: 'Github',
host: 'github.com',
type: 'github',
owner: null,
allowLogin: true,
Expand All @@ -30,7 +30,8 @@ async function main() {
.onConflictDoUpdate({
target: forgeSchema.id,
set: {
name: 'Github',
host: 'github.com',
owner: null,
allowLogin: true,
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@
"@gitbeaker/core": "^39.10.3",
"@gitbeaker/rest": "^39.10.3",
"better-sqlite3": "^8.5.0",
"drizzle-orm": "^0.27.2",
"drizzle-orm": "^0.28.5",
"jsonwebtoken": "^9.0.1",
"jwt-decode": "^3.1.2",
"nuxt-icon": "^0.4.1",
"octokit": "^2.1.0",
"simple-git": "^3.19.1",
"vue-markdown-render": "^2.0.1"
"vue-markdown-render": "^2.0.1",
"zod": "^3.22.2"
},
"pnpm": {
"overrides": {
Expand Down
2 changes: 1 addition & 1 deletion pages/auth/login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<UIcon v-if="forge.type === 'github'" name="i-ion-logo-github" class="w-4 h-4 mr-2" />
<UIcon v-else-if="forge.type === 'gitlab'" name="i-ion-logo-gitlab" class="w-4 h-4 mr-2" />

{{ forge.name }}
{{ forge.host }}
</button>
</div>
</div>
Expand Down
59 changes: 59 additions & 0 deletions pages/forges/[forgeId]/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<template>
<div class="flex w-full justify-center">
<UForm v-if="forge" ref="form" :schema="schema" :state="forge" @submit.prevent="submit">
<UFormGroup label="Host" name="host">
<UInput v-model="forge.host" disabled />
</UFormGroup>

<UFormGroup label="Type" name="type">
<UInput v-model="forge.type" disabled />
</UFormGroup>

<UFormGroup label="Client ID" name="clientId">
<UInput v-model="forge.clientId" />
</UFormGroup>

<UFormGroup label="Client Secret" name="clientSecret">
<UInput v-model="forge.clientSecret" />
</UFormGroup>

<div class="flex mt-4 gap-2">
<UButton label="Delete forge" icon="i-heroicons-trash" color="red" @click="deleteForge" />
<UButton type="submit" label="Update forge" icon="i-heroicons-arrow-path-20-solid" />
</div>
</UForm>
</div>
</template>

<script setup lang="ts">
import { z } from 'zod';
const schema = z.object({
host: z.string().nonempty(),
clientId: z.string().nonempty(),
clientSecret: z.string().nonempty(),
});
const route = useRoute();
const forgeId = route.params.forgeId;
const { data: forge } = await useFetch(`/api/forges/${forgeId}`);
const form = ref<HTMLFormElement>();
async function submit() {
await form.value!.validate();
await $fetch(`/api/forges/${forgeId}`, {
method: 'POST',
body: forge.value,
});
}
async function deleteForge() {
await $fetch(`/api/forges/${forgeId}`, {
method: 'DELETE',
});
await navigateTo('/');
}
</script>
3 changes: 0 additions & 3 deletions pages/forges/[forgeId]/settings.vue

This file was deleted.

54 changes: 53 additions & 1 deletion pages/forges/add.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,55 @@
<template>
<div>add forge</div>
<div class="flex w-full justify-center">
<UForm ref="form" :schema="schema" :state="newForge" @submit.prevent="submit">
<UFormGroup label="Host" name="host">
<UInput v-model="newForge.host" />
</UFormGroup>

<UFormGroup label="Type" name="type">
<USelectMenu v-model="newForge.type" :options="forgeTypes" />
</UFormGroup>

<UFormGroup label="Client ID" name="clientId">
<UInput v-model="newForge.clientId" />
</UFormGroup>

<UFormGroup label="Client Secret" name="clientSecret">
<UInput v-model="newForge.clientSecret" />
</UFormGroup>

<UButton type="submit" label="Add forge" icon="i-heroicons-plus" class="mt-2" />
</UForm>
</div>
</template>

<script setup lang="ts">
import { z } from 'zod';
const schema = z.object({
host: z.string().nonempty(),
clientId: z.string().nonempty(),
clientSecret: z.string().nonempty(),
});
const forgeTypes = ['gitlab']; // TODO: support other forges
const newForge = ref({
host: undefined,
type: forgeTypes[0],
clientId: undefined,
clientSecret: undefined,
});
const form = ref<HTMLFormElement>();
async function submit() {
await form.value!.validate();
const forge = await $fetch('/api/forges', {
method: 'POST',
body: newForge.value,
});
await navigateTo(`/forges/${forge.id}`);
}
</script>
12 changes: 7 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions server/api/forges/[forge_id]/index.delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { forgeSchema, userForgesSchema } from '../../../schemas';
import { eq, and } from 'drizzle-orm';

export default defineEventHandler(async (event) => {
const user = await requireUser(event);

const _forgeId = event.context.params?.forge_id;
if (!_forgeId) {
throw createError({
message: 'Cannot create forge with a forge_id',
status: 400,
});
}
const forgeId = parseInt(_forgeId, 10);

await db.delete(userForgesSchema).where(eq(userForgesSchema.forgeId, forgeId)).run();

const forge = await db
.delete(forgeSchema)
.where(and(eq(forgeSchema.owner, user.id), eq(forgeSchema.id, forgeId)))
.returning()
.get();

return forge;
});
23 changes: 23 additions & 0 deletions server/api/forges/[forge_id]/index.get.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { forgeSchema } from '../../../schemas';
import { eq, and } from 'drizzle-orm';

export default defineEventHandler(async (event) => {
const user = await requireUser(event);

const _forgeId = event.context.params?.forge_id;
if (!_forgeId) {
throw createError({
message: 'Cannot create forge with a forge_id',
status: 400,
});
}
const forgeId = parseInt(_forgeId, 10);

const forge = await db
.select()
.from(forgeSchema)
.where(and(eq(forgeSchema.owner, user.id), eq(forgeSchema.id, forgeId)))
.get();

return forge;
});
26 changes: 26 additions & 0 deletions server/api/forges/[forge_id]/index.post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { forgeSchema } from '../../../schemas';
import { eq, and } from 'drizzle-orm';

export default defineEventHandler(async (event) => {
const user = await requireUser(event);

const forgeData = await readBody(event);

const _forgeId = event.context.params?.forge_id;
if (!_forgeId) {
throw createError({
message: 'Cannot create forge with a forge_id',
status: 400,
});
}
const forgeId = parseInt(_forgeId, 10);

const forge = await db
.update(forgeSchema)
.set({ clientId: forgeData.clientId, clientSecret: forgeData.clientSecret })
.where(and(eq(forgeSchema.owner, user.id), eq(forgeSchema.id, forgeId)))
.returning()
.get();

return forge;
});
2 changes: 1 addition & 1 deletion server/api/forges/index.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ export default defineEventHandler(async (event) => {
const forges = await db.select().from(forgeSchema).where(isNull(forgeSchema.owner)).all();

// use map to hide client id and secret
return forges.map((forge) => ({ id: forge.id, name: forge.name, host: forge.host, type: forge.type }));
return forges.map((forge) => ({ id: forge.id, owner: forge.owner, host: forge.host, type: forge.type }));
});
15 changes: 15 additions & 0 deletions server/api/forges/index.post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { forgeSchema } from '../../schemas';

export default defineEventHandler(async (event) => {
const user = await requireUser(event);

const forgeData = await readBody(event);

const forge = await db
.insert(forgeSchema)
.values({ ...forgeData, allowLogin: false, owner: user.id }) // TODO: allow admins to allow login via their forges
.returning()
.get();

return forge;
});
2 changes: 2 additions & 0 deletions server/db/migrations/0003_purple_anthem.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE UNIQUE INDEX `forges_host_unique` ON `forges` (`host`);--> statement-breakpoint
ALTER TABLE `forges` DROP COLUMN `name`;
Loading

0 comments on commit 545f160

Please sign in to comment.