diff --git a/README.md b/README.md index 4b21226..b0ccb1c 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/backend/main.py b/backend/main.py index c2eb5c4..ca1c5ce 100644 --- a/backend/main.py +++ b/backend/main.py @@ -80,6 +80,7 @@ def shutdown_scheduler(): class GeneralApplicationConfigDTO(BaseModel): telegram_enabled: bool + user_initiated: bool class DayTypeWriteDTO(BaseModel): @@ -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 @@ -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"} - diff --git a/backend/routers/users.py b/backend/routers/users.py index 14aa098..fb6ccf3 100644 --- a/backend/routers/users.py +++ b/backend/routers/users.py @@ -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}] diff --git a/frontend/src/App.js b/frontend/src/App.js index bf411d3..04df95a 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -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'; @@ -15,9 +16,10 @@ function App() { : - + } /> } /> + } /> } /> } /> diff --git a/frontend/src/components/login/InitialUserCreation.jsx b/frontend/src/components/login/InitialUserCreation.jsx new file mode 100644 index 0000000..d0c6fe6 --- /dev/null +++ b/frontend/src/components/login/InitialUserCreation.jsx @@ -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 ( +
+
+ setName(e.target.value)} placeholder="Name" required /> + setEmail(e.target.value)} placeholder="Email" required /> + setUsername(e.target.value)} placeholder="Username" required /> + setPassword(e.target.value)} placeholder="Password" required /> + +
+
+ ); +}; + +export default InitialUserCreation; diff --git a/frontend/src/components/login/Login.jsx b/frontend/src/components/login/Login.jsx index 8cb46a1..625740f 100644 --- a/frontend/src/components/login/Login.jsx +++ b/frontend/src/components/login/Login.jsx @@ -12,6 +12,7 @@ const Login = () => { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [isTelegramEnabled, setIsTelegramEnabled] = useState(false); + const [isUserInitiated, setIsUserInitiated] = useState(true); useEffect(() => { @@ -19,13 +20,17 @@ const Login = () => { 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(); diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 774ac53..affc193 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -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; }