initial commit!
This commit is contained in:
commit
b08a188fea
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
**/*.pyc
|
||||
**/node_modules/
|
12
backend/Dockerfile
Normal file
12
backend/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM python:3.9
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ADD requirements.txt /app
|
||||
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
ADD . /app
|
||||
|
||||
CMD uvicorn main:app --host 0.0.0.0 --reload --access-log --log-level debug
|
||||
|
55
backend/archives.py
Normal file
55
backend/archives.py
Normal file
@ -0,0 +1,55 @@
|
||||
from typing import List, Optional, TypeVar
|
||||
from pydantic import BaseModel, UUID4, validator
|
||||
from fastapi import APIRouter, Depends
|
||||
from users import User
|
||||
import uuid
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
class Archive(BaseModel):
|
||||
#id: Optional[UUID4]
|
||||
title: Optional[str]
|
||||
user: Optional[UUID4]
|
||||
|
||||
|
||||
class S3Archive(Archive):
|
||||
endpoint_url: Optional[str]
|
||||
is_public: Optional[bool]
|
||||
|
||||
#@validator("id", pre=True, always=True)
|
||||
#def default_id(cls, v):
|
||||
# return v or uuid.uuid4()
|
||||
|
||||
|
||||
def init_archives_api(app, db, user_dep: User):
|
||||
archives_coll = db["archives"]
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/archives",
|
||||
tags=["archives"],
|
||||
responses={404: {"description": "Not found"}},
|
||||
)
|
||||
|
||||
@router.get("/")
|
||||
async def get_archives(user: User=Depends(user_dep)):
|
||||
cursor = archives_coll.find({})
|
||||
results = await cursor.to_list(length=1000)
|
||||
return {"archives": [{"id": str(res["_id"]), "title": res["title"], "endpoint_url": res["endpoint_url"]} for res in results]}
|
||||
|
||||
@router.get("/{id}")
|
||||
async def get_archives(id: str, user: User=Depends(user_dep)):
|
||||
res = await archives_coll.find_one(ObjectId(id))
|
||||
print(res)
|
||||
if not res:
|
||||
return {}
|
||||
|
||||
return {"id": id, "title": res["title"], "endpoint_url": res["endpoint_url"]}
|
||||
|
||||
@router.post("/")
|
||||
async def add_archive(archive: S3Archive, user: User = Depends(user_dep)):
|
||||
archive.user = user.id
|
||||
print(archive.user)
|
||||
res = await archives_coll.insert_one(archive.dict())
|
||||
return {"added": str(res.inserted_id)}
|
||||
|
||||
app.include_router(router)
|
||||
|
17
backend/crawls.py
Normal file
17
backend/crawls.py
Normal file
@ -0,0 +1,17 @@
|
||||
from typing import List, Optional, TypeVar
|
||||
from pydantic import BaseModel, UUID4, validator
|
||||
from fastapi import APIRouter, Depends
|
||||
from users import User
|
||||
import uuid
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
class SimpleCrawl(BaseModel):
|
||||
url: str
|
||||
scopeType: str
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
17
backend/db.py
Normal file
17
backend/db.py
Normal file
@ -0,0 +1,17 @@
|
||||
import os
|
||||
import motor.motor_asyncio
|
||||
|
||||
|
||||
DATABASE_URL = (
|
||||
f"mongodb://root:example@{os.environ.get('MONGO_HOST', 'localhost')}:27017"
|
||||
)
|
||||
|
||||
|
||||
def init_db():
|
||||
client = motor.motor_asyncio.AsyncIOMotorClient(
|
||||
DATABASE_URL, uuidRepresentation="standard"
|
||||
)
|
||||
|
||||
db = client["browsertrixcloud"]
|
||||
|
||||
return db
|
9
backend/dockerdriver.py
Normal file
9
backend/dockerdriver.py
Normal file
@ -0,0 +1,9 @@
|
||||
import aiodocker
|
||||
|
||||
class DockerDriver(BaseDriver):
|
||||
def __init__(self):
|
||||
self.docker = aiodocker.Docker()
|
||||
self.crawl_image = os.environ.get("CRAWLER_IMAGE", "webrecorder/browsertrix-crawler")
|
||||
|
||||
def start_crawl(self):
|
||||
container = await self.docker.containers.create(config=config)
|
31
backend/main.py
Normal file
31
backend/main.py
Normal file
@ -0,0 +1,31 @@
|
||||
from fastapi import FastAPI, Depends
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
|
||||
from users import init_users_api, User
|
||||
from db import init_db
|
||||
from archives import init_archives_api
|
||||
|
||||
|
||||
db = init_db()
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
fastapi_users = init_users_api(app, db)
|
||||
|
||||
current_active_user = fastapi_users.current_user(active=True)
|
||||
|
||||
init_archives_api(app, db, current_active_user)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {"message": "Hello World"}
|
||||
|
||||
|
||||
@app.get("/protected-route")
|
||||
def protected_route(user: User = Depends(current_active_user)):
|
||||
return f"Hello, {user.email}"
|
3
backend/requirements.txt
Normal file
3
backend/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
uvicorn
|
||||
fastapi-users[mongodb]==6.0.0
|
||||
loguru
|
84
backend/users.py
Normal file
84
backend/users.py
Normal file
@ -0,0 +1,84 @@
|
||||
import os
|
||||
import uuid
|
||||
from fastapi import Request
|
||||
from fastapi_users import FastAPIUsers, models
|
||||
from fastapi_users.authentication import JWTAuthentication
|
||||
from fastapi_users.db import MongoDBUserDatabase
|
||||
|
||||
PASSWORD_SECRET = os.environ.get("PASSWORD_SECRET", uuid.uuid4().hex)
|
||||
|
||||
|
||||
class User(models.BaseUser):
|
||||
pass
|
||||
|
||||
|
||||
class UserCreate(models.BaseUserCreate):
|
||||
pass
|
||||
|
||||
|
||||
class UserUpdate(User, models.BaseUserUpdate):
|
||||
pass
|
||||
|
||||
|
||||
class UserDB(User, models.BaseUserDB):
|
||||
pass
|
||||
|
||||
|
||||
def on_after_register(user: UserDB, request: Request):
|
||||
print(f"User {user.id} has registered.")
|
||||
|
||||
|
||||
def on_after_forgot_password(user: UserDB, token: str, request: Request):
|
||||
print(f"User {user.id} has forgot their password. Reset token: {token}")
|
||||
|
||||
|
||||
def after_verification_request(user: UserDB, token: str, request: Request):
|
||||
print(f"Verification requested for user {user.id}. Verification token: {token}")
|
||||
|
||||
|
||||
def init_users_api(app, db):
|
||||
user_collection = db["users"]
|
||||
|
||||
user_db = MongoDBUserDatabase(UserDB, user_collection)
|
||||
|
||||
jwt_authentication = JWTAuthentication(
|
||||
secret=PASSWORD_SECRET, lifetime_seconds=3600, tokenUrl="/auth/jwt/login"
|
||||
)
|
||||
|
||||
fastapi_users = FastAPIUsers(
|
||||
user_db,
|
||||
[jwt_authentication],
|
||||
User,
|
||||
UserCreate,
|
||||
UserUpdate,
|
||||
UserDB,
|
||||
)
|
||||
app.include_router(
|
||||
fastapi_users.get_auth_router(jwt_authentication),
|
||||
prefix="/auth/jwt",
|
||||
tags=["auth"],
|
||||
)
|
||||
app.include_router(
|
||||
fastapi_users.get_register_router(on_after_register),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
app.include_router(
|
||||
fastapi_users.get_reset_password_router(
|
||||
PASSWORD_SECRET, after_forgot_password=on_after_forgot_password
|
||||
),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
app.include_router(
|
||||
fastapi_users.get_verify_router(
|
||||
PASSWORD_SECRET, after_verification_request=after_verification_request
|
||||
),
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
app.include_router(
|
||||
fastapi_users.get_users_router(), prefix="/users", tags=["users"]
|
||||
)
|
||||
|
||||
return fastapi_users
|
35
docker-compose.yaml
Normal file
35
docker-compose.yaml
Normal file
@ -0,0 +1,35 @@
|
||||
version: '3.5'
|
||||
|
||||
services:
|
||||
backend:
|
||||
build: ./backend
|
||||
image: btrixcloud/backend
|
||||
ports:
|
||||
- 8000:8000
|
||||
|
||||
environment:
|
||||
MONGO_HOST: mongo
|
||||
PASSWORD_SECRET: 'c9085f33ecce4347aa1d69339e16c499'
|
||||
|
||||
mongo:
|
||||
image: mongo
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: root
|
||||
MONGO_INITDB_ROOT_PASSWORD: example
|
||||
|
||||
volumes:
|
||||
- mongodata:/data/db
|
||||
|
||||
minio:
|
||||
image: minio/minio
|
||||
command: server /data
|
||||
ports:
|
||||
- 8010:9000
|
||||
|
||||
volumes:
|
||||
- miniodata:/data
|
||||
|
||||
volumes:
|
||||
mongodata:
|
||||
miniodata:
|
||||
|
Loading…
Reference in New Issue
Block a user