Skip to content

Commit

Permalink
Merge branch 'main' into TS-Conditional-Builder
Browse files Browse the repository at this point in the history
  • Loading branch information
LatentDream authored Feb 26, 2024
2 parents 5b86646 + 8f046e1 commit b981326
Show file tree
Hide file tree
Showing 24 changed files with 608 additions and 264 deletions.
2 changes: 2 additions & 0 deletions captain/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
log,
test_sequence,
cloud,
auth,
)
from captain.utils.config import origins
from captain.utils.logger import logger
Expand Down Expand Up @@ -48,3 +49,4 @@ async def startup_event(app: FastAPI):
app.include_router(pymgr.router)
app.include_router(test_sequence.router)
app.include_router(cloud.router)
app.include_router(auth.router)
17 changes: 8 additions & 9 deletions captain/middleware/auth_middleware.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from fastapi import Request, HTTPException
from fastapi import Request, HTTPException, status
from captain.services.auth.auth_service import validate_credentials
import base64

Expand All @@ -14,27 +14,26 @@ async def update():
"""
exception_txt = "You are not authorized to perform this action"
auth_header = req.headers.get("Authorization")
studio_cookie = req.cookies.get("studio-auth")

if not auth_header or not auth_header.startswith("Basic "):
if not studio_cookie:
raise HTTPException(
status_code=403,
status_code=status.HTTP_401_UNAUTHORIZED,
detail=exception_txt,
)
try:
credentials_b64 = auth_header[6:]
credentials = base64.b64decode(credentials_b64).decode("utf-8")

try:
credentials = base64.b64decode(studio_cookie).decode("utf-8")
username, password = credentials.split(":", 1)
authorized = validate_credentials(username, password)

if not authorized:
raise HTTPException(
status_code=403,
status_code=status.HTTP_401_UNAUTHORIZED,
detail=exception_txt,
)
except Exception:
raise HTTPException(
status_code=403,
status_code=status.HTTP_401_UNAUTHORIZED,
detail=exception_txt,
)
32 changes: 32 additions & 0 deletions captain/routes/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from fastapi import APIRouter, Response
from captain.services.auth.auth_service import (
validate_credentials,
get_base64_credentials,
)
from captain.types.auth import Auth

router = APIRouter(tags=["auth"])


@router.post("/auth/login/")
async def login(response: Response, auth: Auth):
if not validate_credentials(auth.username, auth.password):
response.set_cookie(
key="studio-auth",
value="",
path="/",
samesite="none",
secure=True,
)
return "Login failed"

encoded_credentials = get_base64_credentials(auth.username, auth.password)

response.set_cookie(
key="studio-auth",
value=encoded_credentials,
path="/",
samesite="none",
secure=True,
)
return "Login successful"
10 changes: 5 additions & 5 deletions captain/routes/key.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from typing import Optional

from fastapi import APIRouter, Response, status
from fastapi import APIRouter, Response, status, Depends
from flojoy import delete_env_var, get_credentials, get_env_var, set_env_var

from captain.middleware.auth_middleware import is_admin
from captain.types.key import EnvVar
from captain.utils.logger import logger

router = APIRouter(tags=["env"])


@router.post("/env/")
@router.post("/env/", dependencies=[Depends(is_admin)])
async def set_env_var_route(env_var: EnvVar):
try:
set_env_var(env_var.key, env_var.value)
Expand All @@ -25,7 +25,7 @@ async def set_env_var_route(env_var: EnvVar):
return Response(status_code=200)


@router.delete("/env/{key_name}")
@router.delete("/env/{key_name}", dependencies=[Depends(is_admin)])
async def delete_env_var_route(key_name: str):
try:
delete_env_var(key_name)
Expand All @@ -36,7 +36,7 @@ async def delete_env_var_route(key_name: str):
return Response(status_code=200)


@router.get("/env/{key_name}", response_model=EnvVar)
@router.get("/env/{key_name}", response_model=EnvVar, dependencies=[Depends(is_admin)])
async def get_env_var_by_name_route(key_name: str):
value: Optional[str] = get_env_var(key_name)
if value is None:
Expand Down
34 changes: 23 additions & 11 deletions captain/services/auth/auth_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import json
import bcrypt
import base64


def compare_pass(hashed_password: str, plain_password: str):
Expand All @@ -10,24 +11,35 @@ def compare_pass(hashed_password: str, plain_password: str):


def validate_credentials(username: str, password: str):
user = get_user(username)

if (not user) or user.get("role") != "Admin":
return False

if user.get("password") and (not compare_pass(user.get("password", ""), password)):
return False

return True


def get_user(username: str):
db_path = os.environ.get("LOCAL_DB_PATH", None)

if not db_path:
return False
return None

if not os.path.exists(db_path):
return False
return None

with open(db_path, "r") as f:
config = json.load(f)
users = config.get("users", [])
users: list[dict[str, str]] = config.get("users", [])
for user in users:
if user.get("name") == username:
return user

return None

for user in users:
if (
user.get("name") == username
and compare_pass(user.get("password"), password)
and user.get("role") == "Admin"
):
return True

return False
def get_base64_credentials(username: str, password: str):
return base64.b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8")
6 changes: 6 additions & 0 deletions captain/types/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from pydantic import BaseModel


class Auth(BaseModel):
username: str
password: str
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "blocks",
"type": "module",
"version": "0.2.1",
"version": "0.2.2",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
"plotly.js": "file:bauhaus/plotly.js-2.23.2.tgz",
"react": "^18.2.0",
"react-dial-knob": "file:bauhaus/react-dial-knob-1.3.0.tgz",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-draggable": "^4.4.6",
"react-error-boundary": "^4.0.12",
Expand Down
9 changes: 1 addition & 8 deletions pkgs/flojoy/flojoy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from flojoy.connection_manager import DeviceConnectionManager
from .dao import Dao
from .config import FlojoyConfig, logger
from .env_var import get_env_var
from .node_init import NodeInit, NodeInitService

import base64
Expand Down Expand Up @@ -311,13 +310,7 @@ def get_credentials() -> list[dict[str, str]]:
with open(file_path, "r") as f:
keys = f.read().strip().split(",")

credentials_list: list[dict[str, str]] = []
for key in keys:
val = get_env_var(key)
if val:
credentials_list.append({"key": key, "value": val})

return credentials_list
return [{"key": key, "value": ""} for key in keys]


def get_node_init_function(node_func: Callable) -> NodeInit:
Expand Down
69 changes: 69 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b981326

Please sign in to comment.