This commit is contained in:
retoor 2025-11-13 20:42:43 +01:00
parent 160be767aa
commit 74c9fd82d7
53 changed files with 74 additions and 73 deletions

View File

@ -1,8 +1,8 @@
POSTGRES_USER=rbox_user
POSTGRES_PASSWORD=rbox_password
POSTGRES_DB=rbox_db
POSTGRES_USER=mywebdav_user
POSTGRES_PASSWORD=mywebdav_password
POSTGRES_DB=mywebdav_db
DATABASE_URL=postgres://rbox_user:rbox_password@db:5432/rbox_db
DATABASE_URL=postgres://mywebdav_user:mywebdav_password@db:5432/mywebdav_db
REDIS_URL=redis://redis:6379/0
SECRET_KEY=change-this-to-a-random-secret-key-in-production
@ -18,7 +18,7 @@ STORAGE_PATH=/app/data
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_ENDPOINT_URL=
S3_BUCKET_NAME=rbox-storage
S3_BUCKET_NAME=mywebdav-storage
SMTP_SERVER=
SMTP_PORT=587

2
.gitignore vendored
View File

@ -9,7 +9,7 @@ storage
*.so
*.txt
poetry.lock
rbox.*
mywebdav.*
.Python
build/
develop-eggs/

View File

@ -33,4 +33,4 @@ COPY . .
EXPOSE 8000
# Command to run the application (will be overridden by docker-compose)
CMD ["poetry", "run", "uvicorn", "rbox.main:app", "--host", "0.0.0.0", "--port", "8000"]
CMD ["poetry", "run", "uvicorn", "mywebdav.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@ -5,10 +5,10 @@ PIP := .venv/bin/pip
PYTEST := .venv/bin/pytest
BLACK := .venv/bin/black
RUFF := .venv/bin/ruff
RBOX := .venv/bin/rbox
MYWEBDAV := .venv/bin/mywebdav
all:
$(RBOX) --port 9004
$(MYWEBDAV) --port 9004
help:
@echo "RBox Development Makefile"
@ -33,6 +33,7 @@ help:
install:
@echo "Installing dependencies..."
python -m venv .venv
$(PIP) install -e .
$(PIP) install -r requirements.txt
@echo "Dependencies installed successfully"
@ -45,7 +46,7 @@ dev:
run:
@echo "Starting RBox application..."
@echo "Access the application at http://localhost:8000"
$(PYTHON) -m rbox.main
$(PYTHON) -m mywebdav.main
test:
@echo "Running all tests..."
@ -68,33 +69,33 @@ e2e-setup:
test-coverage:
@echo "Running tests with coverage..."
$(PYTEST) tests/ -v --cov=rbox --cov-report=html --cov-report=term
$(PYTEST) tests/ -v --cov=mywebdav --cov-report=html --cov-report=term
@echo "Coverage report generated in htmlcov/index.html"
lint:
@echo "Running linting checks..."
$(RUFF) check rbox/
$(RUFF) check mywebdav/
@echo "Linting complete"
format:
@echo "Formatting code..."
$(BLACK) rbox/ tests/
$(BLACK) mywebdav/ tests/
@echo "Code formatting complete"
migrate:
@echo "Running database migrations..."
@echo "Tortoise ORM auto-generates schemas on startup"
$(PYTHON) -c "from rbox.main import app; print('Database schema will be created on first run')"
$(PYTHON) -c "from mywebdav.main import app; print('Database schema will be created on first run')"
init-db:
@echo "Initializing database with default data..."
$(PYTHON) -c "import asyncio; \
from tortoise import Tortoise; \
from rbox.settings import settings; \
from rbox.billing.models import PricingConfig; \
from mywebdav.settings import settings; \
from mywebdav.billing.models import PricingConfig; \
from decimal import Decimal; \
async def init(): \
await Tortoise.init(db_url=settings.DATABASE_URL, modules={'models': ['rbox.models', 'rbox.billing.models']}); \
await Tortoise.init(db_url=settings.DATABASE_URL, modules={'models': ['mywebdav.models', 'mywebdav.billing.models']}); \
await Tortoise.generate_schemas(); \
count = await PricingConfig.all().count(); \
if count == 0: \
@ -114,7 +115,7 @@ init-db:
reset-db:
@echo "WARNING: This will delete all data!"
@read -p "Are you sure? (yes/no): " confirm && [ "$$confirm" = "yes" ] || exit 1
@rm -f rbox.db app/rbox.db storage/rbox.db
@rm -f mywebdav.db app/mywebdav.db storage/mywebdav.db
@echo "Database reset complete. Run 'make init-db' to reinitialize"
clean:
@ -134,7 +135,7 @@ setup-env:
@echo "Setting up environment file..."
@if [ ! -f .env ]; then \
cp .env.example .env 2>/dev/null || \
echo "DATABASE_URL=sqlite:///app/rbox.db\nSECRET_KEY=$$(openssl rand -hex 32)\nSTRIPE_SECRET_KEY=\nSTRIPE_PUBLISHABLE_KEY=\nSTRIPE_WEBHOOK_SECRET=" > .env; \
echo "DATABASE_URL=sqlite:///app/mywebdav.db\nSECRET_KEY=$$(openssl rand -hex 32)\nSTRIPE_SECRET_KEY=\nSTRIPE_PUBLISHABLE_KEY=\nSTRIPE_WEBHOOK_SECRET=" > .env; \
echo ".env file created. Please update with your configuration."; \
else \
echo ".env file already exists"; \

View File

@ -24,7 +24,7 @@ services:
build:
context: .
dockerfile: Dockerfile
command: /usr/local/bin/gunicorn rbox.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
command: /usr/local/bin/gunicorn mywebdav.main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
volumes:
- app_data:/app/data # For uploaded files
environment:

View File

@ -109,7 +109,7 @@ class InvoiceGenerator:
customer_id=subscription.stripe_customer_id,
description=f"MyWebdav Usage Invoice for {period_start.strftime('%B %Y')}",
line_items=stripe_line_items,
metadata={"rbox_invoice_id": str(invoice.id)}
metadata={"mywebdav_invoice_id": str(invoice.id)}
)
invoice.stripe_invoice_id = stripe_invoice.id

View File

@ -74,8 +74,8 @@ register_tortoise(
app,
db_url=settings.DATABASE_URL,
modules={
"models": ["rbox.models"],
"billing": ["rbox.billing.models"]
"models": ["mywebdav.models"],
"billing": ["mywebdav.billing.models"]
},
generate_schemas=True,
add_exception_handlers=True,

View File

@ -303,10 +303,10 @@ async def stripe_webhook(request: Request):
if event["type"] == "invoice.payment_succeeded":
invoice_data = event["data"]["object"]
rbox_invoice_id = invoice_data.get("metadata", {}).get("rbox_invoice_id")
mywebdav_invoice_id = invoice_data.get("metadata", {}).get("mywebdav_invoice_id")
if rbox_invoice_id:
invoice = await Invoice.get_or_none(id=int(rbox_invoice_id))
if mywebdav_invoice_id:
invoice = await Invoice.get_or_none(id=int(mywebdav_invoice_id))
if invoice:
await InvoiceGenerator.mark_invoice_paid(invoice)

View File

@ -93,7 +93,7 @@ class FileRequestOut(BaseModel):
class Config:
from_attributes = True
from rbox.models import Folder, File, Share, FileVersion
from mywebdav.models import Folder, File, Share, FileVersion
FolderOut = pydantic_model_creator(Folder, name="FolderOut")
FileOut = pydantic_model_creator(File, name="FileOut")

View File

@ -1,5 +1,5 @@
[tool.poetry]
name = "rbox"
name = "mywebdav"
version = "0.1.0"
description = "A self-hosted cloud storage web application"
authors = ["Your Name <you@example.com>"]
@ -43,5 +43,5 @@ requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.scripts]
rbox = "rbox.main:main"
mywebdav = "mywebdav.main:main"

View File

@ -15,4 +15,4 @@ echo "Waiting for database to be ready..."
sleep 5
echo "Starting application..."
poetry run uvicorn rbox.main:app --reload --host 0.0.0.0 --port 8000
poetry run uvicorn mywebdav.main:app --reload --host 0.0.0.0 --port 8000

View File

@ -1050,7 +1050,7 @@ body.dark-mode {
margin: 0;
}
rbox-app {
mywebdav-app {
display: flex;
flex-direction: column;
min-height: 100vh;

View File

@ -21,7 +21,7 @@
<link rel="apple-touch-icon" href="/static/icons/icon-192x192.png">
</head>
<body>
<rbox-app></rbox-app>
<mywebdav-app></mywebdav-app>
<script type="module" src="/static/js/main.js"></script>
</body>
</html>

View File

@ -1,7 +1,7 @@
// static/js/components/cookie-consent.js
import app from '../app.js';
const COOKIE_CONSENT_KEY = 'rbox_cookie_consent';
const COOKIE_CONSENT_KEY = 'mywebdav_cookie_consent';
export class CookieConsent extends HTMLElement {
constructor() {

View File

@ -60,7 +60,7 @@ export class UserSettings extends HTMLElement {
}
const data = await response.json();
const filename = `rbox_user_data_${new Date().toISOString().slice(0,10)}.json`;
const filename = `mywebdav_user_data_${new Date().toISOString().slice(0,10)}.json`;
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');

View File

@ -11,8 +11,8 @@ if (startupResults.failed.length > 0) {
import('./app.js').then(({ default: app }) => {
return Promise.all([
import('./components/error-boundary.js'),
import('./components/rbox-app.js')
]).then(([errorBoundary, rboxApp]) => {
import('./components/mywebdav-app.js')
]).then(([errorBoundary, mywebdavApp]) => {
if (!app.isReady()) {
console.error('CRITICAL: Application failed to initialize properly');
document.body.innerHTML = `
@ -27,7 +27,7 @@ if (startupResults.failed.length > 0) {
return;
}
customElements.define('rbox-app', rboxApp.RBoxApp);
customElements.define('mywebdav-app', mywebdavApp.RBoxApp);
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {

View File

@ -6,7 +6,7 @@ This Cookie Policy (\"Agreement\") is entered into by and between:
**Company:** RBox Technologies
Address: [Company Address]
Website: https://rbox.com
Website: https://mywebdav.com
and

View File

@ -2,7 +2,7 @@
**Last Updated:** November 12, 2025
RBox operates the rbox website and web application (the "Service"). This page informs you of our policies regarding the collection, use, and disclosure of personal information when you use our Service.
RBox operates the mywebdav website and web application (the "Service"). This page informs you of our policies regarding the collection, use, and disclosure of personal information when you use our Service.
If you choose to use our Service, you agree to the collection and use of information in relation to this policy. The personal information we collect is used to provide and improve the Service. We will not use or share your information except as described in this Privacy Policy.
@ -79,7 +79,7 @@ Depending on your location, you may have rights regarding your personal informat
- Data portability
- Objection to processing
To exercise these rights, contact us at [privacy@rbox.com](mailto:privacy@rbox.com).
To exercise these rights, contact us at [privacy@mywebdav.com](mailto:privacy@mywebdav.com).
## Children's Privacy
@ -93,5 +93,5 @@ We may update this Privacy Policy from time to time. We will notify you of chang
If you have questions about this Privacy Policy, contact us at:
Email: privacy@rbox.com
Website: https://rbox.com
Email: privacy@mywebdav.com
Website: https://mywebdav.com

View File

@ -74,6 +74,6 @@ We reserve the right to modify these Terms at any time. We will notify users of
## 13. Contact Us
If you have questions about these Terms, please contact us at legal@rbox.com.
If you have questions about these Terms, please contact us at legal@mywebdav.com.
By using RBox, you acknowledge that you have read, understood, and agree to be bound by these Terms of Service.

View File

@ -1,10 +1,10 @@
const CACHE_NAME = 'rbox-cache-v11';
const CACHE_NAME = 'mywebdav-cache-v11';
const urlsToCache = [
'/',
'/static/index.html',
'/static/css/style.css',
'/static/js/main.js',
'/static/js/components/rbox-app.js',
'/static/js/components/mywebdav-app.js',
'/static/manifest.json',
'/static/icons/icon-192x192.png',
'/static/icons/icon-512x512.png'

View File

@ -4,10 +4,10 @@ from datetime import date, datetime
from httpx import AsyncClient
from fastapi import status
from tortoise.contrib.test import initializer, finalizer
from rbox.main import app
from rbox.models import User
from rbox.billing.models import PricingConfig, Invoice, UsageAggregate, UserSubscription
from rbox.auth import create_access_token
from mywebdav.main import app
from mywebdav.models import User
from mywebdav.billing.models import PricingConfig, Invoice, UsageAggregate, UserSubscription
from mywebdav.auth import create_access_token
@pytest.fixture(scope="module")
def event_loop():
@ -18,7 +18,7 @@ def event_loop():
@pytest.fixture(scope="module", autouse=True)
async def initialize_tests():
initializer(["rbox.models", "rbox.billing.models"], db_url="sqlite://:memory:")
initializer(["mywebdav.models", "mywebdav.billing.models"], db_url="sqlite://:memory:")
yield
await finalizer()

View File

@ -2,9 +2,9 @@ import pytest
from decimal import Decimal
from datetime import date, datetime
from tortoise.contrib.test import initializer, finalizer
from rbox.models import User
from rbox.billing.models import Invoice, InvoiceLineItem, PricingConfig, UsageAggregate, UserSubscription
from rbox.billing.invoice_generator import InvoiceGenerator
from mywebdav.models import User
from mywebdav.billing.models import Invoice, InvoiceLineItem, PricingConfig, UsageAggregate, UserSubscription
from mywebdav.billing.invoice_generator import InvoiceGenerator
@pytest.fixture(scope="module")
def event_loop():
@ -15,7 +15,7 @@ def event_loop():
@pytest.fixture(scope="module", autouse=True)
async def initialize_tests():
initializer(["rbox.models", "rbox.billing.models"], db_url="sqlite://:memory:")
initializer(["mywebdav.models", "mywebdav.billing.models"], db_url="sqlite://:memory:")
yield
await finalizer()

View File

@ -3,8 +3,8 @@ import pytest_asyncio
from decimal import Decimal
from datetime import date, datetime
from tortoise.contrib.test import initializer, finalizer
from rbox.models import User
from rbox.billing.models import (
from mywebdav.models import User
from mywebdav.billing.models import (
SubscriptionPlan, UserSubscription, UsageRecord, UsageAggregate,
Invoice, InvoiceLineItem, PricingConfig, PaymentMethod, BillingEvent
)
@ -18,7 +18,7 @@ def event_loop():
@pytest_asyncio.fixture(scope="module", autouse=True)
async def initialize_tests():
initializer(["rbox.models", "rbox.billing.models"], db_url="sqlite://:memory:")
initializer(["mywebdav.models", "mywebdav.billing.models"], db_url="sqlite://:memory:")
yield
await finalizer()

View File

@ -1,7 +1,7 @@
import pytest
def test_billing_module_imports():
from rbox.billing import models, stripe_client, usage_tracker, invoice_generator, scheduler
from mywebdav.billing import models, stripe_client, usage_tracker, invoice_generator, scheduler
assert models is not None
assert stripe_client is not None
assert usage_tracker is not None
@ -9,7 +9,7 @@ def test_billing_module_imports():
assert scheduler is not None
def test_billing_models_exist():
from rbox.billing.models import (
from mywebdav.billing.models import (
SubscriptionPlan, UserSubscription, UsageRecord, UsageAggregate,
Invoice, InvoiceLineItem, PricingConfig, PaymentMethod, BillingEvent
)
@ -24,14 +24,14 @@ def test_billing_models_exist():
assert BillingEvent is not None
def test_stripe_client_exists():
from rbox.billing.stripe_client import StripeClient
from mywebdav.billing.stripe_client import StripeClient
assert StripeClient is not None
assert hasattr(StripeClient, 'create_customer')
assert hasattr(StripeClient, 'create_invoice')
assert hasattr(StripeClient, 'finalize_invoice')
def test_usage_tracker_exists():
from rbox.billing.usage_tracker import UsageTracker
from mywebdav.billing.usage_tracker import UsageTracker
assert UsageTracker is not None
assert hasattr(UsageTracker, 'track_storage')
assert hasattr(UsageTracker, 'track_bandwidth')
@ -40,38 +40,38 @@ def test_usage_tracker_exists():
assert hasattr(UsageTracker, 'get_monthly_usage')
def test_invoice_generator_exists():
from rbox.billing.invoice_generator import InvoiceGenerator
from mywebdav.billing.invoice_generator import InvoiceGenerator
assert InvoiceGenerator is not None
assert hasattr(InvoiceGenerator, 'generate_monthly_invoice')
assert hasattr(InvoiceGenerator, 'finalize_invoice')
assert hasattr(InvoiceGenerator, 'mark_invoice_paid')
def test_scheduler_exists():
from rbox.billing.scheduler import scheduler, start_scheduler, stop_scheduler
from mywebdav.billing.scheduler import scheduler, start_scheduler, stop_scheduler
assert scheduler is not None
assert callable(start_scheduler)
assert callable(stop_scheduler)
def test_routers_exist():
from rbox.routers import billing, admin_billing
from mywebdav.routers import billing, admin_billing
assert billing is not None
assert admin_billing is not None
assert hasattr(billing, 'router')
assert hasattr(admin_billing, 'router')
def test_middleware_exists():
from rbox.middleware.usage_tracking import UsageTrackingMiddleware
from mywebdav.middleware.usage_tracking import UsageTrackingMiddleware
assert UsageTrackingMiddleware is not None
def test_settings_updated():
from rbox.settings import settings
from mywebdav.settings import settings
assert hasattr(settings, 'STRIPE_SECRET_KEY')
assert hasattr(settings, 'STRIPE_PUBLISHABLE_KEY')
assert hasattr(settings, 'STRIPE_WEBHOOK_SECRET')
assert hasattr(settings, 'BILLING_ENABLED')
def test_main_includes_billing():
from rbox.main import app
from mywebdav.main import app
routes = [route.path for route in app.routes]
billing_routes = [r for r in routes if '/billing' in r]
assert len(billing_routes) > 0

View File

@ -2,9 +2,9 @@ import pytest
from decimal import Decimal
from datetime import date, datetime, timedelta
from tortoise.contrib.test import initializer, finalizer
from rbox.models import User, File, Folder
from rbox.billing.models import UsageRecord, UsageAggregate
from rbox.billing.usage_tracker import UsageTracker
from mywebdav.models import User, File, Folder
from mywebdav.billing.models import UsageRecord, UsageAggregate
from mywebdav.billing.usage_tracker import UsageTracker
@pytest.fixture(scope="module")
def event_loop():
@ -15,7 +15,7 @@ def event_loop():
@pytest.fixture(scope="module", autouse=True)
async def initialize_tests():
initializer(["rbox.models", "rbox.billing.models"], db_url="sqlite://:memory:")
initializer(["mywebdav.models", "mywebdav.billing.models"], db_url="sqlite://:memory:")
yield
await finalizer()

View File

@ -2,8 +2,8 @@ import pytest
import asyncio
from playwright.async_api import expect
from datetime import datetime, date
from rbox.billing.models import UsageAggregate, Invoice
from rbox.models import User
from mywebdav.billing.models import UsageAggregate, Invoice
from mywebdav.models import User
@pytest.mark.asyncio
class TestBillingIntegrationFlow: