Skip to content

Commit

Permalink
Merge pull request #36 from devansh-srv/dbFix
Browse files Browse the repository at this point in the history
fix: neonDB pool_recycle
  • Loading branch information
devansh-srv authored Jan 30, 2025
2 parents 4fe746b + 3b22c14 commit 4ac8fce
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 87 deletions.
2 changes: 1 addition & 1 deletion backend/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from flask_cors import CORS
from config import Config

db = SQLAlchemy()
db = SQLAlchemy(engine_options=Config.SQLALCHEMY_ENGINE_OPTIONS)
bcrypt = Bcrypt()
jwt = JWTManager()

Expand Down
2 changes: 1 addition & 1 deletion backend/app/routes/auth_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def signup():
new_user = User(username=data['username'], email=data['email'], password=hashed_password, role=data['role'])
db.session.add(new_user)
db.session.commit()
return jsonify({"message": "User created successfully"}), 201
return jsonify({"message": f"{data['role']} created successfully"}), 201

@auth_bp.route('/api/login', methods=['POST'])
def login():
Expand Down
4 changes: 4 additions & 0 deletions backend/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class Config:
'POSTGRES_URI',
'postgresql://postgres:postgres@localhost:5432/local_database' # Default fallback
)
SQLALCHEMY_ENGINE_OPTIONS = {
"pool_recycle": 240, # Recycle connections before Neon shuts down
"pool_pre_ping": True, # Check connection status before queries
}
SQLALCHEMY_TRACK_MODIFICATIONS = False
JWT_SECRET_KEY = 'your-secret-key'
JWT_ACCESS_TOKEN_EXPIRES = timedelta(hours=1)
33 changes: 30 additions & 3 deletions client/src/components/AdminSignup.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { useNavigate } from 'react-router-dom';
const AdminSignup = ({ onLogin }) => {
const [formData, setFormData] = useState({ username: '', email: '', password: '' });
const [captchaToken, setCaptchaToken] = useState('');
const [status, setStatus] = useState(null)
const [color, setColor] = useState(null)
const [showPassword, setShowPassword] = useState(false);
const SITE_KEY = process.env.REACT_APP_SITE_KEY || '1x00000000000000000000AA';
const navigate = useNavigate();
Expand All @@ -23,22 +25,47 @@ const AdminSignup = ({ onLogin }) => {
e.preventDefault();
try {
console.log("FormData:", formData);
await signup({ ...formData, role: 'admin', 'cf-turnstile-response': captchaToken });
const signupResponse = await signup({ ...formData, role: 'admin', 'cf-turnstile-response': captchaToken });

setStatus(signupResponse.data.message)
setColor('bg-emerald-700')
setInterval(() => {
setStatus(null)
setColor(null)
}, 3000)
const loginResponse = await login({ ...formData, role: 'admin', 'cf-turnstile-response': captchaToken });

localStorage.setItem("token", loginResponse.data.access_token);

onLogin({ username: formData.username, role: 'admin' });

navigate('/admin-dashboard');

} catch (error) {
console.error('Signup failed:', error);
if (error.status === 400) {
alert(error?.response?.data?.message)
} else {
console.error('Signup failed:', error);
setStatus('Signup Failed. Please Try Again')
setColor('bg-red-500')
setInterval(() => {
setStatus(null)
setColor(null)
}, 3000)
}

}
};

return (
<div className="flex justify-center items-center py-12 px-4 w-full min-h-screen bg-gradient-to-br from-emerald-500 to-blue-200">

{status && (
<div className={`flex fixed top-5 left-1/2 items-center py-2 px-4 text-white ${color} rounded-lg shadow-lg transition-transform duration-300 transform -translate-x-1/2 animate-slideIn}`} >
<span>{status}</span>
</div>
)
}
<div className="w-full max-w-md rounded-xl shadow-xl bg-white/90 backdrop-blur-sm">
<div className="p-8">
<div className="mb-1 text-sm font-semibold tracking-wide text-emerald-700 uppercase">Admin Registration</div>
Expand Down Expand Up @@ -116,7 +143,7 @@ const AdminSignup = ({ onLogin }) => {
</form>
</div>
</div>
</div>
</div >
);
};

Expand Down
27 changes: 25 additions & 2 deletions client/src/components/BuyerSignup.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const BuyerSignup = ({ onLogin }) => {
const [formData, setFormData] = useState({ username: '', email: '', password: '' });
const [captchaToken, setCaptchaToken] = useState('');
const [showPassword, setShowPassword] = useState(false);
const [status, setStatus] = useState(null)
const [color, setColor] = useState(null)
const navigate = useNavigate();
const SITE_KEY = process.env.REACT_APP_SITE_KEY || '1x00000000000000000000AA';
const handleChange = (e) => {
Expand All @@ -22,7 +24,13 @@ const BuyerSignup = ({ onLogin }) => {
e.preventDefault();
try {
console.log("FormData:", formData);
await signup({ ...formData, role: 'buyer', 'cf-turnstile-response': captchaToken });
const signupResponse = await signup({ ...formData, role: 'buyer', 'cf-turnstile-response': captchaToken });
setStatus(signupResponse.data.message)
setColor('bg-indigo-700')
setInterval(() => {
setStatus(null)
setColor(null)
}, 3000)
const loginResponse = await login({ ...formData, role: 'buyer', 'cf-turnstile-response': captchaToken });

localStorage.setItem("token", loginResponse.data.access_token);
Expand All @@ -31,13 +39,28 @@ const BuyerSignup = ({ onLogin }) => {
navigate('/buyer-dashboard');

} catch (error) {
console.error('Signup failed:', error);
if (error.status === 400) { alert(error?.response?.data?.message) } else {
console.error('Signup failed:', error);
setStatus('Signup Failed. Please Try Again')
setColor('bg-red-500')
setInterval(() => {
setStatus(null)
setColor(null)
}, 3000)
}

}
};

return (
<div className="flex justify-center items-center py-12 px-4 w-full min-h-screen bg-gradient-to-br from-indigo-500 to-blue-400">

{status && (
<div className={`flex fixed top-5 left-1/2 items-center py-2 px-4 text-white ${color} rounded-lg shadow-lg transition-transform duration-300 transform -translate-x-1/2 animate-slideIn}`} >
<span>{status}</span>
</div>
)
}
<div className="w-full max-w-md rounded-xl shadow-xl bg-white/90 backdrop-blur-sm">
<div className="p-8">
<div className="mb-1 text-sm font-semibold tracking-wide text-blue-700 uppercase">Buyer Registration</div>
Expand Down
175 changes: 95 additions & 80 deletions client/src/components/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Turnstile } from '@marsidev/react-turnstile';
const Login = ({ onLogin }) => {
const [formData, setFormData] = useState({ username: '', password: '', role: 'buyer' });
const [captchaToken, setCaptchaToken] = useState('');
const [status, setStatus] = useState(null)
const navigate = useNavigate();
const SITE_KEY = process.env.REACT_APP_SITE_KEY || '1x00000000000000000000AA';
const [showPassword, setShowPassword] = useState(false);
Expand All @@ -29,94 +30,108 @@ const Login = ({ onLogin }) => {
onLogin({ username: formData.username, role: userRole });
navigate(userRole === 'admin' ? '/admin-dashboard' : '/buyer-dashboard');
} catch (error) {
console.error('Login failed:', error);
if (error.status === 401) {
setStatus(error?.response?.data?.message)
setInterval(() => setStatus(null), 3000)
} else if (error.status === 400) {
alert(error?.response?.data?.message);
} else {
console.error('Login failed:', error);
}

}
};

return (
<div className="min-h-screen w-full flex items-center justify-center bg-gradient-to-br from-emerald-100 to-blue-200 py-12 px-4">
<div className="w-full max-w-md bg-white/80 backdrop-blur-sm rounded-xl shadow-xl">
<div className="p-8 bg-emerald-50/90 shadow-lg rounded-xl">
<div className="mb-1 text-sm font-semibold tracking-wide uppercase text-emerald-700">Welcome back</div>
<h2 className="block mt-1 text-2xl font-medium leading-tight text-emerald-800">Login to your account</h2>
<form onSubmit={handleSubmit} className="mt-6 space-y-6">
<div>
<label className="block mb-2 text-sm font-medium text-emerald-700" htmlFor="username">
Username
</label>
<input
className="w-full px-3 py-2 border border-emerald-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-emerald-500 bg-emerald-100/50"
id="username"
type="text"
name="username"
value={formData.username}
onChange={handleChange}
required
/>
<>
<div className="flex justify-center items-center py-12 px-4 w-full min-h-screen bg-gradient-to-br from-emerald-100 to-blue-200">
{status && (
<div className="flex fixed top-5 left-1/2 items-center py-2 px-4 text-white bg-red-500 rounded-lg shadow-lg transition-transform duration-300 transform -translate-x-1/2 animate-slideIn">
<span>{status}</span>
</div>
<div>
<label className="block mb-2 text-sm font-medium text-emerald-700" htmlFor="password">
Password
</label>
<div className="relative">
<input
className="w-full px-3 py-2 border border-emerald-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-emerald-500 bg-emerald-100/50"
id="password"
type={showPassword ? 'text' : 'password'}
name="password"
value={formData.password}
onChange={handleChange}
required
/>
<button
type="button"
className="absolute inset-y-0 right-3 flex items-center text-emerald-600"
onClick={() => setShowPassword((prev) => !prev)}
>
{showPassword ? 'Hide' : 'Show'}
</button>
</div>
</div>
<div>
<label className="block mb-2 text-sm font-medium text-emerald-700" htmlFor="role">
Role
</label>
<select
className="w-full px-3 py-2 border border-emerald-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-emerald-500 bg-emerald-100/50"
id="role"
name="role"
value={formData.role}
onChange={handleChange}
>
<option value="buyer">Buyer</option>
<option value="admin">Admin</option>
</select>
</div>
<div>
<Turnstile
options={{
theme: 'light',
}}
siteKey={SITE_KEY}
onError={() => alert('CAPTCHA failed Try again')}
onSuccess={(token) => setCaptchaToken(token)}
/>
</div>
<div>
<button
className="w-full px-4 py-2 text-white font-semibold bg-emerald-600 hover:bg-emerald-700 rounded-lg transition-colors duration-300"
type="submit"
>
Sign In
</button>
</div>
</form>
</div>
)}

<div className="w-full max-w-md rounded-xl shadow-xl bg-white/80 backdrop-blur-sm">
<div className="p-8 rounded-xl shadow-lg bg-emerald-50/90">
<div className="mb-1 text-sm font-semibold tracking-wide text-emerald-700 uppercase">Welcome back</div>
<h2 className="block mt-1 text-2xl font-medium leading-tight text-emerald-800">Login to your account</h2>
<form onSubmit={handleSubmit} className="mt-6 space-y-6">
<div>
<label className="block mb-2 text-sm font-medium text-emerald-700" htmlFor="username">
Username
</label>
<input
className="py-2 px-3 w-full rounded-lg border border-emerald-300 focus:ring-2 focus:ring-emerald-500 focus:outline-none bg-emerald-100/50"
id="username"
type="text"
name="username"
value={formData.username}
onChange={handleChange}
required
/>
</div>
<div>
<label className="block mb-2 text-sm font-medium text-emerald-700" htmlFor="password">
Password
</label>
<div className="relative">
<input
className="py-2 px-3 w-full rounded-lg border border-emerald-300 focus:ring-2 focus:ring-emerald-500 focus:outline-none bg-emerald-100/50"
id="password"
type={showPassword ? 'text' : 'password'}
name="password"
value={formData.password}
onChange={handleChange}
required
/>
<button
type="button"
className="flex absolute inset-y-0 right-3 items-center text-emerald-600"
onClick={() => setShowPassword((prev) => !prev)}
>
{showPassword ? 'Hide' : 'Show'}
</button>
</div>
</div>
<div>
<label className="block mb-2 text-sm font-medium text-emerald-700" htmlFor="role">
Role
</label>
<select
className="py-2 px-3 w-full rounded-lg border border-emerald-300 focus:ring-2 focus:ring-emerald-500 focus:outline-none bg-emerald-100/50"
id="role"
name="role"
value={formData.role}
onChange={handleChange}
>
<option value="buyer">Buyer</option>
<option value="admin">Admin</option>
</select>
</div>
<div>
<Turnstile
options={{
theme: 'light',
}}
siteKey={SITE_KEY}
onError={() => alert('CAPTCHA failed Try again')}
onSuccess={(token) => setCaptchaToken(token)}
/>
</div>
<div>
<button
className="py-2 px-4 w-full font-semibold text-white bg-emerald-600 rounded-lg transition-colors duration-300 hover:bg-emerald-700"
type="submit"
>
Sign In
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</>
);
};

export default Login;
export default Login;

0 comments on commit 4ac8fce

Please sign in to comment.