mirror of
				https://gitea.publichub.eu/oscar.krause/fastapi-dls.git
				synced 2025-11-04 13:56:11 +00:00 
			
		
		
		
	Merge branch 'dev' into 'main'
1.3.4 See merge request oscar.krause/fastapi-dls!22
This commit is contained in:
		@@ -11,6 +11,7 @@ license=('MIT')
 | 
			
		||||
depends=('python' 'python-jose' 'python-starlette' 'python-httpx' 'python-fastapi' 'python-dotenv' 'python-dateutil' 'python-sqlalchemy' 'python-pycryptodome' 'uvicorn' 'python-markdown' 'openssl')
 | 
			
		||||
provider=("$pkgname")
 | 
			
		||||
install="$pkgname.install"
 | 
			
		||||
backup=('etc/default/fastapi-dls')
 | 
			
		||||
source=('git+file:///builds/oscar.krause/fastapi-dls' # https://gitea.publichub.eu/oscar.krause/fastapi-dls.git
 | 
			
		||||
        "$pkgname.default"
 | 
			
		||||
        "$pkgname.service"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								README.md
									
									
									
									
									
								
							@@ -7,11 +7,31 @@ Compatibility tested with official DLS 2.0.1.
 | 
			
		||||
This service can be used without internet connection.
 | 
			
		||||
Only the clients need a connection to this service on configured port.
 | 
			
		||||
 | 
			
		||||
**Official Links**
 | 
			
		||||
 | 
			
		||||
- https://git.collinwebdesigns.de/oscar.krause/fastapi-dls
 | 
			
		||||
- https://gitea.publichub.eu/oscar.krause/fastapi-dls
 | 
			
		||||
- Docker Image `collinwebdesigns/fastapi-dls:latest`
 | 
			
		||||
 | 
			
		||||
*All other repositories are forks! (which  is no bad - just for information and bug reports)*
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
[[_TOC_]]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Setup (Service)
 | 
			
		||||
 | 
			
		||||
**System requirements**
 | 
			
		||||
 | 
			
		||||
- 256mb ram
 | 
			
		||||
- 4gb hdd
 | 
			
		||||
 | 
			
		||||
Tested with Ubuntu 22.10 (from Proxmox templates), actually its consuming 100mb ram and 750mb hdd.
 | 
			
		||||
 | 
			
		||||
**Prepare your system**
 | 
			
		||||
 | 
			
		||||
- Make sure your timezone is set correct on you fastapi-dls server and your client
 | 
			
		||||
 | 
			
		||||
## Docker
 | 
			
		||||
 | 
			
		||||
Docker-Images are available here:
 | 
			
		||||
@@ -348,10 +368,6 @@ Shows current runtime environment variables and their values.
 | 
			
		||||
 | 
			
		||||
HTML rendered README.md.
 | 
			
		||||
 | 
			
		||||
### `GET /-/docs`, `GET /-/redoc`
 | 
			
		||||
 | 
			
		||||
OpenAPI specifications rendered from `GET /-/openapi.json`.
 | 
			
		||||
 | 
			
		||||
### `GET /-/manage`
 | 
			
		||||
 | 
			
		||||
Shows a very basic UI to delete origins or leases.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								app/main.py
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								app/main.py
									
									
									
									
									
								
							@@ -22,12 +22,13 @@ from sqlalchemy.orm import sessionmaker
 | 
			
		||||
from util import load_key, load_file
 | 
			
		||||
from orm import Origin, Lease, init as db_init, migrate
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger()
 | 
			
		||||
load_dotenv('../version.env')
 | 
			
		||||
 | 
			
		||||
TZ = datetime.now().astimezone().tzinfo
 | 
			
		||||
 | 
			
		||||
VERSION, COMMIT, DEBUG = env('VERSION', 'unknown'), env('COMMIT', 'unknown'), bool(env('DEBUG', False))
 | 
			
		||||
 | 
			
		||||
config = dict(openapi_url='/-/openapi.json', docs_url='/-/docs', redoc_url='/-/redoc')
 | 
			
		||||
config = dict(openapi_url=None, docs_url=None, redoc_url=None)  # dict(openapi_url='/-/openapi.json', docs_url='/-/docs', redoc_url='/-/redoc')
 | 
			
		||||
app = FastAPI(title='FastAPI-DLS', description='Minimal Delegated License Service (DLS).', version=VERSION, **config)
 | 
			
		||||
db = create_engine(str(env('DATABASE', 'sqlite:///db.sqlite')))
 | 
			
		||||
db_init(db), migrate(db)
 | 
			
		||||
@@ -44,6 +45,7 @@ TOKEN_EXPIRE_DELTA = relativedelta(days=int(env('TOKEN_EXPIRE_DAYS', 1)), hours=
 | 
			
		||||
LEASE_EXPIRE_DELTA = relativedelta(days=int(env('LEASE_EXPIRE_DAYS', 90)), hours=int(env('LEASE_EXPIRE_HOURS', 0)))
 | 
			
		||||
LEASE_RENEWAL_PERIOD = float(env('LEASE_RENEWAL_PERIOD', 0.15))
 | 
			
		||||
LEASE_RENEWAL_DELTA = timedelta(days=int(env('LEASE_EXPIRE_DAYS', 90)), hours=int(env('LEASE_EXPIRE_HOURS', 0)))
 | 
			
		||||
CLIENT_TOKEN_EXPIRE_DELTA = relativedelta(years=12)
 | 
			
		||||
CORS_ORIGINS = str(env('CORS_ORIGINS', '')).split(',') if (env('CORS_ORIGINS')) else [f'https://{DLS_URL}']
 | 
			
		||||
 | 
			
		||||
jwt_encode_key = jwk.construct(INSTANCE_KEY_RSA.export_key().decode('utf-8'), algorithm=ALGORITHMS.RS256)
 | 
			
		||||
@@ -58,6 +60,8 @@ app.add_middleware(
 | 
			
		||||
    allow_headers=['*'],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
logging.basicConfig()
 | 
			
		||||
logger = logging.getLogger(__name__)
 | 
			
		||||
logger.setLevel(logging.DEBUG if DEBUG else logging.INFO)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -97,6 +101,7 @@ async def _config():
 | 
			
		||||
        'LEASE_EXPIRE_DELTA': str(LEASE_EXPIRE_DELTA),
 | 
			
		||||
        'LEASE_RENEWAL_PERIOD': str(LEASE_RENEWAL_PERIOD),
 | 
			
		||||
        'CORS_ORIGINS': str(CORS_ORIGINS),
 | 
			
		||||
        'TZ': str(TZ),
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -192,7 +197,7 @@ async def _lease_delete(request: Request, lease_ref: str):
 | 
			
		||||
@app.get('/-/client-token', summary='* Client-Token', description='creates a new messenger token for this service instance')
 | 
			
		||||
async def _client_token():
 | 
			
		||||
    cur_time = datetime.utcnow()
 | 
			
		||||
    exp_time = cur_time + relativedelta(years=12)
 | 
			
		||||
    exp_time = cur_time + CLIENT_TOKEN_EXPIRE_DELTA
 | 
			
		||||
 | 
			
		||||
    payload = {
 | 
			
		||||
        "jti": str(uuid4()),
 | 
			
		||||
@@ -529,6 +534,18 @@ async def leasing_v1_lessor_shutdown(request: Request):
 | 
			
		||||
    return JSONr(response)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@app.on_event('startup')
 | 
			
		||||
async def app_on_startup():
 | 
			
		||||
    logger.info(f'''
 | 
			
		||||
    Using timezone: {str(TZ)}. Make sure this is correct and match your clients!
 | 
			
		||||
    
 | 
			
		||||
    Your clients renew their license every {str(Lease.calculate_renewal(LEASE_RENEWAL_PERIOD, LEASE_RENEWAL_DELTA))}.
 | 
			
		||||
    If the renewal fails, the license is {str(LEASE_RENEWAL_DELTA)} valid.
 | 
			
		||||
    
 | 
			
		||||
    Your client-token file (.tok) is valid for {str(CLIENT_TOKEN_EXPIRE_DELTA)}.
 | 
			
		||||
    ''')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    import uvicorn
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								app/orm.py
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								app/orm.py
									
									
									
									
									
								
							@@ -57,12 +57,12 @@ class Origin(Base):
 | 
			
		||||
        session.close()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def delete(engine: Engine, origins: ["Origin"] = None) -> int:
 | 
			
		||||
    def delete(engine: Engine, origin_refs: [str] = None) -> int:
 | 
			
		||||
        session = sessionmaker(bind=engine)()
 | 
			
		||||
        if origins is None:
 | 
			
		||||
        if origin_refs is None:
 | 
			
		||||
            deletions = session.query(Origin).delete()
 | 
			
		||||
        else:
 | 
			
		||||
            deletions = session.query(Origin).filter(Origin.origin_ref in origins).delete()
 | 
			
		||||
            deletions = session.query(Origin).filter(Origin.origin_ref in origin_refs).delete()
 | 
			
		||||
        session.commit()
 | 
			
		||||
        session.close()
 | 
			
		||||
        return deletions
 | 
			
		||||
@@ -170,6 +170,14 @@ class Lease(Base):
 | 
			
		||||
        renew = delta.total_seconds() * LEASE_RENEWAL_PERIOD
 | 
			
		||||
        renew = datetime.timedelta(seconds=renew)
 | 
			
		||||
        expires = delta - renew  # 19.2
 | 
			
		||||
 | 
			
		||||
        import datetime
 | 
			
		||||
        LEASE_RENEWAL_PERIOD=0.15  # 15%
 | 
			
		||||
        delta = datetime.timedelta(days=90)
 | 
			
		||||
        renew = delta.total_seconds() * LEASE_RENEWAL_PERIOD
 | 
			
		||||
        renew = datetime.timedelta(seconds=renew)
 | 
			
		||||
        expires = delta - renew  # 76 days, 12:00:00 hours
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        renew = delta.total_seconds() * renewal_period
 | 
			
		||||
        renew = timedelta(seconds=renew)
 | 
			
		||||
 
 | 
			
		||||
@@ -5,4 +5,4 @@ pycryptodome==3.16.0
 | 
			
		||||
python-dateutil==2.8.2
 | 
			
		||||
sqlalchemy==1.4.46
 | 
			
		||||
markdown==3.4.1
 | 
			
		||||
python-dotenv==0.21.0
 | 
			
		||||
python-dotenv==0.21.1
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
VERSION=1.3.3
 | 
			
		||||
VERSION=1.3.4
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user