feat: make command parameter optional in set_alarm mutation

This commit is contained in:
Markus Graf
2026-05-11 15:05:29 +02:00
parent 5b5b845e41
commit ff79224560
10 changed files with 152 additions and 98 deletions
+20 -11
View File
@@ -1,6 +1,7 @@
import uuid
from crontab import CronTab
class CrontabManager:
COMMENT_PREFIX = "wecker-alarm:"
@@ -21,29 +22,37 @@ class CrontabManager:
if job.comment.startswith(self.COMMENT_PREFIX):
alarm_id = job.comment.split(self.COMMENT_PREFIX)[1].strip()
# job.slices is a valid cron slice object, str(job.slices) gives the expression
alarms.append({
"id": alarm_id,
"cron_expression": str(job.slices),
"command": job.command,
"is_enabled": job.is_enabled()
})
alarms.append(
{
"id": alarm_id,
"cron_expression": str(job.slices),
"command": job.command,
"is_enabled": job.is_enabled(),
}
)
return alarms
def set_alarm(self, alarm_id: str | None, cron_expression: str, command: str, is_enabled: bool = True):
def set_alarm(
self,
alarm_id: str | None,
cron_expression: str,
command: str,
is_enabled: bool = True,
):
if not alarm_id:
alarm_id = str(uuid.uuid4())
cron = self._get_cron()
comment = f"{self.COMMENT_PREFIX}{alarm_id}"
# Remove existing if any
cron.remove_all(comment=comment)
# Create new
job = cron.new(command=command, comment=comment)
job.setall(cron_expression)
job.enable(is_enabled)
cron.write()
return alarm_id
+4 -1
View File
@@ -11,16 +11,18 @@ load_dotenv()
API_KEY_NAME = "X-API-Key"
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False)
def get_api_key(api_key_header: str = Security(api_key_header)):
expected_api_key = os.getenv("API_KEY")
if not expected_api_key:
# If no key is configured, deny all requests for safety
raise HTTPException(status_code=500, detail="API_KEY not configured on server")
if api_key_header == expected_api_key:
return api_key_header
raise HTTPException(status_code=401, detail="Invalid or missing API Key")
graphql_app = GraphQLRouter(schema)
app = FastAPI(title="Wecker API")
@@ -28,6 +30,7 @@ app = FastAPI(title="Wecker API")
# Add auth dependency to the graphql route
app.include_router(graphql_app, prefix="/graphql", dependencies=[Depends(get_api_key)])
@app.get("/health")
def health_check():
return {"status": "ok"}
+16 -4
View File
@@ -1,12 +1,16 @@
import strawberry
from typing import List, Optional
import os
import sys
from pathlib import Path
from api.crontab_manager import CrontabManager
def get_manager():
tabfile = os.getenv("TABFILE")
return CrontabManager(tabfile=tabfile)
@strawberry.type
class Alarm:
id: str
@@ -14,6 +18,7 @@ class Alarm:
command: str
is_enabled: bool
@strawberry.type
class Query:
@strawberry.field
@@ -30,28 +35,34 @@ class Query:
return Alarm(**a)
return None
@strawberry.type
class Mutation:
@strawberry.field
def set_alarm(
self,
cron_expression: str,
command: str,
command: Optional[str] = None,
is_enabled: bool = True,
id: Optional[str] = None
id: Optional[str] = None,
) -> Alarm:
if command is None:
project_root = Path(__file__).parent.parent.absolute()
python_exec = sys.executable
command = f"cd {project_root} && {python_exec} wecker.py > wecker.log 2>&1"
manager = get_manager()
new_id = manager.set_alarm(
alarm_id=id,
cron_expression=cron_expression,
command=command,
is_enabled=is_enabled
is_enabled=is_enabled,
)
return Alarm(
id=new_id,
cron_expression=cron_expression,
command=command,
is_enabled=is_enabled
is_enabled=is_enabled,
)
@strawberry.field
@@ -65,4 +76,5 @@ class Mutation:
return True
return False
schema = strawberry.Schema(query=Query, mutation=Mutation)