Skip to content

Commit

Permalink
initial user creation form on first start
Browse files Browse the repository at this point in the history
  • Loading branch information
larinam committed Mar 29, 2024
1 parent fb0a032 commit c8a93f3
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 11 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ A modern tool to manage calendar scheduling business processes.
### Authentication
#### User/Password authentication
* For USERNAME/PASSWORD AUTHENTICATION generate a string like this run: `openssl rand -hex 32` and set `AUTHENTICATION_SECRET_KEY` in the environment.
* Create an initial user with the `/users/create-initial` method which can be reached through `/docs` URL.
#### Telegram authentication
* See https://core.telegram.org/widgets/login
* Configure TELEGRAM_BOT_TOKEN in the backend .env
Expand Down
4 changes: 2 additions & 2 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def shutdown_scheduler():

class GeneralApplicationConfigDTO(BaseModel):
telegram_enabled: bool
user_initiated: bool


class DayTypeWriteDTO(BaseModel):
Expand Down Expand Up @@ -223,7 +224,7 @@ def get_holidays(year: int = datetime.datetime.now().year) -> dict:
# General Application Cofiguration
@app.get("/config", response_model=GeneralApplicationConfigDTO)
async def get_config():
return {"telegram_enabled": bool(TELEGRAM_BOT_TOKEN)}
return {"telegram_enabled": bool(TELEGRAM_BOT_TOKEN), "user_initiated": User.objects.count() > 0}


# Authentication
Expand Down Expand Up @@ -581,4 +582,3 @@ def delete_day_type(day_type_id: str,
raise HTTPException(status_code=404, detail="DayType not found")

return {"message": "DayType deleted successfully"}

5 changes: 0 additions & 5 deletions backend/routers/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,3 @@ async def read_users(current_user: Annotated[User, Depends(get_current_active_us
@router.get("/users/me/", response_model=UserDTO)
async def read_users_me(current_user: Annotated[User, Depends(get_current_active_user)]):
return current_user


@router.get("/users/me/items/")
async def read_own_items(current_user: Annotated[User, Depends(get_current_active_user)]):
return [{"item_id": "Foo", "owner": current_user.auth_details.username}]
4 changes: 3 additions & 1 deletion frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {ToastContainer} from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import MainComponent from './components/MainComponent';
import Login from './components/login/Login';
import InitialUserCreation from './components/login/InitialUserCreation';
import './styles.css';
import {useAuth} from './contexts/AuthContext';

Expand All @@ -15,9 +16,10 @@ function App() {
<Route index element={
!isAuthenticated ?
<Navigate to="/login" /> :
<Navigate to="/main" />
<Navigate to="/main" />
} />
<Route path="/login" element={<Login />} />
<Route path="/create-initial-user" element={<InitialUserCreation />} />
<Route path="/main/*" element={<MainComponent />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
Expand Down
36 changes: 36 additions & 0 deletions frontend/src/components/login/InitialUserCreation.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, {useState} from 'react';
import {useNavigate} from 'react-router-dom';
import {useApi} from '../../hooks/useApi';

const InitialUserCreation = () => {
const navigate = useNavigate();
const { apiCall } = useApi();
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');

const handleSubmit = async (e) => {
e.preventDefault();
try {
await apiCall('/users/create-initial', 'POST', { name, email, username, password });
navigate('/login');
} catch (error) {
console.error('Error creating initial user:', error);
}
};

return (
<div className="initialUserCreationContainer">
<form onSubmit={handleSubmit} className="formStyle">
<input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Name" required />
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" required />
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" required />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" required />
<button type="submit" className="buttonStyle">Create Initial User</button>
</form>
</div>
);
};

export default InitialUserCreation;
7 changes: 6 additions & 1 deletion frontend/src/components/login/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,25 @@ const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [isTelegramEnabled, setIsTelegramEnabled] = useState(false);
const [isUserInitiated, setIsUserInitiated] = useState(true);


useEffect(() => {
const fetchConfig = async () => {
try {
const config = await apiCall('/config');
setIsTelegramEnabled(config.telegram_enabled);
setIsUserInitiated(config.user_initialted);
if (!isUserInitiated) {
navigate('/create-initial-user')
}
} catch (error) {
console.error('Error fetching configuration:', error);
}
};

fetchConfig();
}, [apiCall]);
}, []);

const handleSubmit = async (e) => {
e.preventDefault();
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ form {
gap: 10px; /* Spacing between form elements */
}

form input[type="text"], form input[type="password"] {
form input[type="text"], form input[type="password"], form input[type="email"] {
padding: 8px;
}

Expand Down

0 comments on commit c8a93f3

Please sign in to comment.