Forbidden page
This commit is contained in:
parent
3f4e529a53
commit
d6413fa514
8 changed files with 198 additions and 65 deletions
12
package-lock.json
generated
12
package-lock.json
generated
|
@ -12,6 +12,7 @@
|
|||
"bits-ui": "^0.21.7",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"drag-drop-touch": "^1.3.1",
|
||||
"firebase": "^10.11.1",
|
||||
"firebase-admin": "^12.1.0",
|
||||
|
@ -2808,6 +2809,17 @@
|
|||
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
||||
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.4.5",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
||||
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/drag-drop-touch": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/drag-drop-touch/-/drag-drop-touch-1.3.1.tgz",
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
"bits-ui": "^0.21.7",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"drag-drop-touch": "^1.3.1",
|
||||
"firebase": "^10.11.1",
|
||||
"firebase-admin": "^12.1.0",
|
||||
|
|
10
src/lib/components/Myerror.svelte
Normal file
10
src/lib/components/Myerror.svelte
Normal file
|
@ -0,0 +1,10 @@
|
|||
<script lang="ts">
|
||||
export let username = 'userdata.username'
|
||||
</script>
|
||||
<div class="text-center">
|
||||
<h1 class=" text-warning text-4xl">403</h1>
|
||||
<span class="text-gray-500">The Profile of <strong class="text-xl text-warning">@{username}</strong> is not public!</span>
|
||||
</div>
|
||||
<div class=" my-4">
|
||||
<img src="403.png" alt="forbidden"/>
|
||||
</div>
|
101
src/lib/firebase.ts
Normal file
101
src/lib/firebase.ts
Normal file
|
@ -0,0 +1,101 @@
|
|||
// Import the functions you need from the SDKs you need
|
||||
import { initializeApp } from "firebase/app";
|
||||
import { doc, getFirestore, onSnapshot } from "firebase/firestore";
|
||||
import { getAuth, onAuthStateChanged, type User } from "firebase/auth";
|
||||
import { getStorage } from "firebase/storage";
|
||||
import { writable, type Readable, derived } from "svelte/store";
|
||||
import { env } from "$env/dynamic/public";
|
||||
|
||||
// TODO: Add SDKs for Firebase products that you want to use
|
||||
// https://firebase.google.com/docs/web/setup#available-libraries
|
||||
// Your web app's Firebase configuration
|
||||
const firebaseConfig = {
|
||||
|
||||
apiKey: env.PUBLIC_API_KEY,
|
||||
authDomain: env.PUBLIC_AUTH_DOMAIN ,
|
||||
projectId: env.PUBLIC_PROJECT_ID,
|
||||
storageBucket: env.PUBLIC_STORAGE_BUCKET,
|
||||
messagingSenderId: env.PUBLIC_MESSAGING_SENDER_ID,
|
||||
appId: env.PUBLIC_APP_ID,
|
||||
|
||||
};
|
||||
|
||||
// Initialize Firebase
|
||||
const app = initializeApp(firebaseConfig);
|
||||
|
||||
export const db = getFirestore();
|
||||
export const auth = getAuth();
|
||||
export const storage = getStorage();
|
||||
|
||||
/**
|
||||
* @returns a store with the current firebase user
|
||||
*/
|
||||
|
||||
function userStore() {
|
||||
let unsubscribe: () => void;
|
||||
|
||||
if (!auth || !globalThis.window) {
|
||||
console.warn("Auth is not initialized or not in browser");
|
||||
const { subscribe } = writable<User | null>(null);
|
||||
return {
|
||||
subscribe,
|
||||
};
|
||||
}
|
||||
|
||||
const { subscribe } = writable(auth?.currentUser ?? null, (set) => {
|
||||
unsubscribe = onAuthStateChanged(auth, (user) => {
|
||||
set(user);
|
||||
});
|
||||
|
||||
return () => unsubscribe();
|
||||
});
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
};
|
||||
}
|
||||
|
||||
export const user = userStore();
|
||||
|
||||
/**
|
||||
* @param {string} path document path or reference
|
||||
* @returns a store with realtime updates on document data
|
||||
*/
|
||||
export function docStore<T>(path: string) {
|
||||
let unsubscribe: () => void;
|
||||
|
||||
const docRef = doc(db, path);
|
||||
|
||||
const { subscribe } = writable<T | null>(null, (set) => {
|
||||
unsubscribe = onSnapshot(docRef, (snapshot) => {
|
||||
set((snapshot.data() as T) ?? null);
|
||||
});
|
||||
|
||||
return () => unsubscribe();
|
||||
});
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
ref: docRef,
|
||||
id: docRef.id,
|
||||
};
|
||||
}
|
||||
|
||||
interface UserData {
|
||||
username: string;
|
||||
bio: string;
|
||||
photoURL: string;
|
||||
links: any[];
|
||||
published: boolean;
|
||||
}
|
||||
|
||||
export const userData: Readable<UserData | null> = derived(
|
||||
user,
|
||||
($user, set) => {
|
||||
if ($user) {
|
||||
return docStore<UserData>(`users/${$user.uid}`).subscribe(set);
|
||||
} else {
|
||||
set(null);
|
||||
}
|
||||
},
|
||||
);
|
|
@ -9,8 +9,10 @@
|
|||
} from "firebase/auth";
|
||||
import { goto } from "$app/navigation";
|
||||
import { toasts, ToastContainer, FlatToast } from "svelte-toasts";
|
||||
import Myerror from "$lib/components/Myerror.svelte"
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
async function signInWithGoogle() {
|
||||
const provider = new GoogleAuthProvider();
|
||||
const user = await signInWithPopup(auth, provider);
|
||||
|
@ -36,6 +38,10 @@
|
|||
navigator.clipboard.writeText(copytext)
|
||||
showToast()
|
||||
}
|
||||
|
||||
|
||||
let unpublished = data.published
|
||||
let username = data.username
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
@ -47,6 +53,11 @@
|
|||
<meta property="og:url" content="https://nmd.mov/{data.username}" />
|
||||
</svelte:head>
|
||||
|
||||
{#if unpublished && data.username != $userData?.username}
|
||||
<div class="card card-body m-auto">
|
||||
<Myerror {username}></Myerror>
|
||||
</div>
|
||||
{:else}
|
||||
<main class=" prose text-center mx-auto mt-8">
|
||||
<h1 class="text-4xl text-teal-700">
|
||||
@{data.username}
|
||||
|
@ -102,3 +113,4 @@
|
|||
>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { collection, getDocs, limit, query, where } from 'firebase/firestore';
|
||||
import type { PageLoad } from './$types';
|
||||
import { db, userData } from '$lib/firebase';
|
||||
import { db, userData} from '$lib/firebase';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const load = (async ({ params }) => {
|
||||
|
@ -20,14 +20,11 @@ export const load = (async ({ params }) => {
|
|||
throw error(404, "that user does not exists")
|
||||
}
|
||||
|
||||
if (!data.published) {
|
||||
throw error(403, `The Profile of @${data.username} is not public!`)
|
||||
}
|
||||
|
||||
return {
|
||||
username: data.username,
|
||||
photoURL: data.photoURL,
|
||||
bio: data.bio,
|
||||
links: data.links ?? [],
|
||||
published: Boolean
|
||||
}
|
||||
}) satisfies PageLoad;
|
||||
|
|
BIN
static/403.png
Normal file
BIN
static/403.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
|
@ -2,67 +2,67 @@ import { fontFamily } from "tailwindcss/defaultTheme";
|
|||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
const config = {
|
||||
darkMode: ["class"],
|
||||
content: ["./src/**/*.{html,js,svelte,ts}"],
|
||||
plugins: [require("daisyui")],
|
||||
daisyui: {
|
||||
themes: ["dark"],
|
||||
darkMode: ["class"],
|
||||
content: ["./src/**/*.{html,js,svelte,ts}"],
|
||||
plugins: [require("daisyui")],
|
||||
daisyui: {
|
||||
themes: ["dark"],
|
||||
},
|
||||
safelist: ["dark"],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
screens: {
|
||||
"2xl": "1400px",
|
||||
},
|
||||
},
|
||||
safelist: ["dark"],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
screens: {
|
||||
"2xl": "1400px"
|
||||
}
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border) / <alpha-value>)",
|
||||
input: "hsl(var(--input) / <alpha-value>)",
|
||||
ring: "hsl(var(--ring) / <alpha-value>)",
|
||||
background: "hsl(var(--background) / <alpha-value>)",
|
||||
foreground: "hsl(var(--foreground) / <alpha-value>)",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary) / <alpha-value>)",
|
||||
foreground: "hsl(var(--primary-foreground) / <alpha-value>)"
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: "hsl(var(--secondary) / <alpha-value>)",
|
||||
foreground: "hsl(var(--secondary-foreground) / <alpha-value>)"
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
|
||||
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)"
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: "hsl(var(--muted) / <alpha-value>)",
|
||||
foreground: "hsl(var(--muted-foreground) / <alpha-value>)"
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: "hsl(var(--accent) / <alpha-value>)",
|
||||
foreground: "hsl(var(--accent-foreground) / <alpha-value>)"
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: "hsl(var(--popover) / <alpha-value>)",
|
||||
foreground: "hsl(var(--popover-foreground) / <alpha-value>)"
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card) / <alpha-value>)",
|
||||
foreground: "hsl(var(--card-foreground) / <alpha-value>)"
|
||||
}
|
||||
},
|
||||
borderRadius: {
|
||||
lg: "var(--radius)",
|
||||
md: "calc(var(--radius) - 2px)",
|
||||
sm: "calc(var(--radius) - 4px)"
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [...fontFamily.sans]
|
||||
}
|
||||
}
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border) / <alpha-value>)",
|
||||
input: "hsl(var(--input) / <alpha-value>)",
|
||||
ring: "hsl(var(--ring) / <alpha-value>)",
|
||||
background: "hsl(var(--background) / <alpha-value>)",
|
||||
foreground: "hsl(var(--foreground) / <alpha-value>)",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary) / <alpha-value>)",
|
||||
foreground: "hsl(var(--primary-foreground) / <alpha-value>)",
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: "hsl(var(--secondary) / <alpha-value>)",
|
||||
foreground: "hsl(var(--secondary-foreground) / <alpha-value>)",
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
|
||||
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)",
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: "hsl(var(--muted) / <alpha-value>)",
|
||||
foreground: "hsl(var(--muted-foreground) / <alpha-value>)",
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: "hsl(var(--accent) / <alpha-value>)",
|
||||
foreground: "hsl(var(--accent-foreground) / <alpha-value>)",
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: "hsl(var(--popover) / <alpha-value>)",
|
||||
foreground: "hsl(var(--popover-foreground) / <alpha-value>)",
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card) / <alpha-value>)",
|
||||
foreground: "hsl(var(--card-foreground) / <alpha-value>)",
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
lg: "var(--radius)",
|
||||
md: "calc(var(--radius) - 2px)",
|
||||
sm: "calc(var(--radius) - 4px)",
|
||||
},
|
||||
fontFamily: {
|
||||
sans: [...fontFamily.sans],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
Loading…
Reference in a new issue