mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-02 12:49:20 +01:00
* fix: cache is not exportet from react * fix: format issue * wip: add usage of group permissions * feat: show inherited groups and add manage group * refactor: improve board access management * chore: address pull request feedback * fix: type issues * fix: migrations * test: add unit tests for board permissions, permissions and board router * test: add unit tests for board router and get current user permissions method * fix: format issues * fix: deepsource issue
94 lines
2.5 KiB
TypeScript
94 lines
2.5 KiB
TypeScript
import { cookies } from "next/headers";
|
|
import type { Adapter } from "@auth/core/adapters";
|
|
import type { NextAuthConfig } from "next-auth";
|
|
|
|
import type { Database } from "@homarr/db";
|
|
import { eq, inArray } from "@homarr/db";
|
|
import { groupMembers, groupPermissions } from "@homarr/db/schema/sqlite";
|
|
import { getPermissionsWithChildren } from "@homarr/definitions";
|
|
|
|
import {
|
|
expireDateAfter,
|
|
generateSessionToken,
|
|
sessionMaxAgeInSeconds,
|
|
sessionTokenCookieName,
|
|
} from "./session";
|
|
|
|
export const getCurrentUserPermissions = async (
|
|
db: Database,
|
|
userId: string,
|
|
) => {
|
|
const dbGroupMembers = await db.query.groupMembers.findMany({
|
|
where: eq(groupMembers.userId, userId),
|
|
});
|
|
const groupIds = dbGroupMembers.map((groupMember) => groupMember.groupId);
|
|
const dbGroupPermissions = await db
|
|
.selectDistinct({
|
|
permission: groupPermissions.permission,
|
|
})
|
|
.from(groupPermissions)
|
|
.where(
|
|
groupIds.length > 0
|
|
? inArray(groupPermissions.groupId, groupIds)
|
|
: undefined,
|
|
);
|
|
const permissionKeys = dbGroupPermissions.map(({ permission }) => permission);
|
|
|
|
return getPermissionsWithChildren(permissionKeys);
|
|
};
|
|
|
|
export const createSessionCallback = (
|
|
db: Database,
|
|
): NextAuthCallbackOf<"session"> => {
|
|
return async ({ session, user }) => {
|
|
return {
|
|
...session,
|
|
user: {
|
|
...session.user,
|
|
id: user.id,
|
|
name: user.name,
|
|
permissions: await getCurrentUserPermissions(db, user.id),
|
|
},
|
|
};
|
|
};
|
|
};
|
|
|
|
export const createSignInCallback =
|
|
(
|
|
adapter: Adapter,
|
|
isCredentialsRequest: boolean,
|
|
): NextAuthCallbackOf<"signIn"> =>
|
|
async ({ user }) => {
|
|
if (!isCredentialsRequest) return true;
|
|
|
|
if (!user) return true;
|
|
|
|
// https://github.com/nextauthjs/next-auth/issues/6106
|
|
if (!adapter?.createSession) {
|
|
return false;
|
|
}
|
|
|
|
const sessionToken = generateSessionToken();
|
|
const sessionExpiry = expireDateAfter(sessionMaxAgeInSeconds);
|
|
|
|
await adapter.createSession({
|
|
sessionToken,
|
|
userId: user.id!,
|
|
expires: sessionExpiry,
|
|
});
|
|
|
|
cookies().set(sessionTokenCookieName, sessionToken, {
|
|
path: "/",
|
|
expires: sessionExpiry,
|
|
httpOnly: true,
|
|
sameSite: "lax",
|
|
secure: true,
|
|
});
|
|
|
|
return true;
|
|
};
|
|
|
|
type NextAuthCallbackRecord = Exclude<NextAuthConfig["callbacks"], undefined>;
|
|
export type NextAuthCallbackOf<TKey extends keyof NextAuthCallbackRecord> =
|
|
Exclude<NextAuthCallbackRecord[TKey], undefined>;
|