support magic link login (#3702)

This commit is contained in:
LawyZheng
2025-10-14 16:24:14 +08:00
committed by GitHub
parent eda2dcffa4
commit dc832ea6db
19 changed files with 443 additions and 30 deletions

View File

@@ -91,7 +91,7 @@ from skyvern.forge.sdk.schemas.runs import Run
from skyvern.forge.sdk.schemas.task_generations import TaskGeneration
from skyvern.forge.sdk.schemas.task_v2 import TaskV2, TaskV2Status, Thought, ThoughtType
from skyvern.forge.sdk.schemas.tasks import OrderBy, SortDirection, Task, TaskStatus
from skyvern.forge.sdk.schemas.totp_codes import TOTPCode
from skyvern.forge.sdk.schemas.totp_codes import OTPType, TOTPCode
from skyvern.forge.sdk.schemas.workflow_runs import WorkflowRunBlock
from skyvern.forge.sdk.workflow.models.parameter import (
AWSSecretParameter,
@@ -2610,11 +2610,12 @@ class AgentDB:
return None
return TaskGeneration.model_validate(task_generation)
async def get_totp_codes(
async def get_otp_codes(
self,
organization_id: str,
totp_identifier: str,
valid_lifespan_minutes: int = settings.TOTP_LIFESPAN_MINUTES,
otp_type: OTPType | None = None,
) -> list[TOTPCode]:
"""
1. filter by:
@@ -2634,17 +2635,20 @@ class AgentDB:
.filter_by(organization_id=organization_id)
.filter_by(totp_identifier=totp_identifier)
.filter(TOTPCodeModel.created_at > datetime.utcnow() - timedelta(minutes=valid_lifespan_minutes))
.order_by(asc(all_null), TOTPCodeModel.created_at.desc())
)
if otp_type:
query = query.filter(TOTPCodeModel.otp_type == otp_type)
query = query.order_by(asc(all_null), TOTPCodeModel.created_at.desc())
totp_code = (await session.scalars(query)).all()
return [TOTPCode.model_validate(totp_code) for totp_code in totp_code]
async def create_totp_code(
async def create_otp_code(
self,
organization_id: str,
totp_identifier: str,
content: str,
code: str,
otp_type: OTPType,
task_id: str | None = None,
workflow_id: str | None = None,
workflow_run_id: str | None = None,
@@ -2662,6 +2666,7 @@ class AgentDB:
workflow_run_id=workflow_run_id,
source=source,
expired_at=expired_at,
otp_type=otp_type,
)
session.add(new_totp_code)
await session.commit()

View File

@@ -54,7 +54,7 @@ STEP_PREFIX = "stp"
TASK_GENERATION_PREFIX = "tg"
TASK_PREFIX = "tsk"
TASK_RUN_PREFIX = "tr"
TOTP_CODE_PREFIX = "totp"
OTP_CODE_PREFIX = "otp"
USER_PREFIX = "u"
WORKFLOW_PARAMETER_PREFIX = "wp"
WORKFLOW_PERMANENT_ID_PREFIX = "wpid"
@@ -169,9 +169,9 @@ def generate_ai_suggestion_id() -> str:
return f"{AI_SUGGESTION_PREFIX}_{int_id}"
def generate_totp_code_id() -> str:
def generate_otp_code_id() -> str:
int_id = generate_id()
return f"{TOTP_CODE_PREFIX}_{int_id}"
return f"{OTP_CODE_PREFIX}_{int_id}"
def generate_action_id() -> str:

View File

@@ -35,6 +35,7 @@ from skyvern.forge.sdk.db.id import (
generate_org_id,
generate_organization_auth_token_id,
generate_organization_bitwarden_collection_id,
generate_otp_code_id,
generate_output_parameter_id,
generate_persistent_browser_session_id,
generate_script_block_id,
@@ -47,7 +48,6 @@ from skyvern.forge.sdk.db.id import (
generate_task_run_id,
generate_task_v2_id,
generate_thought_id,
generate_totp_code_id,
generate_workflow_id,
generate_workflow_parameter_id,
generate_workflow_permanent_id,
@@ -579,9 +579,12 @@ class AISuggestionModel(Base):
class TOTPCodeModel(Base):
__tablename__ = "totp_codes"
__table_args__ = (Index("ix_totp_codes_org_created_at", "organization_id", "created_at"),)
__table_args__ = (
Index("ix_totp_codes_org_created_at", "organization_id", "created_at"),
Index("ix_totp_codes_otp_type", "organization_id", "otp_type"),
)
totp_code_id = Column(String, primary_key=True, default=generate_totp_code_id)
totp_code_id = Column(String, primary_key=True, default=generate_otp_code_id)
totp_identifier = Column(String, nullable=False, index=True)
organization_id = Column(String, ForeignKey("organizations.organization_id"))
task_id = Column(String, ForeignKey("tasks.task_id"))
@@ -593,6 +596,7 @@ class TOTPCodeModel(Base):
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False, index=True)
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
expired_at = Column(DateTime, index=True)
otp_type = Column(String, server_default=sqlalchemy.text("'totp'"))
class ActionModel(Base):

View File

@@ -67,6 +67,7 @@ from skyvern.webeye.actions.actions import (
DownloadFileAction,
DragAction,
ExtractAction,
GotoUrlAction,
InputTextAction,
KeypressAction,
LeftMouseAction,
@@ -105,6 +106,7 @@ ACTION_TYPE_TO_CLASS = {
ActionType.DRAG: DragAction,
ActionType.VERIFICATION_CODE: VerificationCodeAction,
ActionType.LEFT_MOUSE: LeftMouseAction,
ActionType.GOTO_URL: GotoUrlAction,
}