Skip to content

Commit

Permalink
feat: OAuth api permissions and user creation (#131)
Browse files Browse the repository at this point in the history
* fix: ui adjustment to page titles

* feat: create service user insert form

* feat: add service user permissions and introspection to API auth

* fix: types for email not null

* wip

* fix: user actions return first user

Signed-off-by: Francisco Madeira <[email protected]>

* refactor: components with version query

Signed-off-by: Francisco Madeira <[email protected]>

* refactor: projects page only render one tab content at a time

Signed-off-by: Francisco Madeira <[email protected]>

---------

Signed-off-by: Francisco Madeira <[email protected]>
Co-authored-by: Rui Silva <[email protected]>
Signed-off-by: Francisco Madeira <[email protected]>
  • Loading branch information
fgmadeira and lopesdasilva committed Feb 7, 2025
1 parent 4de31a3 commit a071af6
Show file tree
Hide file tree
Showing 46 changed files with 740 additions and 563 deletions.
5 changes: 5 additions & 0 deletions .changeset/thirty-keys-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ethereal-nexus/dashboard': minor
---

feat: added service users auth for API calls
2 changes: 1 addition & 1 deletion .github/workflows/dashboard-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
echo "${{ secrets.DRIZZLE_DATABASE_URL }}" >> .env
corepack enable && corepack prepare [email protected] --activate
pnpm i --frozen-lockfile
pnpm --filter "@ethereal-nexus/dashboard" run db:push --force
pnpm --filter "@ethereal-nexus/dashboard" run db:push
sed -i '/^DRIZZLE_DATABASE_URL/d' .env
- name: Build and push container image to registry
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dashboard-preview-cleanup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Delete Neon Branch
uses: neondatabase/delete-branch-action@v3.1.3
uses: neondatabase/delete-branch-action@v3
with:
project_id: ${{ env.NEON_PROJECT_ID }}
branch: preview/pr-${{ github.event.number }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dashboard-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
corepack enable && corepack prepare [email protected] --activate
pnpm i --frozen-lockfile
pnpm --filter "@ethereal-nexus/dashboard" run db:push --force
pnpm --filter "@ethereal-nexus/dashboard" run db:push
- name: Deploy Container App
uses: azure/container-apps-deploy-action@v1
Expand Down
22 changes: 18 additions & 4 deletions pnpm-lock.yaml

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

3 changes: 1 addition & 2 deletions web/dashboard/drizzle.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ export default defineConfig({
dbCredentials: {
url: process.env.DRIZZLE_DATABASE_URL!,
},
verbose: true,
strict: false,
verbose: true
})
4 changes: 3 additions & 1 deletion web/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"lint": "next lint",
"format": "prettier --write \"{,!(.next)/**/}*.{ts, tsx}\"",
"test": "set TZ=UTC && jest --coverage --max-workers=75%",
"db:push": "drizzle-kit push",
"db:push": "drizzle-kit push --config=drizzle.config.ts --force",
"db:generate": "drizzle-kit generate"
},
"dependencies": {
Expand Down Expand Up @@ -50,11 +50,13 @@
"encoding": "^0.1.13",
"formidable": "^3.5.2",
"gunzip-maybe": "^1.4.2",
"jose": "^5.9.6",
"lucide-react": "^0.460.0",
"next": "15.1.6",
"next-auth": "5.0.0-beta.25",
"next-swagger-doc": "^0.4.1",
"next-themes": "^0.2.1",
"openid-client": "^6.1.7",
"postgres": "3.3.5",
"react": "19.0.0",
"react-dom": "19.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,32 @@ import React from "react";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { useRouter } from 'next/navigation';
import UserInviteForm from '@/components/user/user-invitation-form';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import OauthUserForm from '@/components/user/oauth-user-form';

export default function NewUserModal() {
const router = useRouter();

return <Dialog open={true} onOpenChange={router.back}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogTitle>Create User</DialogTitle>
<DialogDescription>
Create a new user
</DialogDescription>
</DialogHeader>
<UserInviteForm />
<Tabs>
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="email">Email User</TabsTrigger>
<TabsTrigger value="oauth">Service User</TabsTrigger>
</TabsList>
<TabsContent value="email">
<UserInviteForm />
</TabsContent>
<TabsContent value="oauth">
<OauthUserForm />
</TabsContent>
</Tabs>
</DialogContent>
</Dialog>
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from "react";

import NewUserModal from './modal';

export default function NewUserModalPage() {
Expand Down
2 changes: 1 addition & 1 deletion web/dashboard/src/app/(session)/(admin)/users/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Separator } from "@/components/ui/separator";
import React from 'react';
import UserInviteForm from '@/components/user/user-invitation-form';

export default async function NewUser({ params }: any) {
export default async function NewUser() {
return (
<div className="container space-y-6">
<div>
Expand Down
59 changes: 25 additions & 34 deletions web/dashboard/src/app/(session)/(admin)/users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,36 @@ import { columns } from '@/components/user/table/columns';
import { getUsers } from '@/data/users/actions';
import { DataTable } from '@/components/ui/data-table/data-table';
import Link from 'next/link';
import { buttonVariants } from '@/components/ui/button';
import { Button, buttonVariants } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { Plus } from 'lucide-react';
import { notFound } from 'next/navigation';

export default async function Teams() {
const users = await getUsers()
const users = await getUsers();

if(!users.success) {
notFound();
}

return (
<div className="container h-full flex-1 flex-col space-y-8 p-8 md:flex">
<div className="w-full flex items-end">
<div className="mr-auto">
<h2 className="text-2xl font-bold tracking-tight">Users</h2>
<p className="text-muted-foreground">Manage your users here</p>
</div>
<Link
href="/users/new"
passHref
className={cn(
buttonVariants({
variant: 'outline',
size: 'sm',
className: 'mr-2 transition-colors bg-orange-500 rounded-full text-white h-9 px-5 flex justify-center items-center',
})
)}
>
<Plus />
<span className="text-sm font-bold">Invite user</span>
</Link>
</div>
{
users.success ?
<DataTable
entity={'users'}
columns={columns}
data={users.data}
filterColumn={'name'}
/> :
users.error.message
}
</div>
<>
<h1 className="text-4xl font-semibold">Users</h1>
<p className="mb-10">Manage your users here</p>
<DataTable
entity={'users'}
columns={columns}
data={users.data}
filterColumn={'name'}
createSlot={
<Button className="ml-auto" asChild>
<Link href="/users/new">
<Plus />
<span className="text-sm font-bold">Invite user</span>
</Link>
</Button>
}
/>
</>
);
}
61 changes: 21 additions & 40 deletions web/dashboard/src/app/(session)/components/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,45 @@ import React from 'react';
import { notFound } from 'next/navigation';
import { Sparkles } from 'lucide-react';
import Link from 'next/link';
import { cn } from '@/lib/utils';
import { auth } from '@/auth';
import { DataTable } from '@/components/ui/data-table/data-table';
import { columns } from '@/components/components/table/columns';
import { Button } from '@/components/ui/button';
import { getComponents } from '@/data/components/actions';
import { buttonVariants } from '@/components/ui/button';
import process from 'node:process';

export default async function Components() {
const session = await auth();
const components = await getComponents();

const components = await getComponents();
if (!components.success) {
notFound();
}

return (
<div className="container h-full flex-1 flex-col space-y-8 p-8 md:flex">
<div className="w-full flex items-end">
<div className="mr-auto">
<h2 className="text-2xl font-bold tracking-tight">Components</h2>
<p className="text-muted-foreground">Manage your components here!</p>
</div>
{
!!process.env.OPENAI_API_KEY ?
<Link
href="/components/generate"
passHref
className={cn(
buttonVariants({
variant: 'outline',
size: 'sm',
className: 'relative overflow-hidden transition-colors rounded-full text-white h-9 p-0.5'
}),
session?.user?.role === 'viewer' && 'pointer-events-none opacity-50'
)}
>
<span
className="absolute inset-[-2000%] animate-[spin_2s_linear_infinite] bg-[conic-gradient(from_90deg_at_50%_50%,#FE6630_0%,#D9508A_25%,#8F26D3_50%,#D9508A_75%,#FE6630_100%)]" />
<span
className="flex h-full w-full cursor-pointer items-center justify-center rounded-full bg-background px-5 py-1 text-sm font-medium text-orange-400 backdrop-blur-3xl">
<span className="animate-twinkle mr-1">
<Sparkles className="h-5 w-5" />
</span>
<span className="text-sm font-bold">
Generate component
</span>
</span>
</Link> :
null
}
</div>
<>
<h1 className="text-4xl font-semibold">Components</h1>
<p className="mb-10">Manage your components here</p>
<DataTable
columns={columns}
data={components.data}
entity="components"
filterColumn={'name'}
createSlot={
!!process.env.OPENAI_API_KEY ?
<Button asChild variant="outline" className="ml-auto border-0 relative overflow-hidden p-0.5" disabled={session?.user?.role === 'viewer'}>
<Link
href="/components/generate"
>
<span className="absolute inset-[-2000%] animate-[spin_2s_linear_infinite] bg-[conic-gradient(from_90deg_at_50%_50%,#FE6630_0%,#D9508A_25%,#8F26D3_50%,#D9508A_75%,#FE6630_100%)]" />
<span className="flex h-full w-full items-center justify-center rounded-full bg-background px-5 backdrop-blur-3xl">
<Sparkles className="h-5 w-5 mr-1" />
Generate component
</span>
</Link>
</Button> :
null
}
/>
</div>
</>
);
}
Loading

0 comments on commit a071af6

Please sign in to comment.