Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api/create file #452

Merged
merged 4 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions middleware.ts → src/Middleware/AuthMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import jwt from "jsonwebtoken";
import User from "@/models/user";
import { mongoDB } from "@/lib/MongoDB";

export async function middleware(req: NextRequest) {
export async function AuthMiddleware(req: any) {
try {
const token : any = req.cookies.get('accessToken') || req.headers.get('Authorization')?.replace('Bearer ', '');
const token = req.cookies.get('accessToken') || req.headers.get('Authorization')?.replace('Bearer ', '');

if (!token) {
if (!token || token === undefined) {
return NextResponse.json({ error: 'Unauthorized Access!' }, { status: 401 });
}

const decodedToken : any = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET as string);
const decodedToken:any = jwt.verify(token, process.env.NEXTAUTH_SECRET as string);

await mongoDB();
const user = await User.findById(decodedToken._id).select('-password -refreshToken');

if (!user) return NextResponse.json({ error: 'Unauthorized Access!' }, { status: 401 });
if (!user) {
return NextResponse.json({ error: 'Unauthorized Access!' }, { status: 401 });
}

// Pass user data in request headers for further processing in API route
req.headers.set('user', JSON.stringify(user));

return NextResponse.next();
} catch (err) {
console.log(err);
return NextResponse.json({ message: 'Error occurred!' }, { status: 500 });
}
}

export const config = {
matcher: ["/dashboard"],
};
35 changes: 35 additions & 0 deletions src/app/api/files/create/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { mongoDB } from "@/lib/MongoDB";
import { AuthMiddleware } from "@/Middleware/AuthMiddleware";
import FileModel from "@/models/file";
import { ApiUser } from "@/types/types";
import { NextResponse } from "next/server";

export const POST = async (req: Request) => {

const result = await AuthMiddleware(req);

if (result instanceof NextResponse) {

try {
const { fileName, filePrivate } = await req.json();

await mongoDB();

const user: ApiUser = JSON.parse(req.headers.get("user") || "{}");

const file = await FileModel.create({
fileName,
filePrivate,
createdBy:user._id,
readBy:[user._id],
writtenBy:[user._id]
});

return NextResponse.json({ status: 200 });
} catch (err) {
return NextResponse.json(`Err : ${err}`, {status:500});
}
} else {
return result;
}
};
2 changes: 1 addition & 1 deletion src/app/api/files/private/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ export const PUT = async(req: Request) => {
} catch (err) {
console.log(err)
}
}
}
19 changes: 19 additions & 0 deletions src/app/api/health/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { AuthMiddleware } from "@/Middleware/AuthMiddleware";
import { NextRequest } from "next/server";
import { NextResponse } from "next/server";

export const GET = async (req: NextRequest, res: NextResponse) => {
try {
const result = await AuthMiddleware(req);
// If middleware returns NextResponse.next(), proceed with API logic
if (result.status==200) {
return NextResponse.json({ status: "UP" }, { status: 200 });
} else {
// Handle any errors from the middleware
return result;
}
} catch (error) {
console.error("Error in health endpoint:", error);
return NextResponse.json({ message: 'Error occurred!' }, { status: 500 });
}
};
33 changes: 33 additions & 0 deletions src/app/api/teams/create/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { mongoDB } from "@/lib/MongoDB";
import { AuthMiddleware } from "@/Middleware/AuthMiddleware";
import TeamModel from "@/models/team";
import { ApiUser } from "@/types/types";
import { NextResponse } from "next/server";

export const POST = async (req: Request) => {

const result = await AuthMiddleware(req);

if (result instanceof NextResponse) {

try {
const { teamName } = await req.json();

await mongoDB();

const user: ApiUser = JSON.parse(req.headers.get("user") || "{}");

const team = await TeamModel.create({
teamName,
createdBy:user._id,
teamMembers:[user._id]
});

return NextResponse.json({ status: 200 });
} catch (err) {
return NextResponse.json(`Err : ${err}`, {status:500});
}
} else {
return result;
}
};
52 changes: 17 additions & 35 deletions src/app/dashboard/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import { useMutation } from "convex/react";
import Image from "next/image";
import { SessionProvider, useSession } from "next-auth/react";
import Link from "next/link";
import { logIn } from "../Redux/Auth/auth-slice";


function DashboardLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const {data:session,status} = useSession();
const { data: session, status } = useSession();
const createTeam = useMutation(api.teams.createTeam);
const convex = useConvex();
const [fileList_, setFileList_] = useState();
Expand All @@ -30,22 +30,6 @@ function DashboardLayout({
const [hasCheckedTeam, setHasCheckedTeam] = useState(false);
const dispatch = useDispatch();

// useEffect(() => {
// if (session) {
// dispatch(
// logIn({
// id: session.user.id,
// accessToken: session.user.accessToken,
// refreshToken: session.user.refreshToken,
// email: session.user.email,
// firstName: session.user.firstName,
// lastName: session.user.lastName,
// image:session.user.image
// })
// );
// }
// }, [session]);

useEffect(() => {
if (session && !hasCheckedTeam) {
checkTeam();
Expand Down Expand Up @@ -88,40 +72,38 @@ function DashboardLayout({
/>
</div>
<div className="relative bg-white dark:bg-gray-800 p-8 rounded-lg shadow-2xl max-w-md w-full text-center z-10">
<h1 className="text-2xl font-semibold text-gray-800 dark:text-gray-200 mb-4">Welcome!</h1>
<h1 className="text-2xl font-semibold text-gray-800 dark:text-gray-200 mb-4">
Welcome!
</h1>
<p className="text-gray-600 dark:text-gray-400 mb-6">
To access this page, please{" "}
<Button asChild>
<Link href={"/signin"}>
Login
</Link>
<Link href={"/signin"}>Login</Link>
</Button>
</p>
<p className="text-sm text-gray-500 dark:text-gray-300">
Don&apos;t have an account?
<span className="text-orange-600 underline hover:text-blue-800 transition duration-300">
<Link href={"/signup"}>
Signup
</Link>
<Link href={"/signup"}>Signup</Link>
</span>
</p>
</div>
</div>
);

return (!loading || session === undefined) ? (
return !loading || session === undefined ? (
<div>
<FileListContext.Provider value={{ fileList_, setFileList_ }}>
<SessionProvider>
<div className="md:grid md:grid-cols-4">
<div
className={`bg-background z-[2] h-screen md:w-72 w-36 fixed ${count ? "" : "md:relative hidden"}`}
>
<SideNav />
<SessionProvider>
<div className="md:grid md:grid-cols-4">
<div
className={`bg-background z-[2] h-screen md:w-72 w-36 fixed ${count ? "" : "md:relative hidden"}`}
>
<SideNav />
</div>
<div className="col-span-4 md:ml-72">{children}</div>
</div>
<div className="col-span-4 md:ml-72">{children}</div>
</div>
</SessionProvider>
</SessionProvider>
</FileListContext.Provider>
</div>
) : (
Expand Down
21 changes: 20 additions & 1 deletion src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import Link from "next/link";
import InviteModal from "@/components/shared/InviteModal";
import JoinTeamModal from "@/components/shared/JoinTeamModal";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import axiosProtectedInstance from "@/config/AxiosProtectedRoute";
import { checkHealthUrl } from "@/lib/API-URLs";
import createAxiosInstance from "@/config/AxiosProtectedRoute";
import { useRouter } from "next/navigation";
import { logOut } from "../Redux/Auth/auth-slice";

export interface FILE {
archive: boolean;
Expand All @@ -39,8 +44,22 @@ function Dashboard() {
const dispatch = useDispatch();
const [userData, setUserdata] = useState<any>();
const user = useSelector((state:RootState) => state.auth.user);
const router = useRouter()


const accessToken = useSelector((state:RootState)=>state.auth.user.accessToken);

const axiosInstance = createAxiosInstance(accessToken);

useEffect(() => {
const checkHealth = async () => {
const res = await axiosInstance.get(checkHealthUrl);
if(res.status !== 200) {
router.push('/signin');
dispatch(logOut())
};
};
checkHealth();
}, []);

const checkUser = async () => {
const result = await convex.query(api.user.getUser, { email: user?.email });
Expand Down
1 change: 1 addition & 0 deletions src/config/AxiosInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const axiosInstance = axios.create({
timeout: 10000, // Request timeout
headers: {
'Content-Type': 'application/json',

},
});

Expand Down
33 changes: 33 additions & 0 deletions src/config/AxiosProtectedRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import axios, { AxiosInstance } from 'axios';

const createAxiosInstance = (accessToken?: string): AxiosInstance => {
if (accessToken === undefined) {
throw new Error('Access token is required to create an authenticated Axios instance.');
}

const instance = axios.create({
baseURL: process.env.NEXT_PUBLIC_CLIENT_URL, // Replace with your API base URL
timeout: 10000, // Request timeout
headers: {
'Content-Type': 'application/json',
// Optionally add other headers
},
});

// Request interceptor to include Bearer token if accessToken is provided
instance.interceptors.request.use(
(config) => {
if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);

return instance;
};

export default createAxiosInstance;
3 changes: 2 additions & 1 deletion src/lib/API-URLs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export const getTeamMembersData = "/api/teams/members";
export const deleteTeamMemberUrl = "/api/teams/members";
export const updateReadAccessUrl = "/api/files/read";
export const updateWriteAccessUrl = "/api/files/write";
export const registerUserUrl = "/api/auth/register";
export const registerUserUrl = "/api/auth/register";
export const checkHealthUrl = "/api/health";
8 changes: 2 additions & 6 deletions src/models/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ interface File {
archive: boolean;
document: string;
whiteboard: string;
private: boolean;
filePrivate: boolean;
writtenBy: any[];
readBy: any[];
write: boolean;
read: boolean;
}

const FileSchema = new Schema<File>(
Expand All @@ -20,11 +18,9 @@ const FileSchema = new Schema<File>(
archive: { type: Boolean },
document: { type: String },
whiteboard: { type: String },
private: { type: Boolean, required: true },
filePrivate: { type: Boolean, required: true },
writtenBy: [{ type: Schema.Types.ObjectId, required: true, ref: "User" }],
readBy: [{ type: Schema.Types.ObjectId, required: true, ref: "User" }],
write: { type: Boolean },
read: { type: Boolean },
},
{ timestamps: true }
);
Expand Down
2 changes: 1 addition & 1 deletion src/models/user.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose, { Schema } from "mongoose";
import jwt from "jsonwebtoken"

interface User {
export interface User {
email: string;
firstName: string;
lastName: string;
Expand Down
8 changes: 7 additions & 1 deletion src/types/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { User } from "@/models/user";

type USER = {
isAuth: boolean;
id:string;
Expand All @@ -7,4 +9,8 @@ type USER = {
refreshToken:string;
accessToken:string;
image:string | undefined;
};
};

interface ApiUser extends User{
_id:string;
}
Loading