diff --git a/backend/pnpm-lock.yaml b/backend/pnpm-lock.yaml index 40205ea..49c8eab 100644 --- a/backend/pnpm-lock.yaml +++ b/backend/pnpm-lock.yaml @@ -2512,8 +2512,8 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} fast-xml-builder@1.2.0: resolution: {integrity: sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==} @@ -6028,14 +6028,14 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -6845,7 +6845,7 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-uri@3.1.0: {} + fast-uri@3.1.2: {} fast-xml-builder@1.2.0: dependencies: diff --git a/backend/src/modules/iam/iam.service.ts b/backend/src/modules/iam/iam.service.ts index 48be185..b7b252d 100644 --- a/backend/src/modules/iam/iam.service.ts +++ b/backend/src/modules/iam/iam.service.ts @@ -154,7 +154,10 @@ export class IamService { * Membuat inisial nama dengan desain premium & gradasi warna yang dinamis */ function generateSvgAvatar(name: string): string { - const initial = name ? name.trim().charAt(0).toUpperCase() : '?'; + const MAX_NAME_LENGTH = 128; + const safeName = + typeof name === 'string' ? name.trim().slice(0, MAX_NAME_LENGTH) : ''; + const initial = safeName ? safeName.charAt(0).toUpperCase() : '?'; // Daftar warna gradasi premium yang modern dan estetis const gradients = [ @@ -168,8 +171,8 @@ function generateSvgAvatar(name: string): string { // Hitung hash deterministik dari nama agar pengguna yang sama selalu mendapat gradasi warna yang sama let hash = 0; - for (let i = 0; i < name.length; i++) { - hash = name.charCodeAt(i) + ((hash << 5) - hash); + for (let i = 0; i < safeName.length; i++) { + hash = safeName.charCodeAt(i) + ((hash << 5) - hash); } const index = Math.abs(hash) % gradients.length; const { start, end } = gradients[index]; diff --git a/frontend/app/features/listings/components/create/ListingDigitalProductStep.tsx b/frontend/app/features/listings/components/create/ListingDigitalProductStep.tsx index be9c05d..493716a 100644 --- a/frontend/app/features/listings/components/create/ListingDigitalProductStep.tsx +++ b/frontend/app/features/listings/components/create/ListingDigitalProductStep.tsx @@ -59,10 +59,27 @@ export function ListingDigitalProductStep() { } }; - const isGoogleDrive = listingData.digitalLink.toLowerCase().includes("drive.google.com") || - listingData.digitalLink.toLowerCase().includes("docs.google.com"); - - const isDropbox = listingData.digitalLink.toLowerCase().includes("dropbox.com"); + const hasAllowedHost = (url: string, allowedHosts: string[]) => { + try { + const hostname = new URL(url).hostname.toLowerCase(); + return allowedHosts.some((allowedHost) => { + const normalizedAllowedHost = allowedHost.toLowerCase(); + return ( + hostname === normalizedAllowedHost || + hostname.endsWith(`.${normalizedAllowedHost}`) + ); + }); + } catch { + return false; + } + }; + + const isGoogleDrive = hasAllowedHost(listingData.digitalLink, [ + "drive.google.com", + "docs.google.com", + ]); + + const isDropbox = hasAllowedHost(listingData.digitalLink, ["dropbox.com"]); return (