Skip to content

Commit

Permalink
minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
itsmegood committed Jan 31, 2024
1 parent ee8f3bc commit 5b88936
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 141 deletions.
5 changes: 5 additions & 0 deletions app/components/ui/icons/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Icons

This directory contains SVG icons that are used by the app.

Everything in this directory is generated by `npm run build:icons`.
11 changes: 5 additions & 6 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { z } from 'zod'
import { GeneralErrorBoundary } from './components/error-boundary.tsx'
import { ErrorList } from './components/forms.tsx'
import { EpicProgress } from './components/progress-bar.tsx'
import { SearchBar } from './components/search-bar.tsx'
import { useToast } from './components/toaster.tsx'
import { Button } from './components/ui/button.tsx'
import {
Expand Down Expand Up @@ -230,8 +229,8 @@ function App() {
m => m.id === 'routes/c.$companyId+/_layout_company',
)

const isOnSearchPage = matches.find(m => m.id === 'routes/users+/index')
const searchBar = isOnSearchPage ? null : <SearchBar status="idle" />
// const isOnSearchPage = matches.find(m => m.id === 'routes/users+/index')
// const searchBar = isOnSearchPage ? null : <SearchBar status="idle" />
useToast(data.toast)

return (
Expand All @@ -241,9 +240,9 @@ function App() {
<header className="container py-6">
<nav className="flex flex-wrap items-center justify-between gap-4 sm:flex-nowrap md:gap-8">
<Logo />
<div className="ml-auto hidden max-w-sm flex-1 sm:block">
{/* <div className="ml-auto hidden max-w-sm flex-1 sm:block">
{searchBar}
</div>
</div> */}
<div className="flex items-center gap-10">
{user ? (
<UserDropdown />
Expand All @@ -253,7 +252,7 @@ function App() {
</Button>
)}
</div>
<div className="block w-full sm:hidden">{searchBar}</div>
{/* <div className="block w-full sm:hidden">{searchBar}</div> */}
</nav>
</header>
)}
Expand Down
17 changes: 15 additions & 2 deletions app/routes/_marketing+/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import { type MetaFunction } from '@remix-run/node'
import {
type LoaderFunctionArgs,
redirect,
type MetaFunction,
} from '@remix-run/node'
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '#app/components/ui/tooltip.tsx'
import { getUserId } from '#app/utils/auth.server.ts'
import { cn } from '#app/utils/misc.tsx'
import { logos } from './logos/logos.ts'

// export async function loader({ request }: LoaderFunctionArgs) {
// const userId = await getUserId(request)

// if (userId) {
// return redirect('/studio')
// }
// }

export const meta: MetaFunction = () => [{ title: 'Epic Notes' }]

// Tailwind Grid cell classes lookup
Expand Down Expand Up @@ -84,7 +97,7 @@ export default function Index() {
<TooltipTrigger asChild>
<a
href={logo.href}
className="grid size-20 place-items-center rounded-2xl bg-violet-600/10 p-4 transition hover:-rotate-6 hover:bg-violet-600/15 sm:size-24 dark:bg-violet-200 dark:hover:bg-violet-100"
className="grid size-20 place-items-center rounded-2xl bg-violet-600/10 p-4 transition hover:-rotate-6 hover:bg-violet-600/15 dark:bg-violet-200 dark:hover:bg-violet-100 sm:size-24"
>
<img src={logo.src} alt="" />
</a>
Expand Down
2 changes: 1 addition & 1 deletion app/routes/admin+/cache.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
getInstanceInfo,
} from '#app/utils/litefs.server.ts'
import { useDebounce, useDoubleCheck } from '#app/utils/misc.tsx'
import { requireUserWithRole } from '#app/utils/permissions.ts'
import { requireUserWithRole } from '#app/utils/permissions.server'

export const handle: SEOHandle = {
getSitemapEntries: () => null,
Expand Down
2 changes: 1 addition & 1 deletion app/routes/admin+/cache_.lru.$cacheKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { json, type LoaderFunctionArgs } from '@remix-run/node'
import { getAllInstances, getInstanceInfo } from 'litefs-js'
import { ensureInstance } from 'litefs-js/remix.js'
import { lruCache } from '#app/utils/cache.server.ts'
import { requireUserWithRole } from '#app/utils/permissions.ts'
import { requireUserWithRole } from '#app/utils/permissions.server'

export async function loader({ request, params }: LoaderFunctionArgs) {
await requireUserWithRole(request, 'admin')
Expand Down
2 changes: 1 addition & 1 deletion app/routes/admin+/cache_.sqlite.$cacheKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { json, type LoaderFunctionArgs } from '@remix-run/node'
import { getAllInstances, getInstanceInfo } from 'litefs-js'
import { ensureInstance } from 'litefs-js/remix.js'
import { cache } from '#app/utils/cache.server.ts'
import { requireUserWithRole } from '#app/utils/permissions.ts'
import { requireUserWithRole } from '#app/utils/permissions.server'

export async function loader({ request, params }: LoaderFunctionArgs) {
await requireUserWithRole(request, 'admin')
Expand Down
7 changes: 2 additions & 5 deletions app/routes/users+/$username_+/notes.$noteId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ import { StatusButton } from '#app/components/ui/status-button.tsx'
import { requireUserId } from '#app/utils/auth.server.ts'
import { prisma } from '#app/utils/db.server.ts'
import { getNoteImgSrc, useIsPending } from '#app/utils/misc.tsx'
import {
requireUserWithPermission,
userHasPermission,
} from '#app/utils/permissions.ts'
import { requireUserWithPermission } from '#app/utils/permissions.server.ts'
import { redirectWithToast } from '#app/utils/toast.server.ts'
import { useOptionalUser } from '#app/utils/user.ts'
import { userHasPermission, useOptionalUser } from '#app/utils/user.ts'
import { type loader as notesLoader } from './notes.tsx'

export async function loader({ params }: LoaderFunctionArgs) {
Expand Down
43 changes: 1 addition & 42 deletions app/utils/permissions.ts → app/utils/permissions.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { json } from '@remix-run/node'
import { requireUserId } from './auth.server.ts'
import { prisma } from './db.server.ts'
import { type useUser } from './user.ts'
import { type PermissionString, parsePermissionString } from './user.ts'

export async function requireUserWithPermission(
request: Request,
Expand Down Expand Up @@ -58,44 +58,3 @@ export async function requireUserWithRole(request: Request, name: string) {
}
return user.id
}

type Action = 'create' | 'read' | 'update' | 'delete'
type Entity = 'user' | 'note'
type Access = 'own' | 'any' | 'own,any' | 'any,own'
type PermissionString = `${Action}:${Entity}` | `${Action}:${Entity}:${Access}`
function parsePermissionString(permissionString: PermissionString) {
const [action, entity, access] = permissionString.split(':') as [
Action,
Entity,
Access | undefined,
]
return {
action,
entity,
access: access ? (access.split(',') as Array<Access>) : undefined,
}
}

export function userHasPermission(
user: Pick<ReturnType<typeof useUser>, 'roles'> | null | undefined,
permission: PermissionString,
) {
if (!user) return false
const { action, entity, access } = parsePermissionString(permission)
return user.roles.some(role =>
role.permissions.some(
permission =>
permission.entity === entity &&
permission.action === action &&
(!access || access.includes(permission.access)),
),
)
}

export function userHasRole(
user: Pick<ReturnType<typeof useUser>, 'roles'> | null,
role: string,
) {
if (!user) return false
return user.roles.some(r => r.name === role)
}
44 changes: 44 additions & 0 deletions app/utils/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,47 @@ export function useUser() {
}
return maybeUser
}

type Action = 'create' | 'read' | 'update' | 'delete'
type Entity = 'user' | 'note'
type Access = 'own' | 'any' | 'own,any' | 'any,own'
export type PermissionString =
| `${Action}:${Entity}`
| `${Action}:${Entity}:${Access}`

export function parsePermissionString(permissionString: PermissionString) {
const [action, entity, access] = permissionString.split(':') as [
Action,
Entity,
Access | undefined,
]
return {
action,
entity,
access: access ? (access.split(',') as Array<Access>) : undefined,
}
}

export function userHasPermission(
user: Pick<ReturnType<typeof useUser>, 'roles'> | null | undefined,
permission: PermissionString,
) {
if (!user) return false
const { action, entity, access } = parsePermissionString(permission)
return user.roles.some(role =>
role.permissions.some(
permission =>
permission.entity === entity &&
permission.action === action &&
(!access || access.includes(permission.access)),
),
)
}

export function userHasRole(
user: Pick<ReturnType<typeof useUser>, 'roles'> | null,
role: string,
) {
if (!user) return false
return user.roles.some(r => r.name === role)
}
Loading

0 comments on commit 5b88936

Please sign in to comment.