mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-26 14:56:39 +00:00
♻️ make logo URL optional
This commit is contained in:
committed by
Owen Schwartz
parent
c92b5942fc
commit
b7df8b7319
@@ -214,7 +214,7 @@ export const loginPageOrg = pgTable("loginPageOrg", {
|
|||||||
|
|
||||||
export const loginPageBranding = pgTable("loginPageBranding", {
|
export const loginPageBranding = pgTable("loginPageBranding", {
|
||||||
loginPageBrandingId: serial("loginPageBrandingId").primaryKey(),
|
loginPageBrandingId: serial("loginPageBrandingId").primaryKey(),
|
||||||
logoUrl: text("logoUrl").notNull(),
|
logoUrl: text("logoUrl"),
|
||||||
logoWidth: integer("logoWidth").notNull(),
|
logoWidth: integer("logoWidth").notNull(),
|
||||||
logoHeight: integer("logoHeight").notNull(),
|
logoHeight: integer("logoHeight").notNull(),
|
||||||
primaryColor: text("primaryColor"),
|
primaryColor: text("primaryColor"),
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ export const loginPageBranding = sqliteTable("loginPageBranding", {
|
|||||||
loginPageBrandingId: integer("loginPageBrandingId").primaryKey({
|
loginPageBrandingId: integer("loginPageBrandingId").primaryKey({
|
||||||
autoIncrement: true
|
autoIncrement: true
|
||||||
}),
|
}),
|
||||||
logoUrl: text("logoUrl").notNull(),
|
logoUrl: text("logoUrl"),
|
||||||
logoWidth: integer("logoWidth").notNull(),
|
logoWidth: integer("logoWidth").notNull(),
|
||||||
logoHeight: integer("logoHeight").notNull(),
|
logoHeight: integer("logoHeight").notNull(),
|
||||||
primaryColor: text("primaryColor"),
|
primaryColor: text("primaryColor"),
|
||||||
|
|||||||
@@ -35,7 +35,29 @@ const paramsSchema = z.strictObject({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const bodySchema = z.strictObject({
|
const bodySchema = z.strictObject({
|
||||||
logoUrl: z.url(),
|
logoUrl: z
|
||||||
|
.union([
|
||||||
|
z.string().length(0),
|
||||||
|
z.url().refine(
|
||||||
|
async (url) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
return (
|
||||||
|
response.status === 200 &&
|
||||||
|
(
|
||||||
|
response.headers.get("content-type") ?? ""
|
||||||
|
).startsWith("image/")
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: "Invalid logo URL, must be a valid image URL"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
])
|
||||||
|
.optional(),
|
||||||
logoWidth: z.coerce.number<number>().min(1),
|
logoWidth: z.coerce.number<number>().min(1),
|
||||||
logoHeight: z.coerce.number<number>().min(1),
|
logoHeight: z.coerce.number<number>().min(1),
|
||||||
resourceTitle: z.string(),
|
resourceTitle: z.string(),
|
||||||
@@ -95,6 +117,10 @@ export async function upsertLoginPageBranding(
|
|||||||
typeof loginPageBranding
|
typeof loginPageBranding
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
if ((updateData.logoUrl ?? "").trim().length === 0) {
|
||||||
|
updateData.logoUrl = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
build !== "saas" &&
|
build !== "saas" &&
|
||||||
!config.getRawPrivateConfig().flags.use_org_only_idp
|
!config.getRawPrivateConfig().flags.use_org_only_idp
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
GetLoginPageResponse
|
GetLoginPageResponse
|
||||||
} from "@server/routers/loginPage/types";
|
} from "@server/routers/loginPage/types";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
export interface AuthPageProps {
|
export interface AuthPageProps {
|
||||||
params: Promise<{ orgId: string }>;
|
params: Promise<{ orgId: string }>;
|
||||||
@@ -18,6 +19,12 @@ export interface AuthPageProps {
|
|||||||
|
|
||||||
export default async function AuthPage(props: AuthPageProps) {
|
export default async function AuthPage(props: AuthPageProps) {
|
||||||
const orgId = (await props.params).orgId;
|
const orgId = (await props.params).orgId;
|
||||||
|
|
||||||
|
// custom auth branding is only available in enterprise and saas
|
||||||
|
if (build === "oss") {
|
||||||
|
redirect(`/${orgId}/settings/general/`);
|
||||||
|
}
|
||||||
|
|
||||||
let subscriptionStatus: GetOrgTierResponse | null = null;
|
let subscriptionStatus: GetOrgTierResponse | null = null;
|
||||||
try {
|
try {
|
||||||
const subRes = await getCachedSubscription(orgId);
|
const subRes = await getCachedSubscription(orgId);
|
||||||
|
|||||||
@@ -42,24 +42,27 @@ export type AuthPageCustomizationProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const AuthPageFormSchema = z.object({
|
const AuthPageFormSchema = z.object({
|
||||||
logoUrl: z.url().refine(
|
logoUrl: z.union([
|
||||||
async (url) => {
|
z.string().length(0),
|
||||||
try {
|
z.url().refine(
|
||||||
const response = await fetch(url);
|
async (url) => {
|
||||||
return (
|
try {
|
||||||
response.status === 200 &&
|
const response = await fetch(url);
|
||||||
(response.headers.get("content-type") ?? "").startsWith(
|
return (
|
||||||
"image/"
|
response.status === 200 &&
|
||||||
)
|
(response.headers.get("content-type") ?? "").startsWith(
|
||||||
);
|
"image/"
|
||||||
} catch (error) {
|
)
|
||||||
return false;
|
);
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: "Invalid logo URL, must be a valid image URL"
|
||||||
}
|
}
|
||||||
},
|
)
|
||||||
{
|
]),
|
||||||
error: "Invalid logo URL, must be a valid image URL"
|
|
||||||
}
|
|
||||||
),
|
|
||||||
logoWidth: z.coerce.number<number>().min(1),
|
logoWidth: z.coerce.number<number>().min(1),
|
||||||
logoHeight: z.coerce.number<number>().min(1),
|
logoHeight: z.coerce.number<number>().min(1),
|
||||||
orgTitle: z.string().optional(),
|
orgTitle: z.string().optional(),
|
||||||
@@ -90,7 +93,6 @@ export default function AuthPageBrandingForm({
|
|||||||
deleteBranding,
|
deleteBranding,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [setIsDeleteModalOpen] = useState(false);
|
|
||||||
|
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import Image from "next/image";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
type BrandingLogoProps = {
|
type BrandingLogoProps = {
|
||||||
logoPath?: string;
|
logoPath?: string | null;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ type ResourceAuthPortalProps = {
|
|||||||
idps?: LoginFormIDP[];
|
idps?: LoginFormIDP[];
|
||||||
orgId?: string;
|
orgId?: string;
|
||||||
branding?: {
|
branding?: {
|
||||||
logoUrl: string;
|
logoUrl?: string | null;
|
||||||
logoWidth: number;
|
logoWidth: number;
|
||||||
logoHeight: number;
|
logoHeight: number;
|
||||||
primaryColor: string | null;
|
primaryColor: string | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user