From 19c1eb6cf6b296dacd94a30c4d6c6ea16720a0ea Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Tue, 15 Aug 2023 20:32:53 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9B=20fix(auth.py):=20change=20cre?= =?UTF-8?q?ate=5Fuser=5Flongterm=5Ftoken=20to=20use=20create=5Fsuper=5Fuse?= =?UTF-8?q?r=20to=20ensure=20super=20user=20exists=20before=20creating=20t?= =?UTF-8?q?oken=20=E2=9C=A8=20feat(auth.py):=20add=20create=5Fsuper=5Fuser?= =?UTF-8?q?=20function=20to=20create=20super=20user=20if=20it=20doesn't=20?= =?UTF-8?q?exist=20=F0=9F=90=9B=20fix(login.py):=20remove=20hardcoded=20us?= =?UTF-8?q?er=5Fid=20and=20use=20create=5Fuser=5Flongterm=5Ftoken=20withou?= =?UTF-8?q?t=20arguments=20=F0=9F=90=9B=20fix(users.py):=20remove=20redund?= =?UTF-8?q?ant=20password=20hashing=20in=20add=5Fsuper=5Fuser=5Ffor=5Ftest?= =?UTF-8?q?ing=5Fpurposes=5Fdelete=5Fme=5Fbefore=5Fmerge=5Finto=5Fdev=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(base.py):=20change=20AUTO=5FLOGIN=20default?= =?UTF-8?q?=20value=20to=20False=20and=20add=20FIRST=5FSUPERUSER=20and=20F?= =?UTF-8?q?IRST=5FSUPERUSER=5FPASSWORD=20settings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/auth/auth.py | 34 +++++++++++++++---- src/backend/langflow/routers/login.py | 4 +-- src/backend/langflow/routers/users.py | 3 +- .../langflow/services/settings/base.py | 5 ++- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/backend/langflow/auth/auth.py b/src/backend/langflow/auth/auth.py index b9e8dba3a..28d242342 100644 --- a/src/backend/langflow/auth/auth.py +++ b/src/backend/langflow/auth/auth.py @@ -83,18 +83,40 @@ def create_token(data: dict, expires_delta: timedelta): ) -def create_user_longterm_token( - user_id: UUID, db: Session = Depends(get_session), update_last_login: bool = False -) -> dict: +def create_super_user(db: Session = Depends(get_session)) -> User: + settings_manager = get_settings_manager() + + super_user = get_user_by_username(db, settings_manager.settings.FIRST_SUPERUSER) + + if not super_user: + super_user = User( + username=settings_manager.settings.FIRST_SUPERUSER, + password=get_password_hash( + settings_manager.settings.FIRST_SUPERUSER_PASSWORD + ), + is_superuser=True, + is_active=True, + last_login_at=None, + ) + + db.add(super_user) + db.commit() + db.refresh(super_user) + + return super_user + + +def create_user_longterm_token(db: Session = Depends(get_session)) -> dict: + super_user = create_super_user(db) + access_token_expires_longterm = timedelta(days=365) access_token = create_token( - data={"sub": str(user_id)}, + data={"sub": str(super_user.id)}, expires_delta=access_token_expires_longterm, ) # Update: last_login_at - if update_last_login: - update_user_last_login_at(user_id, db) + update_user_last_login_at(super_user.id, db) return { "access_token": access_token, diff --git a/src/backend/langflow/routers/login.py b/src/backend/langflow/routers/login.py index 7d114473d..de255a0d5 100644 --- a/src/backend/langflow/routers/login.py +++ b/src/backend/langflow/routers/login.py @@ -1,4 +1,3 @@ -from uuid import UUID from sqlalchemy.orm import Session from fastapi import APIRouter, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm @@ -38,8 +37,7 @@ async def auto_login(db: Session = Depends(get_session)): settings_manager = get_settings_manager() if settings_manager.settings.AUTO_LOGIN: - user_id = UUID("3fa85f64-5717-4562-b3fc-2c963f66afa6") - return create_user_longterm_token(user_id, db) + return create_user_longterm_token(db) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, diff --git a/src/backend/langflow/routers/users.py b/src/backend/langflow/routers/users.py index da738a5cd..04972c976 100644 --- a/src/backend/langflow/routers/users.py +++ b/src/backend/langflow/routers/users.py @@ -115,14 +115,13 @@ def add_super_user_for_testing_purposes_delete_me_before_merge_into_dev( """ new_user = User( username="superuser", - password="12345", + password=get_password_hash("12345"), is_active=True, is_superuser=True, last_login_at=None, ) try: - new_user.password = get_password_hash(new_user.password) db.add(new_user) db.commit() db.refresh(new_user) diff --git a/src/backend/langflow/services/settings/base.py b/src/backend/langflow/services/settings/base.py index d8b3f3ad6..d99f0f8b5 100644 --- a/src/backend/langflow/services/settings/base.py +++ b/src/backend/langflow/services/settings/base.py @@ -41,9 +41,12 @@ class Settings(BaseSettings): ALGORITHM: str = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 REFRESH_TOKEN_EXPIRE_MINUTES: int = 70 + # If AUTO_LOGIN = True # > The application does not request login and logs in automatically as a super user. - AUTO_LOGIN: bool = True + AUTO_LOGIN: bool = False + FIRST_SUPERUSER: str = "superuser" + FIRST_SUPERUSER_PASSWORD: str = "12345" @validator("DATABASE_URL", pre=True) def set_database_url(cls, value): From 85add46761ec56b4e8bfbc7bb2adc4597899dbbe Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Tue, 15 Aug 2023 18:04:10 -0300 Subject: [PATCH 2/2] feat(AdminPage): add support for UserInputType in handleNewUser function to improve type safety and prevent potential errors fix(UserInputType): make is_active and is_superuser optional in UserInputType to allow for flexibility in user input --- src/frontend/src/pages/AdminPage/index.tsx | 3 ++- src/frontend/src/types/components/index.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/pages/AdminPage/index.tsx b/src/frontend/src/pages/AdminPage/index.tsx index f7b34da57..9a108be9b 100644 --- a/src/frontend/src/pages/AdminPage/index.tsx +++ b/src/frontend/src/pages/AdminPage/index.tsx @@ -25,6 +25,7 @@ import { } from "../../controllers/API"; import ConfirmationModal from "../../modals/ConfirmationModal"; import UserManagementModal from "../../modals/UserManagementModal"; +import { UserInputType } from "../../types/components"; export default function AdminPage() { const [inputValue, setInputValue] = useState(""); @@ -164,7 +165,7 @@ export default function AdminPage() { }); } - function handleNewUser(user) { + function handleNewUser(user: UserInputType) { addUser(user) .then((res) => { resetFilter(); diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 0f2b8c8f5..ddac47d9f 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -230,6 +230,6 @@ export type loginInputStateType = { export type UserInputType = { username: string; password: string; - is_active: boolean; - is_superuser: boolean; + is_active?: boolean; + is_superuser?: boolean; };