Skip to content

Commit

Permalink
some changes to authentication + styling form_create page (#69)
Browse files Browse the repository at this point in the history
lil changes in authentication
  • Loading branch information
Anas-github-acc authored Jul 27, 2024
1 parent 3d5fa3e commit 8a021a8
Show file tree
Hide file tree
Showing 33 changed files with 2,209 additions and 224 deletions.
939 changes: 878 additions & 61 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@
"@emotion/react": "^11.12.0",
"@emotion/styled": "^11.12.0",
"@mui/material": "^5.16.4",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@reduxjs/toolkit": "^2.2.6",
"@supabase/ssr": "^0.4.0",
"@vercel/analytics": "^1.3.1",
"@vercel/speed-insights": "^1.0.12",
"axios": "^1.7.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"ldrs": "^1.0.2",
"lucide-react": "^0.408.0",
"next": "14.2.5",
"next-client-cookies": "^1.1.1",
Expand All @@ -45,4 +50,4 @@
"tailwindcss": "^3.4.1",
"typescript": "^5"
}
}
}
Binary file added public/placeholder-user.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/profile-pic.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions src/app/api/logout/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {NextRequest, NextResponse} from "next/server";
import {createClient} from "@/utils/supabase/server";

export async function GET(req: NextRequest) {
const supabase = createClient()

const { error } = await supabase.auth.signOut()

if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}

return NextResponse.json({ data: 'Logout successful' }, { status: 200 });
}
29 changes: 29 additions & 0 deletions src/app/api/rest/v1/isUsername/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {NextRequest, NextResponse} from "next/server";

export async function POST(req: NextRequest): Promise<NextResponse> {
let response = NextResponse.next({
request: {
headers: req.headers,
},
})

const body = await req.json()

if ( !body.username ) {
return NextResponse.json({ error: 'username is required' })
}

let res = await fetch(`${process.env.NEXT_PUBLIC_SUPABASE_URL}/rest/v1/rpc/is_username_exist`, {
method: 'POST',
headers: {
"apikey": process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
"Authorization": `Bearer ${process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body)
});

let data = await res.json();

return NextResponse.json({ state: data });
}
39 changes: 39 additions & 0 deletions src/app/api/rest/v1/users/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {NextRequest, NextResponse} from "next/server";
import { createClient } from "@/utils/supabase/server";
import { User } from "@supabase/supabase-js";

export async function POST(req: NextRequest): Promise<NextResponse> {
let response = NextResponse.next({
request: {
headers: req.headers,
},
})

const body = await req.json()
const supabase = createClient();
const searchParams = req.nextUrl.searchParams;
const option = searchParams.get('option');

let data: User | User[] | null = null;

if ( option === 'insert' ) {
const { data: user, error: error } = await supabase
.from('users')
.insert([{id: body.id, username: body.username, admin: body.admin}])
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
data = user;
} else if ( option === 'update' ) {
const { data: user, error: error } = await supabase
.from('users')
.update({username: body.username})
.match({id: body.id})
if (error) {
return NextResponse.json({ error: error.message }, { status: 500 });
}
data = user;
}

return NextResponse.json({ data: data });
}
62 changes: 27 additions & 35 deletions src/app/auth/action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,61 +21,53 @@ export const Login = async (

export const SignUp = async (
credentials : {
username: string | null,
email: string ,
password: string ,
}) => {
const origin = headers().get("origin");
const referer = headers().get("referer");
const query = referer?.split('?')[1].split('&');
const org = query?.find((q) => q.includes('organisation')) || '';

const username = credentials.username;
const supabase = createClient();
const { data: { session }, error, } = await supabase.auth.signUp({

const { data: { user, session }, error, } = await supabase.auth.signUp({
email: credentials.email as string,
password: credentials.password as string,
options: {
emailRedirectTo: `${origin}/auth/callback`,
emailRedirectTo: `${origin}/auth/confirm`,
data: { username: username },
},
});

if (error) {
console.log(error);
return { error: error.message };
}
if (session) {
if (session || user?.role !== 'authenticated') {
return { error: 'Email already exists' };
}
return { error: null };
};

export const AuthSignIn = async () => {
const origin = headers().get("origin");
const gmail = cookies()?.get('email')?.value || '';

const supabase = createClient();
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: `${origin}/auth/callback`,
queryParams: {
include_granted_scopes: 'true',
access_type: 'offline',
prompt: 'select_account',
login_hint: gmail,
},
},
});
if (error) return { error: error.message, url: null };
if (data.url) return { error: null, url: data.url };
return { error: 'Error signing in', url: null };
}

export async function usernameExisits(username: string): Promise<boolean> {
const origin = headers().get("origin");
const gmail = cookies()?.get('email')?.value || '';

const supabase = createClient();
let { data, error } = await supabase
.rpc('is_username_exist', {
username: username,
});
if (error) console.error(error)
return data;
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: `${origin}/auth/callback`,
queryParams: {
include_granted_scopes: 'true',
access_type: 'offline',
prompt: 'select_account',
login_hint: gmail,
},
},
});
if (error) return { error: error.message, url: null };
if (data.url) return { error: null, url: data.url };
return { error: 'Error signing in', url: null };
}

export const checkEmailForOrganisation = (
Expand Down
1 change: 1 addition & 0 deletions src/app/auth/callback/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ export async function GET(req: NextRequest, res: NextResponse) {
console.log('x ',error);
}
}

return NextResponse.redirect(url);
}
27 changes: 14 additions & 13 deletions src/app/auth/component/component.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { FormEvent, use, useEffect, useState } from "react";
import { usernameExisits } from "@/app/auth/action";
import React, { FormEvent, use, useEffect, useState } from "react";
import axios from "axios";

import { Label } from "@/components/ui/label"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import Loader from '@/components/ui/loader'

import { VscEye, VscEyeClosed } from "react-icons/vsc";
import CircularProgress from '@mui/material/CircularProgress';
import { VscEye, VscEyeClosed } from "react-icons/vsc"
import styles from './styles.module.css'
import { cn } from "@/lib/utils"


interface Props {
auth: string | null
SignUp: (e: EventTarget & HTMLFormElement) => Promise<boolean | void>
Expand Down Expand Up @@ -89,23 +90,22 @@ export function Component( props : Props) {
return ;
}
setLoading(true);
const data = await usernameExisits(username)
console.log('data = ',data);
if (data) {
const nextUserSibling = current.username.nextSibling as HTMLElement;
const res = await axios.post('/api/rest/v1/isUsername', {username: username});

if (res.data.state) {
const nextUserSibling = current.username.nextElementSibling as HTMLElement;
nextUserSibling.innerText = 'Username already exists';
} else {
const nextUserSibling = current.username.nextSibling as HTMLElement;
const nextUserSibling = current.username.nextElementSibling as HTMLElement;
nextUserSibling.innerText = '';
if (validatePassword(password) && password.length>=8) {

const bool = await props.SignUp(current)
if (!bool) setLoading(false);

const nextSibling = current.password.nextSibling as HTMLElement;
const nextSibling = current.password.nextElementSibling as HTMLElement;
nextSibling.innerText = '';
} else {
const nextSibling = current.password.nextSibling as HTMLElement;
const nextSibling = current.password.nextElementSibling as HTMLElement;
if (!validatePassword(password, 1)) {
nextSibling.innerText = 'Password must be at least 8 characters long';
} else if (!validatePassword(password, 2)) {
Expand Down Expand Up @@ -171,7 +171,8 @@ export function Component( props : Props) {
className="group relative flex w-full justify-center rounded-[8px] bg-primary py-6 px-4 text-md font-bold text-primary-foreground transition-colors focus:opacity-90 focus:outline-none"
disabled={loading}
>
{loading ? <i className="flex text-primary-foreground mr-2"><CircularProgress color="inherit" size={25} thickness={3}/></i> : structure.button.text}
{loading ?
<i className="flex text-primary-foreground mr-2"><Loader /></i>: structure.button.text}
</Button>
</div>
</form>
Expand Down
9 changes: 3 additions & 6 deletions src/app/auth/component/oauth.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React, { useState } from "react";
import { Button } from "@/components/ui/button"
import Loader from '@/components/ui/loader'

// -- icons --
import CircularProgress from '@mui/material/CircularProgress';
import { FcGoogle } from "react-icons/fc";

import { JSX, SVGProps } from "react"

interface Props{
Expand Down Expand Up @@ -34,10 +33,8 @@ export function OAuthComponent(props : Props) {
variant="outline"
className="group relative flex w-full justify-center rounded-[8px] border border-input bg-background py-6 px-4 text-md font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus:opacity-90"
>
{loading ? <i className="flex text-black"><CircularProgress color="inherit" size={30} thickness={2} style={{}}/></i>:
<>
<FcGoogle size={21} className="ml-2 mr-[.1em]"/>oogle
</>}
{loading ? <i className="flex text-black"><Loader /></i> :
<><FcGoogle size={21} className="ml-2 mr-[.1em]"/>oogle</>}
</Button>
</>
)
Expand Down
15 changes: 1 addition & 14 deletions src/app/auth/confirm/route.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { type EmailOtpType } from '@supabase/supabase-js'
import { type NextRequest, NextResponse } from 'next/server'
import { cookies } from 'next/headers'

import { createClient } from '@/utils/supabase/server'

export async function GET(req: NextRequest) {
const { searchParams } = new URL(req.url)
const token_hash = searchParams.get('token_hash')
const type = searchParams.get('type') as EmailOtpType | null
const next = searchParams.get('next') ?? '/create_form'
const next = searchParams.get('next') ?? '/form_create'

const redirectTo = req.nextUrl.clone()
redirectTo.pathname = next
Expand All @@ -21,18 +20,6 @@ export async function GET(req: NextRequest) {
type: type || 'email',
token_hash: token_hash ,
})
const user = data?.user
if (!error && user) {
const getCookies = cookies();
const username = getCookies?.get('username')?.value;
getCookies?.delete('username');
const { error: insertError } = await supabase
.from('users')
.insert([
{ id: user?.id, username: username }
]);
if (insertError) console.error('Error inserting user data:', insertError.message);
}
if (!error) {
redirectTo.searchParams.delete('next')
return NextResponse.redirect(redirectTo)
Expand Down
Loading

1 comment on commit 8a021a8

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for iiitvcc ready!

✅ Preview
https://iiitvcc-gal9sq4bq-iiitv-coding-clubs-projects.vercel.app

Built with commit 8a021a8.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.