Skip to content
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
9 changes: 1 addition & 8 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,5 @@ jobs:
if: success()
run: |
ssh -p ${{ secrets.SSH_PORT }} ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }} '
cd /home/coding-family/__app__ && \
git fetch origin production && \
git pull origin production && \
git reset --hard origin/production && \
node -v && \
yarn app:install && \
yarn app:build && \
yarn app:restart
${{ secrets.DEPLOY_SCRIPT }}
'
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/node_modules
ssh-temp
/node_modules
14 changes: 12 additions & 2 deletions backend/src/models/User.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,25 @@ const userSchema = new Schema<IUserModel>(
lowercase: true,
trim: true,
match: [/^[^\s@]+@[^\s@]+\.[^\s@]+$/, 'Please enter a valid email address.'],
required: [true, 'Email is required.'],
required: [
function (this: IUserModel) {
return !this.githubID && !this.googleID;
},
'Email is required.',
],
},
password: {
type: String,
match: [
/(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/,
'Password must have at least 6 characters and contain at least one number, one lowercase, and one uppercase letter.',
],
required: [true, 'Password is required.'],
required: [
function (this: IUserModel) {
return !this.githubID && !this.googleID;
},
'Password is required.',
],
},
avatar: {
type: String,
Expand Down
2 changes: 1 addition & 1 deletion frontend/features/auth-flow/context/Auth.context.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createContext, useContext, useEffect, useState } from "react";
import AuthService from "/common/services/AuthService";
import { LoadingSpinner } from "/common/components";
import { useUserContext } from "../../user-section/context";
import { useUserContext } from "/features/user-section/context";

const AuthContext = createContext();

Expand Down
6 changes: 4 additions & 2 deletions frontend/features/auth-flow/hooks/useAuth.hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,20 @@ export function useAuthHook() {
},

// OAuth providers
logGithubUserIn: (code) =>
logGithubUserIn: (code, isFetching) =>
fetcher({
method: "POST",
endPoint: "/auth/github",
reqBody: { code },
isFetching,
}),

logGoogleUserIn: (code) =>
logGoogleUserIn: (code, isFetching) =>
fetcher({
method: "POST",
endPoint: "/auth/google",
reqBody: { code },
isFetching,
}),

// Token management
Expand Down
46 changes: 30 additions & 16 deletions frontend/features/auth-flow/pages/LoginGithub.page.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
import { useAuthContext } from "../context";
import AuthService from "/common/services/AuthService";
import { useAuthContext } from "/features/auth-flow/context";
import { useAuthHook } from "/features/auth-flow/hooks";
import { LoadingSpinner } from "/common/components";

export function LoginGithub() {
const { storeToken, authenticateUser } = useAuthContext();
const [isFetching, setIsFetching] = useState(false);
const { authenticateUser } = useAuthContext();
const [searchParams] = useSearchParams();
const code = searchParams.get("code");
const { logGithubUserIn, storeUserToken } = useAuthHook();
const { data, isLoading, isValidating, error } = logGithubUserIn(
code,
isFetching
);

const headersAuth = data?.headers?.authorization;

useEffect(() => {
if (code) {
AuthService.loginGithub(code)
.then((response) => {
const accessToken = response.headers.authorization.split(" ")[1];
storeToken(accessToken);
authenticateUser();
})
.catch((error) => {
console.error("GithubAuth : ", error);
});
if (code) setIsFetching(true);

if (headersAuth) {
const accessToken = headersAuth.split(" ")[1];
storeUserToken(accessToken);
authenticateUser();
return;
}

if (error) {
console.log(error);
return;
}
window.location.replace(`${import.meta.env.VITE_SERVER_URL}/auth/github`);
}, [code, authenticateUser, storeToken]);

if (!code)
window.location.replace(`${import.meta.env.VITE_SERVER_URL}/auth/github`);
}, [code, headersAuth, error]);

if (isLoading || isValidating) return <LoadingSpinner />;

return (
<div>
Expand Down
44 changes: 29 additions & 15 deletions frontend/features/auth-flow/pages/LoginGoogle.page.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
import { useAuthContext } from "../context";
import AuthService from "/common/services/AuthService";
import { useAuthHook } from "/features/auth-flow/hooks";
import { LoadingSpinner } from "/common/components";

export function LoginGoogle() {
const { storeToken, authenticateUser } = useAuthContext();
const [isFetching, setIsFetching] = useState(false);
const { authenticateUser } = useAuthContext();
const [searchParams] = useSearchParams();
const code = searchParams.get("code");
const { logGoogleUserIn, storeUserToken } = useAuthHook();
const { data, isLoading, isValidating, error } = logGoogleUserIn(
code,
isFetching
);

const headersAuth = data?.headers?.authorization;

useEffect(() => {
if (code) {
AuthService.loginGoogle(code)
.then((response) => {
const accessToken = response.headers.authorization.split(" ")[1];
storeToken(accessToken);
authenticateUser();
})
.catch((error) => {
console.error("GoogleAuth:", error);
});
if (code) setIsFetching(true);

if (headersAuth) {
const accessToken = headersAuth.split(" ")[1];
storeUserToken(accessToken);
authenticateUser();
return;
}

if (error) {
console.log(error);
return;
}
window.location.replace(`${import.meta.env.VITE_SERVER_URL}/auth/google`);
}, [code, authenticateUser, storeToken]);

if (!code)
window.location.replace(`${import.meta.env.VITE_SERVER_URL}/auth/google`);
}, [code, headersAuth, error]);

if (isLoading || isValidating) return <LoadingSpinner />;

return (
<div>
Expand Down
12 changes: 4 additions & 8 deletions frontend/features/user-section/pages/UserEditProfile.page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,12 @@ import { NavLink } from "react-router-dom";
import validator from "validator";
import countries from "/common/assets/countries.json";
import { useAuthContext } from "../../auth-flow/context";
import { useUserContext } from "../context";

export function UserEditProfile() {
const {
user,
authenticateUser,
updateUserInfo,
errorMessage,
setErrorMessage,
} = useAuthContext();

const { authenticateUser, updateUserInfo, errorMessage, setErrorMessage } =
useAuthContext();
const { user } = useUserContext();
useEffect(() => {
authenticateUser();
}, [authenticateUser]);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"app:dev": "yarn kill-port && concurrently \"yarn --cwd ./backend dev\" \"yarn --cwd frontend dev\"",
"app:build": "yarn --cwd ./frontend build && yarn --cwd ./backend build",
"app:start": "yarn --cwd ./backend start",
"app:restart": "pm2 restart all",
"app:restart": "pm2 stop all && pm2 flush && pm2 start all",
"format": "yarn --cwd ./frontend format && yarn --cwd ./backend format"
},
"keywords": [],
Expand Down