Skip to content

Commit 3fa39a5

Browse files
committed
Introduce admin role and improved cmdk
1 parent 04b0655 commit 3fa39a5

15 files changed

+290
-31
lines changed

engine/.sqlx/query-1f612b9033ba9ff47bcfe182f04c913a240359154f13cee1b2e93687b6dd497c.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

engine/.sqlx/query-5c960227b225a6ecf280a18a5a07af798d6e361b745bf0f2a04286538798f72b.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

engine/.sqlx/query-73c17b2964e6fdbbfe600c687110004c85905d2f75128538a1f7aa267b05b6f9.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

engine/.sqlx/query-fdce7cbc7f0b0f4353c10600e949623ea7d7d8a7ddf98596f724827c6570c33f.json

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

engine/migrations/0003_admin.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- add admin flag to users table
2+
ALTER TABLE users ADD COLUMN admin BOOLEAN DEFAULT FALSE;
3+
-- set admin flag for existing users max 1, the first user created
4+
UPDATE users SET admin = TRUE WHERE created_at = (SELECT MIN(created_at) FROM users);

engine/src/models/user/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,27 @@ pub struct User {
1717
#[oai(skip)]
1818
pub password: String,
1919
pub created_at: DateTime<Utc>,
20+
pub admin: Option<bool>,
2021
}
2122

2223
impl User {
2324
pub async fn new(
2425
db: &Database,
2526
name: impl AsRef<str>,
2627
password: impl AsRef<str>,
28+
admin: Option<bool>,
2729
) -> Result<(Self, Team), sqlx::Error> {
2830
let user_id = generate_id(IdType::USER);
2931
let name = name.as_ref();
3032
let password = password.as_ref();
3133

3234
let user = query_as!(
3335
User,
34-
"INSERT INTO users (user_id, name, password) VALUES ($1, $2, $3) RETURNING *",
36+
"INSERT INTO users (user_id, name, password, admin) VALUES ($1, $2, $3, $4) RETURNING *",
3537
user_id,
3638
name,
37-
password
39+
password,
40+
admin
3841
)
3942
.fetch_one(&db.pool)
4043
.await?;

engine/src/routes/auth/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ impl AuthApi {
102102
&state.0.database,
103103
&request.username,
104104
&hash_password(&request.password),
105+
Some(true),
105106
)
106107
.await
107108
.map_err(HttpError::from)?;

web/src/api/schema.gen.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,7 @@ export type components = {
820820
name: string;
821821
/** Format: date-time */
822822
created_at: string;
823+
admin?: boolean;
823824
};
824825
UserTeamInvite: {
825826
invite_id: string;

web/src/components/modal/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,21 @@ export const ModalContent = React.forwardRef<
2828
React.ComponentPropsWithoutRef<typeof Dialog.Content> & {
2929
noPadding?: boolean;
3030
noCloseButton?: boolean;
31+
noBg?: boolean;
3132
}
3233
>(
3334
(
34-
{ className, children, noPadding, noCloseButton, ...properties },
35+
{ className, children, noPadding, noCloseButton, noBg, ...properties },
3536
reference
3637
) => (
3738
<Dialog.Portal>
3839
<ModalOverlay />
3940
<Dialog.Content
4041
ref={reference}
4142
className={clsx(
42-
'bg-default data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border shadow-lg duration-200 sm:rounded-lg',
43+
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border shadow-lg duration-200 sm:rounded-lg',
4344
noPadding ? '' : 'p-6',
45+
noBg ? '' : 'bg-default',
4446
className
4547
)}
4648
{...properties}

web/src/gui/command/CommandPalette.tsx

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import { useParams } from '@tanstack/react-router';
1+
import { useNavigate, useParams } from '@tanstack/react-router';
22
import { Command } from 'cmdk';
3-
import { useEffect, useState } from 'react';
3+
import { FC, useEffect, useState } from 'react';
44
import { FiArrowRight, FiChevronRight } from 'react-icons/fi';
55

6-
import { useSite, useTeam } from '@/api';
6+
import { useMe, useSite, useTeam } from '@/api';
77
import { ModalContent } from '@/components';
88
import { ModalRoot } from '@/components/modal';
99

1010
import {
11+
admin_commands,
1112
CommandEntityGroup,
1213
main_commands,
1314
site_commands,
@@ -33,17 +34,28 @@ export const CommandPalette = () => {
3334

3435
return (
3536
<ModalRoot open={open} onOpenChange={setOpen}>
36-
<ModalContent noPadding noCloseButton>
37-
<CommandPaletteInternal />
37+
<ModalContent
38+
noPadding
39+
noCloseButton
40+
// frosted glass effect
41+
// noBg
42+
// className="dark:text-default bg-white/90 text-neutral-700 backdrop-blur-sm dark:bg-black/30"
43+
className=""
44+
>
45+
<CommandPaletteInternal requestClose={() => setOpen(false)} />
3846
</ModalContent>
3947
</ModalRoot>
4048
);
4149
};
4250

43-
const CommandPaletteInternal = () => {
51+
const CommandPaletteInternal: FC<{ requestClose: () => void }> = ({
52+
requestClose,
53+
}) => {
4454
const routeParameters = useParams({ from: undefined as any });
4555
const { data: site } = useSite(routeParameters['siteId']);
4656
const { data: team } = useTeam(routeParameters['teamId'] || site?.team_id);
57+
const { data: user } = useMe();
58+
const navigate = useNavigate();
4759

4860
return (
4961
<Command label="Global Command Palette">
@@ -72,17 +84,10 @@ const CommandPaletteInternal = () => {
7284
)}
7385
</ul>
7486
</div>
75-
<Command.List className="p-2">
76-
<Command.Empty>No results found.</Command.Empty>
77-
78-
{/* <Command.Group heading="Letters">
79-
{main_commands.map((command) => (
80-
<Command.Item key={command.slug}>
81-
<command.icon className="size-4" />
82-
{command.title}
83-
</Command.Item>
84-
))}
85-
</Command.Group> */}
87+
<Command.List className="max-h-[50vh] overflow-y-auto p-2">
88+
<Command.Empty className="text-sm">
89+
No results found.
90+
</Command.Empty>
8691

8792
{(
8893
[
@@ -102,13 +107,35 @@ const CommandPaletteInternal = () => {
102107
commands: team_commands,
103108
}
104109
: undefined,
110+
user?.admin
111+
? {
112+
title: 'Administration',
113+
commands: admin_commands,
114+
}
115+
: undefined,
105116
] as CommandEntityGroup[]
106117
)
107118
.filter(Boolean)
108119
.map(({ title, commands }) => (
109120
<Command.Group key={title} heading={title}>
110121
{commands.map((command) => (
111-
<Command.Item key={command.slug}>
122+
<Command.Item
123+
key={command.slug}
124+
onSelect={() => {
125+
if (command.navigate_to) {
126+
console.log(command.navigate_to);
127+
navigate({
128+
to: command.navigate_to,
129+
params: {
130+
siteId: site?.site_id,
131+
teamId: team?.team_id,
132+
},
133+
});
134+
requestClose();
135+
}
136+
}}
137+
keywords={command.aliases}
138+
>
112139
<span className="flex w-full items-center gap-2">
113140
<command.icon className="size-4" />
114141
{command.title}

0 commit comments

Comments
 (0)