summaryrefslogtreecommitdiff
path: root/frontend/lib
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2025-08-11 11:51:39 +0100
committerdiogo464 <[email protected]>2025-08-11 11:51:39 +0100
commit4af66f418b6837b6441b4e8eaf2d8ede585238b9 (patch)
tree34a4e913a2848515166b2ac0489794419a33bfcc /frontend/lib
parent0d3488a3811c8d58bd570af64cc29840df9ba439 (diff)
snapshot
Diffstat (limited to 'frontend/lib')
-rw-r--r--frontend/lib/auth.ts103
-rw-r--r--frontend/lib/drive.ts91
-rw-r--r--frontend/lib/env.ts3
-rw-r--r--frontend/lib/utils.ts26
4 files changed, 223 insertions, 0 deletions
diff --git a/frontend/lib/auth.ts b/frontend/lib/auth.ts
new file mode 100644
index 0000000..fe00b11
--- /dev/null
+++ b/frontend/lib/auth.ts
@@ -0,0 +1,103 @@
1import { cookies } from 'next/headers';
2import { Env_is_development } from './env';
3import { Elsie } from 'next/font/google';
4
5export interface UserSessionCookie {
6 name: string,
7 value: string,
8}
9
10export interface UserAuth {
11 isLoggedIn: boolean,
12 username: string,
13 name: string,
14 email: string,
15 provider: string,
16 oauth: boolean,
17}
18
19export async function Auth_extract_session_cookie(): Promise<UserSessionCookie | null> {
20 const cookieStore = await cookies();
21 for (const cookie of cookieStore.getAll()) {
22 if (!cookie.name.includes("tinyauth-session"))
23 continue;
24 return {
25 name: cookie.name,
26 value: cookie.value,
27 } as UserSessionCookie;
28 }
29 return null;
30}
31
32export async function Auth_get_user(): Promise<UserAuth> {
33 const cookie = await Auth_extract_session_cookie();
34 const endpoint = Auth_tinyauth_endpoint();
35
36 try {
37 const headers: Record<string, string> = {};
38 if (cookie) {
39 headers['Cookie'] = `${cookie.name}=${cookie.value}`;
40 }
41
42 const response = await fetch(`${endpoint}/api/user`, {
43 method: 'GET',
44 headers
45 });
46
47 if (!response.ok) {
48 return {
49 isLoggedIn: false,
50 username: '',
51 name: '',
52 email: '',
53 provider: '',
54 oauth: false
55 };
56 }
57
58 const data = await response.json();
59
60 return {
61 isLoggedIn: data.isLoggedIn || false,
62 username: data.username || '',
63 name: data.name || '',
64 email: data.email || '',
65 provider: data.provider || '',
66 oauth: data.oauth || false
67 };
68 } catch (error) {
69 console.error('Failed to fetch user:', error);
70 return {
71 isLoggedIn: false,
72 username: '',
73 name: '',
74 email: '',
75 provider: '',
76 oauth: false
77 };
78 }
79}
80
81export function Auth_user_can_upload(user: UserAuth): boolean {
82 if (!user.isLoggedIn)
83 return false;
84
85 if (Env_is_development())
86 return true;
87
88 return user.oauth && user.email.endsWith("@campus.fct.unl.pt");
89}
90
91function Auth_tinyauth_endpoint(): string {
92 const endpoint = process.env.TINYAUTH_ENDPOINT;
93 if (endpoint == undefined)
94 throw new Error(`env var TINYAUTH_ENDPOINT not defined`);
95 return endpoint;
96}
97
98export function Auth_tinyauth_public_endpoint(): string {
99 const endpoint = process.env.TINYAUTH_PUBLIC_ENDPOINT;
100 if (endpoint == undefined)
101 throw new Error(`env var TINYAUTH_PUBLIC_ENDPOINT not defined`);
102 return endpoint;
103}
diff --git a/frontend/lib/drive.ts b/frontend/lib/drive.ts
new file mode 100644
index 0000000..4211949
--- /dev/null
+++ b/frontend/lib/drive.ts
@@ -0,0 +1,91 @@
1import { spawnSync } from 'child_process'
2
3export interface DriveLsEntry {
4 path: string
5 type: "dir" | "file"
6 lastmod: number
7 blob: string | null
8 size: number | null
9 author: string
10}
11
12/// lists the given path on the drive
13export async function Drive_ls(path: string, recursive: boolean): Promise<DriveLsEntry[]> {
14 const args = ['ls']
15 if (recursive) {
16 args.push('-r')
17 }
18 if (path) {
19 args.push(path)
20 }
21
22 const result = spawnSync('fctdrive', args, { encoding: 'utf-8' })
23 if (result.error) {
24 throw new Error(`Failed to execute fctdrive: ${result.error.message}`)
25 }
26 if (result.status !== 0) {
27 throw new Error(`fctdrive exited with code ${result.status}: ${result.stderr}`)
28 }
29 const stdout = result.stdout
30 const entries = []
31 for (const line of stdout.split('\n')) {
32 if (line.trim() == "")
33 continue;
34
35 const parts = line.split('\t');
36 const path = parts[0];
37 const type = parts[1];
38 const lastmod = parseInt(parts[2]);
39 const blobStr = parts[3];
40 const sizeStr = parts[4];
41 const author = parts[5];
42
43 var blob = null;
44 if (blobStr != "-")
45 blob = blobStr;
46
47 var size = null;
48 if (sizeStr != "-")
49 size = parseFloat(sizeStr);
50
51 entries.push({
52 path, type, lastmod, blob, size, author
53 } as DriveLsEntry);
54 }
55 return entries;
56}
57
58/// import the file at local_path by moving it to drive_path
59export async function Drive_import(local_path: string, drive_path: string, email: string) {
60 const result = spawnSync('fctdrive', ['import', local_path, "--mode", "move", "--destination", drive_path, "--email", email], { encoding: 'utf-8' });
61 if (result.error) {
62 throw new Error(`Failed to execute fctdrive: ${result.error.message}`);
63 }
64 if (result.status !== 0) {
65 throw new Error(`fctdrive exited with code ${result.status}: ${result.stderr}`);
66 }
67}
68
69/// returns the full filesystem path of the blob given its id
70export async function Drive_blob_path(blob: string): Promise<string> {
71 const result = spawnSync('fctdrive', ['blob', blob], { encoding: 'utf-8' })
72 if (result.error) {
73 throw new Error(`Failed to execute fctdrive: ${result.error.message}`)
74 }
75 if (result.status !== 0) {
76 throw new Error(`fctdrive exited with code ${result.status}: ${result.stderr}`)
77 }
78 return result.stdout.trim();
79}
80
81export function Drive_basename(path: string): string {
82 const parts = path.split('/');
83 return parts[parts.length - 1];
84}
85
86export function Drive_parent(path: string): string | null {
87 const parts = path.split('/');
88 if (parts.length <= 1)
89 return null;
90 return parts[parts.length - 2];
91}
diff --git a/frontend/lib/env.ts b/frontend/lib/env.ts
new file mode 100644
index 0000000..d67fb3c
--- /dev/null
+++ b/frontend/lib/env.ts
@@ -0,0 +1,3 @@
1export function Env_is_development(): boolean {
2 return process.env.NODE_ENV == "development";
3}
diff --git a/frontend/lib/utils.ts b/frontend/lib/utils.ts
new file mode 100644
index 0000000..7a1e30c
--- /dev/null
+++ b/frontend/lib/utils.ts
@@ -0,0 +1,26 @@
1/**
2 * Formats a size in bytes into a human-readable string
3 * @param bytes Size in bytes
4 * @returns Formatted size string (e.g., "1.5 KB", "2.3 MB", "1.2 GB")
5 */
6export function formatSize(bytes: number | null): string {
7 if (bytes === null || bytes === 0) {
8 return '-'
9 }
10
11 const units = ['B', 'KB', 'MB', 'GB', 'TB']
12 let size = bytes
13 let unitIndex = 0
14
15 while (size >= 1024 && unitIndex < units.length - 1) {
16 size /= 1024
17 unitIndex++
18 }
19
20 // Format with appropriate decimal places
21 if (size < 10 && unitIndex > 0) {
22 return `${size.toFixed(1)} ${units[unitIndex]}`
23 } else {
24 return `${Math.round(size)} ${units[unitIndex]}`
25 }
26} \ No newline at end of file