Clean up apis

This commit is contained in:
Gabriel Brown 2024-10-06 15:19:54 -05:00
parent 7371cc8851
commit d7d3c63d7f
37 changed files with 142 additions and 175 deletions

0
.env.example Executable file → Normal file
View File

0
.eslintrc.cjs Executable file → Normal file
View File

0
.gitignore vendored Executable file → Normal file
View File

0
drizzle.config.ts Executable file → Normal file
View File

0
next.config.js Executable file → Normal file
View File

0
package.json Executable file → Normal file
View File

0
pnpm-lock.yaml generated Executable file → Normal file
View File

0
postcss.config.cjs Executable file → Normal file
View File

0
prettier.config.js Executable file → Normal file
View File

0
public/favicon.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -4,15 +4,18 @@ import type { NextRequest } from "next/server";
import { createOrUpdateCountdown } from "~/server/functions"; import { createOrUpdateCountdown } from "~/server/functions";
import { middleware } from "~/middleware"; import { middleware } from "~/middleware";
export const POST = async (request: NextRequest) => { type CreateOrUpdateCountdownRequest = {
const middlewareResponse = middleware(request);
if (middlewareResponse) return middlewareResponse;
try {
const { relationshipId, title, date } = await request.json() as {
relationshipId: string; relationshipId: string;
title: string; title: string;
date: string; date: string;
}; }
export const POST = async (request: NextRequest) => {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try {
const { relationshipId, title, date } =
await request.json()as CreateOrUpdateCountdownRequest;
await createOrUpdateCountdown(Number.parseInt(relationshipId), title, new Date(date)); await createOrUpdateCountdown(Number.parseInt(relationshipId), title, new Date(date));
return NextResponse.json({ message: "Countdown created or updated successfully" }); return NextResponse.json({ message: "Countdown created or updated successfully" });
} catch (error) { } catch (error) {

View File

@ -1,21 +1,19 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { getCountdownByRelationship } from "~/server/functions"; import { getCountdownByRelationship } from "~/server/functions";
import { middleware } from "~/middleware";
export const GET = async (request: Request) => { export const GET = async (request: NextRequest) => {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const url = new URL(request.url); const { searchParams } = new URL(request.url);
const apiKey = url.searchParams.get("apiKey"); const relationshipId: string | null = searchParams.get("relationshipId");
if (apiKey !== process.env.API_KEY) { if (!relationshipId || isNaN(parseInt(relationshipId)))
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
} else {
const relationshipId = url.searchParams.get("relationshipId");
if (!relationshipId)
return NextResponse.json({ message: "Invalid relationshipId" }, { status: 400 }); return NextResponse.json({ message: "Invalid relationshipId" }, { status: 400 });
const countdown = await getCountdownByRelationship(parseInt(relationshipId)); const countdown = await getCountdownByRelationship(parseInt(relationshipId));
return NextResponse.json(countdown); return NextResponse.json(countdown);
}
} catch (error) { } catch (error) {
console.error(error); console.error(error);
return NextResponse.json({ message: "Error" }, { status: 500 }); return NextResponse.json({ message: "Error" }, { status: 500 });

View File

@ -1,24 +1,20 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { fetchMessages } from "~/server/functions"; import { fetchMessages } from "~/server/functions";
import { middleware } from "~/middleware";
export const GET = async (request: Request) => { export const GET = async (request: NextRequest) => {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const url = new URL(request.url); const { searchParams } = new URL(request.url);
const apiKey = url.searchParams.get("apiKey"); const userId: string | null = searchParams.get("userId");
if (apiKey !== process.env.API_KEY) { const partnerId: string | null = searchParams.get("partnerId");
console.log("Invalid API Key"); if (!userId || !partnerId || isNaN(parseInt(userId)) || isNaN(parseInt(partnerId)))
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 }); return NextResponse.json({ message: "Invalid userId or partnerId" }, { status: 400 });
} else {
const userId = url.searchParams.get("userId");
if (!userId)
return NextResponse.json({ message: "Invalid userId" }, { status: 400 });
const partnerId = url.searchParams.get("partnerId");
if (!partnerId)
return NextResponse.json({ message: "Invalid partnerId" }, { status: 400 });
const messages = await fetchMessages(parseInt(userId), parseInt(partnerId)); const messages = await fetchMessages(parseInt(userId), parseInt(partnerId));
return NextResponse.json(messages); return NextResponse.json(messages);
}
} catch (error) { } catch (error) {
console.error(error); console.error(error);
return NextResponse.json({ message: "Error" }, { status: 500 }); return NextResponse.json({ message: "Error" }, { status: 500 });

View File

@ -2,6 +2,7 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server"; import type { NextRequest } from "next/server";
import { sendMessage } from "~/server/functions"; import { sendMessage } from "~/server/functions";
import { middleware } from "~/middleware";
type sendMessageRequest = { type sendMessageRequest = {
senderId: number; senderId: number;
@ -12,24 +13,18 @@ type sendMessageRequest = {
}; };
export const POST = async (request: NextRequest) => { export const POST = async (request: NextRequest) => {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const url = new URL(request.url);
const apiKey = url.searchParams.get("apiKey");
if (apiKey !== process.env.API_KEY) {
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
const body = await request.json() as sendMessageRequest;
const { const {
senderId, senderId,
receiverId, receiverId,
content, content,
mediaUrl = "", mediaUrl = "",
mediaType = "text", mediaType = "text",
} = body; } = await request.json() as sendMessageRequest;
if (!senderId || !receiverId || !content) { if (!senderId || !receiverId || !content || isNaN(senderId) || isNaN(receiverId))
return NextResponse.json({ message: "Missing required fields" }, { status: 400 }); return NextResponse.json({ message: "Missing required fields" }, { status: 400 });
}
const message = await sendMessage(senderId, receiverId, content, mediaUrl, mediaType); const message = await sendMessage(senderId, receiverId, content, mediaUrl, mediaType);
return NextResponse.json(message, { status: 201 }); return NextResponse.json(message, { status: 201 });
} catch (error) { } catch (error) {

View File

@ -1,26 +1,23 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { createRelationshipRequest } from "~/server/functions"; import { createRelationshipRequest } from "~/server/functions";
import { middleware } from "~/middleware";
type CreateRequestRequest = { type CreateRequestRequest = {
apiKey: string;
userId: number; userId: number;
targetUserId: number; targetUserId: number;
} }
export async function POST(request: Request) { export async function POST(request: NextRequest) {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const { apiKey, userId, targetUserId } = await request.json() as CreateRequestRequest; const { userId, targetUserId } = await request.json() as CreateRequestRequest;
console.log("Received request:", { apiKey, userId, targetUserId }); console.log("Received request:", { userId, targetUserId });
if (apiKey !== process.env.API_KEY) { if (!userId || !targetUserId || isNaN(userId) || isNaN(targetUserId))
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
if (!userId || !targetUserId) {
return NextResponse.json({ message: "Missing required fields" }, { status: 400 }); return NextResponse.json({ message: "Missing required fields" }, { status: 400 });
}
console.log("Creating relationship request for user:", userId); console.log("Creating relationship request for user:", userId);
const result = await createRelationshipRequest(userId, targetUserId); const result = await createRelationshipRequest(userId, targetUserId);

View File

@ -1,28 +1,20 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { deleteRelationship } from "~/server/functions"; import { deleteRelationship } from "~/server/functions";
import { middleware } from "~/middleware";
interface DeleteRelationshipRequest { export async function POST(request: NextRequest) {
apiKey: string; const middlewareResponse = await middleware(request);
relationshipId: number; if (middlewareResponse) return middlewareResponse;
}
export async function POST(request: Request) {
try { try {
const { apiKey, relationshipId } = await request.json() as DeleteRelationshipRequest; const { relationshipId } = await request.json() as { relationshipId: string };
console.log("Received request:", { apiKey, relationshipId });
if (apiKey !== process.env.API_KEY) { if (!relationshipId || isNaN(parseInt(relationshipId)))
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
if (!relationshipId) {
return NextResponse.json({ message: "Missing required fields" }, { status: 400 }); return NextResponse.json({ message: "Missing required fields" }, { status: 400 });
}
console.log("Deleting relationship:", relationshipId); console.log("Deleting relationship:", relationshipId);
const result = await deleteRelationship(relationshipId); const result = await deleteRelationship(parseInt(relationshipId));
if (result.success) { if (result.success) {
console.log("Relationship deleted successfully"); console.log("Relationship deleted successfully");

View File

@ -1,26 +1,23 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { updateRelationshipRequest } from "~/server/functions"; import { updateRelationshipRequest } from "~/server/functions";
import { middleware } from "~/middleware";
interface UpdateRequestRequest { interface UpdateRequestRequest {
apiKey: string;
relationshipId: number; relationshipId: number;
status: 'accepted' | 'rejected'; status: 'accepted' | 'rejected';
} }
export async function POST(request: Request) { export async function POST(request: NextRequest) {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const { apiKey, relationshipId, status } = await request.json() as UpdateRequestRequest; const { relationshipId, status } = await request.json() as UpdateRequestRequest;
console.log("Received request:", { apiKey, relationshipId, status }); console.log("Received request:", { relationshipId, status });
if (apiKey !== process.env.API_KEY) { if (!relationshipId || !status || isNaN(relationshipId))
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
if (!relationshipId || !status) {
return NextResponse.json({ message: "Missing required fields" }, { status: 400 }); return NextResponse.json({ message: "Missing required fields" }, { status: 400 });
}
console.log("Updating relationship request:", relationshipId); console.log("Updating relationship request:", relationshipId);
const result = await updateRelationshipRequest(relationshipId, status); const result = await updateRelationshipRequest(relationshipId, status);

View File

@ -1,21 +1,19 @@
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { updateUserPushToken } from '~/server/functions'; import { updateUserPushToken } from '~/server/functions';
import { middleware } from "~/middleware";
type Data = { type Data = {
apiKey: string;
userId: string; userId: string;
pushToken: string; pushToken: string;
}; };
export const POST = async (request: Request) => { export const POST = async (request: NextRequest) => {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const { apiKey, userId, pushToken } = await request.json() as Data; const { userId, pushToken } = await request.json() as Data;
console.log('Received request:', { apiKey, userId, pushToken }); console.log('Received request:', { userId, pushToken });
if (apiKey !== process.env.API_KEY) {
console.log('Invalid API Key');
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
console.log('Updating push token for user:', userId); console.log('Updating push token for user:', userId);
await updateUserPushToken(parseInt(userId), pushToken); await updateUserPushToken(parseInt(userId), pushToken);

View File

@ -1,23 +1,21 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { changePassword } from "~/server/functions"; import { changePassword } from "~/server/functions";
import { middleware } from "~/middleware";
type Data = { type Data = {
apiKey: string;
userId: number; userId: number;
oldPassword: string; oldPassword: string;
newPassword: string; newPassword: string;
}; };
export const POST = async (request: Request) => { export const POST = async (request: NextRequest) => {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const { apiKey, userId, oldPassword, newPassword } = await request.json() as Data; const { userId, oldPassword, newPassword } = await request.json() as Data;
console.log("Received request:", { apiKey, userId, oldPassword, newPassword }); console.log("Received request:", { userId, oldPassword, newPassword });
if (apiKey !== process.env.API_KEY) {
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
console.log("Changing password for user:", userId); console.log("Changing password for user:", userId);
await changePassword(userId, oldPassword, newPassword); await changePassword(userId, oldPassword, newPassword);

View File

@ -1,6 +1,8 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { createUser } from "~/server/functions"; import { createUser } from "~/server/functions";
import { middleware } from "~/middleware";
type CreateUserRequest = { type CreateUserRequest = {
username: string; username: string;
@ -11,20 +13,10 @@ type CreateUserRequest = {
pushToken?: string; pushToken?: string;
}; };
export async function POST(request: Request) { export async function POST(request: NextRequest) {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const url = new URL(request.url);
const apiKey = url.searchParams.get("apiKey");
if (apiKey !== process.env.API_KEY) {
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
// Parse the request body instead of using URL parameters for POST requests
const body = await request.json() as CreateUserRequest;
// Destructure the body with default values for optional fields
const { const {
username, username,
email, email,
@ -32,7 +24,7 @@ export async function POST(request: Request) {
name, name,
pfpURL = "", pfpURL = "",
pushToken = "" pushToken = ""
} = body; } = await request.json() as CreateUserRequest;
// Validate required fields // Validate required fields
if (!username || !email || !passwordHash || !name) { if (!username || !email || !passwordHash || !name) {

View File

@ -1,22 +1,19 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { getUserById } from "~/server/functions"; import { getUserById } from "~/server/functions";
import { middleware } from "~/middleware";
export const GET = async (request: Request) => { export const GET = async (request: NextRequest) => {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const url = new URL(request.url); const url = new URL(request.url);
const apiKey = url.searchParams.get("apiKey");
if (apiKey !== process.env.API_KEY) {
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
} else {
const userId = url.searchParams.get("userId"); const userId = url.searchParams.get("userId");
if (!userId) { if (!userId || isNaN(parseInt(userId)))
return NextResponse.json({ message: "Invalid userId" }, { status: 400 }); return NextResponse.json({ message: "Invalid userId" }, { status: 400 });
}
const user = await getUserById(parseInt(userId)); const user = await getUserById(parseInt(userId));
return NextResponse.json(user); return NextResponse.json(user);
}
} catch (error) { } catch (error) {
console.error(error); console.error(error);
return NextResponse.json({ message: "Error" }, { status: 500 }); return NextResponse.json({ message: "Error" }, { status: 500 });

View File

@ -1,19 +1,17 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { getUserByUsername } from "~/server/functions"; import { getUserByUsername } from "~/server/functions";
import { middleware } from "~/middleware";
export const GET = async (request: Request) => { export const GET = async (request: NextRequest) => {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const url = new URL(request.url); const url = new URL(request.url);
const apiKey = url.searchParams.get("apiKey");
if (apiKey !== process.env.API_KEY) {
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
} else {
const username = url.searchParams.get("username") ?? "2"; const username = url.searchParams.get("username") ?? "2";
const user = await getUserByUsername(username); const user = await getUserByUsername(username);
return NextResponse.json(user); return NextResponse.json(user);
}
} catch (error) { } catch (error) {
console.error(error); console.error(error);
return NextResponse.json({ message: "Error" }, { status: 500 }); return NextResponse.json({ message: "Error" }, { status: 500 });

View File

@ -1,22 +1,20 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { login } from "~/server/functions"; import { login } from "~/server/functions";
import { middleware } from "~/middleware";
interface LoginRequest { type LoginRequest = {
apiKey: string;
username: string; username: string;
password: string; password: string;
} }
export async function POST(request: Request) { export async function POST(request: NextRequest) {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const { apiKey, username, password } = await request.json() as LoginRequest; const { username, password } = await request.json() as LoginRequest;
console.log("Received request:", { apiKey, username, password }); console.log("Received request:", { username, password });
if (apiKey !== process.env.API_KEY) {
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
if (!username || !password) { if (!username || !password) {
return NextResponse.json({ message: "Missing required fields" }, { status: 400 }); return NextResponse.json({ message: "Missing required fields" }, { status: 400 });

View File

@ -6,7 +6,7 @@ import { middleware } from "~/middleware";
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
export const POST = async (request: NextRequest) => { export const POST = async (request: NextRequest) => {
const middlewareResponse = middleware(request); const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse; if (middlewareResponse) return middlewareResponse;
try { try {

View File

@ -5,7 +5,7 @@ import { refreshToken } from "~/server/functions";
import { middleware } from "~/middleware"; import { middleware } from "~/middleware";
export async function POST(request: NextRequest) { export async function POST(request: NextRequest) {
const middlewareResponse = middleware(request); const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse; if (middlewareResponse) return middlewareResponse;
try { try {
const { refreshToken: token } = await request.json() as { refreshToken: string }; const { refreshToken: token } = await request.json() as { refreshToken: string };

View File

@ -1,26 +1,23 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { updateUserPFP } from "~/server/functions"; import { updateUserPFP } from "~/server/functions";
import { middleware } from "~/middleware";
interface UpdatePfpRequest { interface UpdatePfpRequest {
apiKey: string;
userId: number; userId: number;
pfpURL: string; pfpURL: string;
} }
export async function POST(request: Request) { export async function POST(request: NextRequest) {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const { apiKey, userId, pfpURL } = await request.json() as UpdatePfpRequest; const { userId, pfpURL } = await request.json() as UpdatePfpRequest;
console.log("Received request:", { apiKey, userId, pfpURL }); console.log("Received request:", { userId, pfpURL });
if (apiKey !== process.env.API_KEY) { if (!userId || !pfpURL || isNaN(userId))
console.log("Invalid API Key");
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
if (!userId || !pfpURL) {
return NextResponse.json({ message: "Missing required fields" }, { status: 400 }); return NextResponse.json({ message: "Missing required fields" }, { status: 400 });
}
console.log("Updating profile picture for user:", userId); console.log("Updating profile picture for user:", userId);
const result = await updateUserPFP(userId, pfpURL); const result = await updateUserPFP(userId, pfpURL);

View File

@ -1,25 +1,27 @@
"use server"; "use server";
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { updateUserPushToken } from "~/server/functions"; import { updateUserPushToken } from "~/server/functions";
import { middleware } from "~/middleware";
interface UpdatePushTokenRequest { interface UpdatePushTokenRequest {
apiKey: string;
userId: number; userId: number;
pushToken: string; pushToken: string;
} }
export async function POST(request: Request) { export async function POST(request: NextRequest) {
const middlewareResponse = await middleware(request);
if (middlewareResponse) return middlewareResponse;
try { try {
const { apiKey, userId, pushToken } = await request.json() as UpdatePushTokenRequest; const { userId, pushToken } = await request.json() as UpdatePushTokenRequest;
console.log("Received request:", { apiKey, userId, pushToken }); console.log("Received request:", { userId, pushToken });
if (apiKey !== process.env.API_KEY) {
console.log("Invalid API Key"); if (!userId || !pushToken || isNaN(userId))
return NextResponse.json({ message: "Invalid API Key" }, { status: 401 });
}
if (!userId || !pushToken)
return NextResponse.json({ message: "Missing required fields" }, { status: 400 }); return NextResponse.json({ message: "Missing required fields" }, { status: 400 });
console.log("Updating push token for user:", userId); console.log("Updating push token for user:", userId);
const result = await updateUserPushToken(userId, pushToken); const result = await updateUserPushToken(userId, pushToken);
if (result.success) { if (result.success) {
console.log("Push token updated successfully"); console.log("Push token updated successfully");
return NextResponse.json({ message: "Push token updated successfully" }); return NextResponse.json({ message: "Push token updated successfully" });

0
src/app/layout.tsx Executable file → Normal file
View File

0
src/app/page.tsx Executable file → Normal file
View File

0
src/env.js Executable file → Normal file
View File

View File

@ -1,11 +1,20 @@
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) { export async function middleware(request: NextRequest): Promise<NextResponse | undefined> {
try {
const apiKey = request.headers.get('x-api-key'); const apiKey = request.headers.get('x-api-key');
if (!apiKey || apiKey !== process.env.API_KEY) if (!apiKey || apiKey !== process.env.API_KEY) {
return NextResponse.json({ message: 'Invalid API key' }, { status: 401 }); return NextResponse.json({ message: 'Invalid API key' }, { status: 401 });
}
// If the API key is valid, we don't return anything, allowing the request to proceed
return undefined;
} catch (error) {
console.error('Middleware error:', error);
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
}
} }
export const config = { export const config = {

0
src/server/db/index.ts Executable file → Normal file
View File

0
src/server/db/schema.ts Executable file → Normal file
View File

0
src/server/functions.ts Executable file → Normal file
View File

0
src/styles/globals.css Executable file → Normal file
View File

0
tailwind.config.ts Executable file → Normal file
View File

0
tsconfig.json Executable file → Normal file
View File