From 4911f0eacbfd972a319f358e9b1be0a209b5267a Mon Sep 17 00:00:00 2001 From: Matej Zeman <zeman339@gmail.com> Date: Tue, 26 Apr 2022 23:45:12 +0200 Subject: [PATCH 01/13] re #9577 Api code documentation. --- server/doc/sql_app/api/devices.html | 189 +++ server/doc/sql_app/api/devices_web.html | 289 ++++ server/doc/sql_app/api/index.html | 110 ++ server/doc/sql_app/api/licenses.html | 160 ++ server/doc/sql_app/api/licenses_web.html | 212 +++ server/doc/sql_app/api/pcs.html | 188 +++ server/doc/sql_app/api/pcs_web.html | 201 +++ server/doc/sql_app/api/teams.html | 188 +++ server/doc/sql_app/api/teams_web.html | 200 +++ server/doc/sql_app/api/usb_logs.html | 265 +++ server/doc/sql_app/api/usb_logs_web.html | 202 +++ server/doc/sql_app/crud.html | 1165 +++++++++++++ server/doc/sql_app/database.html | 100 ++ server/doc/sql_app/documentation.html | 85 + server/doc/sql_app/main.html | 91 ++ server/doc/sql_app/models.html | 1911 ++++++++++++++++++++++ server/doc/sql_app/schemas.html | 1808 ++++++++++++++++++++ server/sql_app/api/devices.py | 11 + server/sql_app/api/devices_web.py | 22 +- server/sql_app/api/licenses.py | 7 + server/sql_app/api/licenses_web.py | 16 +- server/sql_app/api/pcs.py | 10 + server/sql_app/api/pcs_web.py | 14 +- server/sql_app/api/teams.py | 10 + server/sql_app/api/teams_web.py | 14 +- server/sql_app/api/usb_logs.py | 17 + server/sql_app/api/usb_logs_web.py | 11 +- server/sql_app/crud.py | 119 ++ server/sql_app/database.py | 11 +- server/sql_app/main.py | 7 +- server/sql_app/models.py | 42 + server/sql_app/schemas.py | 33 + 32 files changed, 7698 insertions(+), 10 deletions(-) create mode 100644 server/doc/sql_app/api/devices.html create mode 100644 server/doc/sql_app/api/devices_web.html create mode 100644 server/doc/sql_app/api/index.html create mode 100644 server/doc/sql_app/api/licenses.html create mode 100644 server/doc/sql_app/api/licenses_web.html create mode 100644 server/doc/sql_app/api/pcs.html create mode 100644 server/doc/sql_app/api/pcs_web.html create mode 100644 server/doc/sql_app/api/teams.html create mode 100644 server/doc/sql_app/api/teams_web.html create mode 100644 server/doc/sql_app/api/usb_logs.html create mode 100644 server/doc/sql_app/api/usb_logs_web.html create mode 100644 server/doc/sql_app/crud.html create mode 100644 server/doc/sql_app/database.html create mode 100644 server/doc/sql_app/documentation.html create mode 100644 server/doc/sql_app/main.html create mode 100644 server/doc/sql_app/models.html create mode 100644 server/doc/sql_app/schemas.html diff --git a/server/doc/sql_app/api/devices.html b/server/doc/sql_app/api/devices.html new file mode 100644 index 0000000..44cffd7 --- /dev/null +++ b/server/doc/sql_app/api/devices.html @@ -0,0 +1,189 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.devices API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.devices</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List + +from fastapi import Depends, FastAPI, HTTPException, APIRouter +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine + +models.Base.metadata.create_all(bind=engine) + +# prefix used for all endpoints in this file +device = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@device.post("/device", response_model=schemas.Device) +def create_device(device: schemas.DeviceCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new device + """ + print(crud.create_device(db=db, device=device)) + + +@device.get("/devices", response_model=List[schemas.Device]) +def read_devices(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Endpoint returns all devices in database + """ + devices = crud.get_devices(db, skip=skip, limit=limit) + return devices + + +@device.get("/device/{device_id}", response_model=schemas.Device) +def read_device(device_id: int, db: Session = Depends(get_db)): + """ + Returns one specific device by given id + """ + db_device = crud.get_device(db, device_id=device_id) + if db_device is None: + raise HTTPException(status_code=404, detail="Device not found") + return db_device</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.devices.create_device"><code class="name flex"> +<span>def <span class="ident">create_device</span></span>(<span>device: <a title="sql_app.schemas.DeviceCreate" href="../schemas.html#sql_app.schemas.DeviceCreate">DeviceCreate</a>, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint used for creating new device</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@device.post("/device", response_model=schemas.Device) +def create_device(device: schemas.DeviceCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new device + """ + print(crud.create_device(db=db, device=device))</code></pre> +</details> +</dd> +<dt id="sql_app.api.devices.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.devices.read_device"><code class="name flex"> +<span>def <span class="ident">read_device</span></span>(<span>device_id: int, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns one specific device by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@device.get("/device/{device_id}", response_model=schemas.Device) +def read_device(device_id: int, db: Session = Depends(get_db)): + """ + Returns one specific device by given id + """ + db_device = crud.get_device(db, device_id=device_id) + if db_device is None: + raise HTTPException(status_code=404, detail="Device not found") + return db_device</code></pre> +</details> +</dd> +<dt id="sql_app.api.devices.read_devices"><code class="name flex"> +<span>def <span class="ident">read_devices</span></span>(<span>skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint returns all devices in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@device.get("/devices", response_model=List[schemas.Device]) +def read_devices(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Endpoint returns all devices in database + """ + devices = crud.get_devices(db, skip=skip, limit=limit) + return devices</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.devices.create_device" href="#sql_app.api.devices.create_device">create_device</a></code></li> +<li><code><a title="sql_app.api.devices.get_db" href="#sql_app.api.devices.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.devices.read_device" href="#sql_app.api.devices.read_device">read_device</a></code></li> +<li><code><a title="sql_app.api.devices.read_devices" href="#sql_app.api.devices.read_devices">read_devices</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/devices_web.html b/server/doc/sql_app/api/devices_web.html new file mode 100644 index 0000000..b4028ad --- /dev/null +++ b/server/doc/sql_app/api/devices_web.html @@ -0,0 +1,289 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.devices_web API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.devices_web</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List + +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from datetime import datetime +from ..database import SessionLocal, engine +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +models.Base.metadata.create_all(bind=engine) + +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/devices") + +# prefix used for all endpoints in this file +device_web = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@device_web.get("/devices-web", response_class=HTMLResponse) +async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all devices and its current states + """ + devices = crud.get_devices(db, skip=skip, limit=limit) + statuses = [] + # adding state for each device in list + for i in range(0, len(devices)): + statuses.append(devices[i].logs[len(devices[i].logs)-1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses}) + + +@device_web.post("/devices-web", response_class=HTMLResponse) +async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: str = Form("all"), + db: Session = Depends(get_db)): + """ + Endpoint used for filtering devices by license. returns html template with only + devices that has assigned license defined by user input + """ + devices = crud.get_devices(db, skip=skip, limit=limit) + def_devices = [] + for dev in devices: + for l in dev.licenses: + if dev not in def_devices and l.licenses.name == lic: + def_devices.append(dev) + # if input was default all + if lic == "all": + def_devices = devices + statuses = [] + for i in range(0, len(def_devices)): + statuses.append(def_devices[i].logs[len(def_devices[i].logs) - 1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("devices.html", {"request": request, "devs": len(def_devices), "devices": def_devices, + "statuses": statuses, "licenses": licenses}) + + +@device_web.get("/device-license/{device_id}", response_class=HTMLResponse) +async def connect_dev_lic(request: Request, device_id: int, db: Session = Depends(get_db)): + """ + Returns template with one device and all available licenses that can be assigned to it. + """ + device = crud.get_device(db, device_id) + licenses = crud.get_licenses(db, 0, 100) + return templates.TemplateResponse("devicelicense.html", + {"request": request, "device": device, "licenses": licenses}) + + +@device_web.post("/devices-web/{device_id}", response_class=HTMLResponse) +async def connect_post(request: Request, device_id: int, lic: str = Form(...), skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint called from template for connecting device with license. Adds entry to devices_licenses + table and returns template with all devices in database + """ + crud.create_device_license(db, device_id, int(lic), datetime.now()) + devices = crud.get_devices(db, skip=skip, limit=limit) + statuses = [] + # adding state for each device in list + for i in range(0, len(devices)): + statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses})</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.devices_web.connect_dev_lic"><code class="name flex"> +<span>async def <span class="ident">connect_dev_lic</span></span>(<span>request: starlette.requests.Request, device_id: int, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with one device and all available licenses that can be assigned to it.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@device_web.get("/device-license/{device_id}", response_class=HTMLResponse) +async def connect_dev_lic(request: Request, device_id: int, db: Session = Depends(get_db)): + """ + Returns template with one device and all available licenses that can be assigned to it. + """ + device = crud.get_device(db, device_id) + licenses = crud.get_licenses(db, 0, 100) + return templates.TemplateResponse("devicelicense.html", + {"request": request, "device": device, "licenses": licenses})</code></pre> +</details> +</dd> +<dt id="sql_app.api.devices_web.connect_post"><code class="name flex"> +<span>async def <span class="ident">connect_post</span></span>(<span>request: starlette.requests.Request, device_id: int, lic: str = Form(Ellipsis), skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint called from template for connecting device with license. Adds entry to devices_licenses +table and returns template with all devices in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@device_web.post("/devices-web/{device_id}", response_class=HTMLResponse) +async def connect_post(request: Request, device_id: int, lic: str = Form(...), skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint called from template for connecting device with license. Adds entry to devices_licenses + table and returns template with all devices in database + """ + crud.create_device_license(db, device_id, int(lic), datetime.now()) + devices = crud.get_devices(db, skip=skip, limit=limit) + statuses = [] + # adding state for each device in list + for i in range(0, len(devices)): + statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses})</code></pre> +</details> +</dd> +<dt id="sql_app.api.devices_web.filter_devices"><code class="name flex"> +<span>async def <span class="ident">filter_devices</span></span>(<span>request: starlette.requests.Request, skip: int = 0, limit: int = 100, lic: str = Form(all), db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint used for filtering devices by license. returns html template with only +devices that has assigned license defined by user input</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@device_web.post("/devices-web", response_class=HTMLResponse) +async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: str = Form("all"), + db: Session = Depends(get_db)): + """ + Endpoint used for filtering devices by license. returns html template with only + devices that has assigned license defined by user input + """ + devices = crud.get_devices(db, skip=skip, limit=limit) + def_devices = [] + for dev in devices: + for l in dev.licenses: + if dev not in def_devices and l.licenses.name == lic: + def_devices.append(dev) + # if input was default all + if lic == "all": + def_devices = devices + statuses = [] + for i in range(0, len(def_devices)): + statuses.append(def_devices[i].logs[len(def_devices[i].logs) - 1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("devices.html", {"request": request, "devs": len(def_devices), "devices": def_devices, + "statuses": statuses, "licenses": licenses})</code></pre> +</details> +</dd> +<dt id="sql_app.api.devices_web.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.devices_web.read_devices"><code class="name flex"> +<span>async def <span class="ident">read_devices</span></span>(<span>request: starlette.requests.Request, skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with all devices and its current states</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@device_web.get("/devices-web", response_class=HTMLResponse) +async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all devices and its current states + """ + devices = crud.get_devices(db, skip=skip, limit=limit) + statuses = [] + # adding state for each device in list + for i in range(0, len(devices)): + statuses.append(devices[i].logs[len(devices[i].logs)-1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses})</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.devices_web.connect_dev_lic" href="#sql_app.api.devices_web.connect_dev_lic">connect_dev_lic</a></code></li> +<li><code><a title="sql_app.api.devices_web.connect_post" href="#sql_app.api.devices_web.connect_post">connect_post</a></code></li> +<li><code><a title="sql_app.api.devices_web.filter_devices" href="#sql_app.api.devices_web.filter_devices">filter_devices</a></code></li> +<li><code><a title="sql_app.api.devices_web.get_db" href="#sql_app.api.devices_web.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.devices_web.read_devices" href="#sql_app.api.devices_web.read_devices">read_devices</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/index.html b/server/doc/sql_app/api/index.html new file mode 100644 index 0000000..edd8582 --- /dev/null +++ b/server/doc/sql_app/api/index.html @@ -0,0 +1,110 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api</code></h1> +</header> +<section id="section-intro"> +</section> +<section> +<h2 class="section-title" id="header-submodules">Sub-modules</h2> +<dl> +<dt><code class="name"><a title="sql_app.api.devices" href="devices.html">sql_app.api.devices</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.devices_web" href="devices_web.html">sql_app.api.devices_web</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.licenses" href="licenses.html">sql_app.api.licenses</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.licenses_web" href="licenses_web.html">sql_app.api.licenses_web</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.pcs" href="pcs.html">sql_app.api.pcs</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.pcs_web" href="pcs_web.html">sql_app.api.pcs_web</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.teams" href="teams.html">sql_app.api.teams</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.teams_web" href="teams_web.html">sql_app.api.teams_web</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.usb_logs" href="usb_logs.html">sql_app.api.usb_logs</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.api.usb_logs_web" href="usb_logs_web.html">sql_app.api.usb_logs_web</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</section> +<section> +</section> +<section> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app" href="../index.html">sql_app</a></code></li> +</ul> +</li> +<li><h3><a href="#header-submodules">Sub-modules</a></h3> +<ul> +<li><code><a title="sql_app.api.devices" href="devices.html">sql_app.api.devices</a></code></li> +<li><code><a title="sql_app.api.devices_web" href="devices_web.html">sql_app.api.devices_web</a></code></li> +<li><code><a title="sql_app.api.licenses" href="licenses.html">sql_app.api.licenses</a></code></li> +<li><code><a title="sql_app.api.licenses_web" href="licenses_web.html">sql_app.api.licenses_web</a></code></li> +<li><code><a title="sql_app.api.pcs" href="pcs.html">sql_app.api.pcs</a></code></li> +<li><code><a title="sql_app.api.pcs_web" href="pcs_web.html">sql_app.api.pcs_web</a></code></li> +<li><code><a title="sql_app.api.teams" href="teams.html">sql_app.api.teams</a></code></li> +<li><code><a title="sql_app.api.teams_web" href="teams_web.html">sql_app.api.teams_web</a></code></li> +<li><code><a title="sql_app.api.usb_logs" href="usb_logs.html">sql_app.api.usb_logs</a></code></li> +<li><code><a title="sql_app.api.usb_logs_web" href="usb_logs_web.html">sql_app.api.usb_logs_web</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/licenses.html b/server/doc/sql_app/api/licenses.html new file mode 100644 index 0000000..6a4aa66 --- /dev/null +++ b/server/doc/sql_app/api/licenses.html @@ -0,0 +1,160 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.licenses API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.licenses</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List + +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from sqlalchemy.orm import Session +from datetime import datetime +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine + +models.Base.metadata.create_all(bind=engine) + +# prefix used for all endpoints in this file +licenses = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@licenses.get("/licenses", response_model=List[schemas.License]) +def read_licenses(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all licenses currently saved in database. + """ + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return licenses + + +@licenses.post("/device-license", response_model=schemas.DeviceLicense) +def create_device_license(device_license: schemas.DeviceLicenseCreate, db: Session = Depends(get_db)): + """ + Creates entry for devices_licenses table thus connecting device with its license. + """ + print(crud.create_device_license(db=db, device=device_license.device_id, license=device_license.license_id, + time=datetime.now()))</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.licenses.create_device_license"><code class="name flex"> +<span>def <span class="ident">create_device_license</span></span>(<span>device_license: <a title="sql_app.schemas.DeviceLicenseCreate" href="../schemas.html#sql_app.schemas.DeviceLicenseCreate">DeviceLicenseCreate</a>, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Creates entry for devices_licenses table thus connecting device with its license.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@licenses.post("/device-license", response_model=schemas.DeviceLicense) +def create_device_license(device_license: schemas.DeviceLicenseCreate, db: Session = Depends(get_db)): + """ + Creates entry for devices_licenses table thus connecting device with its license. + """ + print(crud.create_device_license(db=db, device=device_license.device_id, license=device_license.license_id, + time=datetime.now()))</code></pre> +</details> +</dd> +<dt id="sql_app.api.licenses.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.licenses.read_licenses"><code class="name flex"> +<span>def <span class="ident">read_licenses</span></span>(<span>skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all licenses currently saved in database.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@licenses.get("/licenses", response_model=List[schemas.License]) +def read_licenses(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all licenses currently saved in database. + """ + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return licenses</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.licenses.create_device_license" href="#sql_app.api.licenses.create_device_license">create_device_license</a></code></li> +<li><code><a title="sql_app.api.licenses.get_db" href="#sql_app.api.licenses.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.licenses.read_licenses" href="#sql_app.api.licenses.read_licenses">read_licenses</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/licenses_web.html b/server/doc/sql_app/api/licenses_web.html new file mode 100644 index 0000000..fb9ff21 --- /dev/null +++ b/server/doc/sql_app/api/licenses_web.html @@ -0,0 +1,212 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.licenses_web API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.licenses_web</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List + +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from sqlalchemy.orm import Session +from datetime import date +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +models.Base.metadata.create_all(bind=engine) + +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/licenses") +device_templates = Jinja2Templates(directory="../templates/devices") + +# prefix used for all endpoints in this file +licenses_web = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@licenses_web.get("/license-create", response_class=HTMLResponse) +async def licenses_create_web(request: Request): + """ + Returns template with Form for creating new license. + """ + return templates.TemplateResponse("license_create.html", {"request": request}) + + +@licenses_web.get("/licenses-web", response_class=HTMLResponse) +async def read_licenses_web(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all licenses currently saved in database + """ + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("licenses.html", {"request": request, "licenses": licenses}) + + +@licenses_web.post("/licenses-web", response_class=HTMLResponse) +def create_license(request: Request, name: str = Form(...), expdate: date = Form(...), skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint called from create license form. Creates new license and returns template with all licenses in database + """ + db_license = crud.create_license(db, name, expdate) + if db_license is None: + print("something went wrong") + devices = crud.get_devices(db, skip=skip, limit=limit) + statuses = [] + for i in range(0, len(devices)): + statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return device_templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses})</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.licenses_web.create_license"><code class="name flex"> +<span>def <span class="ident">create_license</span></span>(<span>request: starlette.requests.Request, name: str = Form(Ellipsis), expdate: datetime.date = Form(Ellipsis), skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint called from create license form. Creates new license and returns template with all licenses in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@licenses_web.post("/licenses-web", response_class=HTMLResponse) +def create_license(request: Request, name: str = Form(...), expdate: date = Form(...), skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint called from create license form. Creates new license and returns template with all licenses in database + """ + db_license = crud.create_license(db, name, expdate) + if db_license is None: + print("something went wrong") + devices = crud.get_devices(db, skip=skip, limit=limit) + statuses = [] + for i in range(0, len(devices)): + statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return device_templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses})</code></pre> +</details> +</dd> +<dt id="sql_app.api.licenses_web.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.licenses_web.licenses_create_web"><code class="name flex"> +<span>async def <span class="ident">licenses_create_web</span></span>(<span>request: starlette.requests.Request)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with Form for creating new license.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@licenses_web.get("/license-create", response_class=HTMLResponse) +async def licenses_create_web(request: Request): + """ + Returns template with Form for creating new license. + """ + return templates.TemplateResponse("license_create.html", {"request": request})</code></pre> +</details> +</dd> +<dt id="sql_app.api.licenses_web.read_licenses_web"><code class="name flex"> +<span>async def <span class="ident">read_licenses_web</span></span>(<span>request: starlette.requests.Request, skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with all licenses currently saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@licenses_web.get("/licenses-web", response_class=HTMLResponse) +async def read_licenses_web(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all licenses currently saved in database + """ + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("licenses.html", {"request": request, "licenses": licenses})</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.licenses_web.create_license" href="#sql_app.api.licenses_web.create_license">create_license</a></code></li> +<li><code><a title="sql_app.api.licenses_web.get_db" href="#sql_app.api.licenses_web.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.licenses_web.licenses_create_web" href="#sql_app.api.licenses_web.licenses_create_web">licenses_create_web</a></code></li> +<li><code><a title="sql_app.api.licenses_web.read_licenses_web" href="#sql_app.api.licenses_web.read_licenses_web">read_licenses_web</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/pcs.html b/server/doc/sql_app/api/pcs.html new file mode 100644 index 0000000..e362d48 --- /dev/null +++ b/server/doc/sql_app/api/pcs.html @@ -0,0 +1,188 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.pcs API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.pcs</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List +from fastapi import Depends, FastAPI, HTTPException, APIRouter +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine + +models.Base.metadata.create_all(bind=engine) + +# prefix used for all endpoints in this file +pcs = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@pcs.post("/pc", response_model=schemas.PC) +def create_pc(pc: schemas.PCCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new pc + """ + print(crud.create_pc(db=db, user=pc.username, host=pc.hostname)) + + +@pcs.get("/pcs", response_model=List[schemas.PC]) +def read_pcs(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all pcs currently saved in database + """ + pcs = crud.get_pcs(db, skip=skip, limit=limit) + return pcs + + +@pcs.get("/pc/{pc_id}", response_model=schemas.PC) +def read_pc(pc_id: int, db: Session = Depends(get_db)): + """ + Returns one specific pc by given id + """ + db_pc = crud.get_pc(db, pc_id=pc_id) + if db_pc is None: + raise HTTPException(status_code=404, detail="Device not found") + return db_pc</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.pcs.create_pc"><code class="name flex"> +<span>def <span class="ident">create_pc</span></span>(<span>pc: <a title="sql_app.schemas.PCCreate" href="../schemas.html#sql_app.schemas.PCCreate">PCCreate</a>, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint used for creating new pc</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@pcs.post("/pc", response_model=schemas.PC) +def create_pc(pc: schemas.PCCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new pc + """ + print(crud.create_pc(db=db, user=pc.username, host=pc.hostname))</code></pre> +</details> +</dd> +<dt id="sql_app.api.pcs.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.pcs.read_pc"><code class="name flex"> +<span>def <span class="ident">read_pc</span></span>(<span>pc_id: int, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns one specific pc by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@pcs.get("/pc/{pc_id}", response_model=schemas.PC) +def read_pc(pc_id: int, db: Session = Depends(get_db)): + """ + Returns one specific pc by given id + """ + db_pc = crud.get_pc(db, pc_id=pc_id) + if db_pc is None: + raise HTTPException(status_code=404, detail="Device not found") + return db_pc</code></pre> +</details> +</dd> +<dt id="sql_app.api.pcs.read_pcs"><code class="name flex"> +<span>def <span class="ident">read_pcs</span></span>(<span>skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all pcs currently saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@pcs.get("/pcs", response_model=List[schemas.PC]) +def read_pcs(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all pcs currently saved in database + """ + pcs = crud.get_pcs(db, skip=skip, limit=limit) + return pcs</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.pcs.create_pc" href="#sql_app.api.pcs.create_pc">create_pc</a></code></li> +<li><code><a title="sql_app.api.pcs.get_db" href="#sql_app.api.pcs.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.pcs.read_pc" href="#sql_app.api.pcs.read_pc">read_pc</a></code></li> +<li><code><a title="sql_app.api.pcs.read_pcs" href="#sql_app.api.pcs.read_pcs">read_pcs</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/pcs_web.html b/server/doc/sql_app/api/pcs_web.html new file mode 100644 index 0000000..5f11982 --- /dev/null +++ b/server/doc/sql_app/api/pcs_web.html @@ -0,0 +1,201 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.pcs_web API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.pcs_web</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +models.Base.metadata.create_all(bind=engine) + +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/pcs") + +# prefix used for all endpoints in this file +pcs_web = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@pcs_web.get("/pcs-web", response_class=HTMLResponse) +async def read_pcs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all pcs currently saved in database + """ + pcs = crud.get_pcs(db, skip=skip, limit=limit) + return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs}) + + +@pcs_web.get("/pc-team/{pc_id}", response_class=HTMLResponse) +async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(get_db)): + """ + Returns template with Form for connecting pc with team + """ + pc = crud.get_pc(db, pc_id) + teams = crud.get_teams(db, 0, 100) + return templates.TemplateResponse("pcteam.html", + {"request": request, "pc": pc, "teams": teams}) + + +@pcs_web.post("/pcs-web/{pc_id}", response_class=HTMLResponse) +async def connect_post(request: Request, pc_id: int, team: str = Form(...), skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint called from within form for connecting pc with team. Updates certain pc with new team. + """ + old_pc = crud.update_pc(db, pc_id, team) + pcs = crud.get_pcs(db, skip=skip, limit=limit) + return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs})</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.pcs_web.connect_pc_team"><code class="name flex"> +<span>async def <span class="ident">connect_pc_team</span></span>(<span>request: starlette.requests.Request, pc_id: int, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with Form for connecting pc with team</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@pcs_web.get("/pc-team/{pc_id}", response_class=HTMLResponse) +async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(get_db)): + """ + Returns template with Form for connecting pc with team + """ + pc = crud.get_pc(db, pc_id) + teams = crud.get_teams(db, 0, 100) + return templates.TemplateResponse("pcteam.html", + {"request": request, "pc": pc, "teams": teams})</code></pre> +</details> +</dd> +<dt id="sql_app.api.pcs_web.connect_post"><code class="name flex"> +<span>async def <span class="ident">connect_post</span></span>(<span>request: starlette.requests.Request, pc_id: int, team: str = Form(Ellipsis), skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint called from within form for connecting pc with team. Updates certain pc with new team.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@pcs_web.post("/pcs-web/{pc_id}", response_class=HTMLResponse) +async def connect_post(request: Request, pc_id: int, team: str = Form(...), skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint called from within form for connecting pc with team. Updates certain pc with new team. + """ + old_pc = crud.update_pc(db, pc_id, team) + pcs = crud.get_pcs(db, skip=skip, limit=limit) + return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs})</code></pre> +</details> +</dd> +<dt id="sql_app.api.pcs_web.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.pcs_web.read_pcs"><code class="name flex"> +<span>async def <span class="ident">read_pcs</span></span>(<span>request: starlette.requests.Request, skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with all pcs currently saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@pcs_web.get("/pcs-web", response_class=HTMLResponse) +async def read_pcs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all pcs currently saved in database + """ + pcs = crud.get_pcs(db, skip=skip, limit=limit) + return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs})</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.pcs_web.connect_pc_team" href="#sql_app.api.pcs_web.connect_pc_team">connect_pc_team</a></code></li> +<li><code><a title="sql_app.api.pcs_web.connect_post" href="#sql_app.api.pcs_web.connect_post">connect_post</a></code></li> +<li><code><a title="sql_app.api.pcs_web.get_db" href="#sql_app.api.pcs_web.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.pcs_web.read_pcs" href="#sql_app.api.pcs_web.read_pcs">read_pcs</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/teams.html b/server/doc/sql_app/api/teams.html new file mode 100644 index 0000000..00afc9a --- /dev/null +++ b/server/doc/sql_app/api/teams.html @@ -0,0 +1,188 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.teams API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.teams</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List + +from fastapi import Depends, FastAPI, HTTPException, APIRouter +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine + +models.Base.metadata.create_all(bind=engine) + +# prefix used for all endpoints in this file +teams = APIRouter(prefix="/api/v1") + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@teams.post("/team", response_model=schemas.Team) +def create_device(team: schemas.TeamCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new pc + """ + print(crud.create_team(db=db, name=team.name)) + + +@teams.get("/teams", response_model=List[schemas.Device]) +def read_devices(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all pcs saved in database + """ + teams = crud.get_teams(db, skip=skip, limit=limit) + return teams + + +@teams.get("/team/{team_id}", response_model=schemas.Device) +def read_device(team_id: int, db: Session = Depends(get_db)): + """ + Returns one specific team by given id + """ + db_team = crud.get_team(db, team_id=team_id) + if db_team is None: + raise HTTPException(status_code=404, detail="Device not found") + return db_team</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.teams.create_device"><code class="name flex"> +<span>def <span class="ident">create_device</span></span>(<span>team: <a title="sql_app.schemas.TeamCreate" href="../schemas.html#sql_app.schemas.TeamCreate">TeamCreate</a>, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint used for creating new pc</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@teams.post("/team", response_model=schemas.Team) +def create_device(team: schemas.TeamCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new pc + """ + print(crud.create_team(db=db, name=team.name))</code></pre> +</details> +</dd> +<dt id="sql_app.api.teams.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.teams.read_device"><code class="name flex"> +<span>def <span class="ident">read_device</span></span>(<span>team_id: int, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns one specific team by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@teams.get("/team/{team_id}", response_model=schemas.Device) +def read_device(team_id: int, db: Session = Depends(get_db)): + """ + Returns one specific team by given id + """ + db_team = crud.get_team(db, team_id=team_id) + if db_team is None: + raise HTTPException(status_code=404, detail="Device not found") + return db_team</code></pre> +</details> +</dd> +<dt id="sql_app.api.teams.read_devices"><code class="name flex"> +<span>def <span class="ident">read_devices</span></span>(<span>skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all pcs saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@teams.get("/teams", response_model=List[schemas.Device]) +def read_devices(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all pcs saved in database + """ + teams = crud.get_teams(db, skip=skip, limit=limit) + return teams</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.teams.create_device" href="#sql_app.api.teams.create_device">create_device</a></code></li> +<li><code><a title="sql_app.api.teams.get_db" href="#sql_app.api.teams.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.teams.read_device" href="#sql_app.api.teams.read_device">read_device</a></code></li> +<li><code><a title="sql_app.api.teams.read_devices" href="#sql_app.api.teams.read_devices">read_devices</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/teams_web.html b/server/doc/sql_app/api/teams_web.html new file mode 100644 index 0000000..bee1c5d --- /dev/null +++ b/server/doc/sql_app/api/teams_web.html @@ -0,0 +1,200 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.teams_web API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.teams_web</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List + +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +models.Base.metadata.create_all(bind=engine) + +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/teams") + +# prefix used for all endpoints in this file +teams_web = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@teams_web.get("/teams-web", response_class=HTMLResponse) +async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all teams currently saved in database + """ + teams = crud.get_teams(db, skip=skip, limit=limit) + return templates.TemplateResponse("teams.html", {"request": request, "teams": teams}) + + +@teams_web.get("/team-create", response_class=HTMLResponse) +async def team_create_web(request: Request): + """ + Returns template with form for creating new team + """ + return templates.TemplateResponse("team_create.html", {"request": request}) + + +@teams_web.post("/teams-web", response_class=HTMLResponse) +def create_team(request: Request, name: str = Form(...), skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint called from within form for creating new team. Creates new team and returns all teams in database + """ + team = crud.create_team(db, name) + if team is None: + print("something went wrong") + teams = crud.get_teams(db, skip=skip, limit=limit) + return templates.TemplateResponse("teams.html", {"request": request, "teams": teams})</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.teams_web.create_team"><code class="name flex"> +<span>def <span class="ident">create_team</span></span>(<span>request: starlette.requests.Request, name: str = Form(Ellipsis), skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint called from within form for creating new team. Creates new team and returns all teams in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@teams_web.post("/teams-web", response_class=HTMLResponse) +def create_team(request: Request, name: str = Form(...), skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint called from within form for creating new team. Creates new team and returns all teams in database + """ + team = crud.create_team(db, name) + if team is None: + print("something went wrong") + teams = crud.get_teams(db, skip=skip, limit=limit) + return templates.TemplateResponse("teams.html", {"request": request, "teams": teams})</code></pre> +</details> +</dd> +<dt id="sql_app.api.teams_web.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.teams_web.read_devices"><code class="name flex"> +<span>async def <span class="ident">read_devices</span></span>(<span>request: starlette.requests.Request, skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with all teams currently saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@teams_web.get("/teams-web", response_class=HTMLResponse) +async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all teams currently saved in database + """ + teams = crud.get_teams(db, skip=skip, limit=limit) + return templates.TemplateResponse("teams.html", {"request": request, "teams": teams})</code></pre> +</details> +</dd> +<dt id="sql_app.api.teams_web.team_create_web"><code class="name flex"> +<span>async def <span class="ident">team_create_web</span></span>(<span>request: starlette.requests.Request)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with form for creating new team</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@teams_web.get("/team-create", response_class=HTMLResponse) +async def team_create_web(request: Request): + """ + Returns template with form for creating new team + """ + return templates.TemplateResponse("team_create.html", {"request": request})</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.teams_web.create_team" href="#sql_app.api.teams_web.create_team">create_team</a></code></li> +<li><code><a title="sql_app.api.teams_web.get_db" href="#sql_app.api.teams_web.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.teams_web.read_devices" href="#sql_app.api.teams_web.read_devices">read_devices</a></code></li> +<li><code><a title="sql_app.api.teams_web.team_create_web" href="#sql_app.api.teams_web.team_create_web">team_create_web</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/usb_logs.html b/server/doc/sql_app/api/usb_logs.html new file mode 100644 index 0000000..499c94e --- /dev/null +++ b/server/doc/sql_app/api/usb_logs.html @@ -0,0 +1,265 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.usb_logs API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.usb_logs</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from datetime import datetime +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine + +models.Base.metadata.create_all(bind=engine) + +# prefix used for all endpoints in this file +usblogs = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@usblogs.post("/usb-logs", response_model=schemas.USBLog) +def create_device_logs(log: schemas.USBTempBase, db: Session = Depends(get_db)): + """ + Endpoint called from keyman detecting client. Parses timestamp into datetime object. + Finds if device and pc defined in message already exists and creates them if necessary. + Saves log into database + """ + dev = crud.find_device(db, log.device) + dat = datetime.strptime(log.timestamp, '%Y-%m-%d %H:%M:%S') + if dev is None: + dev = crud.create_device(db=db, device=log.device) + pc = crud.find_pc(db, log.username, log.hostname) + if pc is None: + pc = crud.create_pc(db=db, user=log.username, host=log.hostname) + + print(crud.create_device_logs(db=db, item=log, dev_id=dev.id, pc_id=pc.id, date=dat)) + + +@usblogs.post("/ld-logs", response_model=schemas.LDLog) +def create_ld_logs(log: schemas.LDTempBase, db: Session = Depends(get_db)): + """ + Endpoint called from debugger detecting client. Parses timestamp into datetime object. + Finds if head device and body device defined in message already exists and creates them if necessary. + Saves log into database + """ + head_dev = crud.find_head_device(db, log.head_device) + body_dev = crud.find_body_device(db, log.body_device) + if head_dev is None: + crud.create_head_device(db, log.head_device) + if body_dev is None: + crud.create_body_device(db, log.body_device) + + pc = crud.find_pc(db, log.username, log.hostname) + if pc is None: + pc = crud.create_pc(db=db, user=log.username, host=log.hostname) + dat = datetime.strptime(log.timestamp, '%Y-%m-%d %H:%M:%S') + print(crud.create_ld_logs(db=db, item=log, head_id=head_dev.id, body_id=body_dev.id, pc_id=pc.id, date=dat)) + + +@usblogs.get("/logs", response_model=List[schemas.USBLog]) +def read_logs(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all usb logs saved in database + """ + items = crud.get_logs(db, skip=skip, limit=limit) + return items + + +@usblogs.get("/logs/{device_id}", response_model=List[schemas.USBLog]) +def read_log(device_id: int, db: Session = Depends(get_db)): + """ + Returns one specific log by given id + """ + db_log = crud.get_log(db, device_id=device_id) + if db_log is None: + raise HTTPException(status_code=404, detail="Logs not found") + return db_log</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.usb_logs.create_device_logs"><code class="name flex"> +<span>def <span class="ident">create_device_logs</span></span>(<span>log: <a title="sql_app.schemas.USBTempBase" href="../schemas.html#sql_app.schemas.USBTempBase">USBTempBase</a>, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint called from keyman detecting client. Parses timestamp into datetime object. +Finds if device and pc defined in message already exists and creates them if necessary. +Saves log into database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@usblogs.post("/usb-logs", response_model=schemas.USBLog) +def create_device_logs(log: schemas.USBTempBase, db: Session = Depends(get_db)): + """ + Endpoint called from keyman detecting client. Parses timestamp into datetime object. + Finds if device and pc defined in message already exists and creates them if necessary. + Saves log into database + """ + dev = crud.find_device(db, log.device) + dat = datetime.strptime(log.timestamp, '%Y-%m-%d %H:%M:%S') + if dev is None: + dev = crud.create_device(db=db, device=log.device) + pc = crud.find_pc(db, log.username, log.hostname) + if pc is None: + pc = crud.create_pc(db=db, user=log.username, host=log.hostname) + + print(crud.create_device_logs(db=db, item=log, dev_id=dev.id, pc_id=pc.id, date=dat))</code></pre> +</details> +</dd> +<dt id="sql_app.api.usb_logs.create_ld_logs"><code class="name flex"> +<span>def <span class="ident">create_ld_logs</span></span>(<span>log: <a title="sql_app.schemas.LDTempBase" href="../schemas.html#sql_app.schemas.LDTempBase">LDTempBase</a>, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint called from debugger detecting client. Parses timestamp into datetime object. +Finds if head device and body device defined in message already exists and creates them if necessary. +Saves log into database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@usblogs.post("/ld-logs", response_model=schemas.LDLog) +def create_ld_logs(log: schemas.LDTempBase, db: Session = Depends(get_db)): + """ + Endpoint called from debugger detecting client. Parses timestamp into datetime object. + Finds if head device and body device defined in message already exists and creates them if necessary. + Saves log into database + """ + head_dev = crud.find_head_device(db, log.head_device) + body_dev = crud.find_body_device(db, log.body_device) + if head_dev is None: + crud.create_head_device(db, log.head_device) + if body_dev is None: + crud.create_body_device(db, log.body_device) + + pc = crud.find_pc(db, log.username, log.hostname) + if pc is None: + pc = crud.create_pc(db=db, user=log.username, host=log.hostname) + dat = datetime.strptime(log.timestamp, '%Y-%m-%d %H:%M:%S') + print(crud.create_ld_logs(db=db, item=log, head_id=head_dev.id, body_id=body_dev.id, pc_id=pc.id, date=dat))</code></pre> +</details> +</dd> +<dt id="sql_app.api.usb_logs.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.usb_logs.read_log"><code class="name flex"> +<span>def <span class="ident">read_log</span></span>(<span>device_id: int, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns one specific log by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@usblogs.get("/logs/{device_id}", response_model=List[schemas.USBLog]) +def read_log(device_id: int, db: Session = Depends(get_db)): + """ + Returns one specific log by given id + """ + db_log = crud.get_log(db, device_id=device_id) + if db_log is None: + raise HTTPException(status_code=404, detail="Logs not found") + return db_log</code></pre> +</details> +</dd> +<dt id="sql_app.api.usb_logs.read_logs"><code class="name flex"> +<span>def <span class="ident">read_logs</span></span>(<span>skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all usb logs saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@usblogs.get("/logs", response_model=List[schemas.USBLog]) +def read_logs(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all usb logs saved in database + """ + items = crud.get_logs(db, skip=skip, limit=limit) + return items</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.usb_logs.create_device_logs" href="#sql_app.api.usb_logs.create_device_logs">create_device_logs</a></code></li> +<li><code><a title="sql_app.api.usb_logs.create_ld_logs" href="#sql_app.api.usb_logs.create_ld_logs">create_ld_logs</a></code></li> +<li><code><a title="sql_app.api.usb_logs.get_db" href="#sql_app.api.usb_logs.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.usb_logs.read_log" href="#sql_app.api.usb_logs.read_log">read_log</a></code></li> +<li><code><a title="sql_app.api.usb_logs.read_logs" href="#sql_app.api.usb_logs.read_logs">read_logs</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/api/usb_logs_web.html b/server/doc/sql_app/api/usb_logs_web.html new file mode 100644 index 0000000..fb54ab6 --- /dev/null +++ b/server/doc/sql_app/api/usb_logs_web.html @@ -0,0 +1,202 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.api.usb_logs_web API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.api.usb_logs_web</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from datetime import datetime +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +models.Base.metadata.create_all(bind=engine) + +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/usb-logs") + +# prefix used for all endpoints in this file +usblogs_web = APIRouter(prefix="/api/v1") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@usblogs_web.get("/logs-web", response_class=HTMLResponse) +async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all usb logs currently saved in database with its pcs, teams and licenses. + """ + logs = crud.get_logs(db, skip=skip, limit=limit) + pcs = [] + for log in logs: + if log.pc_id not in pcs: + pcs.append(log.pc_id) + pc_obj = crud.find_pcs(db, pcs) + teams = crud.get_teams(db, skip=skip, limit=limit) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses}) + + +@usblogs_web.post("/logs-web", response_class=HTMLResponse) +async def filter_logs(request: Request, pc: str = Form("all"), team: str = Form("all"), lic: str = Form("all"), + skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint used for filtering usb logs by user given form inputs. + """ + log = crud.get_filtered_logs(db, pc, team, lic) + logs_ids = [] + for l in log: + logs_ids.append(l[0]) + logs = crud.find_filtered_logs(db, logs_ids) + pc_obj = crud.get_pcs(db, skip=skip, limit=limit) + teams = crud.get_teams(db, skip=skip, limit=limit) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses})</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.api.usb_logs_web.filter_logs"><code class="name flex"> +<span>async def <span class="ident">filter_logs</span></span>(<span>request: starlette.requests.Request, pc: str = Form(all), team: str = Form(all), lic: str = Form(all), skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Endpoint used for filtering usb logs by user given form inputs.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@usblogs_web.post("/logs-web", response_class=HTMLResponse) +async def filter_logs(request: Request, pc: str = Form("all"), team: str = Form("all"), lic: str = Form("all"), + skip: int = 0, limit: int = 100, + db: Session = Depends(get_db)): + """ + Endpoint used for filtering usb logs by user given form inputs. + """ + log = crud.get_filtered_logs(db, pc, team, lic) + logs_ids = [] + for l in log: + logs_ids.append(l[0]) + logs = crud.find_filtered_logs(db, logs_ids) + pc_obj = crud.get_pcs(db, skip=skip, limit=limit) + teams = crud.get_teams(db, skip=skip, limit=limit) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses})</code></pre> +</details> +</dd> +<dt id="sql_app.api.usb_logs_web.get_db"><code class="name flex"> +<span>def <span class="ident">get_db</span></span>(<span>)</span> +</code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close()</code></pre> +</details> +</dd> +<dt id="sql_app.api.usb_logs_web.read_logs"><code class="name flex"> +<span>async def <span class="ident">read_logs</span></span>(<span>request: starlette.requests.Request, skip: int = 0, limit: int = 100, db: sqlalchemy.orm.session.Session = Depends(get_db))</span> +</code></dt> +<dd> +<div class="desc"><p>Returns template with all usb logs currently saved in database with its pcs, teams and licenses.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">@usblogs_web.get("/logs-web", response_class=HTMLResponse) +async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all usb logs currently saved in database with its pcs, teams and licenses. + """ + logs = crud.get_logs(db, skip=skip, limit=limit) + pcs = [] + for log in logs: + if log.pc_id not in pcs: + pcs.append(log.pc_id) + pc_obj = crud.find_pcs(db, pcs) + teams = crud.get_teams(db, skip=skip, limit=limit) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses})</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app.api" href="index.html">sql_app.api</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.api.usb_logs_web.filter_logs" href="#sql_app.api.usb_logs_web.filter_logs">filter_logs</a></code></li> +<li><code><a title="sql_app.api.usb_logs_web.get_db" href="#sql_app.api.usb_logs_web.get_db">get_db</a></code></li> +<li><code><a title="sql_app.api.usb_logs_web.read_logs" href="#sql_app.api.usb_logs_web.read_logs">read_logs</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/crud.html b/server/doc/sql_app/crud.html new file mode 100644 index 0000000..b6620d0 --- /dev/null +++ b/server/doc/sql_app/crud.html @@ -0,0 +1,1165 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.crud API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.crud</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from datetime import datetime, date + +from sqlalchemy.orm import Session +from sqlalchemy import and_, desc +from . import models, schemas + + +def get_device(db: Session, device_id: int): + """ + returns one specific devices by given id + """ + return db.query(models.Device).filter(models.Device.id == device_id).first() + + +def get_devices(db: Session, skip: int = 0, limit: int = 100): + """ + returns all devices in database + """ + return db.query(models.Device).offset(skip).limit(limit).all() + + +def find_device(db: Session, device: schemas.DeviceBase): + """ + finds one device with product_id, vendor_id and serial_number same as in given DeviceBase object + """ + return db.query(models.Device).filter(and_(models.Device.product_id == device.product_id, + models.Device.vendor_id == device.vendor_id, + models.Device.serial_number == device.serial_number)).first() + + +def create_device(db: Session, device: schemas.DeviceBase): + """ + creates new device with data from given DeviceBase object + """ + db_device = models.Device(vendor_id=device.vendor_id, product_id=device.product_id, + serial_number=device.serial_number, assigned=False) + db.add(db_device) + db.commit() + db.refresh(db_device) + return db_device + + +def get_license(db: Session, license_id: int): + """ + returns one specific license by given id + """ + return db.query(models.License).filter(models.License.id == license_id).first() + + +def get_licenses(db: Session, skip: int = 0, limit: int = 100): + """ + returns all licenses in database + """ + return db.query(models.License).offset(skip).limit(limit).all() + + +def find_license(db: Session, name: str): + """ + finds one license by given string name + """ + return db.query(models.License).filter(models.License.name == name).first() + + +def create_license(db: Session, name: str, expdate: date): + """ + creates new license with given name and expiration date + """ + db_license = models.License(name=name, expiration_date=expdate) + db.add(db_license) + db.commit() + db.refresh(db_license) + return db_license + + +def get_license_devices(db: Session, license_id: int): + """ + returns all entries in devices_licenses table + """ + return db.query(models.DeviceLicense).filter(models.DeviceLicense.license_id == license_id).all() + + +def create_device_license(db: Session, device: int, license: int, time: datetime): + """ + creates new entry in devices_licenses table with device id, license id and time. + """ + db_device_license = models.DeviceLicense(device_id=device, license_id=license, + assigned_datetime=time) + db.add(db_device_license) + db.commit() + db.refresh(db_device_license) + return db_device_license + + +def find_pc_by_username(db: Session, name: str): + """ + Finds one pc by given username + """ + return db.query(models.PC).filter(models.PC.username == name).first() + + +def get_pc(db: Session, pc_id: int): + """ + returns one specific pc by given id + """ + return db.query(models.PC).filter(models.PC.id == pc_id).first() + + +def update_pc(db: Session, pc_id: int, team: str): + """ + Function updates team of one specific pc + """ + old_pc = get_pc(db, pc_id) + team = get_team(db, int(team)) + new = {'id': old_pc.id, 'username': old_pc.username, 'hostname': old_pc.hostname, 'assigned': True, + 'team_id': team.id} + for key, value in new.items(): + setattr(old_pc, key, value) + db.commit() + db.refresh(old_pc) + return old_pc + + +def get_pcs(db: Session, skip: int = 0, limit: int = 100): + """ + returns all pcs in database + """ + return db.query(models.PC).offset(skip).limit(limit).all() + + +def find_pc(db: Session, username: str, hostname: str): + """ + Finds one pc with given username and hostname + """ + return db.query(models.PC).filter(and_(models.PC.username == username, + models.PC.hostname == hostname)).first() + + +def find_pc_by_name(db: Session, username: str): + """ + Finds one pc by its username + """ + return db.query(models.PC).filter(models.PC.username == username).first() + + +def find_pc_by_name_all(db: Session, username: str): + """ + Finds all pcs with same username + """ + return db.query(models.PC).filter(models.PC.username == username).offset(0).limit(100).all() + + +def find_pcs(db: Session, pcs: []): + """ + Finds all pcs with ids in given id array + """ + return db.query(models.PC).filter(models.PC.id.in_(pcs)).all() + + +def get_pcs_by_team(db: Session, team_id: int): + """ + returns all pcs in given team by team id + """ + return db.query(models.PC).filter(models.PC.team_id == team_id).all() + + +def create_pc(db: Session, user: str, host: str): + """ + creates new pc with given username and hostname + """ + db_pc = models.PC(username=user, hostname=host, assigned=False) + db.add(db_pc) + db.commit() + db.refresh(db_pc) + return db_pc + + +def get_team(db: Session, team_id: int): + """ + returns one specific team wit given id + """ + return db.query(models.Team).filter(models.Team.id == team_id).first() + + +def get_teams(db: Session, skip: int = 0, limit: int = 100): + """ + returns all teams currently saved in database + """ + return db.query(models.Team).offset(skip).limit(limit).all() + + +def find_team(db: Session, name: str): + """ + Finds one specific team by its name + """ + return db.query(models.Team).filter(models.Team.name == name).first() + + +def create_team(db: Session, name: str): + """ + Creates new team with given name + """ + db_team = models.Team(name=name) + db.add(db_team) + db.commit() + db.refresh(db_team) + return db_team + + +def get_head_device(db: Session, head_id: int): + """ + Returns one specific head device by given id + """ + return db.query(models.HeadDevice).filter(models.HeadDevice.id == head_id).first() + + +def get_head_devices(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all head devices saved in database + """ + return db.query(models.HeadDevice).offset(skip).limit(limit).all() + + +def find_head_device(db: Session, serial: schemas.HeadDeviceBase): + """ + Finds one head device by its serial number + """ + return db.query(models.HeadDevice).filter(models.HeadDevice.serial_number == serial.serial_number).first() + + +def create_head_device(db: Session, log: schemas.HeadDeviceBase): + """ + Creates new head device + """ + db_head = models.HeadDevice(serial_number=log.serial_number) + db.add(db_head) + db.commit() + db.refresh(db_head) + return db_head + + +def get_body_device(db: Session, body_id: int): + """ + Returns one specific body device by given id + """ + return db.query(models.BodyDevice).filter(models.BodyDevice.id == body_id).first() + + +def get_body_devices(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all body devices saved in database + """ + return db.query(models.BodyDevice).offset(skip).limit(limit).all() + + +def find_body_device(db: Session, serial: schemas.BodyDeviceBase): + """ + Finds one body device by its serial number + """ + return db.query(models.BodyDevice).filter(models.BodyDevice.serial_number == serial.serial_number).first() + + +def create_body_device(db: Session, log: schemas.BodyDeviceBase): + """ + Creates new Body device + """ + db_body = models.BodyDevice(serial_number=log.serial_number) + db.add(db_body) + db.commit() + db.refresh(db_body) + return db_body + + +def get_ld_logs(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all ld debugger logs in database + """ + return db.query(models.LDLog).offset(skip).limit(limit).all() + + +def create_ld_logs(db: Session, item: schemas.LDTempBase, head_id: int, body_id: int, pc_id: int, date: datetime): + """ + Creates new ld log for ld_logs database table + """ + db_ld = models.LDLog(pc_id=pc_id, timestamp=date, status=item.status, head_id=head_id, body_id=body_id) + db.add(db_ld) + db.commit() + db.refresh(db_ld) + return db_ld + + +def get_logs(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all usb logs in database ordered by timestamp + """ + return db.query(models.USBLog).order_by(desc(models.USBLog.timestamp)).offset(skip).limit(limit).all() + + +def get_log(db: Session, device_id: int, skip: int = 0, limit: int = 100): + """ + Returns all usb logs in database sorted by id + """ + return db.query(models.USBLog).filter(models.USBLog.device_id == device_id).offset(skip).limit(limit).all() + + +def find_filtered_logs(db: Session, logs: []): + """ + Returns all usb logs with ids in given id array. + """ + return db.query(models.USBLog).filter(models.USBLog.id.in_(logs)).order_by(desc(models.USBLog.timestamp)).all() + + +def get_filtered_logs(db: Session, pc: str, tema: str, lic: str): + """ + Function creates query string used for filtering by pc username, team name and license name. + Depending on selected filters assembles query string for database + """ + execute_string = "SELECT * FROM usb_logs AS logs" + if pc != "all": + pcs = find_pc_by_username(db, pc) + execute_string += " WHERE logs.pc_id = " + str(pcs.id) + if tema != "all": + team = find_team(db, tema) + pcs = get_pcs_by_team(db, team.id) + pc_ids = "(" + for p in pcs: + pc_ids += str(p.id) + ", " + def_pc_ids = pc_ids[:-2] + ")" + if pc != "all": + execute_string += " AND logs.pc_id IN " + def_pc_ids + else: + execute_string += " WHERE logs.pc_id IN " + def_pc_ids + if lic != "all": + license = find_license(db, lic) + device_licenses = get_license_devices(db, license.id) + dev_ids = "(" + for dev in device_licenses: + dev_ids += str(dev.device_id) + ", " + defin_ids = dev_ids[:-2] + ")" + if pc != "all" or tema != "all": + execute_string += " AND logs.device_id IN " + defin_ids + else: + execute_string += " WHERE logs.device_id IN " + defin_ids + + # executing assembled query string + result = db.execute(execute_string) + return result + + +def create_device_logs(db: Session, item: schemas.USBTempBase, dev_id: int, pc_id: int, date: datetime): + """ + Creates new USB log for usb_logs database table + """ + db_log = models.USBLog(pc_id=pc_id, timestamp=date, status=item.status, device_id=dev_id) + db.add(db_log) + db.commit() + db.refresh(db_log) + return db_log</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-functions">Functions</h2> +<dl> +<dt id="sql_app.crud.create_body_device"><code class="name flex"> +<span>def <span class="ident">create_body_device</span></span>(<span>db: sqlalchemy.orm.session.Session, log: <a title="sql_app.schemas.BodyDeviceBase" href="schemas.html#sql_app.schemas.BodyDeviceBase">BodyDeviceBase</a>)</span> +</code></dt> +<dd> +<div class="desc"><p>Creates new Body device</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_body_device(db: Session, log: schemas.BodyDeviceBase): + """ + Creates new Body device + """ + db_body = models.BodyDevice(serial_number=log.serial_number) + db.add(db_body) + db.commit() + db.refresh(db_body) + return db_body</code></pre> +</details> +</dd> +<dt id="sql_app.crud.create_device"><code class="name flex"> +<span>def <span class="ident">create_device</span></span>(<span>db: sqlalchemy.orm.session.Session, device: <a title="sql_app.schemas.DeviceBase" href="schemas.html#sql_app.schemas.DeviceBase">DeviceBase</a>)</span> +</code></dt> +<dd> +<div class="desc"><p>creates new device with data from given DeviceBase object</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_device(db: Session, device: schemas.DeviceBase): + """ + creates new device with data from given DeviceBase object + """ + db_device = models.Device(vendor_id=device.vendor_id, product_id=device.product_id, + serial_number=device.serial_number, assigned=False) + db.add(db_device) + db.commit() + db.refresh(db_device) + return db_device</code></pre> +</details> +</dd> +<dt id="sql_app.crud.create_device_license"><code class="name flex"> +<span>def <span class="ident">create_device_license</span></span>(<span>db: sqlalchemy.orm.session.Session, device: int, license: int, time: datetime.datetime)</span> +</code></dt> +<dd> +<div class="desc"><p>creates new entry in devices_licenses table with device id, license id and time.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_device_license(db: Session, device: int, license: int, time: datetime): + """ + creates new entry in devices_licenses table with device id, license id and time. + """ + db_device_license = models.DeviceLicense(device_id=device, license_id=license, + assigned_datetime=time) + db.add(db_device_license) + db.commit() + db.refresh(db_device_license) + return db_device_license</code></pre> +</details> +</dd> +<dt id="sql_app.crud.create_device_logs"><code class="name flex"> +<span>def <span class="ident">create_device_logs</span></span>(<span>db: sqlalchemy.orm.session.Session, item: <a title="sql_app.schemas.USBTempBase" href="schemas.html#sql_app.schemas.USBTempBase">USBTempBase</a>, dev_id: int, pc_id: int, date: datetime.datetime)</span> +</code></dt> +<dd> +<div class="desc"><p>Creates new USB log for usb_logs database table</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_device_logs(db: Session, item: schemas.USBTempBase, dev_id: int, pc_id: int, date: datetime): + """ + Creates new USB log for usb_logs database table + """ + db_log = models.USBLog(pc_id=pc_id, timestamp=date, status=item.status, device_id=dev_id) + db.add(db_log) + db.commit() + db.refresh(db_log) + return db_log</code></pre> +</details> +</dd> +<dt id="sql_app.crud.create_head_device"><code class="name flex"> +<span>def <span class="ident">create_head_device</span></span>(<span>db: sqlalchemy.orm.session.Session, log: <a title="sql_app.schemas.HeadDeviceBase" href="schemas.html#sql_app.schemas.HeadDeviceBase">HeadDeviceBase</a>)</span> +</code></dt> +<dd> +<div class="desc"><p>Creates new head device</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_head_device(db: Session, log: schemas.HeadDeviceBase): + """ + Creates new head device + """ + db_head = models.HeadDevice(serial_number=log.serial_number) + db.add(db_head) + db.commit() + db.refresh(db_head) + return db_head</code></pre> +</details> +</dd> +<dt id="sql_app.crud.create_ld_logs"><code class="name flex"> +<span>def <span class="ident">create_ld_logs</span></span>(<span>db: sqlalchemy.orm.session.Session, item: <a title="sql_app.schemas.LDTempBase" href="schemas.html#sql_app.schemas.LDTempBase">LDTempBase</a>, head_id: int, body_id: int, pc_id: int, date: datetime.datetime)</span> +</code></dt> +<dd> +<div class="desc"><p>Creates new ld log for ld_logs database table</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_ld_logs(db: Session, item: schemas.LDTempBase, head_id: int, body_id: int, pc_id: int, date: datetime): + """ + Creates new ld log for ld_logs database table + """ + db_ld = models.LDLog(pc_id=pc_id, timestamp=date, status=item.status, head_id=head_id, body_id=body_id) + db.add(db_ld) + db.commit() + db.refresh(db_ld) + return db_ld</code></pre> +</details> +</dd> +<dt id="sql_app.crud.create_license"><code class="name flex"> +<span>def <span class="ident">create_license</span></span>(<span>db: sqlalchemy.orm.session.Session, name: str, expdate: datetime.date)</span> +</code></dt> +<dd> +<div class="desc"><p>creates new license with given name and expiration date</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_license(db: Session, name: str, expdate: date): + """ + creates new license with given name and expiration date + """ + db_license = models.License(name=name, expiration_date=expdate) + db.add(db_license) + db.commit() + db.refresh(db_license) + return db_license</code></pre> +</details> +</dd> +<dt id="sql_app.crud.create_pc"><code class="name flex"> +<span>def <span class="ident">create_pc</span></span>(<span>db: sqlalchemy.orm.session.Session, user: str, host: str)</span> +</code></dt> +<dd> +<div class="desc"><p>creates new pc with given username and hostname</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_pc(db: Session, user: str, host: str): + """ + creates new pc with given username and hostname + """ + db_pc = models.PC(username=user, hostname=host, assigned=False) + db.add(db_pc) + db.commit() + db.refresh(db_pc) + return db_pc</code></pre> +</details> +</dd> +<dt id="sql_app.crud.create_team"><code class="name flex"> +<span>def <span class="ident">create_team</span></span>(<span>db: sqlalchemy.orm.session.Session, name: str)</span> +</code></dt> +<dd> +<div class="desc"><p>Creates new team with given name</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def create_team(db: Session, name: str): + """ + Creates new team with given name + """ + db_team = models.Team(name=name) + db.add(db_team) + db.commit() + db.refresh(db_team) + return db_team</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_body_device"><code class="name flex"> +<span>def <span class="ident">find_body_device</span></span>(<span>db: sqlalchemy.orm.session.Session, serial: <a title="sql_app.schemas.BodyDeviceBase" href="schemas.html#sql_app.schemas.BodyDeviceBase">BodyDeviceBase</a>)</span> +</code></dt> +<dd> +<div class="desc"><p>Finds one body device by its serial number</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_body_device(db: Session, serial: schemas.BodyDeviceBase): + """ + Finds one body device by its serial number + """ + return db.query(models.BodyDevice).filter(models.BodyDevice.serial_number == serial.serial_number).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_device"><code class="name flex"> +<span>def <span class="ident">find_device</span></span>(<span>db: sqlalchemy.orm.session.Session, device: <a title="sql_app.schemas.DeviceBase" href="schemas.html#sql_app.schemas.DeviceBase">DeviceBase</a>)</span> +</code></dt> +<dd> +<div class="desc"><p>finds one device with product_id, vendor_id and serial_number same as in given DeviceBase object</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_device(db: Session, device: schemas.DeviceBase): + """ + finds one device with product_id, vendor_id and serial_number same as in given DeviceBase object + """ + return db.query(models.Device).filter(and_(models.Device.product_id == device.product_id, + models.Device.vendor_id == device.vendor_id, + models.Device.serial_number == device.serial_number)).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_filtered_logs"><code class="name flex"> +<span>def <span class="ident">find_filtered_logs</span></span>(<span>db: sqlalchemy.orm.session.Session, logs: [])</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all usb logs with ids in given id array.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_filtered_logs(db: Session, logs: []): + """ + Returns all usb logs with ids in given id array. + """ + return db.query(models.USBLog).filter(models.USBLog.id.in_(logs)).order_by(desc(models.USBLog.timestamp)).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_head_device"><code class="name flex"> +<span>def <span class="ident">find_head_device</span></span>(<span>db: sqlalchemy.orm.session.Session, serial: <a title="sql_app.schemas.HeadDeviceBase" href="schemas.html#sql_app.schemas.HeadDeviceBase">HeadDeviceBase</a>)</span> +</code></dt> +<dd> +<div class="desc"><p>Finds one head device by its serial number</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_head_device(db: Session, serial: schemas.HeadDeviceBase): + """ + Finds one head device by its serial number + """ + return db.query(models.HeadDevice).filter(models.HeadDevice.serial_number == serial.serial_number).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_license"><code class="name flex"> +<span>def <span class="ident">find_license</span></span>(<span>db: sqlalchemy.orm.session.Session, name: str)</span> +</code></dt> +<dd> +<div class="desc"><p>finds one license by given string name</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_license(db: Session, name: str): + """ + finds one license by given string name + """ + return db.query(models.License).filter(models.License.name == name).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_pc"><code class="name flex"> +<span>def <span class="ident">find_pc</span></span>(<span>db: sqlalchemy.orm.session.Session, username: str, hostname: str)</span> +</code></dt> +<dd> +<div class="desc"><p>Finds one pc with given username and hostname</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_pc(db: Session, username: str, hostname: str): + """ + Finds one pc with given username and hostname + """ + return db.query(models.PC).filter(and_(models.PC.username == username, + models.PC.hostname == hostname)).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_pc_by_name"><code class="name flex"> +<span>def <span class="ident">find_pc_by_name</span></span>(<span>db: sqlalchemy.orm.session.Session, username: str)</span> +</code></dt> +<dd> +<div class="desc"><p>Finds one pc by its username</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_pc_by_name(db: Session, username: str): + """ + Finds one pc by its username + """ + return db.query(models.PC).filter(models.PC.username == username).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_pc_by_name_all"><code class="name flex"> +<span>def <span class="ident">find_pc_by_name_all</span></span>(<span>db: sqlalchemy.orm.session.Session, username: str)</span> +</code></dt> +<dd> +<div class="desc"><p>Finds all pcs with same username</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_pc_by_name_all(db: Session, username: str): + """ + Finds all pcs with same username + """ + return db.query(models.PC).filter(models.PC.username == username).offset(0).limit(100).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_pc_by_username"><code class="name flex"> +<span>def <span class="ident">find_pc_by_username</span></span>(<span>db: sqlalchemy.orm.session.Session, name: str)</span> +</code></dt> +<dd> +<div class="desc"><p>Finds one pc by given username</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_pc_by_username(db: Session, name: str): + """ + Finds one pc by given username + """ + return db.query(models.PC).filter(models.PC.username == name).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_pcs"><code class="name flex"> +<span>def <span class="ident">find_pcs</span></span>(<span>db: sqlalchemy.orm.session.Session, pcs: [])</span> +</code></dt> +<dd> +<div class="desc"><p>Finds all pcs with ids in given id array</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_pcs(db: Session, pcs: []): + """ + Finds all pcs with ids in given id array + """ + return db.query(models.PC).filter(models.PC.id.in_(pcs)).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.find_team"><code class="name flex"> +<span>def <span class="ident">find_team</span></span>(<span>db: sqlalchemy.orm.session.Session, name: str)</span> +</code></dt> +<dd> +<div class="desc"><p>Finds one specific team by its name</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def find_team(db: Session, name: str): + """ + Finds one specific team by its name + """ + return db.query(models.Team).filter(models.Team.name == name).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_body_device"><code class="name flex"> +<span>def <span class="ident">get_body_device</span></span>(<span>db: sqlalchemy.orm.session.Session, body_id: int)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns one specific body device by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_body_device(db: Session, body_id: int): + """ + Returns one specific body device by given id + """ + return db.query(models.BodyDevice).filter(models.BodyDevice.id == body_id).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_body_devices"><code class="name flex"> +<span>def <span class="ident">get_body_devices</span></span>(<span>db: sqlalchemy.orm.session.Session, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all body devices saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_body_devices(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all body devices saved in database + """ + return db.query(models.BodyDevice).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_device"><code class="name flex"> +<span>def <span class="ident">get_device</span></span>(<span>db: sqlalchemy.orm.session.Session, device_id: int)</span> +</code></dt> +<dd> +<div class="desc"><p>returns one specific devices by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_device(db: Session, device_id: int): + """ + returns one specific devices by given id + """ + return db.query(models.Device).filter(models.Device.id == device_id).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_devices"><code class="name flex"> +<span>def <span class="ident">get_devices</span></span>(<span>db: sqlalchemy.orm.session.Session, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>returns all devices in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_devices(db: Session, skip: int = 0, limit: int = 100): + """ + returns all devices in database + """ + return db.query(models.Device).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_filtered_logs"><code class="name flex"> +<span>def <span class="ident">get_filtered_logs</span></span>(<span>db: sqlalchemy.orm.session.Session, pc: str, tema: str, lic: str)</span> +</code></dt> +<dd> +<div class="desc"><p>Function creates query string used for filtering by pc username, team name and license name. +Depending on selected filters assembles query string for database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_filtered_logs(db: Session, pc: str, tema: str, lic: str): + """ + Function creates query string used for filtering by pc username, team name and license name. + Depending on selected filters assembles query string for database + """ + execute_string = "SELECT * FROM usb_logs AS logs" + if pc != "all": + pcs = find_pc_by_username(db, pc) + execute_string += " WHERE logs.pc_id = " + str(pcs.id) + if tema != "all": + team = find_team(db, tema) + pcs = get_pcs_by_team(db, team.id) + pc_ids = "(" + for p in pcs: + pc_ids += str(p.id) + ", " + def_pc_ids = pc_ids[:-2] + ")" + if pc != "all": + execute_string += " AND logs.pc_id IN " + def_pc_ids + else: + execute_string += " WHERE logs.pc_id IN " + def_pc_ids + if lic != "all": + license = find_license(db, lic) + device_licenses = get_license_devices(db, license.id) + dev_ids = "(" + for dev in device_licenses: + dev_ids += str(dev.device_id) + ", " + defin_ids = dev_ids[:-2] + ")" + if pc != "all" or tema != "all": + execute_string += " AND logs.device_id IN " + defin_ids + else: + execute_string += " WHERE logs.device_id IN " + defin_ids + + # executing assembled query string + result = db.execute(execute_string) + return result</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_head_device"><code class="name flex"> +<span>def <span class="ident">get_head_device</span></span>(<span>db: sqlalchemy.orm.session.Session, head_id: int)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns one specific head device by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_head_device(db: Session, head_id: int): + """ + Returns one specific head device by given id + """ + return db.query(models.HeadDevice).filter(models.HeadDevice.id == head_id).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_head_devices"><code class="name flex"> +<span>def <span class="ident">get_head_devices</span></span>(<span>db: sqlalchemy.orm.session.Session, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all head devices saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_head_devices(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all head devices saved in database + """ + return db.query(models.HeadDevice).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_ld_logs"><code class="name flex"> +<span>def <span class="ident">get_ld_logs</span></span>(<span>db: sqlalchemy.orm.session.Session, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all ld debugger logs in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_ld_logs(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all ld debugger logs in database + """ + return db.query(models.LDLog).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_license"><code class="name flex"> +<span>def <span class="ident">get_license</span></span>(<span>db: sqlalchemy.orm.session.Session, license_id: int)</span> +</code></dt> +<dd> +<div class="desc"><p>returns one specific license by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_license(db: Session, license_id: int): + """ + returns one specific license by given id + """ + return db.query(models.License).filter(models.License.id == license_id).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_license_devices"><code class="name flex"> +<span>def <span class="ident">get_license_devices</span></span>(<span>db: sqlalchemy.orm.session.Session, license_id: int)</span> +</code></dt> +<dd> +<div class="desc"><p>returns all entries in devices_licenses table</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_license_devices(db: Session, license_id: int): + """ + returns all entries in devices_licenses table + """ + return db.query(models.DeviceLicense).filter(models.DeviceLicense.license_id == license_id).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_licenses"><code class="name flex"> +<span>def <span class="ident">get_licenses</span></span>(<span>db: sqlalchemy.orm.session.Session, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>returns all licenses in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_licenses(db: Session, skip: int = 0, limit: int = 100): + """ + returns all licenses in database + """ + return db.query(models.License).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_log"><code class="name flex"> +<span>def <span class="ident">get_log</span></span>(<span>db: sqlalchemy.orm.session.Session, device_id: int, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all usb logs in database sorted by id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_log(db: Session, device_id: int, skip: int = 0, limit: int = 100): + """ + Returns all usb logs in database sorted by id + """ + return db.query(models.USBLog).filter(models.USBLog.device_id == device_id).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_logs"><code class="name flex"> +<span>def <span class="ident">get_logs</span></span>(<span>db: sqlalchemy.orm.session.Session, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>Returns all usb logs in database ordered by timestamp</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_logs(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all usb logs in database ordered by timestamp + """ + return db.query(models.USBLog).order_by(desc(models.USBLog.timestamp)).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_pc"><code class="name flex"> +<span>def <span class="ident">get_pc</span></span>(<span>db: sqlalchemy.orm.session.Session, pc_id: int)</span> +</code></dt> +<dd> +<div class="desc"><p>returns one specific pc by given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_pc(db: Session, pc_id: int): + """ + returns one specific pc by given id + """ + return db.query(models.PC).filter(models.PC.id == pc_id).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_pcs"><code class="name flex"> +<span>def <span class="ident">get_pcs</span></span>(<span>db: sqlalchemy.orm.session.Session, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>returns all pcs in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_pcs(db: Session, skip: int = 0, limit: int = 100): + """ + returns all pcs in database + """ + return db.query(models.PC).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_pcs_by_team"><code class="name flex"> +<span>def <span class="ident">get_pcs_by_team</span></span>(<span>db: sqlalchemy.orm.session.Session, team_id: int)</span> +</code></dt> +<dd> +<div class="desc"><p>returns all pcs in given team by team id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_pcs_by_team(db: Session, team_id: int): + """ + returns all pcs in given team by team id + """ + return db.query(models.PC).filter(models.PC.team_id == team_id).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_team"><code class="name flex"> +<span>def <span class="ident">get_team</span></span>(<span>db: sqlalchemy.orm.session.Session, team_id: int)</span> +</code></dt> +<dd> +<div class="desc"><p>returns one specific team wit given id</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_team(db: Session, team_id: int): + """ + returns one specific team wit given id + """ + return db.query(models.Team).filter(models.Team.id == team_id).first()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.get_teams"><code class="name flex"> +<span>def <span class="ident">get_teams</span></span>(<span>db: sqlalchemy.orm.session.Session, skip: int = 0, limit: int = 100)</span> +</code></dt> +<dd> +<div class="desc"><p>returns all teams currently saved in database</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def get_teams(db: Session, skip: int = 0, limit: int = 100): + """ + returns all teams currently saved in database + """ + return db.query(models.Team).offset(skip).limit(limit).all()</code></pre> +</details> +</dd> +<dt id="sql_app.crud.update_pc"><code class="name flex"> +<span>def <span class="ident">update_pc</span></span>(<span>db: sqlalchemy.orm.session.Session, pc_id: int, team: str)</span> +</code></dt> +<dd> +<div class="desc"><p>Function updates team of one specific pc</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def update_pc(db: Session, pc_id: int, team: str): + """ + Function updates team of one specific pc + """ + old_pc = get_pc(db, pc_id) + team = get_team(db, int(team)) + new = {'id': old_pc.id, 'username': old_pc.username, 'hostname': old_pc.hostname, 'assigned': True, + 'team_id': team.id} + for key, value in new.items(): + setattr(old_pc, key, value) + db.commit() + db.refresh(old_pc) + return old_pc</code></pre> +</details> +</dd> +</dl> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app" href="index.html">sql_app</a></code></li> +</ul> +</li> +<li><h3><a href="#header-functions">Functions</a></h3> +<ul class=""> +<li><code><a title="sql_app.crud.create_body_device" href="#sql_app.crud.create_body_device">create_body_device</a></code></li> +<li><code><a title="sql_app.crud.create_device" href="#sql_app.crud.create_device">create_device</a></code></li> +<li><code><a title="sql_app.crud.create_device_license" href="#sql_app.crud.create_device_license">create_device_license</a></code></li> +<li><code><a title="sql_app.crud.create_device_logs" href="#sql_app.crud.create_device_logs">create_device_logs</a></code></li> +<li><code><a title="sql_app.crud.create_head_device" href="#sql_app.crud.create_head_device">create_head_device</a></code></li> +<li><code><a title="sql_app.crud.create_ld_logs" href="#sql_app.crud.create_ld_logs">create_ld_logs</a></code></li> +<li><code><a title="sql_app.crud.create_license" href="#sql_app.crud.create_license">create_license</a></code></li> +<li><code><a title="sql_app.crud.create_pc" href="#sql_app.crud.create_pc">create_pc</a></code></li> +<li><code><a title="sql_app.crud.create_team" href="#sql_app.crud.create_team">create_team</a></code></li> +<li><code><a title="sql_app.crud.find_body_device" href="#sql_app.crud.find_body_device">find_body_device</a></code></li> +<li><code><a title="sql_app.crud.find_device" href="#sql_app.crud.find_device">find_device</a></code></li> +<li><code><a title="sql_app.crud.find_filtered_logs" href="#sql_app.crud.find_filtered_logs">find_filtered_logs</a></code></li> +<li><code><a title="sql_app.crud.find_head_device" href="#sql_app.crud.find_head_device">find_head_device</a></code></li> +<li><code><a title="sql_app.crud.find_license" href="#sql_app.crud.find_license">find_license</a></code></li> +<li><code><a title="sql_app.crud.find_pc" href="#sql_app.crud.find_pc">find_pc</a></code></li> +<li><code><a title="sql_app.crud.find_pc_by_name" href="#sql_app.crud.find_pc_by_name">find_pc_by_name</a></code></li> +<li><code><a title="sql_app.crud.find_pc_by_name_all" href="#sql_app.crud.find_pc_by_name_all">find_pc_by_name_all</a></code></li> +<li><code><a title="sql_app.crud.find_pc_by_username" href="#sql_app.crud.find_pc_by_username">find_pc_by_username</a></code></li> +<li><code><a title="sql_app.crud.find_pcs" href="#sql_app.crud.find_pcs">find_pcs</a></code></li> +<li><code><a title="sql_app.crud.find_team" href="#sql_app.crud.find_team">find_team</a></code></li> +<li><code><a title="sql_app.crud.get_body_device" href="#sql_app.crud.get_body_device">get_body_device</a></code></li> +<li><code><a title="sql_app.crud.get_body_devices" href="#sql_app.crud.get_body_devices">get_body_devices</a></code></li> +<li><code><a title="sql_app.crud.get_device" href="#sql_app.crud.get_device">get_device</a></code></li> +<li><code><a title="sql_app.crud.get_devices" href="#sql_app.crud.get_devices">get_devices</a></code></li> +<li><code><a title="sql_app.crud.get_filtered_logs" href="#sql_app.crud.get_filtered_logs">get_filtered_logs</a></code></li> +<li><code><a title="sql_app.crud.get_head_device" href="#sql_app.crud.get_head_device">get_head_device</a></code></li> +<li><code><a title="sql_app.crud.get_head_devices" href="#sql_app.crud.get_head_devices">get_head_devices</a></code></li> +<li><code><a title="sql_app.crud.get_ld_logs" href="#sql_app.crud.get_ld_logs">get_ld_logs</a></code></li> +<li><code><a title="sql_app.crud.get_license" href="#sql_app.crud.get_license">get_license</a></code></li> +<li><code><a title="sql_app.crud.get_license_devices" href="#sql_app.crud.get_license_devices">get_license_devices</a></code></li> +<li><code><a title="sql_app.crud.get_licenses" href="#sql_app.crud.get_licenses">get_licenses</a></code></li> +<li><code><a title="sql_app.crud.get_log" href="#sql_app.crud.get_log">get_log</a></code></li> +<li><code><a title="sql_app.crud.get_logs" href="#sql_app.crud.get_logs">get_logs</a></code></li> +<li><code><a title="sql_app.crud.get_pc" href="#sql_app.crud.get_pc">get_pc</a></code></li> +<li><code><a title="sql_app.crud.get_pcs" href="#sql_app.crud.get_pcs">get_pcs</a></code></li> +<li><code><a title="sql_app.crud.get_pcs_by_team" href="#sql_app.crud.get_pcs_by_team">get_pcs_by_team</a></code></li> +<li><code><a title="sql_app.crud.get_team" href="#sql_app.crud.get_team">get_team</a></code></li> +<li><code><a title="sql_app.crud.get_teams" href="#sql_app.crud.get_teams">get_teams</a></code></li> +<li><code><a title="sql_app.crud.update_pc" href="#sql_app.crud.update_pc">update_pc</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/database.html b/server/doc/sql_app/database.html new file mode 100644 index 0000000..fc8a9c7 --- /dev/null +++ b/server/doc/sql_app/database.html @@ -0,0 +1,100 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.database API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.database</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + + + +# used mainly for testing purposes. Creates local sqllite data file +SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db" +engine = create_engine( + SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} +) +''' + +# Defining connection url with postgresql database +SQLALCHEMY_DATABASE_URL = "postgresql://postgres:postgres@10.5.0.5:5432/usb_api_db" + +# Creating engine for database communication +engine = create_engine( + SQLALCHEMY_DATABASE_URL +) +''' +# Session maker for data transmissions +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +Base = declarative_base()</code></pre> +</details> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-variables">Global variables</h2> +<dl> +<dt id="sql_app.database.engine"><code class="name">var <span class="ident">engine</span></code></dt> +<dd> +<div class="desc"><h1 id="defining-connection-url-with-postgresql-database">Defining connection url with postgresql database</h1> +<p>SQLALCHEMY_DATABASE_URL = "postgresql://postgres:postgres@10.5.0.5:5432/usb_api_db"</p> +<h1 id="creating-engine-for-database-communication">Creating engine for database communication</h1> +<p>engine = create_engine( +SQLALCHEMY_DATABASE_URL +)</p></div> +</dd> +</dl> +</section> +<section> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app" href="index.html">sql_app</a></code></li> +</ul> +</li> +<li><h3><a href="#header-variables">Global variables</a></h3> +<ul class=""> +<li><code><a title="sql_app.database.engine" href="#sql_app.database.engine">engine</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/documentation.html b/server/doc/sql_app/documentation.html new file mode 100644 index 0000000..3807832 --- /dev/null +++ b/server/doc/sql_app/documentation.html @@ -0,0 +1,85 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Package <code>sql_app</code></h1> +</header> +<section id="section-intro"> +</section> +<section> +<h2 class="section-title" id="header-submodules">Sub-modules</h2> +<dl> +<dt><code class="name"><a title="sql_app.api" href="api/index.html">sql_app.api</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.crud" href="crud.html">sql_app.crud</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.database" href="database.html">sql_app.database</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.main" href="main.html">sql_app.main</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.models" href="models.html">sql_app.models</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt><code class="name"><a title="sql_app.schemas" href="schemas.html">sql_app.schemas</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</section> +<section> +</section> +<section> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3><a href="#header-submodules">Sub-modules</a></h3> +<ul> +<li><code><a title="sql_app.api" href="api/index.html">sql_app.api</a></code></li> +<li><code><a title="sql_app.crud" href="crud.html">sql_app.crud</a></code></li> +<li><code><a title="sql_app.database" href="database.html">sql_app.database</a></code></li> +<li><code><a title="sql_app.main" href="main.html">sql_app.main</a></code></li> +<li><code><a title="sql_app.models" href="models.html">sql_app.models</a></code></li> +<li><code><a title="sql_app.schemas" href="schemas.html">sql_app.schemas</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/main.html b/server/doc/sql_app/main.html new file mode 100644 index 0000000..fabf34b --- /dev/null +++ b/server/doc/sql_app/main.html @@ -0,0 +1,91 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.main API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.main</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">import uvicorn +from sql_app.api.devices import device +from sql_app.api.devices_web import device_web +from sql_app.api.licenses import licenses +from sql_app.api.licenses_web import licenses_web +from sql_app.api.pcs import pcs +from sql_app.api.pcs_web import pcs_web +from sql_app.api.usb_logs import usblogs +from sql_app.api.usb_logs_web import usblogs_web +from sql_app.api.teams import teams +from sql_app.api.teams_web import teams_web +from fastapi import FastAPI + + +app = FastAPI() + +# including routers for endpoints used by clients +app.include_router(device) +app.include_router(licenses) +app.include_router(pcs) +app.include_router(usblogs) +app.include_router(teams) + +# including routers for endpoints called from web +app.include_router(device_web) +app.include_router(licenses_web) +app.include_router(pcs_web) +app.include_router(teams_web) +app.include_router(usblogs_web) + + +if __name__ == "__main__": + uvicorn.run(app, host="192.168.0.22", port=8000)</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +</section> +<section> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app" href="index.html">sql_app</a></code></li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/models.html b/server/doc/sql_app/models.html new file mode 100644 index 0000000..6cc705a --- /dev/null +++ b/server/doc/sql_app/models.html @@ -0,0 +1,1911 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.models API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.models</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, DateTime +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func +from .database import Base + + +class Device(Base): + """ + Class defining database table devices + """ + __tablename__ = "devices" + + id = Column(Integer, primary_key=True, index=True) + vendor_id = Column(String, index=True, nullable=False) + product_id = Column(String, index=True, nullable=False) + serial_number = Column(String, index=True, nullable=False) + assigned = Column(Boolean, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with usb_logs and licenses + # tables + logs = relationship("USBLog", back_populates="device") + licenses = relationship("DeviceLicense", back_populates="device_lic") + + +class USBLog(Base): + """ + Class defining database table usb_logs + """ + __tablename__ = "usb_logs" + + id = Column(Integer, primary_key=True, index=True) + pc_id = Column(Integer, ForeignKey("pc.id")) + timestamp = Column(DateTime(timezone=True), server_default=func.now()) + status = Column(String, index=True, nullable=False) + device_id = Column(Integer, ForeignKey("devices.id")) + + # relationships for foreign keys, thus connecting table with devices and pc + # tables + device = relationship("Device", back_populates="logs") + pc = relationship("PC", back_populates="logs_pc") + + +class License(Base): + """ + Class defining database table licenses + """ + __tablename__ = "licenses" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, index=True, nullable=False) + expiration_date = Column(DateTime(timezone=True), server_default=func.now()) + + # relationships for foreign keys, thus connecting table with devices table + devices = relationship("DeviceLicense", back_populates="licenses") + + +class DeviceLicense(Base): + """ + Class defining database table devices_licenses + """ + __tablename__ = "devices_licenses" + + id = Column(Integer, primary_key=True, index=True) + device_id = Column(Integer, ForeignKey("devices.id")) + license_id = Column(Integer, ForeignKey("licenses.id")) + assigned_datetime = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with devices and licenses + # tables + device_lic = relationship("Device", back_populates="licenses") + licenses = relationship("License", back_populates="devices") + + +class PC(Base): + """ + Class defining database table pc + """ + __tablename__ = "pc" + + id = Column(Integer, primary_key=True, index=True) + username = Column(String, index=True, nullable=False) + hostname = Column(String, index=True, nullable=False) + assigned = Column(Boolean, index=True, nullable=False) + team_id = Column(Integer, ForeignKey("teams.id")) + + # relationships for foreign keys, thus connecting table with teams, usb_logs and ld_logs + # tables + team = relationship("Team", back_populates="pcs") + logs_pc = relationship("USBLog", back_populates="pc") + ld_pc = relationship("LDLog", back_populates="ldpc") + + +class Team(Base): + """ + Class defining database table teams + """ + __tablename__ = "teams" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with pc table + pcs = relationship("PC", back_populates="team") + + +class HeadDevice(Base): + """ + Class defining database table head_devices + """ + __tablename__ = "head_devices" + + id = Column(Integer, primary_key=True, index=True) + serial_number = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with ld_logs table + h_logs = relationship("LDLog", back_populates="head_device") + + +class BodyDevice(Base): + """ + Class defining database table body_devices + """ + __tablename__ = "body_devices" + + id = Column(Integer, primary_key=True, index=True) + serial_number = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with ld_logs table + b_logs = relationship("LDLog", back_populates="body_device") + + +class LDLog(Base): + """ + Class defining database table ld_logs + """ + __tablename__ = "ld_logs" + + id = Column(Integer, primary_key=True, index=True) + pc_id = Column(Integer, ForeignKey("pc.id")) + timestamp = Column(DateTime(timezone=True), server_default=func.now()) + status = Column(String, index=True, nullable=False) + head_id = Column(Integer, ForeignKey("head_devices.id")) + body_id = Column(Integer, ForeignKey("body_devices.id")) + + # relationships for foreign keys, thus connecting table with pc, head_devices and body_devices + # tables + ldpc = relationship("PC", back_populates="ld_pc") + head_device = relationship("HeadDevice", back_populates="h_logs") + body_device = relationship("BodyDevice", back_populates="b_logs")</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-classes">Classes</h2> +<dl> +<dt id="sql_app.models.BodyDevice"><code class="flex name class"> +<span>class <span class="ident">BodyDevice</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table body_devices</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class BodyDevice(Base): + """ + Class defining database table body_devices + """ + __tablename__ = "body_devices" + + id = Column(Integer, primary_key=True, index=True) + serial_number = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with ld_logs table + b_logs = relationship("LDLog", back_populates="body_device")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.BodyDevice.b_logs"><code class="name">var <span class="ident">b_logs</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.BodyDevice.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.BodyDevice.serial_number"><code class="name">var <span class="ident">serial_number</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +<dt id="sql_app.models.Device"><code class="flex name class"> +<span>class <span class="ident">Device</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table devices</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class Device(Base): + """ + Class defining database table devices + """ + __tablename__ = "devices" + + id = Column(Integer, primary_key=True, index=True) + vendor_id = Column(String, index=True, nullable=False) + product_id = Column(String, index=True, nullable=False) + serial_number = Column(String, index=True, nullable=False) + assigned = Column(Boolean, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with usb_logs and licenses + # tables + logs = relationship("USBLog", back_populates="device") + licenses = relationship("DeviceLicense", back_populates="device_lic")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.Device.assigned"><code class="name">var <span class="ident">assigned</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.Device.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.Device.licenses"><code class="name">var <span class="ident">licenses</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.Device.logs"><code class="name">var <span class="ident">logs</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.Device.product_id"><code class="name">var <span class="ident">product_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.Device.serial_number"><code class="name">var <span class="ident">serial_number</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.Device.vendor_id"><code class="name">var <span class="ident">vendor_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +<dt id="sql_app.models.DeviceLicense"><code class="flex name class"> +<span>class <span class="ident">DeviceLicense</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table devices_licenses</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class DeviceLicense(Base): + """ + Class defining database table devices_licenses + """ + __tablename__ = "devices_licenses" + + id = Column(Integer, primary_key=True, index=True) + device_id = Column(Integer, ForeignKey("devices.id")) + license_id = Column(Integer, ForeignKey("licenses.id")) + assigned_datetime = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with devices and licenses + # tables + device_lic = relationship("Device", back_populates="licenses") + licenses = relationship("License", back_populates="devices")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.DeviceLicense.assigned_datetime"><code class="name">var <span class="ident">assigned_datetime</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.DeviceLicense.device_id"><code class="name">var <span class="ident">device_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.DeviceLicense.device_lic"><code class="name">var <span class="ident">device_lic</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.DeviceLicense.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.DeviceLicense.license_id"><code class="name">var <span class="ident">license_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.DeviceLicense.licenses"><code class="name">var <span class="ident">licenses</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +<dt id="sql_app.models.HeadDevice"><code class="flex name class"> +<span>class <span class="ident">HeadDevice</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table head_devices</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class HeadDevice(Base): + """ + Class defining database table head_devices + """ + __tablename__ = "head_devices" + + id = Column(Integer, primary_key=True, index=True) + serial_number = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with ld_logs table + h_logs = relationship("LDLog", back_populates="head_device")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.HeadDevice.h_logs"><code class="name">var <span class="ident">h_logs</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.HeadDevice.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.HeadDevice.serial_number"><code class="name">var <span class="ident">serial_number</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +<dt id="sql_app.models.LDLog"><code class="flex name class"> +<span>class <span class="ident">LDLog</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table ld_logs</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LDLog(Base): + """ + Class defining database table ld_logs + """ + __tablename__ = "ld_logs" + + id = Column(Integer, primary_key=True, index=True) + pc_id = Column(Integer, ForeignKey("pc.id")) + timestamp = Column(DateTime(timezone=True), server_default=func.now()) + status = Column(String, index=True, nullable=False) + head_id = Column(Integer, ForeignKey("head_devices.id")) + body_id = Column(Integer, ForeignKey("body_devices.id")) + + # relationships for foreign keys, thus connecting table with pc, head_devices and body_devices + # tables + ldpc = relationship("PC", back_populates="ld_pc") + head_device = relationship("HeadDevice", back_populates="h_logs") + body_device = relationship("BodyDevice", back_populates="b_logs")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.LDLog.body_device"><code class="name">var <span class="ident">body_device</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.LDLog.body_id"><code class="name">var <span class="ident">body_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.LDLog.head_device"><code class="name">var <span class="ident">head_device</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.LDLog.head_id"><code class="name">var <span class="ident">head_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.LDLog.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.LDLog.ldpc"><code class="name">var <span class="ident">ldpc</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.LDLog.pc_id"><code class="name">var <span class="ident">pc_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.LDLog.status"><code class="name">var <span class="ident">status</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.LDLog.timestamp"><code class="name">var <span class="ident">timestamp</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +<dt id="sql_app.models.License"><code class="flex name class"> +<span>class <span class="ident">License</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table licenses</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class License(Base): + """ + Class defining database table licenses + """ + __tablename__ = "licenses" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, index=True, nullable=False) + expiration_date = Column(DateTime(timezone=True), server_default=func.now()) + + # relationships for foreign keys, thus connecting table with devices table + devices = relationship("DeviceLicense", back_populates="licenses")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.License.devices"><code class="name">var <span class="ident">devices</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.License.expiration_date"><code class="name">var <span class="ident">expiration_date</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.License.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.License.name"><code class="name">var <span class="ident">name</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +<dt id="sql_app.models.PC"><code class="flex name class"> +<span>class <span class="ident">PC</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table pc</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class PC(Base): + """ + Class defining database table pc + """ + __tablename__ = "pc" + + id = Column(Integer, primary_key=True, index=True) + username = Column(String, index=True, nullable=False) + hostname = Column(String, index=True, nullable=False) + assigned = Column(Boolean, index=True, nullable=False) + team_id = Column(Integer, ForeignKey("teams.id")) + + # relationships for foreign keys, thus connecting table with teams, usb_logs and ld_logs + # tables + team = relationship("Team", back_populates="pcs") + logs_pc = relationship("USBLog", back_populates="pc") + ld_pc = relationship("LDLog", back_populates="ldpc")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.PC.assigned"><code class="name">var <span class="ident">assigned</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.PC.hostname"><code class="name">var <span class="ident">hostname</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.PC.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.PC.ld_pc"><code class="name">var <span class="ident">ld_pc</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.PC.logs_pc"><code class="name">var <span class="ident">logs_pc</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.PC.team"><code class="name">var <span class="ident">team</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.PC.team_id"><code class="name">var <span class="ident">team_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.PC.username"><code class="name">var <span class="ident">username</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +<dt id="sql_app.models.Team"><code class="flex name class"> +<span>class <span class="ident">Team</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table teams</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class Team(Base): + """ + Class defining database table teams + """ + __tablename__ = "teams" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with pc table + pcs = relationship("PC", back_populates="team")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.Team.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.Team.name"><code class="name">var <span class="ident">name</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.Team.pcs"><code class="name">var <span class="ident">pcs</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +<dt id="sql_app.models.USBLog"><code class="flex name class"> +<span>class <span class="ident">USBLog</span></span> +<span>(</span><span>**kwargs)</span> +</code></dt> +<dd> +<div class="desc"><p>Class defining database table usb_logs</p> +<p>A simple constructor that allows initialization from kwargs.</p> +<p>Sets attributes on the constructed instance using the names and +values in <code>kwargs</code>.</p> +<p>Only keys that are present as +attributes of the instance's class are allowed. These could be, +for example, any mapped columns or relationships.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class USBLog(Base): + """ + Class defining database table usb_logs + """ + __tablename__ = "usb_logs" + + id = Column(Integer, primary_key=True, index=True) + pc_id = Column(Integer, ForeignKey("pc.id")) + timestamp = Column(DateTime(timezone=True), server_default=func.now()) + status = Column(String, index=True, nullable=False) + device_id = Column(Integer, ForeignKey("devices.id")) + + # relationships for foreign keys, thus connecting table with devices and pc + # tables + device = relationship("Device", back_populates="logs") + pc = relationship("PC", back_populates="logs_pc")</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>sqlalchemy.orm.decl_api.Base</li> +</ul> +<h3>Instance variables</h3> +<dl> +<dt id="sql_app.models.USBLog.device"><code class="name">var <span class="ident">device</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.USBLog.device_id"><code class="name">var <span class="ident">device_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.USBLog.id"><code class="name">var <span class="ident">id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.USBLog.pc"><code class="name">var <span class="ident">pc</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.USBLog.pc_id"><code class="name">var <span class="ident">pc_id</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.USBLog.status"><code class="name">var <span class="ident">status</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +<dt id="sql_app.models.USBLog.timestamp"><code class="name">var <span class="ident">timestamp</span></code></dt> +<dd> +<div class="desc"></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">def __get__(self, instance, owner): + if instance is None: + return self + + dict_ = instance_dict(instance) + if self._supports_population and self.key in dict_: + return dict_[self.key] + else: + try: + state = instance_state(instance) + except AttributeError as err: + util.raise_( + orm_exc.UnmappedInstanceError(instance), + replace_context=err, + ) + return self.impl.get(state, dict_)</code></pre> +</details> +</dd> +</dl> +</dd> +</dl> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app" href="index.html">sql_app</a></code></li> +</ul> +</li> +<li><h3><a href="#header-classes">Classes</a></h3> +<ul> +<li> +<h4><code><a title="sql_app.models.BodyDevice" href="#sql_app.models.BodyDevice">BodyDevice</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.models.BodyDevice.b_logs" href="#sql_app.models.BodyDevice.b_logs">b_logs</a></code></li> +<li><code><a title="sql_app.models.BodyDevice.id" href="#sql_app.models.BodyDevice.id">id</a></code></li> +<li><code><a title="sql_app.models.BodyDevice.serial_number" href="#sql_app.models.BodyDevice.serial_number">serial_number</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.models.Device" href="#sql_app.models.Device">Device</a></code></h4> +<ul class="two-column"> +<li><code><a title="sql_app.models.Device.assigned" href="#sql_app.models.Device.assigned">assigned</a></code></li> +<li><code><a title="sql_app.models.Device.id" href="#sql_app.models.Device.id">id</a></code></li> +<li><code><a title="sql_app.models.Device.licenses" href="#sql_app.models.Device.licenses">licenses</a></code></li> +<li><code><a title="sql_app.models.Device.logs" href="#sql_app.models.Device.logs">logs</a></code></li> +<li><code><a title="sql_app.models.Device.product_id" href="#sql_app.models.Device.product_id">product_id</a></code></li> +<li><code><a title="sql_app.models.Device.serial_number" href="#sql_app.models.Device.serial_number">serial_number</a></code></li> +<li><code><a title="sql_app.models.Device.vendor_id" href="#sql_app.models.Device.vendor_id">vendor_id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.models.DeviceLicense" href="#sql_app.models.DeviceLicense">DeviceLicense</a></code></h4> +<ul class="two-column"> +<li><code><a title="sql_app.models.DeviceLicense.assigned_datetime" href="#sql_app.models.DeviceLicense.assigned_datetime">assigned_datetime</a></code></li> +<li><code><a title="sql_app.models.DeviceLicense.device_id" href="#sql_app.models.DeviceLicense.device_id">device_id</a></code></li> +<li><code><a title="sql_app.models.DeviceLicense.device_lic" href="#sql_app.models.DeviceLicense.device_lic">device_lic</a></code></li> +<li><code><a title="sql_app.models.DeviceLicense.id" href="#sql_app.models.DeviceLicense.id">id</a></code></li> +<li><code><a title="sql_app.models.DeviceLicense.license_id" href="#sql_app.models.DeviceLicense.license_id">license_id</a></code></li> +<li><code><a title="sql_app.models.DeviceLicense.licenses" href="#sql_app.models.DeviceLicense.licenses">licenses</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.models.HeadDevice" href="#sql_app.models.HeadDevice">HeadDevice</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.models.HeadDevice.h_logs" href="#sql_app.models.HeadDevice.h_logs">h_logs</a></code></li> +<li><code><a title="sql_app.models.HeadDevice.id" href="#sql_app.models.HeadDevice.id">id</a></code></li> +<li><code><a title="sql_app.models.HeadDevice.serial_number" href="#sql_app.models.HeadDevice.serial_number">serial_number</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.models.LDLog" href="#sql_app.models.LDLog">LDLog</a></code></h4> +<ul class="two-column"> +<li><code><a title="sql_app.models.LDLog.body_device" href="#sql_app.models.LDLog.body_device">body_device</a></code></li> +<li><code><a title="sql_app.models.LDLog.body_id" href="#sql_app.models.LDLog.body_id">body_id</a></code></li> +<li><code><a title="sql_app.models.LDLog.head_device" href="#sql_app.models.LDLog.head_device">head_device</a></code></li> +<li><code><a title="sql_app.models.LDLog.head_id" href="#sql_app.models.LDLog.head_id">head_id</a></code></li> +<li><code><a title="sql_app.models.LDLog.id" href="#sql_app.models.LDLog.id">id</a></code></li> +<li><code><a title="sql_app.models.LDLog.ldpc" href="#sql_app.models.LDLog.ldpc">ldpc</a></code></li> +<li><code><a title="sql_app.models.LDLog.pc_id" href="#sql_app.models.LDLog.pc_id">pc_id</a></code></li> +<li><code><a title="sql_app.models.LDLog.status" href="#sql_app.models.LDLog.status">status</a></code></li> +<li><code><a title="sql_app.models.LDLog.timestamp" href="#sql_app.models.LDLog.timestamp">timestamp</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.models.License" href="#sql_app.models.License">License</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.models.License.devices" href="#sql_app.models.License.devices">devices</a></code></li> +<li><code><a title="sql_app.models.License.expiration_date" href="#sql_app.models.License.expiration_date">expiration_date</a></code></li> +<li><code><a title="sql_app.models.License.id" href="#sql_app.models.License.id">id</a></code></li> +<li><code><a title="sql_app.models.License.name" href="#sql_app.models.License.name">name</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.models.PC" href="#sql_app.models.PC">PC</a></code></h4> +<ul class="two-column"> +<li><code><a title="sql_app.models.PC.assigned" href="#sql_app.models.PC.assigned">assigned</a></code></li> +<li><code><a title="sql_app.models.PC.hostname" href="#sql_app.models.PC.hostname">hostname</a></code></li> +<li><code><a title="sql_app.models.PC.id" href="#sql_app.models.PC.id">id</a></code></li> +<li><code><a title="sql_app.models.PC.ld_pc" href="#sql_app.models.PC.ld_pc">ld_pc</a></code></li> +<li><code><a title="sql_app.models.PC.logs_pc" href="#sql_app.models.PC.logs_pc">logs_pc</a></code></li> +<li><code><a title="sql_app.models.PC.team" href="#sql_app.models.PC.team">team</a></code></li> +<li><code><a title="sql_app.models.PC.team_id" href="#sql_app.models.PC.team_id">team_id</a></code></li> +<li><code><a title="sql_app.models.PC.username" href="#sql_app.models.PC.username">username</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.models.Team" href="#sql_app.models.Team">Team</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.models.Team.id" href="#sql_app.models.Team.id">id</a></code></li> +<li><code><a title="sql_app.models.Team.name" href="#sql_app.models.Team.name">name</a></code></li> +<li><code><a title="sql_app.models.Team.pcs" href="#sql_app.models.Team.pcs">pcs</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.models.USBLog" href="#sql_app.models.USBLog">USBLog</a></code></h4> +<ul class="two-column"> +<li><code><a title="sql_app.models.USBLog.device" href="#sql_app.models.USBLog.device">device</a></code></li> +<li><code><a title="sql_app.models.USBLog.device_id" href="#sql_app.models.USBLog.device_id">device_id</a></code></li> +<li><code><a title="sql_app.models.USBLog.id" href="#sql_app.models.USBLog.id">id</a></code></li> +<li><code><a title="sql_app.models.USBLog.pc" href="#sql_app.models.USBLog.pc">pc</a></code></li> +<li><code><a title="sql_app.models.USBLog.pc_id" href="#sql_app.models.USBLog.pc_id">pc_id</a></code></li> +<li><code><a title="sql_app.models.USBLog.status" href="#sql_app.models.USBLog.status">status</a></code></li> +<li><code><a title="sql_app.models.USBLog.timestamp" href="#sql_app.models.USBLog.timestamp">timestamp</a></code></li> +</ul> +</li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/doc/sql_app/schemas.html b/server/doc/sql_app/schemas.html new file mode 100644 index 0000000..ffeb06a --- /dev/null +++ b/server/doc/sql_app/schemas.html @@ -0,0 +1,1808 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> +<meta name="generator" content="pdoc 0.10.0" /> +<title>sql_app.schemas API documentation</title> +<meta name="description" content="" /> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin> +<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin> +<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin> +<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style> +<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style> +<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style> +<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script> +<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script> +</head> +<body> +<main> +<article id="content"> +<header> +<h1 class="title">Module <code>sql_app.schemas</code></h1> +</header> +<section id="section-intro"> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">from typing import List, Optional +from datetime import datetime, date +from pydantic import BaseModel + + +class DeviceLicenseBase(BaseModel): + device_id: int + license_id: int + assigned_datetime: str + + +class DeviceLicenseCreate(DeviceLicenseBase): + pass + + +class DeviceLicense(DeviceLicenseCreate): + """ + Class used for creating and reading devices_licenses entries + """ + id: int + + class Config: + orm_mode = True + + +class USBLogBase(BaseModel): + timestamp: datetime + status: str + + +class USBLogCreate(USBLogBase): + pass + + +class USBLog(USBLogBase): + """ + Class used for creating and reading usb_logs entries + """ + id: int + device_id: int + pc_id: int + + class Config: + orm_mode = True + + +class DeviceBase(BaseModel): + vendor_id: str + product_id: str + serial_number: str + + +class DeviceCreate(DeviceBase): + pass + + +class Device(DeviceCreate): + """ + Class used for creating and reading devices entries + """ + id: int + assigned: bool + logs: List[USBLog] = [] + licenses: List[DeviceLicense] = [] + + class Config: + orm_mode = True + + +class LDLogBase(BaseModel): + timestamp: datetime + status: str + + +class LDLogCreate(LDLogBase): + pass + + +class LDLog(LDLogCreate): + """ + Class used for creating and reading ld_logs entries + """ + id: int + head_id: int + body_id: int + + class Config: + orm_mode = True + + +class BodyDeviceBase(BaseModel): + serial_number: str + + +class BodyDeviceCreate(BodyDeviceBase): + pass + + +class BodyDevice(BodyDeviceCreate): + """ + Class used for creating and reading body_devices entries + """ + id: int + logs: List[LDLog] = [] + + class Config: + orm_mode = True + + +class HeadDeviceBase(BaseModel): + serial_number: str + + +class HeadDeviceCreate(HeadDeviceBase): + pass + + +class HeadDevice(HeadDeviceCreate): + """ + Class used for creating and reading head_devices entries + """ + id: int + logs: List[LDLog] = [] + + class Config: + orm_mode = True + + +class PCBase(BaseModel): + username: str + hostname: str + + +class PCCreate(PCBase): + pass + + +class PC(PCCreate): + """ + Class used for creating and reading pc entries + """ + id: int + assigned: bool + logs_pc: List[USBLog] = [] + + class Config: + orm_mode = True + + +class TeamBase(BaseModel): + name: str + + +class TeamCreate(TeamBase): + pass + + +class Team(TeamCreate): + """ + Class used for creating and reading team entries + """ + id: int + pcs: List[PC] = [] + + class Config: + orm_mode = True + + +class LicenseBase(BaseModel): + name: str + expiration_date: date + + +class LicenseCreate(LicenseBase): + pass + + +class License(LicenseCreate): + """ + Class used for creating and reading licenses entries + """ + id: int + devices: List[DeviceLicense] = [] + + class Config: + orm_mode = True + + +class USBTempBase(BaseModel): + """ + Class used for reading data from keyman detecting client messages + """ + username: str + hostname: str + timestamp: str + device: DeviceBase + status: str + + +class USBTempCreate(USBTempBase): + pass + + +class USBTemp(USBTempBase): + id: int + device_id: int + + class Config: + orm_mode = True + + +class LDTempBase(BaseModel): + """ + Class used for reading data from debugger detecting client messages + """ + username: str + hostname: str + timestamp: str + head_device: HeadDeviceBase + body_device: BodyDeviceBase + status: str + + +class LDTempCreate(LDTempBase): + pass + + +class LDTemp(LDTempCreate): + id: int + head_id: int + body_id: int + + class Config: + orm_mode = True</code></pre> +</details> +</section> +<section> +</section> +<section> +</section> +<section> +</section> +<section> +<h2 class="section-title" id="header-classes">Classes</h2> +<dl> +<dt id="sql_app.schemas.BodyDevice"><code class="flex name class"> +<span>class <span class="ident">BodyDevice</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading body_devices entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class BodyDevice(BodyDeviceCreate): + """ + Class used for creating and reading body_devices entries + """ + id: int + logs: List[LDLog] = [] + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.BodyDeviceCreate" href="#sql_app.schemas.BodyDeviceCreate">BodyDeviceCreate</a></li> +<li><a title="sql_app.schemas.BodyDeviceBase" href="#sql_app.schemas.BodyDeviceBase">BodyDeviceBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.BodyDevice.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.BodyDevice.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.BodyDevice.logs"><code class="name">var <span class="ident">logs</span> : List[<a title="sql_app.schemas.LDLog" href="#sql_app.schemas.LDLog">LDLog</a>]</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.BodyDeviceBase"><code class="flex name class"> +<span>class <span class="ident">BodyDeviceBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class BodyDeviceBase(BaseModel): + serial_number: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.BodyDeviceCreate" href="#sql_app.schemas.BodyDeviceCreate">BodyDeviceCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.BodyDeviceBase.serial_number"><code class="name">var <span class="ident">serial_number</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.BodyDeviceCreate"><code class="flex name class"> +<span>class <span class="ident">BodyDeviceCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class BodyDeviceCreate(BodyDeviceBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.BodyDeviceBase" href="#sql_app.schemas.BodyDeviceBase">BodyDeviceBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.BodyDevice" href="#sql_app.schemas.BodyDevice">BodyDevice</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.Device"><code class="flex name class"> +<span>class <span class="ident">Device</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading devices entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class Device(DeviceCreate): + """ + Class used for creating and reading devices entries + """ + id: int + assigned: bool + logs: List[USBLog] = [] + licenses: List[DeviceLicense] = [] + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.DeviceCreate" href="#sql_app.schemas.DeviceCreate">DeviceCreate</a></li> +<li><a title="sql_app.schemas.DeviceBase" href="#sql_app.schemas.DeviceBase">DeviceBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +<li>pydantic.main.Device</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.Device.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.Device.assigned"><code class="name">var <span class="ident">assigned</span> : bool</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.Device.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.Device.licenses"><code class="name">var <span class="ident">licenses</span> : List[<a title="sql_app.schemas.DeviceLicense" href="#sql_app.schemas.DeviceLicense">DeviceLicense</a>]</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.Device.logs"><code class="name">var <span class="ident">logs</span> : List[<a title="sql_app.schemas.USBLog" href="#sql_app.schemas.USBLog">USBLog</a>]</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.DeviceBase"><code class="flex name class"> +<span>class <span class="ident">DeviceBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class DeviceBase(BaseModel): + vendor_id: str + product_id: str + serial_number: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.DeviceCreate" href="#sql_app.schemas.DeviceCreate">DeviceCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.DeviceBase.product_id"><code class="name">var <span class="ident">product_id</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.DeviceBase.serial_number"><code class="name">var <span class="ident">serial_number</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.DeviceBase.vendor_id"><code class="name">var <span class="ident">vendor_id</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.DeviceCreate"><code class="flex name class"> +<span>class <span class="ident">DeviceCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class DeviceCreate(DeviceBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.DeviceBase" href="#sql_app.schemas.DeviceBase">DeviceBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.Device" href="#sql_app.schemas.Device">Device</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.DeviceLicense"><code class="flex name class"> +<span>class <span class="ident">DeviceLicense</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading devices_licenses entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class DeviceLicense(DeviceLicenseCreate): + """ + Class used for creating and reading devices_licenses entries + """ + id: int + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.DeviceLicenseCreate" href="#sql_app.schemas.DeviceLicenseCreate">DeviceLicenseCreate</a></li> +<li><a title="sql_app.schemas.DeviceLicenseBase" href="#sql_app.schemas.DeviceLicenseBase">DeviceLicenseBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +<li>pydantic.main.DeviceLicense</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.DeviceLicense.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.DeviceLicense.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.DeviceLicenseBase"><code class="flex name class"> +<span>class <span class="ident">DeviceLicenseBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class DeviceLicenseBase(BaseModel): + device_id: int + license_id: int + assigned_datetime: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.DeviceLicenseCreate" href="#sql_app.schemas.DeviceLicenseCreate">DeviceLicenseCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.DeviceLicenseBase.assigned_datetime"><code class="name">var <span class="ident">assigned_datetime</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.DeviceLicenseBase.device_id"><code class="name">var <span class="ident">device_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.DeviceLicenseBase.license_id"><code class="name">var <span class="ident">license_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.DeviceLicenseCreate"><code class="flex name class"> +<span>class <span class="ident">DeviceLicenseCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class DeviceLicenseCreate(DeviceLicenseBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.DeviceLicenseBase" href="#sql_app.schemas.DeviceLicenseBase">DeviceLicenseBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.DeviceLicense" href="#sql_app.schemas.DeviceLicense">DeviceLicense</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.HeadDevice"><code class="flex name class"> +<span>class <span class="ident">HeadDevice</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading head_devices entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class HeadDevice(HeadDeviceCreate): + """ + Class used for creating and reading head_devices entries + """ + id: int + logs: List[LDLog] = [] + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.HeadDeviceCreate" href="#sql_app.schemas.HeadDeviceCreate">HeadDeviceCreate</a></li> +<li><a title="sql_app.schemas.HeadDeviceBase" href="#sql_app.schemas.HeadDeviceBase">HeadDeviceBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.HeadDevice.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.HeadDevice.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.HeadDevice.logs"><code class="name">var <span class="ident">logs</span> : List[<a title="sql_app.schemas.LDLog" href="#sql_app.schemas.LDLog">LDLog</a>]</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.HeadDeviceBase"><code class="flex name class"> +<span>class <span class="ident">HeadDeviceBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class HeadDeviceBase(BaseModel): + serial_number: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.HeadDeviceCreate" href="#sql_app.schemas.HeadDeviceCreate">HeadDeviceCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.HeadDeviceBase.serial_number"><code class="name">var <span class="ident">serial_number</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.HeadDeviceCreate"><code class="flex name class"> +<span>class <span class="ident">HeadDeviceCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class HeadDeviceCreate(HeadDeviceBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.HeadDeviceBase" href="#sql_app.schemas.HeadDeviceBase">HeadDeviceBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.HeadDevice" href="#sql_app.schemas.HeadDevice">HeadDevice</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.LDLog"><code class="flex name class"> +<span>class <span class="ident">LDLog</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading ld_logs entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LDLog(LDLogCreate): + """ + Class used for creating and reading ld_logs entries + """ + id: int + head_id: int + body_id: int + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LDLogCreate" href="#sql_app.schemas.LDLogCreate">LDLogCreate</a></li> +<li><a title="sql_app.schemas.LDLogBase" href="#sql_app.schemas.LDLogBase">LDLogBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li>pydantic.main.LDLog</li> +<li>pydantic.main.LDLog</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.LDLog.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDLog.body_id"><code class="name">var <span class="ident">body_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDLog.head_id"><code class="name">var <span class="ident">head_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDLog.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.LDLogBase"><code class="flex name class"> +<span>class <span class="ident">LDLogBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LDLogBase(BaseModel): + timestamp: datetime + status: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LDLogCreate" href="#sql_app.schemas.LDLogCreate">LDLogCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.LDLogBase.status"><code class="name">var <span class="ident">status</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDLogBase.timestamp"><code class="name">var <span class="ident">timestamp</span> : datetime.datetime</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.LDLogCreate"><code class="flex name class"> +<span>class <span class="ident">LDLogCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LDLogCreate(LDLogBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LDLogBase" href="#sql_app.schemas.LDLogBase">LDLogBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LDLog" href="#sql_app.schemas.LDLog">LDLog</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.LDTemp"><code class="flex name class"> +<span>class <span class="ident">LDTemp</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for reading data from debugger detecting client messages</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LDTemp(LDTempCreate): + id: int + head_id: int + body_id: int + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LDTempCreate" href="#sql_app.schemas.LDTempCreate">LDTempCreate</a></li> +<li><a title="sql_app.schemas.LDTempBase" href="#sql_app.schemas.LDTempBase">LDTempBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.LDTemp.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDTemp.body_id"><code class="name">var <span class="ident">body_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDTemp.head_id"><code class="name">var <span class="ident">head_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDTemp.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.LDTempBase"><code class="flex name class"> +<span>class <span class="ident">LDTempBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for reading data from debugger detecting client messages</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LDTempBase(BaseModel): + """ + Class used for reading data from debugger detecting client messages + """ + username: str + hostname: str + timestamp: str + head_device: HeadDeviceBase + body_device: BodyDeviceBase + status: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LDTempCreate" href="#sql_app.schemas.LDTempCreate">LDTempCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.LDTempBase.body_device"><code class="name">var <span class="ident">body_device</span> : <a title="sql_app.schemas.BodyDeviceBase" href="#sql_app.schemas.BodyDeviceBase">BodyDeviceBase</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDTempBase.head_device"><code class="name">var <span class="ident">head_device</span> : <a title="sql_app.schemas.HeadDeviceBase" href="#sql_app.schemas.HeadDeviceBase">HeadDeviceBase</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDTempBase.hostname"><code class="name">var <span class="ident">hostname</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDTempBase.status"><code class="name">var <span class="ident">status</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDTempBase.timestamp"><code class="name">var <span class="ident">timestamp</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LDTempBase.username"><code class="name">var <span class="ident">username</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.LDTempCreate"><code class="flex name class"> +<span>class <span class="ident">LDTempCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for reading data from debugger detecting client messages</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LDTempCreate(LDTempBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LDTempBase" href="#sql_app.schemas.LDTempBase">LDTempBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LDTemp" href="#sql_app.schemas.LDTemp">LDTemp</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.License"><code class="flex name class"> +<span>class <span class="ident">License</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading licenses entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class License(LicenseCreate): + """ + Class used for creating and reading licenses entries + """ + id: int + devices: List[DeviceLicense] = [] + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LicenseCreate" href="#sql_app.schemas.LicenseCreate">LicenseCreate</a></li> +<li><a title="sql_app.schemas.LicenseBase" href="#sql_app.schemas.LicenseBase">LicenseBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li>pydantic.main.License</li> +<li>pydantic.main.License</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.License.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.License.devices"><code class="name">var <span class="ident">devices</span> : List[<a title="sql_app.schemas.DeviceLicense" href="#sql_app.schemas.DeviceLicense">DeviceLicense</a>]</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.License.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.LicenseBase"><code class="flex name class"> +<span>class <span class="ident">LicenseBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LicenseBase(BaseModel): + name: str + expiration_date: date</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LicenseCreate" href="#sql_app.schemas.LicenseCreate">LicenseCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.LicenseBase.expiration_date"><code class="name">var <span class="ident">expiration_date</span> : datetime.date</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.LicenseBase.name"><code class="name">var <span class="ident">name</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.LicenseCreate"><code class="flex name class"> +<span>class <span class="ident">LicenseCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class LicenseCreate(LicenseBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.LicenseBase" href="#sql_app.schemas.LicenseBase">LicenseBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.License" href="#sql_app.schemas.License">License</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.PC"><code class="flex name class"> +<span>class <span class="ident">PC</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading pc entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class PC(PCCreate): + """ + Class used for creating and reading pc entries + """ + id: int + assigned: bool + logs_pc: List[USBLog] = [] + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.PCCreate" href="#sql_app.schemas.PCCreate">PCCreate</a></li> +<li><a title="sql_app.schemas.PCBase" href="#sql_app.schemas.PCBase">PCBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li>pydantic.main.PC</li> +<li>pydantic.main.PC</li> +<li>pydantic.main.PC</li> +<li>pydantic.main.PC</li> +<li>pydantic.main.PC</li> +<li>pydantic.main.PC</li> +<li>pydantic.main.PC</li> +<li>pydantic.main.PC</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.PC.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.PC.assigned"><code class="name">var <span class="ident">assigned</span> : bool</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.PC.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.PC.logs_pc"><code class="name">var <span class="ident">logs_pc</span> : List[<a title="sql_app.schemas.USBLog" href="#sql_app.schemas.USBLog">USBLog</a>]</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.PCBase"><code class="flex name class"> +<span>class <span class="ident">PCBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class PCBase(BaseModel): + username: str + hostname: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.PCCreate" href="#sql_app.schemas.PCCreate">PCCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.PCBase.hostname"><code class="name">var <span class="ident">hostname</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.PCBase.username"><code class="name">var <span class="ident">username</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.PCCreate"><code class="flex name class"> +<span>class <span class="ident">PCCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class PCCreate(PCBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.PCBase" href="#sql_app.schemas.PCBase">PCBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.PC" href="#sql_app.schemas.PC">PC</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.Team"><code class="flex name class"> +<span>class <span class="ident">Team</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading team entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class Team(TeamCreate): + """ + Class used for creating and reading team entries + """ + id: int + pcs: List[PC] = [] + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.TeamCreate" href="#sql_app.schemas.TeamCreate">TeamCreate</a></li> +<li><a title="sql_app.schemas.TeamBase" href="#sql_app.schemas.TeamBase">TeamBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li>pydantic.main.Team</li> +<li>pydantic.main.Team</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.Team.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.Team.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.Team.pcs"><code class="name">var <span class="ident">pcs</span> : List[<a title="sql_app.schemas.PC" href="#sql_app.schemas.PC">PC</a>]</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.TeamBase"><code class="flex name class"> +<span>class <span class="ident">TeamBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class TeamBase(BaseModel): + name: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.TeamCreate" href="#sql_app.schemas.TeamCreate">TeamCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.TeamBase.name"><code class="name">var <span class="ident">name</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.TeamCreate"><code class="flex name class"> +<span>class <span class="ident">TeamCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class TeamCreate(TeamBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.TeamBase" href="#sql_app.schemas.TeamBase">TeamBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.Team" href="#sql_app.schemas.Team">Team</a></li> +</ul> +</dd> +<dt id="sql_app.schemas.USBLog"><code class="flex name class"> +<span>class <span class="ident">USBLog</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for creating and reading usb_logs entries</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class USBLog(USBLogBase): + """ + Class used for creating and reading usb_logs entries + """ + id: int + device_id: int + pc_id: int + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.USBLogBase" href="#sql_app.schemas.USBLogBase">USBLogBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +<li>pydantic.main.USBLog</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.USBLog.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBLog.device_id"><code class="name">var <span class="ident">device_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBLog.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBLog.pc_id"><code class="name">var <span class="ident">pc_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.USBLogBase"><code class="flex name class"> +<span>class <span class="ident">USBLogBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class USBLogBase(BaseModel): + timestamp: datetime + status: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.USBLog" href="#sql_app.schemas.USBLog">USBLog</a></li> +<li><a title="sql_app.schemas.USBLogCreate" href="#sql_app.schemas.USBLogCreate">USBLogCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.USBLogBase.status"><code class="name">var <span class="ident">status</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBLogBase.timestamp"><code class="name">var <span class="ident">timestamp</span> : datetime.datetime</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.USBLogCreate"><code class="flex name class"> +<span>class <span class="ident">USBLogCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class USBLogCreate(USBLogBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.USBLogBase" href="#sql_app.schemas.USBLogBase">USBLogBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +</dd> +<dt id="sql_app.schemas.USBTemp"><code class="flex name class"> +<span>class <span class="ident">USBTemp</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for reading data from keyman detecting client messages</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class USBTemp(USBTempBase): + id: int + device_id: int + + class Config: + orm_mode = True</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.USBTempBase" href="#sql_app.schemas.USBTempBase">USBTempBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.USBTemp.Config"><code class="name">var <span class="ident">Config</span></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBTemp.device_id"><code class="name">var <span class="ident">device_id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBTemp.id"><code class="name">var <span class="ident">id</span> : int</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.USBTempBase"><code class="flex name class"> +<span>class <span class="ident">USBTempBase</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for reading data from keyman detecting client messages</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class USBTempBase(BaseModel): + """ + Class used for reading data from keyman detecting client messages + """ + username: str + hostname: str + timestamp: str + device: DeviceBase + status: str</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +<h3>Subclasses</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.USBTemp" href="#sql_app.schemas.USBTemp">USBTemp</a></li> +<li><a title="sql_app.schemas.USBTempCreate" href="#sql_app.schemas.USBTempCreate">USBTempCreate</a></li> +</ul> +<h3>Class variables</h3> +<dl> +<dt id="sql_app.schemas.USBTempBase.device"><code class="name">var <span class="ident">device</span> : <a title="sql_app.schemas.DeviceBase" href="#sql_app.schemas.DeviceBase">DeviceBase</a></code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBTempBase.hostname"><code class="name">var <span class="ident">hostname</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBTempBase.status"><code class="name">var <span class="ident">status</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBTempBase.timestamp"><code class="name">var <span class="ident">timestamp</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +<dt id="sql_app.schemas.USBTempBase.username"><code class="name">var <span class="ident">username</span> : str</code></dt> +<dd> +<div class="desc"></div> +</dd> +</dl> +</dd> +<dt id="sql_app.schemas.USBTempCreate"><code class="flex name class"> +<span>class <span class="ident">USBTempCreate</span></span> +<span>(</span><span>**data: Any)</span> +</code></dt> +<dd> +<div class="desc"><p>Class used for reading data from keyman detecting client messages</p> +<p>Create a new model by parsing and validating input data from keyword arguments.</p> +<p>Raises ValidationError if the input data cannot be parsed to form a valid model.</p></div> +<details class="source"> +<summary> +<span>Expand source code</span> +</summary> +<pre><code class="python">class USBTempCreate(USBTempBase): + pass</code></pre> +</details> +<h3>Ancestors</h3> +<ul class="hlist"> +<li><a title="sql_app.schemas.USBTempBase" href="#sql_app.schemas.USBTempBase">USBTempBase</a></li> +<li>pydantic.main.BaseModel</li> +<li>pydantic.utils.Representation</li> +</ul> +</dd> +</dl> +</section> +</article> +<nav id="sidebar"> +<h1>Index</h1> +<div class="toc"> +<ul></ul> +</div> +<ul id="index"> +<li><h3>Super-module</h3> +<ul> +<li><code><a title="sql_app" href="index.html">sql_app</a></code></li> +</ul> +</li> +<li><h3><a href="#header-classes">Classes</a></h3> +<ul> +<li> +<h4><code><a title="sql_app.schemas.BodyDevice" href="#sql_app.schemas.BodyDevice">BodyDevice</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.BodyDevice.Config" href="#sql_app.schemas.BodyDevice.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.BodyDevice.id" href="#sql_app.schemas.BodyDevice.id">id</a></code></li> +<li><code><a title="sql_app.schemas.BodyDevice.logs" href="#sql_app.schemas.BodyDevice.logs">logs</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.BodyDeviceBase" href="#sql_app.schemas.BodyDeviceBase">BodyDeviceBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.BodyDeviceBase.serial_number" href="#sql_app.schemas.BodyDeviceBase.serial_number">serial_number</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.BodyDeviceCreate" href="#sql_app.schemas.BodyDeviceCreate">BodyDeviceCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.Device" href="#sql_app.schemas.Device">Device</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.Device.Config" href="#sql_app.schemas.Device.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.Device.assigned" href="#sql_app.schemas.Device.assigned">assigned</a></code></li> +<li><code><a title="sql_app.schemas.Device.id" href="#sql_app.schemas.Device.id">id</a></code></li> +<li><code><a title="sql_app.schemas.Device.licenses" href="#sql_app.schemas.Device.licenses">licenses</a></code></li> +<li><code><a title="sql_app.schemas.Device.logs" href="#sql_app.schemas.Device.logs">logs</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.DeviceBase" href="#sql_app.schemas.DeviceBase">DeviceBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.DeviceBase.product_id" href="#sql_app.schemas.DeviceBase.product_id">product_id</a></code></li> +<li><code><a title="sql_app.schemas.DeviceBase.serial_number" href="#sql_app.schemas.DeviceBase.serial_number">serial_number</a></code></li> +<li><code><a title="sql_app.schemas.DeviceBase.vendor_id" href="#sql_app.schemas.DeviceBase.vendor_id">vendor_id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.DeviceCreate" href="#sql_app.schemas.DeviceCreate">DeviceCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.DeviceLicense" href="#sql_app.schemas.DeviceLicense">DeviceLicense</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.DeviceLicense.Config" href="#sql_app.schemas.DeviceLicense.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.DeviceLicense.id" href="#sql_app.schemas.DeviceLicense.id">id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.DeviceLicenseBase" href="#sql_app.schemas.DeviceLicenseBase">DeviceLicenseBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.DeviceLicenseBase.assigned_datetime" href="#sql_app.schemas.DeviceLicenseBase.assigned_datetime">assigned_datetime</a></code></li> +<li><code><a title="sql_app.schemas.DeviceLicenseBase.device_id" href="#sql_app.schemas.DeviceLicenseBase.device_id">device_id</a></code></li> +<li><code><a title="sql_app.schemas.DeviceLicenseBase.license_id" href="#sql_app.schemas.DeviceLicenseBase.license_id">license_id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.DeviceLicenseCreate" href="#sql_app.schemas.DeviceLicenseCreate">DeviceLicenseCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.HeadDevice" href="#sql_app.schemas.HeadDevice">HeadDevice</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.HeadDevice.Config" href="#sql_app.schemas.HeadDevice.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.HeadDevice.id" href="#sql_app.schemas.HeadDevice.id">id</a></code></li> +<li><code><a title="sql_app.schemas.HeadDevice.logs" href="#sql_app.schemas.HeadDevice.logs">logs</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.HeadDeviceBase" href="#sql_app.schemas.HeadDeviceBase">HeadDeviceBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.HeadDeviceBase.serial_number" href="#sql_app.schemas.HeadDeviceBase.serial_number">serial_number</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.HeadDeviceCreate" href="#sql_app.schemas.HeadDeviceCreate">HeadDeviceCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.LDLog" href="#sql_app.schemas.LDLog">LDLog</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.LDLog.Config" href="#sql_app.schemas.LDLog.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.LDLog.body_id" href="#sql_app.schemas.LDLog.body_id">body_id</a></code></li> +<li><code><a title="sql_app.schemas.LDLog.head_id" href="#sql_app.schemas.LDLog.head_id">head_id</a></code></li> +<li><code><a title="sql_app.schemas.LDLog.id" href="#sql_app.schemas.LDLog.id">id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.LDLogBase" href="#sql_app.schemas.LDLogBase">LDLogBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.LDLogBase.status" href="#sql_app.schemas.LDLogBase.status">status</a></code></li> +<li><code><a title="sql_app.schemas.LDLogBase.timestamp" href="#sql_app.schemas.LDLogBase.timestamp">timestamp</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.LDLogCreate" href="#sql_app.schemas.LDLogCreate">LDLogCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.LDTemp" href="#sql_app.schemas.LDTemp">LDTemp</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.LDTemp.Config" href="#sql_app.schemas.LDTemp.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.LDTemp.body_id" href="#sql_app.schemas.LDTemp.body_id">body_id</a></code></li> +<li><code><a title="sql_app.schemas.LDTemp.head_id" href="#sql_app.schemas.LDTemp.head_id">head_id</a></code></li> +<li><code><a title="sql_app.schemas.LDTemp.id" href="#sql_app.schemas.LDTemp.id">id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.LDTempBase" href="#sql_app.schemas.LDTempBase">LDTempBase</a></code></h4> +<ul class="two-column"> +<li><code><a title="sql_app.schemas.LDTempBase.body_device" href="#sql_app.schemas.LDTempBase.body_device">body_device</a></code></li> +<li><code><a title="sql_app.schemas.LDTempBase.head_device" href="#sql_app.schemas.LDTempBase.head_device">head_device</a></code></li> +<li><code><a title="sql_app.schemas.LDTempBase.hostname" href="#sql_app.schemas.LDTempBase.hostname">hostname</a></code></li> +<li><code><a title="sql_app.schemas.LDTempBase.status" href="#sql_app.schemas.LDTempBase.status">status</a></code></li> +<li><code><a title="sql_app.schemas.LDTempBase.timestamp" href="#sql_app.schemas.LDTempBase.timestamp">timestamp</a></code></li> +<li><code><a title="sql_app.schemas.LDTempBase.username" href="#sql_app.schemas.LDTempBase.username">username</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.LDTempCreate" href="#sql_app.schemas.LDTempCreate">LDTempCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.License" href="#sql_app.schemas.License">License</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.License.Config" href="#sql_app.schemas.License.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.License.devices" href="#sql_app.schemas.License.devices">devices</a></code></li> +<li><code><a title="sql_app.schemas.License.id" href="#sql_app.schemas.License.id">id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.LicenseBase" href="#sql_app.schemas.LicenseBase">LicenseBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.LicenseBase.expiration_date" href="#sql_app.schemas.LicenseBase.expiration_date">expiration_date</a></code></li> +<li><code><a title="sql_app.schemas.LicenseBase.name" href="#sql_app.schemas.LicenseBase.name">name</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.LicenseCreate" href="#sql_app.schemas.LicenseCreate">LicenseCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.PC" href="#sql_app.schemas.PC">PC</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.PC.Config" href="#sql_app.schemas.PC.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.PC.assigned" href="#sql_app.schemas.PC.assigned">assigned</a></code></li> +<li><code><a title="sql_app.schemas.PC.id" href="#sql_app.schemas.PC.id">id</a></code></li> +<li><code><a title="sql_app.schemas.PC.logs_pc" href="#sql_app.schemas.PC.logs_pc">logs_pc</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.PCBase" href="#sql_app.schemas.PCBase">PCBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.PCBase.hostname" href="#sql_app.schemas.PCBase.hostname">hostname</a></code></li> +<li><code><a title="sql_app.schemas.PCBase.username" href="#sql_app.schemas.PCBase.username">username</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.PCCreate" href="#sql_app.schemas.PCCreate">PCCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.Team" href="#sql_app.schemas.Team">Team</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.Team.Config" href="#sql_app.schemas.Team.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.Team.id" href="#sql_app.schemas.Team.id">id</a></code></li> +<li><code><a title="sql_app.schemas.Team.pcs" href="#sql_app.schemas.Team.pcs">pcs</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.TeamBase" href="#sql_app.schemas.TeamBase">TeamBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.TeamBase.name" href="#sql_app.schemas.TeamBase.name">name</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.TeamCreate" href="#sql_app.schemas.TeamCreate">TeamCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.USBLog" href="#sql_app.schemas.USBLog">USBLog</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.USBLog.Config" href="#sql_app.schemas.USBLog.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.USBLog.device_id" href="#sql_app.schemas.USBLog.device_id">device_id</a></code></li> +<li><code><a title="sql_app.schemas.USBLog.id" href="#sql_app.schemas.USBLog.id">id</a></code></li> +<li><code><a title="sql_app.schemas.USBLog.pc_id" href="#sql_app.schemas.USBLog.pc_id">pc_id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.USBLogBase" href="#sql_app.schemas.USBLogBase">USBLogBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.USBLogBase.status" href="#sql_app.schemas.USBLogBase.status">status</a></code></li> +<li><code><a title="sql_app.schemas.USBLogBase.timestamp" href="#sql_app.schemas.USBLogBase.timestamp">timestamp</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.USBLogCreate" href="#sql_app.schemas.USBLogCreate">USBLogCreate</a></code></h4> +</li> +<li> +<h4><code><a title="sql_app.schemas.USBTemp" href="#sql_app.schemas.USBTemp">USBTemp</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.USBTemp.Config" href="#sql_app.schemas.USBTemp.Config">Config</a></code></li> +<li><code><a title="sql_app.schemas.USBTemp.device_id" href="#sql_app.schemas.USBTemp.device_id">device_id</a></code></li> +<li><code><a title="sql_app.schemas.USBTemp.id" href="#sql_app.schemas.USBTemp.id">id</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.USBTempBase" href="#sql_app.schemas.USBTempBase">USBTempBase</a></code></h4> +<ul class=""> +<li><code><a title="sql_app.schemas.USBTempBase.device" href="#sql_app.schemas.USBTempBase.device">device</a></code></li> +<li><code><a title="sql_app.schemas.USBTempBase.hostname" href="#sql_app.schemas.USBTempBase.hostname">hostname</a></code></li> +<li><code><a title="sql_app.schemas.USBTempBase.status" href="#sql_app.schemas.USBTempBase.status">status</a></code></li> +<li><code><a title="sql_app.schemas.USBTempBase.timestamp" href="#sql_app.schemas.USBTempBase.timestamp">timestamp</a></code></li> +<li><code><a title="sql_app.schemas.USBTempBase.username" href="#sql_app.schemas.USBTempBase.username">username</a></code></li> +</ul> +</li> +<li> +<h4><code><a title="sql_app.schemas.USBTempCreate" href="#sql_app.schemas.USBTempCreate">USBTempCreate</a></code></h4> +</li> +</ul> +</li> +</ul> +</nav> +</main> +<footer id="footer"> +<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p> +</footer> +</body> +</html> \ No newline at end of file diff --git a/server/sql_app/api/devices.py b/server/sql_app/api/devices.py index e42ee85..ec5f3dc 100644 --- a/server/sql_app/api/devices.py +++ b/server/sql_app/api/devices.py @@ -7,8 +7,10 @@ from ..database import SessionLocal, engine models.Base.metadata.create_all(bind=engine) +# prefix used for all endpoints in this file device = APIRouter(prefix="/api/v1") + # Dependency def get_db(): db = SessionLocal() @@ -20,17 +22,26 @@ def get_db(): @device.post("/device", response_model=schemas.Device) def create_device(device: schemas.DeviceCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new device + """ print(crud.create_device(db=db, device=device)) @device.get("/devices", response_model=List[schemas.Device]) def read_devices(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Endpoint returns all devices in database + """ devices = crud.get_devices(db, skip=skip, limit=limit) return devices @device.get("/device/{device_id}", response_model=schemas.Device) def read_device(device_id: int, db: Session = Depends(get_db)): + """ + Returns one specific device by given id + """ db_device = crud.get_device(db, device_id=device_id) if db_device is None: raise HTTPException(status_code=404, detail="Device not found") diff --git a/server/sql_app/api/devices_web.py b/server/sql_app/api/devices_web.py index 00c668d..76b3cb8 100644 --- a/server/sql_app/api/devices_web.py +++ b/server/sql_app/api/devices_web.py @@ -11,8 +11,11 @@ from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) -templates = Jinja2Templates(directory="templates/devices") +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/devices") + +# prefix used for all endpoints in this file device_web = APIRouter(prefix="/api/v1") @@ -27,8 +30,12 @@ def get_db(): @device_web.get("/devices-web", response_class=HTMLResponse) async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all devices and its current states + """ devices = crud.get_devices(db, skip=skip, limit=limit) statuses = [] + # adding state for each device in list for i in range(0, len(devices)): statuses.append(devices[i].logs[len(devices[i].logs)-1].status) licenses = crud.get_licenses(db, skip=skip, limit=limit) @@ -39,12 +46,17 @@ async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Se @device_web.post("/devices-web", response_class=HTMLResponse) async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: str = Form("all"), db: Session = Depends(get_db)): + """ + Endpoint used for filtering devices by license. returns html template with only + devices that has assigned license defined by user input + """ devices = crud.get_devices(db, skip=skip, limit=limit) def_devices = [] for dev in devices: for l in dev.licenses: if dev not in def_devices and l.licenses.name == lic: def_devices.append(dev) + # if input was default all if lic == "all": def_devices = devices statuses = [] @@ -57,6 +69,9 @@ async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: @device_web.get("/device-license/{device_id}", response_class=HTMLResponse) async def connect_dev_lic(request: Request, device_id: int, db: Session = Depends(get_db)): + """ + Returns template with one device and all available licenses that can be assigned to it. + """ device = crud.get_device(db, device_id) licenses = crud.get_licenses(db, 0, 100) return templates.TemplateResponse("devicelicense.html", @@ -66,9 +81,14 @@ async def connect_dev_lic(request: Request, device_id: int, db: Session = Depend @device_web.post("/devices-web/{device_id}", response_class=HTMLResponse) async def connect_post(request: Request, device_id: int, lic: str = Form(...), skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Endpoint called from template for connecting device with license. Adds entry to devices_licenses + table and returns template with all devices in database + """ crud.create_device_license(db, device_id, int(lic), datetime.now()) devices = crud.get_devices(db, skip=skip, limit=limit) statuses = [] + # adding state for each device in list for i in range(0, len(devices)): statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) licenses = crud.get_licenses(db, skip=skip, limit=limit) diff --git a/server/sql_app/api/licenses.py b/server/sql_app/api/licenses.py index b79c7b9..4eb2a3e 100644 --- a/server/sql_app/api/licenses.py +++ b/server/sql_app/api/licenses.py @@ -8,6 +8,7 @@ from ..database import SessionLocal, engine models.Base.metadata.create_all(bind=engine) +# prefix used for all endpoints in this file licenses = APIRouter(prefix="/api/v1") @@ -22,11 +23,17 @@ def get_db(): @licenses.get("/licenses", response_model=List[schemas.License]) def read_licenses(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all licenses currently saved in database. + """ licenses = crud.get_licenses(db, skip=skip, limit=limit) return licenses @licenses.post("/device-license", response_model=schemas.DeviceLicense) def create_device_license(device_license: schemas.DeviceLicenseCreate, db: Session = Depends(get_db)): + """ + Creates entry for devices_licenses table thus connecting device with its license. + """ print(crud.create_device_license(db=db, device=device_license.device_id, license=device_license.license_id, time=datetime.now())) diff --git a/server/sql_app/api/licenses_web.py b/server/sql_app/api/licenses_web.py index 46d4011..bfa9362 100644 --- a/server/sql_app/api/licenses_web.py +++ b/server/sql_app/api/licenses_web.py @@ -11,9 +11,12 @@ from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) -templates = Jinja2Templates(directory="templates/licenses") -device_templates = Jinja2Templates(directory="templates/devices") +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/licenses") +device_templates = Jinja2Templates(directory="../templates/devices") + +# prefix used for all endpoints in this file licenses_web = APIRouter(prefix="/api/v1") @@ -28,11 +31,17 @@ def get_db(): @licenses_web.get("/license-create", response_class=HTMLResponse) async def licenses_create_web(request: Request): + """ + Returns template with Form for creating new license. + """ return templates.TemplateResponse("license_create.html", {"request": request}) @licenses_web.get("/licenses-web", response_class=HTMLResponse) async def read_licenses_web(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all licenses currently saved in database + """ licenses = crud.get_licenses(db, skip=skip, limit=limit) return templates.TemplateResponse("licenses.html", {"request": request, "licenses": licenses}) @@ -40,6 +49,9 @@ async def read_licenses_web(request: Request, skip: int = 0, limit: int = 100, d @licenses_web.post("/licenses-web", response_class=HTMLResponse) def create_license(request: Request, name: str = Form(...), expdate: date = Form(...), skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Endpoint called from create license form. Creates new license and returns template with all licenses in database + """ db_license = crud.create_license(db, name, expdate) if db_license is None: print("something went wrong") diff --git a/server/sql_app/api/pcs.py b/server/sql_app/api/pcs.py index ba78f06..11ce207 100644 --- a/server/sql_app/api/pcs.py +++ b/server/sql_app/api/pcs.py @@ -6,6 +6,7 @@ from ..database import SessionLocal, engine models.Base.metadata.create_all(bind=engine) +# prefix used for all endpoints in this file pcs = APIRouter(prefix="/api/v1") @@ -20,17 +21,26 @@ def get_db(): @pcs.post("/pc", response_model=schemas.PC) def create_pc(pc: schemas.PCCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new pc + """ print(crud.create_pc(db=db, user=pc.username, host=pc.hostname)) @pcs.get("/pcs", response_model=List[schemas.PC]) def read_pcs(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all pcs currently saved in database + """ pcs = crud.get_pcs(db, skip=skip, limit=limit) return pcs @pcs.get("/pc/{pc_id}", response_model=schemas.PC) def read_pc(pc_id: int, db: Session = Depends(get_db)): + """ + Returns one specific pc by given id + """ db_pc = crud.get_pc(db, pc_id=pc_id) if db_pc is None: raise HTTPException(status_code=404, detail="Device not found") diff --git a/server/sql_app/api/pcs_web.py b/server/sql_app/api/pcs_web.py index a181380..000e771 100644 --- a/server/sql_app/api/pcs_web.py +++ b/server/sql_app/api/pcs_web.py @@ -9,8 +9,11 @@ from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) -templates = Jinja2Templates(directory="templates/pcs") +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/pcs") + +# prefix used for all endpoints in this file pcs_web = APIRouter(prefix="/api/v1") @@ -25,12 +28,18 @@ def get_db(): @pcs_web.get("/pcs-web", response_class=HTMLResponse) async def read_pcs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all pcs currently saved in database + """ pcs = crud.get_pcs(db, skip=skip, limit=limit) return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs}) @pcs_web.get("/pc-team/{pc_id}", response_class=HTMLResponse) async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(get_db)): + """ + Returns template with Form for connecting pc with team + """ pc = crud.get_pc(db, pc_id) teams = crud.get_teams(db, 0, 100) return templates.TemplateResponse("pcteam.html", @@ -40,6 +49,9 @@ async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(ge @pcs_web.post("/pcs-web/{pc_id}", response_class=HTMLResponse) async def connect_post(request: Request, pc_id: int, team: str = Form(...), skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Endpoint called from within form for connecting pc with team. Updates certain pc with new team. + """ old_pc = crud.update_pc(db, pc_id, team) pcs = crud.get_pcs(db, skip=skip, limit=limit) return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs}) diff --git a/server/sql_app/api/teams.py b/server/sql_app/api/teams.py index b685b28..75c5072 100644 --- a/server/sql_app/api/teams.py +++ b/server/sql_app/api/teams.py @@ -7,6 +7,7 @@ from ..database import SessionLocal, engine models.Base.metadata.create_all(bind=engine) +# prefix used for all endpoints in this file teams = APIRouter(prefix="/api/v1") # Dependency @@ -20,17 +21,26 @@ def get_db(): @teams.post("/team", response_model=schemas.Team) def create_device(team: schemas.TeamCreate, db: Session = Depends(get_db)): + """ + Endpoint used for creating new pc + """ print(crud.create_team(db=db, name=team.name)) @teams.get("/teams", response_model=List[schemas.Device]) def read_devices(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all pcs saved in database + """ teams = crud.get_teams(db, skip=skip, limit=limit) return teams @teams.get("/team/{team_id}", response_model=schemas.Device) def read_device(team_id: int, db: Session = Depends(get_db)): + """ + Returns one specific team by given id + """ db_team = crud.get_team(db, team_id=team_id) if db_team is None: raise HTTPException(status_code=404, detail="Device not found") diff --git a/server/sql_app/api/teams_web.py b/server/sql_app/api/teams_web.py index 20d31ac..a7423b7 100644 --- a/server/sql_app/api/teams_web.py +++ b/server/sql_app/api/teams_web.py @@ -10,8 +10,11 @@ from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) -templates = Jinja2Templates(directory="templates/teams") +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/teams") + +# prefix used for all endpoints in this file teams_web = APIRouter(prefix="/api/v1") @@ -26,18 +29,27 @@ def get_db(): @teams_web.get("/teams-web", response_class=HTMLResponse) async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all teams currently saved in database + """ teams = crud.get_teams(db, skip=skip, limit=limit) return templates.TemplateResponse("teams.html", {"request": request, "teams": teams}) @teams_web.get("/team-create", response_class=HTMLResponse) async def team_create_web(request: Request): + """ + Returns template with form for creating new team + """ return templates.TemplateResponse("team_create.html", {"request": request}) @teams_web.post("/teams-web", response_class=HTMLResponse) def create_team(request: Request, name: str = Form(...), skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Endpoint called from within form for creating new team. Creates new team and returns all teams in database + """ team = crud.create_team(db, name) if team is None: print("something went wrong") diff --git a/server/sql_app/api/usb_logs.py b/server/sql_app/api/usb_logs.py index d07caee..2bf4067 100644 --- a/server/sql_app/api/usb_logs.py +++ b/server/sql_app/api/usb_logs.py @@ -7,6 +7,7 @@ from ..database import SessionLocal, engine models.Base.metadata.create_all(bind=engine) +# prefix used for all endpoints in this file usblogs = APIRouter(prefix="/api/v1") @@ -21,6 +22,11 @@ def get_db(): @usblogs.post("/usb-logs", response_model=schemas.USBLog) def create_device_logs(log: schemas.USBTempBase, db: Session = Depends(get_db)): + """ + Endpoint called from keyman detecting client. Parses timestamp into datetime object. + Finds if device and pc defined in message already exists and creates them if necessary. + Saves log into database + """ dev = crud.find_device(db, log.device) dat = datetime.strptime(log.timestamp, '%Y-%m-%d %H:%M:%S') if dev is None: @@ -34,6 +40,11 @@ def create_device_logs(log: schemas.USBTempBase, db: Session = Depends(get_db)): @usblogs.post("/ld-logs", response_model=schemas.LDLog) def create_ld_logs(log: schemas.LDTempBase, db: Session = Depends(get_db)): + """ + Endpoint called from debugger detecting client. Parses timestamp into datetime object. + Finds if head device and body device defined in message already exists and creates them if necessary. + Saves log into database + """ head_dev = crud.find_head_device(db, log.head_device) body_dev = crud.find_body_device(db, log.body_device) if head_dev is None: @@ -50,12 +61,18 @@ def create_ld_logs(log: schemas.LDTempBase, db: Session = Depends(get_db)): @usblogs.get("/logs", response_model=List[schemas.USBLog]) def read_logs(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns all usb logs saved in database + """ items = crud.get_logs(db, skip=skip, limit=limit) return items @usblogs.get("/logs/{device_id}", response_model=List[schemas.USBLog]) def read_log(device_id: int, db: Session = Depends(get_db)): + """ + Returns one specific log by given id + """ db_log = crud.get_log(db, device_id=device_id) if db_log is None: raise HTTPException(status_code=404, detail="Logs not found") diff --git a/server/sql_app/api/usb_logs_web.py b/server/sql_app/api/usb_logs_web.py index fbce50b..72bb220 100644 --- a/server/sql_app/api/usb_logs_web.py +++ b/server/sql_app/api/usb_logs_web.py @@ -10,8 +10,11 @@ from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) -templates = Jinja2Templates(directory="templates/usb-logs") +# Path to html templates used in this file +templates = Jinja2Templates(directory="../templates/usb-logs") + +# prefix used for all endpoints in this file usblogs_web = APIRouter(prefix="/api/v1") @@ -26,6 +29,9 @@ def get_db(): @usblogs_web.get("/logs-web", response_class=HTMLResponse) async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Returns template with all usb logs currently saved in database with its pcs, teams and licenses. + """ logs = crud.get_logs(db, skip=skip, limit=limit) pcs = [] for log in logs: @@ -42,6 +48,9 @@ async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Sessi async def filter_logs(request: Request, pc: str = Form("all"), team: str = Form("all"), lic: str = Form("all"), skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): + """ + Endpoint used for filtering usb logs by user given form inputs. + """ log = crud.get_filtered_logs(db, pc, team, lic) logs_ids = [] for l in log: diff --git a/server/sql_app/crud.py b/server/sql_app/crud.py index 239b6fb..eb3b7f8 100644 --- a/server/sql_app/crud.py +++ b/server/sql_app/crud.py @@ -6,20 +6,32 @@ from . import models, schemas def get_device(db: Session, device_id: int): + """ + returns one specific devices by given id + """ return db.query(models.Device).filter(models.Device.id == device_id).first() def get_devices(db: Session, skip: int = 0, limit: int = 100): + """ + returns all devices in database + """ return db.query(models.Device).offset(skip).limit(limit).all() def find_device(db: Session, device: schemas.DeviceBase): + """ + finds one device with product_id, vendor_id and serial_number same as in given DeviceBase object + """ return db.query(models.Device).filter(and_(models.Device.product_id == device.product_id, models.Device.vendor_id == device.vendor_id, models.Device.serial_number == device.serial_number)).first() def create_device(db: Session, device: schemas.DeviceBase): + """ + creates new device with data from given DeviceBase object + """ db_device = models.Device(vendor_id=device.vendor_id, product_id=device.product_id, serial_number=device.serial_number, assigned=False) db.add(db_device) @@ -29,18 +41,30 @@ def create_device(db: Session, device: schemas.DeviceBase): def get_license(db: Session, license_id: int): + """ + returns one specific license by given id + """ return db.query(models.License).filter(models.License.id == license_id).first() def get_licenses(db: Session, skip: int = 0, limit: int = 100): + """ + returns all licenses in database + """ return db.query(models.License).offset(skip).limit(limit).all() def find_license(db: Session, name: str): + """ + finds one license by given string name + """ return db.query(models.License).filter(models.License.name == name).first() def create_license(db: Session, name: str, expdate: date): + """ + creates new license with given name and expiration date + """ db_license = models.License(name=name, expiration_date=expdate) db.add(db_license) db.commit() @@ -49,10 +73,16 @@ def create_license(db: Session, name: str, expdate: date): def get_license_devices(db: Session, license_id: int): + """ + returns all entries in devices_licenses table + """ return db.query(models.DeviceLicense).filter(models.DeviceLicense.license_id == license_id).all() def create_device_license(db: Session, device: int, license: int, time: datetime): + """ + creates new entry in devices_licenses table with device id, license id and time. + """ db_device_license = models.DeviceLicense(device_id=device, license_id=license, assigned_datetime=time) db.add(db_device_license) @@ -62,14 +92,23 @@ def create_device_license(db: Session, device: int, license: int, time: datetime def find_pc_by_username(db: Session, name: str): + """ + Finds one pc by given username + """ return db.query(models.PC).filter(models.PC.username == name).first() def get_pc(db: Session, pc_id: int): + """ + returns one specific pc by given id + """ return db.query(models.PC).filter(models.PC.id == pc_id).first() def update_pc(db: Session, pc_id: int, team: str): + """ + Function updates team of one specific pc + """ old_pc = get_pc(db, pc_id) team = get_team(db, int(team)) new = {'id': old_pc.id, 'username': old_pc.username, 'hostname': old_pc.hostname, 'assigned': True, @@ -82,31 +121,52 @@ def update_pc(db: Session, pc_id: int, team: str): def get_pcs(db: Session, skip: int = 0, limit: int = 100): + """ + returns all pcs in database + """ return db.query(models.PC).offset(skip).limit(limit).all() def find_pc(db: Session, username: str, hostname: str): + """ + Finds one pc with given username and hostname + """ return db.query(models.PC).filter(and_(models.PC.username == username, models.PC.hostname == hostname)).first() def find_pc_by_name(db: Session, username: str): + """ + Finds one pc by its username + """ return db.query(models.PC).filter(models.PC.username == username).first() def find_pc_by_name_all(db: Session, username: str): + """ + Finds all pcs with same username + """ return db.query(models.PC).filter(models.PC.username == username).offset(0).limit(100).all() def find_pcs(db: Session, pcs: []): + """ + Finds all pcs with ids in given id array + """ return db.query(models.PC).filter(models.PC.id.in_(pcs)).all() def get_pcs_by_team(db: Session, team_id: int): + """ + returns all pcs in given team by team id + """ return db.query(models.PC).filter(models.PC.team_id == team_id).all() def create_pc(db: Session, user: str, host: str): + """ + creates new pc with given username and hostname + """ db_pc = models.PC(username=user, hostname=host, assigned=False) db.add(db_pc) db.commit() @@ -115,18 +175,30 @@ def create_pc(db: Session, user: str, host: str): def get_team(db: Session, team_id: int): + """ + returns one specific team wit given id + """ return db.query(models.Team).filter(models.Team.id == team_id).first() def get_teams(db: Session, skip: int = 0, limit: int = 100): + """ + returns all teams currently saved in database + """ return db.query(models.Team).offset(skip).limit(limit).all() def find_team(db: Session, name: str): + """ + Finds one specific team by its name + """ return db.query(models.Team).filter(models.Team.name == name).first() def create_team(db: Session, name: str): + """ + Creates new team with given name + """ db_team = models.Team(name=name) db.add(db_team) db.commit() @@ -135,18 +207,30 @@ def create_team(db: Session, name: str): def get_head_device(db: Session, head_id: int): + """ + Returns one specific head device by given id + """ return db.query(models.HeadDevice).filter(models.HeadDevice.id == head_id).first() def get_head_devices(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all head devices saved in database + """ return db.query(models.HeadDevice).offset(skip).limit(limit).all() def find_head_device(db: Session, serial: schemas.HeadDeviceBase): + """ + Finds one head device by its serial number + """ return db.query(models.HeadDevice).filter(models.HeadDevice.serial_number == serial.serial_number).first() def create_head_device(db: Session, log: schemas.HeadDeviceBase): + """ + Creates new head device + """ db_head = models.HeadDevice(serial_number=log.serial_number) db.add(db_head) db.commit() @@ -155,18 +239,30 @@ def create_head_device(db: Session, log: schemas.HeadDeviceBase): def get_body_device(db: Session, body_id: int): + """ + Returns one specific body device by given id + """ return db.query(models.BodyDevice).filter(models.BodyDevice.id == body_id).first() def get_body_devices(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all body devices saved in database + """ return db.query(models.BodyDevice).offset(skip).limit(limit).all() def find_body_device(db: Session, serial: schemas.BodyDeviceBase): + """ + Finds one body device by its serial number + """ return db.query(models.BodyDevice).filter(models.BodyDevice.serial_number == serial.serial_number).first() def create_body_device(db: Session, log: schemas.BodyDeviceBase): + """ + Creates new Body device + """ db_body = models.BodyDevice(serial_number=log.serial_number) db.add(db_body) db.commit() @@ -175,10 +271,16 @@ def create_body_device(db: Session, log: schemas.BodyDeviceBase): def get_ld_logs(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all ld debugger logs in database + """ return db.query(models.LDLog).offset(skip).limit(limit).all() def create_ld_logs(db: Session, item: schemas.LDTempBase, head_id: int, body_id: int, pc_id: int, date: datetime): + """ + Creates new ld log for ld_logs database table + """ db_ld = models.LDLog(pc_id=pc_id, timestamp=date, status=item.status, head_id=head_id, body_id=body_id) db.add(db_ld) db.commit() @@ -187,18 +289,31 @@ def create_ld_logs(db: Session, item: schemas.LDTempBase, head_id: int, body_id: def get_logs(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all usb logs in database ordered by timestamp + """ return db.query(models.USBLog).order_by(desc(models.USBLog.timestamp)).offset(skip).limit(limit).all() def get_log(db: Session, device_id: int, skip: int = 0, limit: int = 100): + """ + Returns all usb logs in database sorted by id + """ return db.query(models.USBLog).filter(models.USBLog.device_id == device_id).offset(skip).limit(limit).all() def find_filtered_logs(db: Session, logs: []): + """ + Returns all usb logs with ids in given id array. + """ return db.query(models.USBLog).filter(models.USBLog.id.in_(logs)).order_by(desc(models.USBLog.timestamp)).all() def get_filtered_logs(db: Session, pc: str, tema: str, lic: str): + """ + Function creates query string used for filtering by pc username, team name and license name. + Depending on selected filters assembles query string for database + """ execute_string = "SELECT * FROM usb_logs AS logs" if pc != "all": pcs = find_pc_by_username(db, pc) @@ -226,11 +341,15 @@ def get_filtered_logs(db: Session, pc: str, tema: str, lic: str): else: execute_string += " WHERE logs.device_id IN " + defin_ids + # executing assembled query string result = db.execute(execute_string) return result def create_device_logs(db: Session, item: schemas.USBTempBase, dev_id: int, pc_id: int, date: datetime): + """ + Creates new USB log for usb_logs database table + """ db_log = models.USBLog(pc_id=pc_id, timestamp=date, status=item.status, device_id=dev_id) db.add(db_log) db.commit() diff --git a/server/sql_app/database.py b/server/sql_app/database.py index 6db3630..842e1ac 100644 --- a/server/sql_app/database.py +++ b/server/sql_app/database.py @@ -1,18 +1,25 @@ from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker -''' + + + +# used mainly for testing purposes. Creates local sqllite data file SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db" engine = create_engine( SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} ) ''' + +# Defining connection url with postgresql database SQLALCHEMY_DATABASE_URL = "postgresql://postgres:postgres@10.5.0.5:5432/usb_api_db" +# Creating engine for database communication engine = create_engine( SQLALCHEMY_DATABASE_URL ) - +''' +# Session maker for data transmissions SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() \ No newline at end of file diff --git a/server/sql_app/main.py b/server/sql_app/main.py index 56e7830..f55ec4f 100644 --- a/server/sql_app/main.py +++ b/server/sql_app/main.py @@ -13,19 +13,22 @@ from fastapi import FastAPI app = FastAPI() + +# including routers for endpoints used by clients app.include_router(device) app.include_router(licenses) app.include_router(pcs) app.include_router(usblogs) app.include_router(teams) +# including routers for endpoints called from web app.include_router(device_web) app.include_router(licenses_web) app.include_router(pcs_web) app.include_router(teams_web) app.include_router(usblogs_web) -''' + if __name__ == "__main__": uvicorn.run(app, host="192.168.0.22", port=8000) -''' + diff --git a/server/sql_app/models.py b/server/sql_app/models.py index a4837e1..1040967 100644 --- a/server/sql_app/models.py +++ b/server/sql_app/models.py @@ -5,6 +5,9 @@ from .database import Base class Device(Base): + """ + Class defining database table devices + """ __tablename__ = "devices" id = Column(Integer, primary_key=True, index=True) @@ -13,11 +16,16 @@ class Device(Base): serial_number = Column(String, index=True, nullable=False) assigned = Column(Boolean, index=True, nullable=False) + # relationships for foreign keys, thus connecting table with usb_logs and licenses + # tables logs = relationship("USBLog", back_populates="device") licenses = relationship("DeviceLicense", back_populates="device_lic") class USBLog(Base): + """ + Class defining database table usb_logs + """ __tablename__ = "usb_logs" id = Column(Integer, primary_key=True, index=True) @@ -26,21 +34,30 @@ class USBLog(Base): status = Column(String, index=True, nullable=False) device_id = Column(Integer, ForeignKey("devices.id")) + # relationships for foreign keys, thus connecting table with devices and pc + # tables device = relationship("Device", back_populates="logs") pc = relationship("PC", back_populates="logs_pc") class License(Base): + """ + Class defining database table licenses + """ __tablename__ = "licenses" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True, nullable=False) expiration_date = Column(DateTime(timezone=True), server_default=func.now()) + # relationships for foreign keys, thus connecting table with devices table devices = relationship("DeviceLicense", back_populates="licenses") class DeviceLicense(Base): + """ + Class defining database table devices_licenses + """ __tablename__ = "devices_licenses" id = Column(Integer, primary_key=True, index=True) @@ -48,11 +65,16 @@ class DeviceLicense(Base): license_id = Column(Integer, ForeignKey("licenses.id")) assigned_datetime = Column(String, index=True, nullable=False) + # relationships for foreign keys, thus connecting table with devices and licenses + # tables device_lic = relationship("Device", back_populates="licenses") licenses = relationship("License", back_populates="devices") class PC(Base): + """ + Class defining database table pc + """ __tablename__ = "pc" id = Column(Integer, primary_key=True, index=True) @@ -61,38 +83,56 @@ class PC(Base): assigned = Column(Boolean, index=True, nullable=False) team_id = Column(Integer, ForeignKey("teams.id")) + # relationships for foreign keys, thus connecting table with teams, usb_logs and ld_logs + # tables team = relationship("Team", back_populates="pcs") logs_pc = relationship("USBLog", back_populates="pc") ld_pc = relationship("LDLog", back_populates="ldpc") class Team(Base): + """ + Class defining database table teams + """ __tablename__ = "teams" id = Column(Integer, primary_key=True, index=True) name = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with pc table pcs = relationship("PC", back_populates="team") class HeadDevice(Base): + """ + Class defining database table head_devices + """ __tablename__ = "head_devices" id = Column(Integer, primary_key=True, index=True) serial_number = Column(String, index=True, nullable=False) + # relationships for foreign keys, thus connecting table with ld_logs table h_logs = relationship("LDLog", back_populates="head_device") class BodyDevice(Base): + """ + Class defining database table body_devices + """ __tablename__ = "body_devices" id = Column(Integer, primary_key=True, index=True) serial_number = Column(String, index=True, nullable=False) + # relationships for foreign keys, thus connecting table with ld_logs table b_logs = relationship("LDLog", back_populates="body_device") class LDLog(Base): + """ + Class defining database table ld_logs + """ __tablename__ = "ld_logs" id = Column(Integer, primary_key=True, index=True) @@ -102,6 +142,8 @@ class LDLog(Base): head_id = Column(Integer, ForeignKey("head_devices.id")) body_id = Column(Integer, ForeignKey("body_devices.id")) + # relationships for foreign keys, thus connecting table with pc, head_devices and body_devices + # tables ldpc = relationship("PC", back_populates="ld_pc") head_device = relationship("HeadDevice", back_populates="h_logs") body_device = relationship("BodyDevice", back_populates="b_logs") diff --git a/server/sql_app/schemas.py b/server/sql_app/schemas.py index 25baafd..c0fe099 100644 --- a/server/sql_app/schemas.py +++ b/server/sql_app/schemas.py @@ -14,6 +14,9 @@ class DeviceLicenseCreate(DeviceLicenseBase): class DeviceLicense(DeviceLicenseCreate): + """ + Class used for creating and reading devices_licenses entries + """ id: int class Config: @@ -30,6 +33,9 @@ class USBLogCreate(USBLogBase): class USBLog(USBLogBase): + """ + Class used for creating and reading usb_logs entries + """ id: int device_id: int pc_id: int @@ -49,6 +55,9 @@ class DeviceCreate(DeviceBase): class Device(DeviceCreate): + """ + Class used for creating and reading devices entries + """ id: int assigned: bool logs: List[USBLog] = [] @@ -68,6 +77,9 @@ class LDLogCreate(LDLogBase): class LDLog(LDLogCreate): + """ + Class used for creating and reading ld_logs entries + """ id: int head_id: int body_id: int @@ -85,6 +97,9 @@ class BodyDeviceCreate(BodyDeviceBase): class BodyDevice(BodyDeviceCreate): + """ + Class used for creating and reading body_devices entries + """ id: int logs: List[LDLog] = [] @@ -101,6 +116,9 @@ class HeadDeviceCreate(HeadDeviceBase): class HeadDevice(HeadDeviceCreate): + """ + Class used for creating and reading head_devices entries + """ id: int logs: List[LDLog] = [] @@ -118,6 +136,9 @@ class PCCreate(PCBase): class PC(PCCreate): + """ + Class used for creating and reading pc entries + """ id: int assigned: bool logs_pc: List[USBLog] = [] @@ -135,6 +156,9 @@ class TeamCreate(TeamBase): class Team(TeamCreate): + """ + Class used for creating and reading team entries + """ id: int pcs: List[PC] = [] @@ -152,6 +176,9 @@ class LicenseCreate(LicenseBase): class License(LicenseCreate): + """ + Class used for creating and reading licenses entries + """ id: int devices: List[DeviceLicense] = [] @@ -160,6 +187,9 @@ class License(LicenseCreate): class USBTempBase(BaseModel): + """ + Class used for reading data from keyman detecting client messages + """ username: str hostname: str timestamp: str @@ -180,6 +210,9 @@ class USBTemp(USBTempBase): class LDTempBase(BaseModel): + """ + Class used for reading data from debugger detecting client messages + """ username: str hostname: str timestamp: str -- GitLab From 4babde6cd991d06de409029153111de7a09bfc36 Mon Sep 17 00:00:00 2001 From: Matej Zeman <zeman339@gmail.com> Date: Tue, 26 Apr 2022 23:47:21 +0200 Subject: [PATCH 02/13] re #9577 Api code documentation. --- server/sql_app/api/devices_web.py | 2 +- server/sql_app/api/licenses_web.py | 4 ++-- server/sql_app/api/pcs_web.py | 2 +- server/sql_app/api/teams_web.py | 2 +- server/sql_app/api/usb_logs_web.py | 2 +- server/sql_app/database.py | 4 ++-- server/sql_app/main.py | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/server/sql_app/api/devices_web.py b/server/sql_app/api/devices_web.py index 76b3cb8..2ab3dc0 100644 --- a/server/sql_app/api/devices_web.py +++ b/server/sql_app/api/devices_web.py @@ -13,7 +13,7 @@ from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) # Path to html templates used in this file -templates = Jinja2Templates(directory="../templates/devices") +templates = Jinja2Templates(directory="templates/devices") # prefix used for all endpoints in this file device_web = APIRouter(prefix="/api/v1") diff --git a/server/sql_app/api/licenses_web.py b/server/sql_app/api/licenses_web.py index bfa9362..4316dd6 100644 --- a/server/sql_app/api/licenses_web.py +++ b/server/sql_app/api/licenses_web.py @@ -13,8 +13,8 @@ from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) # Path to html templates used in this file -templates = Jinja2Templates(directory="../templates/licenses") -device_templates = Jinja2Templates(directory="../templates/devices") +templates = Jinja2Templates(directory="templates/licenses") +device_templates = Jinja2Templates(directory="templates/devices") # prefix used for all endpoints in this file licenses_web = APIRouter(prefix="/api/v1") diff --git a/server/sql_app/api/pcs_web.py b/server/sql_app/api/pcs_web.py index 000e771..a5243fd 100644 --- a/server/sql_app/api/pcs_web.py +++ b/server/sql_app/api/pcs_web.py @@ -11,7 +11,7 @@ from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) # Path to html templates used in this file -templates = Jinja2Templates(directory="../templates/pcs") +templates = Jinja2Templates(directory="templates/pcs") # prefix used for all endpoints in this file pcs_web = APIRouter(prefix="/api/v1") diff --git a/server/sql_app/api/teams_web.py b/server/sql_app/api/teams_web.py index a7423b7..d3b23d0 100644 --- a/server/sql_app/api/teams_web.py +++ b/server/sql_app/api/teams_web.py @@ -12,7 +12,7 @@ from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) # Path to html templates used in this file -templates = Jinja2Templates(directory="../templates/teams") +templates = Jinja2Templates(directory="templates/teams") # prefix used for all endpoints in this file teams_web = APIRouter(prefix="/api/v1") diff --git a/server/sql_app/api/usb_logs_web.py b/server/sql_app/api/usb_logs_web.py index 72bb220..b745384 100644 --- a/server/sql_app/api/usb_logs_web.py +++ b/server/sql_app/api/usb_logs_web.py @@ -12,7 +12,7 @@ from fastapi.templating import Jinja2Templates models.Base.metadata.create_all(bind=engine) # Path to html templates used in this file -templates = Jinja2Templates(directory="../templates/usb-logs") +templates = Jinja2Templates(directory="templates/usb-logs") # prefix used for all endpoints in this file usblogs_web = APIRouter(prefix="/api/v1") diff --git a/server/sql_app/database.py b/server/sql_app/database.py index 842e1ac..5269b28 100644 --- a/server/sql_app/database.py +++ b/server/sql_app/database.py @@ -3,7 +3,7 @@ from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker - +''' # used mainly for testing purposes. Creates local sqllite data file SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db" engine = create_engine( @@ -18,7 +18,7 @@ SQLALCHEMY_DATABASE_URL = "postgresql://postgres:postgres@10.5.0.5:5432/usb_api_ engine = create_engine( SQLALCHEMY_DATABASE_URL ) -''' + # Session maker for data transmissions SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) diff --git a/server/sql_app/main.py b/server/sql_app/main.py index f55ec4f..d871b3e 100644 --- a/server/sql_app/main.py +++ b/server/sql_app/main.py @@ -28,7 +28,7 @@ app.include_router(pcs_web) app.include_router(teams_web) app.include_router(usblogs_web) - +''' if __name__ == "__main__": uvicorn.run(app, host="192.168.0.22", port=8000) - +''' -- GitLab From e10ddd9866b5f001a1eb07d8fc431f4d9fbbfbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Zeman?= <zemanm98@students.zcu.cz> Date: Wed, 27 Apr 2022 13:49:57 +0000 Subject: [PATCH 03/13] User documentation --- README.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d3b683c..c75cf40 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,37 @@ -# Automatická detekce a dokumentace pĹ™ipojenĂ˝ch USB zaĹ™ĂzenĂ - Bug Thugs +# Automatic detection and documentation of connected USB devices - Server - Bug Thugs + +--- + +- [Description](#description) +- [Build](#build) +- [Execution](#execution) + +--- + +## Description + +This server application provides data via endpoints defined in **sql_app.api** package. Files in this package are divided by their respetive funcionality. File **usb_logs_web.py** provides endpoints and methods for main web view **/api/v1/logs-web**, file **usb_logs.py** provides endpoints and methods for client applications. + +**sql_app** package contains files for database communication. **models.py** and **schemas.py** provides classes for mapping objects to database table entries, **database.py** defines database communication session and **crud.py** contains methods with database queries for reading, updating and saving data from client applications and web interfaces. + + +## Build + +Server application comes with dockerFile and docker compose file so build is quite simple. In the server folder run command + +```bash +docker-compose up +``` + +And docker will create image for server application and postgresql database. Database files are stored in own folder, so saved data will be persistent even if docker daemon would unexpectedly shut down. + +## Web Views + +Data from database are easily accesibly from web browser. Main web views url is + +```bash +http://localhost:8000/api/v1/logs-web +``` + +On this page there is select box at the top of the page for accessing different views on other data in database as well as creating new ones -- GitLab From 84a5d57e0dc85c0369414003b950c705c3751f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Zeman?= <zemanm98@students.zcu.cz> Date: Mon, 2 May 2022 16:22:22 +0000 Subject: [PATCH 04/13] Update README.md --- README.md | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/README.md b/README.md index c75cf40..b1b42bb 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,2 @@ -# Automatic detection and documentation of connected USB devices - Server - Bug Thugs - ---- - -- [Description](#description) -- [Build](#build) -- [Execution](#execution) - ---- - -## Description - -This server application provides data via endpoints defined in **sql_app.api** package. Files in this package are divided by their respetive funcionality. File **usb_logs_web.py** provides endpoints and methods for main web view **/api/v1/logs-web**, file **usb_logs.py** provides endpoints and methods for client applications. - -**sql_app** package contains files for database communication. **models.py** and **schemas.py** provides classes for mapping objects to database table entries, **database.py** defines database communication session and **crud.py** contains methods with database queries for reading, updating and saving data from client applications and web interfaces. - - -## Build - -Server application comes with dockerFile and docker compose file so build is quite simple. In the server folder run command - -```bash -docker-compose up -``` - -And docker will create image for server application and postgresql database. Database files are stored in own folder, so saved data will be persistent even if docker daemon would unexpectedly shut down. - -## Web Views - -Data from database are easily accesibly from web browser. Main web views url is - -```bash -http://localhost:8000/api/v1/logs-web -``` - -On this page there is select box at the top of the page for accessing different views on other data in database as well as creating new ones +# Automatic detection and documentation of connected USB devices - Bug Thugs -- GitLab From a290ec5e1107940fc7e2c31098f302e245eed6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Zeman?= <zemanm98@students.zcu.cz> Date: Mon, 2 May 2022 16:23:04 +0000 Subject: [PATCH 05/13] user documentation --- server/README.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/server/README.md b/server/README.md index 7046460..c75cf40 100644 --- a/server/README.md +++ b/server/README.md @@ -1,2 +1,37 @@ -# Automatická detekce a dokumentace pĹ™ipojenĂ˝ch USB zaĹ™ĂzenĂ - Server - Bug Thugs +# Automatic detection and documentation of connected USB devices - Server - Bug Thugs + +--- + +- [Description](#description) +- [Build](#build) +- [Execution](#execution) + +--- + +## Description + +This server application provides data via endpoints defined in **sql_app.api** package. Files in this package are divided by their respetive funcionality. File **usb_logs_web.py** provides endpoints and methods for main web view **/api/v1/logs-web**, file **usb_logs.py** provides endpoints and methods for client applications. + +**sql_app** package contains files for database communication. **models.py** and **schemas.py** provides classes for mapping objects to database table entries, **database.py** defines database communication session and **crud.py** contains methods with database queries for reading, updating and saving data from client applications and web interfaces. + + +## Build + +Server application comes with dockerFile and docker compose file so build is quite simple. In the server folder run command + +```bash +docker-compose up +``` + +And docker will create image for server application and postgresql database. Database files are stored in own folder, so saved data will be persistent even if docker daemon would unexpectedly shut down. + +## Web Views + +Data from database are easily accesibly from web browser. Main web views url is + +```bash +http://localhost:8000/api/v1/logs-web +``` + +On this page there is select box at the top of the page for accessing different views on other data in database as well as creating new ones -- GitLab From af6f58869b8dc8d69b5cdd1afd163eed3004ceaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Zeman?= <zemanm98@students.zcu.cz> Date: Tue, 3 May 2022 11:56:59 +0200 Subject: [PATCH 06/13] prefix path fix and ld-logs new body and head devices fix --- server/sql_app/api/devices_web.py | 2 +- server/sql_app/api/licenses_web.py | 2 +- server/sql_app/api/pcs_web.py | 2 +- server/sql_app/api/teams_web.py | 2 +- server/sql_app/api/usb_logs.py | 4 ++-- server/sql_app/api/usb_logs_web.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/server/sql_app/api/devices_web.py b/server/sql_app/api/devices_web.py index 2ab3dc0..0c6fd0a 100644 --- a/server/sql_app/api/devices_web.py +++ b/server/sql_app/api/devices_web.py @@ -16,7 +16,7 @@ models.Base.metadata.create_all(bind=engine) templates = Jinja2Templates(directory="templates/devices") # prefix used for all endpoints in this file -device_web = APIRouter(prefix="/api/v1") +device_web = APIRouter(prefix="") # Dependency diff --git a/server/sql_app/api/licenses_web.py b/server/sql_app/api/licenses_web.py index 4316dd6..523dbd8 100644 --- a/server/sql_app/api/licenses_web.py +++ b/server/sql_app/api/licenses_web.py @@ -17,7 +17,7 @@ templates = Jinja2Templates(directory="templates/licenses") device_templates = Jinja2Templates(directory="templates/devices") # prefix used for all endpoints in this file -licenses_web = APIRouter(prefix="/api/v1") +licenses_web = APIRouter(prefix="") # Dependency diff --git a/server/sql_app/api/pcs_web.py b/server/sql_app/api/pcs_web.py index a5243fd..b9c614f 100644 --- a/server/sql_app/api/pcs_web.py +++ b/server/sql_app/api/pcs_web.py @@ -14,7 +14,7 @@ models.Base.metadata.create_all(bind=engine) templates = Jinja2Templates(directory="templates/pcs") # prefix used for all endpoints in this file -pcs_web = APIRouter(prefix="/api/v1") +pcs_web = APIRouter(prefix="") # Dependency diff --git a/server/sql_app/api/teams_web.py b/server/sql_app/api/teams_web.py index d3b23d0..30c1acf 100644 --- a/server/sql_app/api/teams_web.py +++ b/server/sql_app/api/teams_web.py @@ -15,7 +15,7 @@ models.Base.metadata.create_all(bind=engine) templates = Jinja2Templates(directory="templates/teams") # prefix used for all endpoints in this file -teams_web = APIRouter(prefix="/api/v1") +teams_web = APIRouter(prefix="") # Dependency diff --git a/server/sql_app/api/usb_logs.py b/server/sql_app/api/usb_logs.py index 2bf4067..e61697f 100644 --- a/server/sql_app/api/usb_logs.py +++ b/server/sql_app/api/usb_logs.py @@ -48,9 +48,9 @@ def create_ld_logs(log: schemas.LDTempBase, db: Session = Depends(get_db)): head_dev = crud.find_head_device(db, log.head_device) body_dev = crud.find_body_device(db, log.body_device) if head_dev is None: - crud.create_head_device(db, log.head_device) + head_dev = crud.create_head_device(db, log.head_device) if body_dev is None: - crud.create_body_device(db, log.body_device) + body_dev = crud.create_body_device(db, log.body_device) pc = crud.find_pc(db, log.username, log.hostname) if pc is None: diff --git a/server/sql_app/api/usb_logs_web.py b/server/sql_app/api/usb_logs_web.py index b745384..0559e59 100644 --- a/server/sql_app/api/usb_logs_web.py +++ b/server/sql_app/api/usb_logs_web.py @@ -15,7 +15,7 @@ models.Base.metadata.create_all(bind=engine) templates = Jinja2Templates(directory="templates/usb-logs") # prefix used for all endpoints in this file -usblogs_web = APIRouter(prefix="/api/v1") +usblogs_web = APIRouter(prefix="") # Dependency -- GitLab From 4858e9ee8b1da8db610e920f829d4ae5f1c74d9a Mon Sep 17 00:00:00 2001 From: Matej Zeman <zeman339@gmail.com> Date: Tue, 3 May 2022 17:02:35 +0200 Subject: [PATCH 07/13] Views navigation fix --- server/templates/devices/devicelicense.html | 2 +- server/templates/devices/devices.html | 14 +++++++------- server/templates/licenses/license_create.html | 2 +- server/templates/licenses/licenses.html | 8 ++++---- server/templates/pcs/pcs.html | 10 +++++----- server/templates/pcs/pcteam.html | 2 +- server/templates/teams/team_create.html | 2 +- server/templates/teams/teams.html | 10 +++++----- server/templates/usb-logs/logs.html | 10 +++++----- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/server/templates/devices/devicelicense.html b/server/templates/devices/devicelicense.html index 054c75b..f3780b1 100644 --- a/server/templates/devices/devicelicense.html +++ b/server/templates/devices/devicelicense.html @@ -9,7 +9,7 @@ <p>Product ID: {{device.product_id}}</p> <p>Serial Number: {{device.serial_number}}</p> </h6> -<form action="/api/v1/devices-web/{{device.id}}" method="post"> +<form action="/devices-web/{{device.id}}" method="post"> <label for="lic">Licenses:</label> <select id="lic" name="lic"> {% for license in licenses %} diff --git a/server/templates/devices/devices.html b/server/templates/devices/devices.html index b5afad1..4d4bd6e 100644 --- a/server/templates/devices/devices.html +++ b/server/templates/devices/devices.html @@ -7,14 +7,14 @@ <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> - <option value="/api/v1/logs-web">Logs</option> - <option value="/api/v1/devices-web">Devices</option> - <option value="/api/v1/teams-web">Teams</option> - <option value="/api/v1/pcs-web">PCs</option> + <option value="/logs-web">Logs</option> + <option value="/devices-web">Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> </select> <input type="submit" value="OK"> </form> -<form action="/api/v1/devices-web" method="post"> +<form action="/devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> <datalist id="licenses"> @@ -35,7 +35,7 @@ </TR> {% for i in range(devs) %} <TR> - <TD class="ID"><a href="/api/v1/device-license/{{devices[i].id}}">{{devices[i].id}}</a></TD> + <TD class="ID"><a href="/device-license/{{devices[i].id}}">{{devices[i].id}}</a></TD> <TD class="Vendor ID">{{devices[i].vendor_id}}</TD> <TD class="Product ID">{{devices[i].product_id}}</TD> <TD class="Serial Number">{{devices[i].serial_number}}</TD> @@ -53,7 +53,7 @@ <TD class="Product ID"></TD> <TD class="Serial Number"></TD> <TD class="License"> - <form action="/api/v1/license-create" method="get"> + <form action="/license-create" method="get"> <input type="submit" value="Add"> </form> </TD> diff --git a/server/templates/licenses/license_create.html b/server/templates/licenses/license_create.html index a68f7d8..709fb52 100644 --- a/server/templates/licenses/license_create.html +++ b/server/templates/licenses/license_create.html @@ -5,7 +5,7 @@ <title>Create a License</title> </head> <body> -<form action="/api/v1/licenses-web" method="post"> +<form action="/licenses-web" method="post"> <label for="name">Name:</label><br> <input type="text" id="name" name="name"><br><br> <label for="expdate">Expiration Date</label> diff --git a/server/templates/licenses/licenses.html b/server/templates/licenses/licenses.html index e456ab0..477983b 100644 --- a/server/templates/licenses/licenses.html +++ b/server/templates/licenses/licenses.html @@ -7,10 +7,10 @@ <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> - <option value="/api/v1/logs-web">Logs</option> - <option value="/api/v1/devices-web">Devices</option> - <option value="/api/v1/teams-web">Teams</option> - <option value="/api/v1/pcs-web">PCs</option> + <option value="/logs-web">Logs</option> + <option value="/devices-web">Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> </select> <input type="submit" value="OK"> </form> diff --git a/server/templates/pcs/pcs.html b/server/templates/pcs/pcs.html index 3b0a2eb..9b7c168 100644 --- a/server/templates/pcs/pcs.html +++ b/server/templates/pcs/pcs.html @@ -7,10 +7,10 @@ <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> - <option value="/api/v1/logs-web">Logs</option> - <option value="/api/v1/devices-web">Devices</option> - <option value="/api/v1/teams-web">Teams</option> - <option value="/api/v1/pcs-web">PCs</option> + <option value="/logs-web">Logs</option> + <option value="/devices-web">Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> </select> <input type="submit" value="OK"> </form> @@ -23,7 +23,7 @@ </TR> {% for pc in pcs %} <TR> - <TD class="ID"><a href="/api/v1/pc-team/{{pc.id}}">{{pc.id}}</a></TD> + <TD class="ID"><a href="/pc-team/{{pc.id}}">{{pc.id}}</a></TD> <TD class="Vendor ID">{{pc.username}}</TD> <TD class="Product ID">{{pc.hostname}}</TD> {% if pc.team == None %} diff --git a/server/templates/pcs/pcteam.html b/server/templates/pcs/pcteam.html index 8559cbc..eebc129 100644 --- a/server/templates/pcs/pcteam.html +++ b/server/templates/pcs/pcteam.html @@ -8,7 +8,7 @@ <h6><p>Username: {{pc.username}}</p> <p>Hostname: {{pc.hostname}}</p> </h6> -<form action="/api/v1/pcs-web/{{pc.id}}" method="post"> +<form action="/pcs-web/{{pc.id}}" method="post"> <label for="team">Teams:</label> <select id="team" name="team"> {% for team in teams %} diff --git a/server/templates/teams/team_create.html b/server/templates/teams/team_create.html index 3ae1c25..16dcc0a 100644 --- a/server/templates/teams/team_create.html +++ b/server/templates/teams/team_create.html @@ -5,7 +5,7 @@ <title>Create a Team</title> </head> <body> -<form action="/api/v1/teams-web" method="post"> +<form action="/teams-web" method="post"> <label for="name">Name:</label><br> <input type="text" id="name" name="name"><br><br> <input type="submit" value="Submit"> diff --git a/server/templates/teams/teams.html b/server/templates/teams/teams.html index 644f6d9..f3fe57a 100644 --- a/server/templates/teams/teams.html +++ b/server/templates/teams/teams.html @@ -7,10 +7,10 @@ <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> - <option value="/api/v1/logs-web">Logs</option> - <option value="/api/v1/devices-web">Devices</option> - <option value="/api/v1/teams-web">Teams</option> - <option value="/api/v1/pcs-web">PCs</option> + <option value="/logs-web">Logs</option> + <option value="/devices-web">Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> </select> <input type="submit" value="OK"> </form> @@ -26,7 +26,7 @@ </TR> {% endfor %} </table> -<form action="/api/v1/team-create" method="get"> +<form action="/team-create" method="get"> <input type="submit" value="Add"> </form> </body> diff --git a/server/templates/usb-logs/logs.html b/server/templates/usb-logs/logs.html index 722c811..ff75863 100644 --- a/server/templates/usb-logs/logs.html +++ b/server/templates/usb-logs/logs.html @@ -7,14 +7,14 @@ <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> - <option value="/api/v1/logs-web">Logs</option> - <option value="/api/v1/devices-web">Devices</option> - <option value="/api/v1/teams-web">Teams</option> - <option value="/api/v1/pcs-web">PCs</option> + <option value="/logs-web">Logs</option> + <option value="/devices-web">Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> </select> <input type="submit" value="OK"> </form> -<form action="/api/v1/logs-web" method="post"> +<form action="/logs-web" method="post"> <label for="pc">PC:</label> <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> <datalist id="pcs"> -- GitLab From c78ad6f2353029028a8a9f69a5827e4fbc21c9b6 Mon Sep 17 00:00:00 2001 From: Matej Zeman <zeman339@gmail.com> Date: Wed, 4 May 2022 13:30:59 +0200 Subject: [PATCH 08/13] re #9708 Login logic with fastapi-jwt --- server/requirements.txt | 3 +- server/sql_app/api/devices_web.py | 122 +++++++++++++++++++++++--- server/templates/devices/devices.html | 3 + server/templates/devices/login.html | 16 ++++ 4 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 server/templates/devices/login.html diff --git a/server/requirements.txt b/server/requirements.txt index acad635..a1e5719 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -4,4 +4,5 @@ SQLAlchemy==1.4.32 uvicorn==0.17.6 psycopg2-binary==2.8.6 jinja2==3.1.1 -python-multipart==0.0.5 \ No newline at end of file +python-multipart==0.0.5 +fastapi-jwt-auth=0.5.0 \ No newline at end of file diff --git a/server/sql_app/api/devices_web.py b/server/sql_app/api/devices_web.py index 0c6fd0a..f47bc28 100644 --- a/server/sql_app/api/devices_web.py +++ b/server/sql_app/api/devices_web.py @@ -1,14 +1,15 @@ -from typing import List - -from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form -from sqlalchemy.orm import Session -from sql_app import crud, models, schemas from datetime import datetime -from ..database import SessionLocal, engine -from fastapi import FastAPI, Request + +from fastapi import Depends, APIRouter, Form +from fastapi import Request from fastapi.responses import HTMLResponse -from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates +from fastapi_jwt_auth import AuthJWT +from pydantic import BaseModel +from sqlalchemy.orm import Session + +from sql_app import crud, models +from ..database import SessionLocal, engine models.Base.metadata.create_all(bind=engine) @@ -19,6 +20,32 @@ templates = Jinja2Templates(directory="templates/devices") device_web = APIRouter(prefix="") + +class Settings(BaseModel): + authjwt_secret_key: str = "secret" + # Configure application to store and get JWT from cookies + authjwt_token_location: set = {"cookies"} + # Disable CSRF Protection for this example. default is True + authjwt_cookie_csrf_protect: bool = False + + +@AuthJWT.load_config +def get_config(): + return Settings() + + +fake_users_db = { + "admin": { + "username": "admin", + "password": "admin" + }, + "editor": { + "username": "editor", + "password": "editor" + }, +} + + # Dependency def get_db(): db = SessionLocal() @@ -28,16 +55,86 @@ def get_db(): db.close() +@device_web.get("/token", response_class=HTMLResponse) +async def login_get(request: Request): + return templates.TemplateResponse("login.html", {"request": request}) + + +@device_web.post("/token", response_class=HTMLResponse) +async def login(username: str = Form(...), password: str = Form(...), Authorize: AuthJWT = Depends()): + user_dict = fake_users_db.get(username) + + access_token = Authorize.create_access_token(subject=username, expires_time=False) + refresh_token = Authorize.create_refresh_token(subject=username, expires_time=False) + + # Set the JWT cookies in the response + Authorize.set_access_cookies(access_token) + Authorize.set_refresh_cookies(refresh_token) + return """ + <html> + <head> + <title>Some HTML in here</title> + </head> + <body> + <h1>Look ma! HTML!</h1> + <form action="/devices-web" method="get"> + <input type="submit" value="Login" /> + </form> + </body> + </html> + """ + + +@device_web.post('/refresh') +def refresh(Authorize: AuthJWT = Depends()): + Authorize.jwt_refresh_token_required() + + current_user = Authorize.get_jwt_subject() + new_access_token = Authorize.create_access_token(subject=current_user) + # Set the JWT cookies in the response + Authorize.set_access_cookies(new_access_token) + return {"msg": "The token has been refresh"} + + +@device_web.get('/logout', response_class=HTMLResponse) +def logout(Authorize: AuthJWT = Depends()): + """ + Because the JWT are stored in an httponly cookie now, we cannot + log the user out by simply deleting the cookies in the frontend. + We need the backend to send us a response to delete the cookies. + """ + Authorize.jwt_required() + + Authorize.unset_jwt_cookies() + return """ + <html> + <head> + <title>Some HTML in here</title> + </head> + <body> + <h1>Look ma! HTML!</h1> + <form action="/devices-web" method="get"> + <input type="submit" value="Login" /> + </form> + </body> + </html> + """ + + @device_web.get("/devices-web", response_class=HTMLResponse) -async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): +async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Returns template with all devices and its current states """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + devices = crud.get_devices(db, skip=skip, limit=limit) statuses = [] # adding state for each device in list for i in range(0, len(devices)): - statuses.append(devices[i].logs[len(devices[i].logs)-1].status) + statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) licenses = crud.get_licenses(db, skip=skip, limit=limit) return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, "statuses": statuses, "licenses": licenses}) @@ -63,8 +160,9 @@ async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: for i in range(0, len(def_devices)): statuses.append(def_devices[i].logs[len(def_devices[i].logs) - 1].status) licenses = crud.get_licenses(db, skip=skip, limit=limit) - return templates.TemplateResponse("devices.html", {"request": request, "devs": len(def_devices), "devices": def_devices, - "statuses": statuses, "licenses": licenses}) + return templates.TemplateResponse("devices.html", + {"request": request, "devs": len(def_devices), "devices": def_devices, + "statuses": statuses, "licenses": licenses}) @device_web.get("/device-license/{device_id}", response_class=HTMLResponse) diff --git a/server/templates/devices/devices.html b/server/templates/devices/devices.html index 4d4bd6e..4c4774e 100644 --- a/server/templates/devices/devices.html +++ b/server/templates/devices/devices.html @@ -14,6 +14,9 @@ </select> <input type="submit" value="OK"> </form> +<form action="/token" method="get"> + <input type="submit" value="Login" /> +</form> <form action="/devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> diff --git a/server/templates/devices/login.html b/server/templates/devices/login.html new file mode 100644 index 0000000..622990b --- /dev/null +++ b/server/templates/devices/login.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Login</title> +</head> +<body> +<form action="/token" method="post"> + <label for="username">Username:</label><br> + <input type="text" id="username" name="username"><br><br> + <label for="password">Expiration Date</label> + <input type="text" id="password" name="password"> + <input type="submit" value="Submit"> +</form> +</body> +</html> \ No newline at end of file -- GitLab From 2fe004b11cd6d2407e4756fb93bb029d9e7ecccf Mon Sep 17 00:00:00 2001 From: Matej Zeman <zeman339@gmail.com> Date: Thu, 5 May 2022 14:49:38 +0200 Subject: [PATCH 09/13] re #9708 updated requirements. Added logout and template versions for host users. --- server/requirements.txt | 2 +- server/sql_app/api/auth.py | 112 +++++++++++++++++ server/sql_app/api/devices_web.py | 116 ++---------------- server/sql_app/api/ld_logs_web.py | 0 server/sql_app/api/licenses_web.py | 13 +- server/sql_app/api/pcs_web.py | 19 +-- server/sql_app/api/teams_web.py | 19 +-- server/sql_app/main.py | 2 + server/templates/{devices => auth}/login.html | 2 +- server/templates/devices/devices.html | 9 +- server/templates/devices/devices_normal.html | 62 ++++++++++ server/templates/licenses/licenses.html | 10 ++ server/templates/pcs/pcs.html | 10 ++ server/templates/pcs/pcs_normal.html | 48 ++++++++ server/templates/teams/teams.html | 10 ++ server/templates/teams/teams_normal.html | 40 ++++++ server/templates/usb-logs/logs.html | 10 ++ 17 files changed, 351 insertions(+), 133 deletions(-) create mode 100644 server/sql_app/api/auth.py create mode 100644 server/sql_app/api/ld_logs_web.py rename server/templates/{devices => auth}/login.html (91%) create mode 100644 server/templates/devices/devices_normal.html create mode 100644 server/templates/pcs/pcs_normal.html create mode 100644 server/templates/teams/teams_normal.html diff --git a/server/requirements.txt b/server/requirements.txt index a1e5719..e70f09c 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -5,4 +5,4 @@ uvicorn==0.17.6 psycopg2-binary==2.8.6 jinja2==3.1.1 python-multipart==0.0.5 -fastapi-jwt-auth=0.5.0 \ No newline at end of file +fastapi-jwt-auth==0.5.0 \ No newline at end of file diff --git a/server/sql_app/api/auth.py b/server/sql_app/api/auth.py new file mode 100644 index 0000000..8178130 --- /dev/null +++ b/server/sql_app/api/auth.py @@ -0,0 +1,112 @@ + + +from fastapi import Depends, APIRouter, Form +from fastapi import Request +from fastapi.responses import HTMLResponse +from fastapi.templating import Jinja2Templates +from fastapi.responses import HTMLResponse +from fastapi_jwt_auth import AuthJWT +from pydantic import BaseModel + + +# Path to html templates used in this file +templates = Jinja2Templates(directory="templates/auth") + +# prefix used for all endpoints in this file +auth = APIRouter(prefix="") + + + +class Settings(BaseModel): + authjwt_secret_key: str = "secret" + # Configure application to store and get JWT from cookies + authjwt_token_location: set = {"cookies"} + # Disable CSRF Protection for this example. default is True + authjwt_cookie_csrf_protect: bool = False + + +@AuthJWT.load_config +def get_config(): + return Settings() + + +fake_users_db = { + "admin": { + "username": "admin", + "password": "admin" + } +} + + +@auth.get("/login", response_class=HTMLResponse) +async def login_get(request: Request): + return templates.TemplateResponse("login.html", {"request": request}) + + +@auth.post("/login", response_class=HTMLResponse) +async def login(username: str = Form(...), password: str = Form(...), Authorize: AuthJWT = Depends()): + user_dict = fake_users_db.get(username) + + if user_dict != None: + if user_dict["username"] == username and user_dict["password"] == password: + access_token = Authorize.create_access_token(subject="admin", expires_time=False) + refresh_token = Authorize.create_refresh_token(subject="admin", expires_time=False) + else: + access_token = Authorize.create_access_token(subject="host", expires_time=False) + refresh_token = Authorize.create_refresh_token(subject="host", expires_time=False) + else: + access_token = Authorize.create_access_token(subject="host", expires_time=False) + refresh_token = Authorize.create_refresh_token(subject="host", expires_time=False) + + # Set the JWT cookies in the response + Authorize.set_access_cookies(access_token) + Authorize.set_refresh_cookies(refresh_token) + return """ + <html> + <head> + <title>Login</title> + </head> + <body> + <h1>Logged in</h1> + <form action="/logs-web" method="get"> + <input type="submit" value="Back" /> + </form> + </body> + </html> + """ + + +@auth.post('/refresh') +def refresh(Authorize: AuthJWT = Depends()): + Authorize.jwt_refresh_token_required() + + current_user = Authorize.get_jwt_subject() + new_access_token = Authorize.create_access_token(subject=current_user) + # Set the JWT cookies in the response + Authorize.set_access_cookies(new_access_token) + return {"msg": "The token has been refresh"} + + +@auth.get('/logout', response_class=HTMLResponse) +def logout(Authorize: AuthJWT = Depends()): + """ + Because the JWT are stored in an httponly cookie now, we cannot + log the user out by simply deleting the cookies in the frontend. + We need the backend to send us a response to delete the cookies. + """ + Authorize.jwt_optional() + + Authorize.unset_jwt_cookies() + return """ + <html> + <head> + <title>Logout</title> + </head> + <body> + <h1>Logged Out</h1> + <form action="/logs-web" method="get"> + <input type="submit" value="Back" /> + </form> + </body> + </html> + """ \ No newline at end of file diff --git a/server/sql_app/api/devices_web.py b/server/sql_app/api/devices_web.py index f47bc28..f10de1b 100644 --- a/server/sql_app/api/devices_web.py +++ b/server/sql_app/api/devices_web.py @@ -2,12 +2,12 @@ from datetime import datetime from fastapi import Depends, APIRouter, Form from fastapi import Request -from fastapi.responses import HTMLResponse +from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates from fastapi_jwt_auth import AuthJWT from pydantic import BaseModel from sqlalchemy.orm import Session - +from sql_app.api.auth import fake_users_db from sql_app import crud, models from ..database import SessionLocal, engine @@ -20,32 +20,6 @@ templates = Jinja2Templates(directory="templates/devices") device_web = APIRouter(prefix="") - -class Settings(BaseModel): - authjwt_secret_key: str = "secret" - # Configure application to store and get JWT from cookies - authjwt_token_location: set = {"cookies"} - # Disable CSRF Protection for this example. default is True - authjwt_cookie_csrf_protect: bool = False - - -@AuthJWT.load_config -def get_config(): - return Settings() - - -fake_users_db = { - "admin": { - "username": "admin", - "password": "admin" - }, - "editor": { - "username": "editor", - "password": "editor" - }, -} - - # Dependency def get_db(): db = SessionLocal() @@ -55,72 +29,6 @@ def get_db(): db.close() -@device_web.get("/token", response_class=HTMLResponse) -async def login_get(request: Request): - return templates.TemplateResponse("login.html", {"request": request}) - - -@device_web.post("/token", response_class=HTMLResponse) -async def login(username: str = Form(...), password: str = Form(...), Authorize: AuthJWT = Depends()): - user_dict = fake_users_db.get(username) - - access_token = Authorize.create_access_token(subject=username, expires_time=False) - refresh_token = Authorize.create_refresh_token(subject=username, expires_time=False) - - # Set the JWT cookies in the response - Authorize.set_access_cookies(access_token) - Authorize.set_refresh_cookies(refresh_token) - return """ - <html> - <head> - <title>Some HTML in here</title> - </head> - <body> - <h1>Look ma! HTML!</h1> - <form action="/devices-web" method="get"> - <input type="submit" value="Login" /> - </form> - </body> - </html> - """ - - -@device_web.post('/refresh') -def refresh(Authorize: AuthJWT = Depends()): - Authorize.jwt_refresh_token_required() - - current_user = Authorize.get_jwt_subject() - new_access_token = Authorize.create_access_token(subject=current_user) - # Set the JWT cookies in the response - Authorize.set_access_cookies(new_access_token) - return {"msg": "The token has been refresh"} - - -@device_web.get('/logout', response_class=HTMLResponse) -def logout(Authorize: AuthJWT = Depends()): - """ - Because the JWT are stored in an httponly cookie now, we cannot - log the user out by simply deleting the cookies in the frontend. - We need the backend to send us a response to delete the cookies. - """ - Authorize.jwt_required() - - Authorize.unset_jwt_cookies() - return """ - <html> - <head> - <title>Some HTML in here</title> - </head> - <body> - <h1>Look ma! HTML!</h1> - <form action="/devices-web" method="get"> - <input type="submit" value="Login" /> - </form> - </body> - </html> - """ - - @device_web.get("/devices-web", response_class=HTMLResponse) async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), Authorize: AuthJWT = Depends()): @@ -136,8 +44,12 @@ async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Se for i in range(0, len(devices)): statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) licenses = crud.get_licenses(db, skip=skip, limit=limit) - return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, - "statuses": statuses, "licenses": licenses}) + if current_user == "admin": + return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses}) + else: + return templates.TemplateResponse("devices_normal.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses}) @device_web.post("/devices-web", response_class=HTMLResponse) @@ -177,18 +89,10 @@ async def connect_dev_lic(request: Request, device_id: int, db: Session = Depend @device_web.post("/devices-web/{device_id}", response_class=HTMLResponse) -async def connect_post(request: Request, device_id: int, lic: str = Form(...), skip: int = 0, limit: int = 100, - db: Session = Depends(get_db)): +async def connect_post(device_id: int, lic: str = Form(...), db: Session = Depends(get_db)): """ Endpoint called from template for connecting device with license. Adds entry to devices_licenses table and returns template with all devices in database """ crud.create_device_license(db, device_id, int(lic), datetime.now()) - devices = crud.get_devices(db, skip=skip, limit=limit) - statuses = [] - # adding state for each device in list - for i in range(0, len(devices)): - statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) - licenses = crud.get_licenses(db, skip=skip, limit=limit) - return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, - "statuses": statuses, "licenses": licenses}) + return RedirectResponse("/devices-web") diff --git a/server/sql_app/api/ld_logs_web.py b/server/sql_app/api/ld_logs_web.py new file mode 100644 index 0000000..e69de29 diff --git a/server/sql_app/api/licenses_web.py b/server/sql_app/api/licenses_web.py index 523dbd8..cebf250 100644 --- a/server/sql_app/api/licenses_web.py +++ b/server/sql_app/api/licenses_web.py @@ -6,7 +6,7 @@ from datetime import date from sql_app import crud, models, schemas from ..database import SessionLocal, engine from fastapi import FastAPI, Request -from fastapi.responses import HTMLResponse +from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates @@ -47,18 +47,11 @@ async def read_licenses_web(request: Request, skip: int = 0, limit: int = 100, d @licenses_web.post("/licenses-web", response_class=HTMLResponse) -def create_license(request: Request, name: str = Form(...), expdate: date = Form(...), skip: int = 0, limit: int = 100, - db: Session = Depends(get_db)): +def create_license(name: str = Form(...), expdate: date = Form(...), db: Session = Depends(get_db)): """ Endpoint called from create license form. Creates new license and returns template with all licenses in database """ db_license = crud.create_license(db, name, expdate) if db_license is None: print("something went wrong") - devices = crud.get_devices(db, skip=skip, limit=limit) - statuses = [] - for i in range(0, len(devices)): - statuses.append(devices[i].logs[len(devices[i].logs) - 1].status) - licenses = crud.get_licenses(db, skip=skip, limit=limit) - return device_templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, - "statuses": statuses, "licenses": licenses}) \ No newline at end of file + return RedirectResponse("/devices-web") diff --git a/server/sql_app/api/pcs_web.py b/server/sql_app/api/pcs_web.py index b9c614f..3a5d66f 100644 --- a/server/sql_app/api/pcs_web.py +++ b/server/sql_app/api/pcs_web.py @@ -4,7 +4,8 @@ from sqlalchemy.orm import Session from sql_app import crud, models, schemas from ..database import SessionLocal, engine from fastapi import FastAPI, Request -from fastapi.responses import HTMLResponse +from fastapi.responses import HTMLResponse, RedirectResponse +from fastapi_jwt_auth import AuthJWT from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates @@ -27,12 +28,18 @@ def get_db(): @pcs_web.get("/pcs-web", response_class=HTMLResponse) -async def read_pcs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): +async def read_pcs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Returns template with all pcs currently saved in database """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() pcs = crud.get_pcs(db, skip=skip, limit=limit) - return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs}) + if current_user == "admin": + return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs}) + else: + return templates.TemplateResponse("pcs_normal.html", {"request": request, "pcs": pcs}) @pcs_web.get("/pc-team/{pc_id}", response_class=HTMLResponse) @@ -47,11 +54,9 @@ async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(ge @pcs_web.post("/pcs-web/{pc_id}", response_class=HTMLResponse) -async def connect_post(request: Request, pc_id: int, team: str = Form(...), skip: int = 0, limit: int = 100, - db: Session = Depends(get_db)): +async def connect_post(pc_id: int, team: str = Form(...), db: Session = Depends(get_db)): """ Endpoint called from within form for connecting pc with team. Updates certain pc with new team. """ old_pc = crud.update_pc(db, pc_id, team) - pcs = crud.get_pcs(db, skip=skip, limit=limit) - return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs}) + RedirectResponse("/pcs-web") diff --git a/server/sql_app/api/teams_web.py b/server/sql_app/api/teams_web.py index 30c1acf..3d9cfd6 100644 --- a/server/sql_app/api/teams_web.py +++ b/server/sql_app/api/teams_web.py @@ -5,7 +5,8 @@ from sqlalchemy.orm import Session from sql_app import crud, models, schemas from ..database import SessionLocal, engine from fastapi import FastAPI, Request -from fastapi.responses import HTMLResponse +from fastapi.responses import HTMLResponse, RedirectResponse +from fastapi_jwt_auth import AuthJWT from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates @@ -28,12 +29,18 @@ def get_db(): @teams_web.get("/teams-web", response_class=HTMLResponse) -async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): +async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Returns template with all teams currently saved in database """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() teams = crud.get_teams(db, skip=skip, limit=limit) - return templates.TemplateResponse("teams.html", {"request": request, "teams": teams}) + if current_user == "admin": + return templates.TemplateResponse("teams.html", {"request": request, "teams": teams}) + else: + return templates.TemplateResponse("teams_normal.html", {"request": request, "teams": teams}) @teams_web.get("/team-create", response_class=HTMLResponse) @@ -45,13 +52,11 @@ async def team_create_web(request: Request): @teams_web.post("/teams-web", response_class=HTMLResponse) -def create_team(request: Request, name: str = Form(...), skip: int = 0, limit: int = 100, - db: Session = Depends(get_db)): +def create_team(name: str = Form(...), db: Session = Depends(get_db)): """ Endpoint called from within form for creating new team. Creates new team and returns all teams in database """ team = crud.create_team(db, name) if team is None: print("something went wrong") - teams = crud.get_teams(db, skip=skip, limit=limit) - return templates.TemplateResponse("teams.html", {"request": request, "teams": teams}) + RedirectResponse("/teams-web") diff --git a/server/sql_app/main.py b/server/sql_app/main.py index d871b3e..774d8eb 100644 --- a/server/sql_app/main.py +++ b/server/sql_app/main.py @@ -9,6 +9,7 @@ from sql_app.api.usb_logs import usblogs from sql_app.api.usb_logs_web import usblogs_web from sql_app.api.teams import teams from sql_app.api.teams_web import teams_web +from sql_app.api.auth import auth from fastapi import FastAPI @@ -27,6 +28,7 @@ app.include_router(licenses_web) app.include_router(pcs_web) app.include_router(teams_web) app.include_router(usblogs_web) +app.include_router(auth) ''' if __name__ == "__main__": diff --git a/server/templates/devices/login.html b/server/templates/auth/login.html similarity index 91% rename from server/templates/devices/login.html rename to server/templates/auth/login.html index 622990b..49fdcdf 100644 --- a/server/templates/devices/login.html +++ b/server/templates/auth/login.html @@ -5,7 +5,7 @@ <title>Login</title> </head> <body> -<form action="/token" method="post"> +<form action="/login" method="post"> <label for="username">Username:</label><br> <input type="text" id="username" name="username"><br><br> <label for="password">Expiration Date</label> diff --git a/server/templates/devices/devices.html b/server/templates/devices/devices.html index 4c4774e..c1abf2d 100644 --- a/server/templates/devices/devices.html +++ b/server/templates/devices/devices.html @@ -3,6 +3,7 @@ <title>Devices Details</title> </head> <body> +<div style='float:left'> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -14,9 +15,15 @@ </select> <input type="submit" value="OK"> </form> -<form action="/token" method="get"> +</div> +<div style='float:left'> +<form action="/login" method="get"> <input type="submit" value="Login" /> </form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="/devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> diff --git a/server/templates/devices/devices_normal.html b/server/templates/devices/devices_normal.html new file mode 100644 index 0000000..18b21a4 --- /dev/null +++ b/server/templates/devices/devices_normal.html @@ -0,0 +1,62 @@ +<html> +<head> + <title>Devices Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/devices-web">Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +<form action="/devices-web" method="post"> + <label for="lic">License:</label> + <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> + <datalist id="licenses"> + {% for license in licenses %} + <option value="{{license.name}}"></option> + {% endfor %} + </datalist> + <input type="submit" value="Filter"> +</form> +<table> + <TR> + <TH>ID</TH> + <TH>Vendor ID</TH> + <TH>Product ID</TH> + <TH>Serial Number</TH> + <TH>Licenses</TH> + <TH>Status</TH> + </TR> + {% for i in range(devs) %} + <TR> + <TD class="ID">{{devices[i].id}}</TD> + <TD class="Vendor ID">{{devices[i].vendor_id}}</TD> + <TD class="Product ID">{{devices[i].product_id}}</TD> + <TD class="Serial Number">{{devices[i].serial_number}}</TD> + <TD class="License"> + {% for lic in devices[i].licenses %} + {{lic.licenses.name}}<BR> + {% endfor %} + </TD> + <TD class="Status">{{statuses[i]}}</TD> + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/licenses/licenses.html b/server/templates/licenses/licenses.html index 477983b..8e5ab8e 100644 --- a/server/templates/licenses/licenses.html +++ b/server/templates/licenses/licenses.html @@ -3,6 +3,7 @@ <title>Licenses Details</title> </head> <body> +<div style='float:left'> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -14,6 +15,15 @@ </select> <input type="submit" value="OK"> </form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <table> <TR> <TH>ID</TH> diff --git a/server/templates/pcs/pcs.html b/server/templates/pcs/pcs.html index 9b7c168..6532f24 100644 --- a/server/templates/pcs/pcs.html +++ b/server/templates/pcs/pcs.html @@ -3,6 +3,7 @@ <title>Pcs Details</title> </head> <body> +<div style='float:left'> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -14,6 +15,15 @@ </select> <input type="submit" value="OK"> </form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <table> <TR> <TH>ID</TH> diff --git a/server/templates/pcs/pcs_normal.html b/server/templates/pcs/pcs_normal.html new file mode 100644 index 0000000..bee77d2 --- /dev/null +++ b/server/templates/pcs/pcs_normal.html @@ -0,0 +1,48 @@ +<html> +<head> + <title>Pcs Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/devices-web">Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +<table> + <TR> + <TH>ID</TH> + <TH>Username</TH> + <TH>Hostname</TH> + <TH>Team</TH> + </TR> + {% for pc in pcs %} + <TR> + <TD class="ID">{{pc.id}}</TD> + <TD class="Vendor ID">{{pc.username}}</TD> + <TD class="Product ID">{{pc.hostname}}</TD> + {% if pc.team == None %} + <TD class="Team">NONE</TD> + {% else %} + <TD class="Team">{{pc.team.name}}</TD> + {% endif %} + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/teams/teams.html b/server/templates/teams/teams.html index f3fe57a..77e5052 100644 --- a/server/templates/teams/teams.html +++ b/server/templates/teams/teams.html @@ -3,6 +3,7 @@ <title>Teams Details</title> </head> <body> +<div style='float:left'> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -14,6 +15,15 @@ </select> <input type="submit" value="OK"> </form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <table> <TR> <TH>ID</TH> diff --git a/server/templates/teams/teams_normal.html b/server/templates/teams/teams_normal.html new file mode 100644 index 0000000..f1a5fc1 --- /dev/null +++ b/server/templates/teams/teams_normal.html @@ -0,0 +1,40 @@ +<html> +<head> + <title>Teams Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/devices-web">Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +<table> + <TR> + <TH>ID</TH> + <TH>Name</TH> + </TR> + {% for team in teams %} + <TR> + <TD class="ID">{{team.id}}</TD> + <TD class="Vendor ID">{{team.name}}</TD> + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/usb-logs/logs.html b/server/templates/usb-logs/logs.html index ff75863..7e7e4be 100644 --- a/server/templates/usb-logs/logs.html +++ b/server/templates/usb-logs/logs.html @@ -3,6 +3,7 @@ <title>Logs Details</title> </head> <body> +<div style='float:left'> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -14,6 +15,15 @@ </select> <input type="submit" value="OK"> </form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="/logs-web" method="post"> <label for="pc">PC:</label> <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> -- GitLab From 7fe7be79d4da62e8ab89c487ae57e8d6e0991f7a Mon Sep 17 00:00:00 2001 From: "zemanm98@students.zcu.cz" <Farnhait123*> Date: Sun, 8 May 2022 10:09:26 +0200 Subject: [PATCH 10/13] Added views for LD logs and forms for connecting body devices with licenses. --- server/sql_app/api/auth.py | 23 ++- server/sql_app/api/bodydevices_web.py | 128 +++++++++++++ server/sql_app/api/devices_web.py | 50 ++++- server/sql_app/api/ld_logs_web.py | 73 ++++++++ server/sql_app/api/licenses_web.py | 6 +- server/sql_app/api/pcs_web.py | 9 +- server/sql_app/api/teams_web.py | 9 +- server/sql_app/api/usb_logs_web.py | 10 +- server/sql_app/crud.py | 173 +++++++++++++++--- server/sql_app/main.py | 6 +- server/sql_app/models.py | 20 +- .../body-devices/body_device_license.html | 30 +++ .../templates/body-devices/body_devices.html | 72 ++++++++ .../body-devices/body_devices_normal.html | 63 +++++++ server/templates/devices/devicelicense.html | 9 + server/templates/devices/devices.html | 5 + server/templates/devices/devices_normal.html | 5 + server/templates/ld-logs/ldlogs.html | 85 +++++++++ server/templates/licenses/licenses.html | 2 + server/templates/pcs/pcs.html | 5 + server/templates/pcs/pcs_normal.html | 5 + server/templates/teams/team_create.html | 2 +- server/templates/teams/teams.html | 5 + server/templates/teams/teams_normal.html | 5 + server/templates/usb-logs/logs.html | 5 + 25 files changed, 746 insertions(+), 59 deletions(-) create mode 100644 server/sql_app/api/bodydevices_web.py create mode 100644 server/templates/body-devices/body_device_license.html create mode 100644 server/templates/body-devices/body_devices.html create mode 100644 server/templates/body-devices/body_devices_normal.html create mode 100644 server/templates/ld-logs/ldlogs.html diff --git a/server/sql_app/api/auth.py b/server/sql_app/api/auth.py index 8178130..069d27c 100644 --- a/server/sql_app/api/auth.py +++ b/server/sql_app/api/auth.py @@ -1,14 +1,10 @@ - - from fastapi import Depends, APIRouter, Form from fastapi import Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates -from fastapi.responses import HTMLResponse from fastapi_jwt_auth import AuthJWT from pydantic import BaseModel - # Path to html templates used in this file templates = Jinja2Templates(directory="templates/auth") @@ -29,7 +25,7 @@ class Settings(BaseModel): def get_config(): return Settings() - +# admin username and password fake_users_db = { "admin": { "username": "admin", @@ -40,13 +36,19 @@ fake_users_db = { @auth.get("/login", response_class=HTMLResponse) async def login_get(request: Request): + """ + return html template for login + """ return templates.TemplateResponse("login.html", {"request": request}) @auth.post("/login", response_class=HTMLResponse) async def login(username: str = Form(...), password: str = Form(...), Authorize: AuthJWT = Depends()): + """ + Endpoint called from login template. Checks if given username and password aligns with admin + username and password and returns token for browser according to given username and password + """ user_dict = fake_users_db.get(username) - if user_dict != None: if user_dict["username"] == username and user_dict["password"] == password: access_token = Authorize.create_access_token(subject="admin", expires_time=False) @@ -78,8 +80,11 @@ async def login(username: str = Form(...), password: str = Form(...), Authorize: @auth.post('/refresh') def refresh(Authorize: AuthJWT = Depends()): + """ + endpoint for refreshing browser token. Not used at the moment since lifetime of given tokens are + unlimited. + """ Authorize.jwt_refresh_token_required() - current_user = Authorize.get_jwt_subject() new_access_token = Authorize.create_access_token(subject=current_user) # Set the JWT cookies in the response @@ -90,9 +95,7 @@ def refresh(Authorize: AuthJWT = Depends()): @auth.get('/logout', response_class=HTMLResponse) def logout(Authorize: AuthJWT = Depends()): """ - Because the JWT are stored in an httponly cookie now, we cannot - log the user out by simply deleting the cookies in the frontend. - We need the backend to send us a response to delete the cookies. + Endpoint for deleting cookie token with acces role. """ Authorize.jwt_optional() diff --git a/server/sql_app/api/bodydevices_web.py b/server/sql_app/api/bodydevices_web.py new file mode 100644 index 0000000..9b13bb7 --- /dev/null +++ b/server/sql_app/api/bodydevices_web.py @@ -0,0 +1,128 @@ +from datetime import datetime + +from fastapi import Depends, APIRouter, Form +from fastapi import Request +from fastapi.responses import HTMLResponse, RedirectResponse +from fastapi.templating import Jinja2Templates +from fastapi_jwt_auth import AuthJWT +from pydantic import BaseModel +from sqlalchemy.orm import Session +from sql_app.api.auth import fake_users_db +from sql_app import crud, models +from ..database import SessionLocal, engine + +models.Base.metadata.create_all(bind=engine) + +# Path to html templates used in this file +templates = Jinja2Templates(directory="templates/body-devices") + +# prefix used for all endpoints in this file +body_device_web = APIRouter(prefix="") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@body_device_web.get("/body-devices-web", response_class=HTMLResponse) +async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): + """ + Returns template with all body devices and its current states + """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + + devices = crud.get_body_devices(db, skip=skip, limit=limit) + statuses = [] + # adding state for each device in list + for i in range(0, len(devices)): + statuses.append(devices[i].b_logs[len(devices[i].b_logs) - 1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + if current_user == "admin": + return templates.TemplateResponse("body_devices.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses, "user": current_user}) + else: + current_user = "guest" + return templates.TemplateResponse("body_devices_normal.html", {"request": request, "devs": len(devices), "devices": devices, + "statuses": statuses, "licenses": licenses, "user": current_user}) + + +@body_device_web.post("/body-devices-web", response_class=HTMLResponse) +async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: str = Form("all"), + db: Session = Depends(get_db), Authorize: AuthJWT = Depends()): + """ + Endpoint used for filtering body devices by license. returns html template with only + body devices that has assigned license defined by user input + """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + devices = crud.get_body_devices(db, skip=skip, limit=limit) + def_devices = [] + for dev in devices: + for l in dev.debug_licenses: + if dev not in def_devices and l.b_licenses.name == lic: + def_devices.append(dev) + # if input was default all + if lic == "all": + def_devices = devices + statuses = [] + for i in range(0, len(def_devices)): + statuses.append(def_devices[i].b_logs[len(def_devices[i].b_logs) - 1].status) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + if current_user == "admin": + return templates.TemplateResponse("body_devices.html", + {"request": request, "devs": len(def_devices), "devices": def_devices, + "statuses": statuses, "licenses": licenses, "user": current_user}) + else: + current_user = "guest" + return templates.TemplateResponse("body_devices_normal.html", + {"request": request, "devs": len(def_devices), "devices": def_devices, + "statuses": statuses, "licenses": licenses, "user": current_user}) + + +@body_device_web.get("/body-device-license/{device_id}", response_class=HTMLResponse) +async def connect_dev_lic(request: Request, device_id: int, db: Session = Depends(get_db)): + """ + Returns template with one body device and all available licenses that can be assigned to it. + """ + device = crud.get_body_device(db, device_id) + dev_licenses = crud.get_bodydevice_license(db, device_id) + lic_names = [] + dev_lics = [] + for dev_lic in dev_licenses: + dev_lics.append(dev_lic.b_licenses) + for dev_lic in dev_licenses: + lic_names.append(dev_lic.b_licenses.name) + licenses = crud.get_licenses(db, 0, 100) + lic_left = [] + for lic in licenses: + if lic.name not in lic_names and lic not in lic_left: + lic_left.append(lic) + return templates.TemplateResponse("body_device_license.html", + {"request": request, "device": device, "licenses": lic_left, "dev_lic": dev_lics}) + + +@body_device_web.post("/body-devices-web/{device_id}") +async def connect_post(device_id: int, lic: str = Form(...), db: Session = Depends(get_db)): + """ + Endpoint called from template for connecting body device with license. Adds entry to bodydevices_licenses + table and redirects to body-devices-web endpoint + """ + crud.create_body_device_license(db, device_id, int(lic), datetime.now()) + return RedirectResponse(url=f"/body-devices-web", status_code=303) + + +@body_device_web.post("/body-devices-web-del/{device_id}") +async def delete_post(device_id: int, b_lic: str = Form(...), db: Session = Depends(get_db)): + """ + Endpoint called from template for connecting body device with license. Adds entry to devices_licenses + table and redirects to body-devices-web endpoint + """ + crud.delete_bodydevice_license(db, device_id, int(b_lic)) + return RedirectResponse(url=f"/body-devices-web", status_code=303) \ No newline at end of file diff --git a/server/sql_app/api/devices_web.py b/server/sql_app/api/devices_web.py index f10de1b..97c38a5 100644 --- a/server/sql_app/api/devices_web.py +++ b/server/sql_app/api/devices_web.py @@ -46,19 +46,22 @@ async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Se licenses = crud.get_licenses(db, skip=skip, limit=limit) if current_user == "admin": return templates.TemplateResponse("devices.html", {"request": request, "devs": len(devices), "devices": devices, - "statuses": statuses, "licenses": licenses}) + "statuses": statuses, "licenses": licenses, "user": current_user}) else: + current_user = "guest" return templates.TemplateResponse("devices_normal.html", {"request": request, "devs": len(devices), "devices": devices, - "statuses": statuses, "licenses": licenses}) + "statuses": statuses, "licenses": licenses, "user": current_user}) @device_web.post("/devices-web", response_class=HTMLResponse) async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: str = Form("all"), - db: Session = Depends(get_db)): + db: Session = Depends(get_db), Authorize: AuthJWT = Depends()): """ Endpoint used for filtering devices by license. returns html template with only devices that has assigned license defined by user input """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() devices = crud.get_devices(db, skip=skip, limit=limit) def_devices = [] for dev in devices: @@ -72,9 +75,15 @@ async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: for i in range(0, len(def_devices)): statuses.append(def_devices[i].logs[len(def_devices[i].logs) - 1].status) licenses = crud.get_licenses(db, skip=skip, limit=limit) - return templates.TemplateResponse("devices.html", - {"request": request, "devs": len(def_devices), "devices": def_devices, - "statuses": statuses, "licenses": licenses}) + if current_user == "admin": + return templates.TemplateResponse("devices.html", + {"request": request, "devs": len(def_devices), "devices": def_devices, + "statuses": statuses, "licenses": licenses, "user": current_user}) + else: + current_user = "guest" + return templates.TemplateResponse("devices_normal.html", + {"request": request, "devs": len(def_devices), "devices": def_devices, + "statuses": statuses, "licenses": licenses, "user": current_user}) @device_web.get("/device-license/{device_id}", response_class=HTMLResponse) @@ -83,16 +92,37 @@ async def connect_dev_lic(request: Request, device_id: int, db: Session = Depend Returns template with one device and all available licenses that can be assigned to it. """ device = crud.get_device(db, device_id) + dev_licenses = crud.get_device_licenses(db, device_id) + lic_names = [] + dev_lics = [] + for dev_lic in dev_licenses: + dev_lics.append(dev_lic.licenses) + for dev_lic in dev_licenses: + lic_names.append(dev_lic.licenses.name) licenses = crud.get_licenses(db, 0, 100) + lic_left = [] + for lic in licenses: + if lic.name not in lic_names and lic not in lic_left: + lic_left.append(lic) return templates.TemplateResponse("devicelicense.html", - {"request": request, "device": device, "licenses": licenses}) + {"request": request, "device": device, "licenses": lic_left, "dev_lic": dev_lics}) -@device_web.post("/devices-web/{device_id}", response_class=HTMLResponse) +@device_web.post("/devices-web/{device_id}") async def connect_post(device_id: int, lic: str = Form(...), db: Session = Depends(get_db)): """ Endpoint called from template for connecting device with license. Adds entry to devices_licenses - table and returns template with all devices in database + table and redirects to devices-web endpoint """ crud.create_device_license(db, device_id, int(lic), datetime.now()) - return RedirectResponse("/devices-web") + return RedirectResponse(url=f"/devices-web", status_code=303) + + +@device_web.post("/devices-web-del/{device_id}") +async def delete_post(device_id: int, lic_del: str = Form(...), db: Session = Depends(get_db)): + """ + Endpoint called from template for deleting device-license connection. Adds entry to bodydevices_licenses + table and redirects to devices-web endpoint + """ + crud.delete_device_license(db, device_id, int(lic_del)) + return RedirectResponse(url=f"/devices-web", status_code=303) diff --git a/server/sql_app/api/ld_logs_web.py b/server/sql_app/api/ld_logs_web.py index e69de29..fbebfec 100644 --- a/server/sql_app/api/ld_logs_web.py +++ b/server/sql_app/api/ld_logs_web.py @@ -0,0 +1,73 @@ +from typing import List +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from datetime import datetime +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse +from fastapi_jwt_auth import AuthJWT +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +models.Base.metadata.create_all(bind=engine) + +# Path to html templates used in this file +templates = Jinja2Templates(directory="templates/ld-logs") + +# prefix used for all endpoints in this file +ldlogs_web = APIRouter(prefix="") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@ldlogs_web.get("/ldlogs-web", response_class=HTMLResponse) +async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): + """ + Returns template with all usb logs currently saved in database with its pcs, teams and licenses. + """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + logs = crud.get_ld_logs(db, skip=skip, limit=limit) + pcs = [] + for log in logs: + if log.pc_id not in pcs: + pcs.append(log.pc_id) + pc_obj = crud.find_pcs(db, pcs) + teams = crud.get_teams(db, skip=skip, limit=limit) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + if current_user != "admin": + current_user = "guest" + return templates.TemplateResponse("ldlogs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) + + +@ldlogs_web.post("/ldlogs-web", response_class=HTMLResponse) +async def filter_logs(request: Request, pc: str = Form("all"), team: str = Form("all"), lic: str = Form("all"), + skip: int = 0, limit: int = 100, + db: Session = Depends(get_db), Authorize: AuthJWT = Depends()): + """ + Endpoint used for filtering ld logs by user given form inputs. + """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + log = crud.get_filtered_ldlogs(db, pc, team, lic) + logs_ids = [] + for l in log: + logs_ids.append(l[0]) + logs = crud.find_filtered_ldlogs(db, logs_ids) + pc_obj = crud.get_pcs(db, skip=skip, limit=limit) + teams = crud.get_teams(db, skip=skip, limit=limit) + licenses = crud.get_licenses(db, skip=skip, limit=limit) + if current_user != "admin": + current_user = "guest" + return templates.TemplateResponse("ldlogs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) diff --git a/server/sql_app/api/licenses_web.py b/server/sql_app/api/licenses_web.py index cebf250..24de037 100644 --- a/server/sql_app/api/licenses_web.py +++ b/server/sql_app/api/licenses_web.py @@ -46,12 +46,12 @@ async def read_licenses_web(request: Request, skip: int = 0, limit: int = 100, d return templates.TemplateResponse("licenses.html", {"request": request, "licenses": licenses}) -@licenses_web.post("/licenses-web", response_class=HTMLResponse) +@licenses_web.post("/licenses-web") def create_license(name: str = Form(...), expdate: date = Form(...), db: Session = Depends(get_db)): """ - Endpoint called from create license form. Creates new license and returns template with all licenses in database + Endpoint called from create license form. Creates new license and redirects to devices-web endpoint """ db_license = crud.create_license(db, name, expdate) if db_license is None: print("something went wrong") - return RedirectResponse("/devices-web") + return RedirectResponse(url=f"/devices-web", status_code=303) diff --git a/server/sql_app/api/pcs_web.py b/server/sql_app/api/pcs_web.py index 3a5d66f..02303ab 100644 --- a/server/sql_app/api/pcs_web.py +++ b/server/sql_app/api/pcs_web.py @@ -37,9 +37,10 @@ async def read_pcs(request: Request, skip: int = 0, limit: int = 100, db: Sessio current_user = Authorize.get_jwt_subject() pcs = crud.get_pcs(db, skip=skip, limit=limit) if current_user == "admin": - return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs}) + return templates.TemplateResponse("pcs.html", {"request": request, "pcs": pcs, "user": current_user}) else: - return templates.TemplateResponse("pcs_normal.html", {"request": request, "pcs": pcs}) + current_user = "guest" + return templates.TemplateResponse("pcs_normal.html", {"request": request, "pcs": pcs, "user": current_user}) @pcs_web.get("/pc-team/{pc_id}", response_class=HTMLResponse) @@ -53,10 +54,10 @@ async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(ge {"request": request, "pc": pc, "teams": teams}) -@pcs_web.post("/pcs-web/{pc_id}", response_class=HTMLResponse) +@pcs_web.post("/pcs-web/{pc_id}") async def connect_post(pc_id: int, team: str = Form(...), db: Session = Depends(get_db)): """ Endpoint called from within form for connecting pc with team. Updates certain pc with new team. """ old_pc = crud.update_pc(db, pc_id, team) - RedirectResponse("/pcs-web") + return RedirectResponse(url=f"/pcs-web", status_code=303) diff --git a/server/sql_app/api/teams_web.py b/server/sql_app/api/teams_web.py index 3d9cfd6..c1752a1 100644 --- a/server/sql_app/api/teams_web.py +++ b/server/sql_app/api/teams_web.py @@ -38,9 +38,10 @@ async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Se current_user = Authorize.get_jwt_subject() teams = crud.get_teams(db, skip=skip, limit=limit) if current_user == "admin": - return templates.TemplateResponse("teams.html", {"request": request, "teams": teams}) + return templates.TemplateResponse("teams.html", {"request": request, "teams": teams, "user": current_user}) else: - return templates.TemplateResponse("teams_normal.html", {"request": request, "teams": teams}) + current_user = "guest" + return templates.TemplateResponse("teams_normal.html", {"request": request, "teams": teams, "user": current_user}) @teams_web.get("/team-create", response_class=HTMLResponse) @@ -51,7 +52,7 @@ async def team_create_web(request: Request): return templates.TemplateResponse("team_create.html", {"request": request}) -@teams_web.post("/teams-web", response_class=HTMLResponse) +@teams_web.post("/teams-web-con") def create_team(name: str = Form(...), db: Session = Depends(get_db)): """ Endpoint called from within form for creating new team. Creates new team and returns all teams in database @@ -59,4 +60,4 @@ def create_team(name: str = Form(...), db: Session = Depends(get_db)): team = crud.create_team(db, name) if team is None: print("something went wrong") - RedirectResponse("/teams-web") + return RedirectResponse(url=f"/teams-web", status_code=303) diff --git a/server/sql_app/api/usb_logs_web.py b/server/sql_app/api/usb_logs_web.py index 0559e59..cb83443 100644 --- a/server/sql_app/api/usb_logs_web.py +++ b/server/sql_app/api/usb_logs_web.py @@ -6,6 +6,7 @@ from sql_app import crud, models, schemas from ..database import SessionLocal, engine from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse +from fastapi_jwt_auth import AuthJWT from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates @@ -28,10 +29,13 @@ def get_db(): @usblogs_web.get("/logs-web", response_class=HTMLResponse) -async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): +async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Returns template with all usb logs currently saved in database with its pcs, teams and licenses. """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() logs = crud.get_logs(db, skip=skip, limit=limit) pcs = [] for log in logs: @@ -40,8 +44,10 @@ async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Sessi pc_obj = crud.find_pcs(db, pcs) teams = crud.get_teams(db, skip=skip, limit=limit) licenses = crud.get_licenses(db, skip=skip, limit=limit) + if current_user != "admin": + current_user = "guest" return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, - "licenses": licenses}) + "licenses": licenses, "user": current_user}) @usblogs_web.post("/logs-web", response_class=HTMLResponse) diff --git a/server/sql_app/crud.py b/server/sql_app/crud.py index eb3b7f8..cc20541 100644 --- a/server/sql_app/crud.py +++ b/server/sql_app/crud.py @@ -74,11 +74,48 @@ def create_license(db: Session, name: str, expdate: date): def get_license_devices(db: Session, license_id: int): """ - returns all entries in devices_licenses table + returns all entries in devices_licenses table with given license_id """ return db.query(models.DeviceLicense).filter(models.DeviceLicense.license_id == license_id).all() +def get_device_licenses(db: Session, device_id: int): + """ + returns all entries in devices_licenses table with given license_id + """ + return db.query(models.DeviceLicense).filter(models.DeviceLicense.device_id == device_id).all() + + +def get_devicelicense_by_devicelicense(db: Session, device_id: int, license_id: int): + """ + returns entry in devices_licenses table with given device id and license id + """ + return db.query(models.DeviceLicense).filter(and_(models.DeviceLicense.device_id == device_id, + models.DeviceLicense.license_id == license_id)).first() + + +def get_bodydevicelicense_by_bodydevicelicense(db: Session, device_id: int, license_id: int): + """ + returns entry in bodydevices_licenses table with given body device id and license id + """ + return db.query(models.BodyDeviceLicense).filter(and_(models.BodyDeviceLicense.bodydevice_id == device_id, + models.BodyDeviceLicense.license_id == license_id)).first() + + +def get_license_bodydevice(db: Session, license_id: int): + """ + returns all entries in bodydevices_licenses with given license_id + """ + return db.query(models.BodyDeviceLicense).filter(models.BodyDeviceLicense.license_id == license_id).all() + + +def get_bodydevice_license(db: Session, device_id: int): + """ + returns all entries in bodydevices_licenses with given license_id + """ + return db.query(models.BodyDeviceLicense).filter(models.BodyDeviceLicense.bodydevice_id == device_id).all() + + def create_device_license(db: Session, device: int, license: int, time: datetime): """ creates new entry in devices_licenses table with device id, license id and time. @@ -91,6 +128,38 @@ def create_device_license(db: Session, device: int, license: int, time: datetime return db_device_license +def delete_device_license(db: Session, device: int, license: int): + """ + deletes entry in devices_licenses table with device id, license id and time. + """ + db_device_license = get_devicelicense_by_devicelicense(db, device, license) + db_lic = db.delete(db_device_license) + db.commit() + return db_lic + + +def delete_bodydevice_license(db: Session, device: int, license: int): + """ + deletes entry in devices_licenses table with device id, license id and time. + """ + db_device_license = get_bodydevicelicense_by_bodydevicelicense(db, device, license) + db_lic = db.delete(db_device_license) + db.commit() + return db_lic + + +def create_body_device_license(db: Session, device: int, license: int, time: datetime): + """ + creates new entry in devices_licenses table with device id, license id and time. + """ + db_device_license = models.BodyDeviceLicense(bodydevice_id=device, license_id=license, + assigned_datetime=time) + db.add(db_device_license) + db.commit() + db.refresh(db_device_license) + return db_device_license + + def find_pc_by_username(db: Session, name: str): """ Finds one pc by given username @@ -107,7 +176,7 @@ def get_pc(db: Session, pc_id: int): def update_pc(db: Session, pc_id: int, team: str): """ - Function updates team of one specific pc + Updates team of one specific pc """ old_pc = get_pc(db, pc_id) team = get_team(db, int(team)) @@ -274,7 +343,7 @@ def get_ld_logs(db: Session, skip: int = 0, limit: int = 100): """ Returns all ld debugger logs in database """ - return db.query(models.LDLog).offset(skip).limit(limit).all() + return db.query(models.LDLog).order_by(desc(models.LDLog.timestamp)).offset(skip).limit(limit).all() def create_ld_logs(db: Session, item: schemas.LDTempBase, head_id: int, body_id: int, pc_id: int, date: datetime): @@ -309,37 +378,95 @@ def find_filtered_logs(db: Session, logs: []): return db.query(models.USBLog).filter(models.USBLog.id.in_(logs)).order_by(desc(models.USBLog.timestamp)).all() +def find_filtered_ldlogs(db: Session, logs: []): + """ + Returns all ld logs with ids in given id array. + """ + return db.query(models.LDLog).filter(models.LDLog.id.in_(logs)).order_by(desc(models.LDLog.timestamp)).all() + + +def get_filtered_ldlogs(db: Session, pc: str, tema: str, lic: str): + """ + Function creates query string used for filtering by pc username, team name and license name. + Depending on selected filters assembles query string for database + """ + execute_string = "SELECT * FROM ld_logs AS logs" + pcs = find_pc_by_username(db, pc) + if pc != "all": + if pcs is not None: + execute_string += " WHERE logs.pc_id = " + str(pcs.id) + if tema != "all": + team = find_team(db, tema) + if team is not None: + pcst = get_pcs_by_team(db, team.id) + pc_ids = "(" + for p in pcst: + pc_ids += str(p.id) + ", " + def_pc_ids = pc_ids[:-2] + ")" + if pc != "all" and pcs is not None: + if len(def_pc_ids) > 1: + execute_string += " AND logs.pc_id IN " + def_pc_ids + else: + if len(def_pc_ids) > 1: + execute_string += " WHERE logs.pc_id IN " + def_pc_ids + if lic != "all": + license = find_license(db, lic) + if license is not None: + device_licenses = get_license_bodydevice(db, license.id) + dev_ids = "(" + for dev in device_licenses: + dev_ids += str(dev.bodydevice_id) + ", " + defin_ids = dev_ids[:-2] + ")" + if pc != "all" or tema != "all": + if len(defin_ids) > 1: + execute_string += " AND logs.body_id IN " + defin_ids + else: + if len(defin_ids) > 1: + execute_string += " WHERE logs.body_id IN " + defin_ids + + # executing assembled query string + result = db.execute(execute_string) + return result + + def get_filtered_logs(db: Session, pc: str, tema: str, lic: str): """ Function creates query string used for filtering by pc username, team name and license name. Depending on selected filters assembles query string for database """ execute_string = "SELECT * FROM usb_logs AS logs" + pcs = find_pc_by_username(db, pc) if pc != "all": - pcs = find_pc_by_username(db, pc) - execute_string += " WHERE logs.pc_id = " + str(pcs.id) + if pcs is not None: + execute_string += " WHERE logs.pc_id = " + str(pcs.id) if tema != "all": team = find_team(db, tema) - pcs = get_pcs_by_team(db, team.id) - pc_ids = "(" - for p in pcs: - pc_ids += str(p.id) + ", " - def_pc_ids = pc_ids[:-2] + ")" - if pc != "all": - execute_string += " AND logs.pc_id IN " + def_pc_ids - else: - execute_string += " WHERE logs.pc_id IN " + def_pc_ids + if team is not None: + pcst = get_pcs_by_team(db, team.id) + pc_ids = "(" + for p in pcst: + pc_ids += str(p.id) + ", " + def_pc_ids = pc_ids[:-2] + ")" + if pc != "all" and pcs is not None: + if len(def_pc_ids) > 1: + execute_string += " AND logs.pc_id IN " + def_pc_ids + else: + if len(def_pc_ids) > 1: + execute_string += " WHERE logs.pc_id IN " + def_pc_ids if lic != "all": license = find_license(db, lic) - device_licenses = get_license_devices(db, license.id) - dev_ids = "(" - for dev in device_licenses: - dev_ids += str(dev.device_id) + ", " - defin_ids = dev_ids[:-2] + ")" - if pc != "all" or tema != "all": - execute_string += " AND logs.device_id IN " + defin_ids - else: - execute_string += " WHERE logs.device_id IN " + defin_ids + if license is not None: + device_licenses = get_license_devices(db, license.id) + dev_ids = "(" + for dev in device_licenses: + dev_ids += str(dev.device_id) + ", " + defin_ids = dev_ids[:-2] + ")" + if pc != "all" or tema != "all": + if len(defin_ids) > 1: + execute_string += " AND logs.device_id IN " + defin_ids + else: + if len(defin_ids) > 1: + execute_string += " WHERE logs.device_id IN " + defin_ids # executing assembled query string result = db.execute(execute_string) diff --git a/server/sql_app/main.py b/server/sql_app/main.py index 774d8eb..a77e626 100644 --- a/server/sql_app/main.py +++ b/server/sql_app/main.py @@ -10,6 +10,8 @@ from sql_app.api.usb_logs_web import usblogs_web from sql_app.api.teams import teams from sql_app.api.teams_web import teams_web from sql_app.api.auth import auth +from sql_app.api.ld_logs_web import ldlogs_web +from sql_app.api.bodydevices_web import body_device_web from fastapi import FastAPI @@ -28,9 +30,11 @@ app.include_router(licenses_web) app.include_router(pcs_web) app.include_router(teams_web) app.include_router(usblogs_web) +app.include_router(ldlogs_web) +app.include_router(body_device_web) app.include_router(auth) ''' if __name__ == "__main__": - uvicorn.run(app, host="192.168.0.22", port=8000) + uvicorn.run(app, host="192.168.176.1", port=8000) ''' diff --git a/server/sql_app/models.py b/server/sql_app/models.py index 1040967..8d62fe9 100644 --- a/server/sql_app/models.py +++ b/server/sql_app/models.py @@ -52,7 +52,7 @@ class License(Base): # relationships for foreign keys, thus connecting table with devices table devices = relationship("DeviceLicense", back_populates="licenses") - + body_devices = relationship("BodyDeviceLicense", back_populates="b_licenses") class DeviceLicense(Base): """ @@ -71,6 +71,23 @@ class DeviceLicense(Base): licenses = relationship("License", back_populates="devices") +class BodyDeviceLicense(Base): + """ + Class defining database table bodydevices_licenses + """ + __tablename__ = "bodydevices_licenses" + + id = Column(Integer, primary_key=True, index=True) + bodydevice_id = Column(Integer, ForeignKey("body_devices.id")) + license_id = Column(Integer, ForeignKey("licenses.id")) + assigned_datetime = Column(String, index=True, nullable=False) + + # relationships for foreign keys, thus connecting table with devices and licenses + # tables + bodydevice_lic = relationship("BodyDevice", back_populates="debug_licenses") + b_licenses = relationship("License", back_populates="body_devices") + + class PC(Base): """ Class defining database table pc @@ -127,6 +144,7 @@ class BodyDevice(Base): # relationships for foreign keys, thus connecting table with ld_logs table b_logs = relationship("LDLog", back_populates="body_device") + debug_licenses = relationship("BodyDeviceLicense", back_populates="bodydevice_lic") class LDLog(Base): diff --git a/server/templates/body-devices/body_device_license.html b/server/templates/body-devices/body_device_license.html new file mode 100644 index 0000000..9c9dee5 --- /dev/null +++ b/server/templates/body-devices/body_device_license.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Body Device License Connect</title> +</head> +<body> +<h6><p>Vendor ID: {{device.vendor_id}}</p> + <p>Serial Number: {{device.serial_number}}</p> +</h6> +<form action="/body-devices-web/{{device.id}}" method="post"> + <label for="lic">Licenses:</label> + <select id="lic" name="lic"> + {% for license in licenses %} + <option value={{license.id}}>{{license.name}}</option> + {% endfor %} + </select> + <input type="submit" value="Connect"> +</form> +<form action="/body-devices-web-del/{{device.id}}" method="post"> + <label for="b_lic">Licenses:</label> + <select id="b_lic" name="b_lic"> + {% for license in dev_lic %} + <option value={{license.id}}>{{license.name}}</option> + {% endfor %} + </select> + <input type="submit" value="Delete"> +</form> +</body> +</html> \ No newline at end of file diff --git a/server/templates/body-devices/body_devices.html b/server/templates/body-devices/body_devices.html new file mode 100644 index 0000000..eb02d61 --- /dev/null +++ b/server/templates/body-devices/body_devices.html @@ -0,0 +1,72 @@ +<html> +<head> + <title>Devices Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> + <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left'> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +</div> +<h4>{{user}}</h4> +<form action="/body-devices-web" method="post"> + <label for="lic">License:</label> + <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> + <datalist id="licenses"> + {% for license in licenses %} + <option value="{{license.name}}"></option> + {% endfor %} + </datalist> + <input type="submit" value="Filter"> +</form> +<table> + <TR> + <TH>ID</TH> + <TH>Serial Number</TH> + <TH>Licenses</TH> + <TH>Status</TH> + </TR> + {% for i in range(devs) %} + <TR> + <TD class="ID"><a href="/body-device-license/{{devices[i].id}}">{{devices[i].id}}</a></TD> + <TD class="Serial Number">{{devices[i].serial_number}}</TD> + <TD class="License"> + {% for lic in devices[i].debug_licenses %} + {{lic.b_licenses.name}}<BR> + {% endfor %} + </TD> + <TD class="Status">{{statuses[i]}}</TD> + </TR> + {% endfor %} + <TR> + <TD class="ID"></TD> + <TD class="Serial Number"></TD> + <TD class="License"> + <form action="/license-create" method="get"> + <input type="submit" value="Add"> + </form> + </TD> + </TR> +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/body-devices/body_devices_normal.html b/server/templates/body-devices/body_devices_normal.html new file mode 100644 index 0000000..a2c3da2 --- /dev/null +++ b/server/templates/body-devices/body_devices_normal.html @@ -0,0 +1,63 @@ +<html> +<head> + <title>Devices Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> + <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left'> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +</div> +<h4>{{user}}</h4> +<form action="/body-devices-web" method="post"> + <label for="lic">License:</label> + <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> + <datalist id="licenses"> + {% for license in licenses %} + <option value="{{license.name}}"></option> + {% endfor %} + </datalist> + <input type="submit" value="Filter"> +</form> +<table> + <TR> + <TH>ID</TH> + <TH>Serial Number</TH> + <TH>Licenses</TH> + <TH>Status</TH> + </TR> + {% for i in range(devs) %} + <TR> + <TD class="ID">{{devices[i].id}}</TD> + <TD class="Serial Number">{{devices[i].serial_number}}</TD> + <TD class="License"> + {% for lic in devices[i].debug_licenses %} + {{lic.b_licenses.name}}<BR> + {% endfor %} + </TD> + <TD class="Status">{{statuses[i]}}</TD> + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/devices/devicelicense.html b/server/templates/devices/devicelicense.html index f3780b1..b8f8833 100644 --- a/server/templates/devices/devicelicense.html +++ b/server/templates/devices/devicelicense.html @@ -18,5 +18,14 @@ </select> <input type="submit" value="Connect"> </form> +<form action="/devices-web-del/{{device.id}}" method="post"> + <label for="lic_del">Licenses:</label> + <select id="lic_del" name="lic_del"> + {% for license in dev_lic %} + <option value={{license.id}}>{{license.name}}</option> + {% endfor %} + </select> + <input type="submit" value="Delete"> +</form> </body> </html> \ No newline at end of file diff --git a/server/templates/devices/devices.html b/server/templates/devices/devices.html index c1abf2d..93dee09 100644 --- a/server/templates/devices/devices.html +++ b/server/templates/devices/devices.html @@ -9,7 +9,9 @@ <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> </select> @@ -21,9 +23,12 @@ <input type="submit" value="Login" /> </form> </div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> +</div> +<h4>{{user}}</h4> <form action="/devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> diff --git a/server/templates/devices/devices_normal.html b/server/templates/devices/devices_normal.html index 18b21a4..a87c3b2 100644 --- a/server/templates/devices/devices_normal.html +++ b/server/templates/devices/devices_normal.html @@ -9,7 +9,9 @@ <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> </select> @@ -21,9 +23,12 @@ <input type="submit" value="Login" /> </form> </div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> +</div> +<h4>{{user}}</h4> <form action="/devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> diff --git a/server/templates/ld-logs/ldlogs.html b/server/templates/ld-logs/ldlogs.html new file mode 100644 index 0000000..e6f6c27 --- /dev/null +++ b/server/templates/ld-logs/ldlogs.html @@ -0,0 +1,85 @@ +<html> +<head> + <title> LD Logs Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> + <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left'> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +</div> +<h4>{{user}}</h4> +<form action="/ldlogs-web" method="post"> + <label for="pc">PC:</label> + <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> + <datalist id="pcs"> + {% for pc in pcs %} + <option value="{{pc.username}}"></option> + {% endfor %} + </datalist> + <label for="team">Team:</label> + <input id="team" name="team" type="text" list="teams" value="" placeholder="all"> + <datalist id="teams"> + {% for team in teams %} + <option value="{{team.name}}"></option> + {% endfor %} + </datalist> + <label for="lic">License:</label> + <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> + <datalist id="licenses"> + {% for license in licenses %} + <option value="{{license.name}}"></option> + {% endfor %} + </datalist> + <input type="submit" value="Filter"> +</form> + <table> + <TR> + <TH>ID</TH> + <TH>PC Username</TH> + <TH>PC Hostname</TH> + <TH>Team</TH> + <TH>Timestamp</TH> + <TH>Status</TH> + <TH>Head Device Serial Number</TH> + <TH>Body Device Serial Number</TH> + </TR> + {% for log in logs %} + <TR> + <TD class="ID">{{log.id}}</TD> + <TD class="Username">{{log.ldpc.username}}</TD> + <TD class="Hostname">{{log.ldpc.hostname}}</TD> + {% if log.ldpc.team == None %} + <TD class="Team">NONE</TD> + {% else %} + <TD class="Team">{{log.ldpc.team.name}}</TD> + {% endif %} + <TD class="Timestamp">{{log.timestamp}}</TD> + <TD class="Status">{{log.status}}</TD> + <TD class="HeadDeviceSerialNumber">{{log.head_device.serial_number}}</TD> + <TD class="BodyDeviceSerialNumber">{{log.body_device.serial_number}}</TD> + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/licenses/licenses.html b/server/templates/licenses/licenses.html index 8e5ab8e..d9faf97 100644 --- a/server/templates/licenses/licenses.html +++ b/server/templates/licenses/licenses.html @@ -9,7 +9,9 @@ <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> </select> diff --git a/server/templates/pcs/pcs.html b/server/templates/pcs/pcs.html index 6532f24..fa268a5 100644 --- a/server/templates/pcs/pcs.html +++ b/server/templates/pcs/pcs.html @@ -9,7 +9,9 @@ <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> </select> @@ -21,9 +23,12 @@ <input type="submit" value="Login" /> </form> </div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> +</div> +<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/pcs/pcs_normal.html b/server/templates/pcs/pcs_normal.html index bee77d2..a17833a 100644 --- a/server/templates/pcs/pcs_normal.html +++ b/server/templates/pcs/pcs_normal.html @@ -9,7 +9,9 @@ <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> </select> @@ -21,9 +23,12 @@ <input type="submit" value="Login" /> </form> </div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> +</div> +<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/teams/team_create.html b/server/templates/teams/team_create.html index 16dcc0a..28fb63d 100644 --- a/server/templates/teams/team_create.html +++ b/server/templates/teams/team_create.html @@ -5,7 +5,7 @@ <title>Create a Team</title> </head> <body> -<form action="/teams-web" method="post"> +<form action="/teams-web-con" method="post"> <label for="name">Name:</label><br> <input type="text" id="name" name="name"><br><br> <input type="submit" value="Submit"> diff --git a/server/templates/teams/teams.html b/server/templates/teams/teams.html index 77e5052..f9889f0 100644 --- a/server/templates/teams/teams.html +++ b/server/templates/teams/teams.html @@ -9,7 +9,9 @@ <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> </select> @@ -21,9 +23,12 @@ <input type="submit" value="Login" /> </form> </div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> +</div> +<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/teams/teams_normal.html b/server/templates/teams/teams_normal.html index f1a5fc1..1e3c70c 100644 --- a/server/templates/teams/teams_normal.html +++ b/server/templates/teams/teams_normal.html @@ -9,7 +9,9 @@ <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> </select> @@ -21,9 +23,12 @@ <input type="submit" value="Login" /> </form> </div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> +</div> +<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/usb-logs/logs.html b/server/templates/usb-logs/logs.html index 7e7e4be..dc83324 100644 --- a/server/templates/usb-logs/logs.html +++ b/server/templates/usb-logs/logs.html @@ -9,7 +9,9 @@ <select id="view" name="view" onchange="this.form.action=this.value;"> <option value=""></option> <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> </select> @@ -21,9 +23,12 @@ <input type="submit" value="Login" /> </form> </div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> +</div> +<h4>{{user}}</h4> <form action="/logs-web" method="post"> <label for="pc">PC:</label> <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> -- GitLab From 5dc6d077ca29461d54a5e6778cc2e204c73b7621 Mon Sep 17 00:00:00 2001 From: Matej Zeman <zeman339@gmail.com> Date: Mon, 9 May 2022 14:43:49 +0200 Subject: [PATCH 11/13] security fix for all endpoints. Added view for Licenses and html template on "/" with information about server endpoints. --- server/sql_app/api/auth.py | 2 +- server/sql_app/api/bodydevices_web.py | 21 ++++++- server/sql_app/api/devices_web.py | 21 ++++++- server/sql_app/api/licenses_web.py | 41 ++++++++++--- server/sql_app/api/pcs_web.py | 14 ++++- server/sql_app/api/teams_web.py | 23 ++++++-- server/sql_app/api/usb_logs_web.py | 12 +++- server/sql_app/main.py | 2 +- server/templates/auth/login.html | 4 +- .../templates/body-devices/body_devices.html | 1 + .../body-devices/body_devices_normal.html | 1 + server/templates/devices/devices.html | 1 + server/templates/devices/devices_normal.html | 1 + server/templates/ld-logs/ldlogs.html | 1 + server/templates/licenses/license_create.html | 2 +- server/templates/licenses/licenses.html | 7 +++ .../templates/licenses/licenses_normal.html | 48 +++++++++++++++ server/templates/pcs/pcs.html | 1 + server/templates/pcs/pcs_normal.html | 1 + server/templates/teams/teams.html | 9 ++- server/templates/teams/teams_normal.html | 7 +++ server/templates/usb-logs/crossroad.html | 59 +++++++++++++++++++ server/templates/usb-logs/logs.html | 1 + 23 files changed, 250 insertions(+), 30 deletions(-) create mode 100644 server/templates/licenses/licenses_normal.html create mode 100644 server/templates/usb-logs/crossroad.html diff --git a/server/sql_app/api/auth.py b/server/sql_app/api/auth.py index 069d27c..f01ef83 100644 --- a/server/sql_app/api/auth.py +++ b/server/sql_app/api/auth.py @@ -1,6 +1,6 @@ from fastapi import Depends, APIRouter, Form from fastapi import Request -from fastapi.responses import HTMLResponse +from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates from fastapi_jwt_auth import AuthJWT from pydantic import BaseModel diff --git a/server/sql_app/api/bodydevices_web.py b/server/sql_app/api/bodydevices_web.py index 9b13bb7..48b345e 100644 --- a/server/sql_app/api/bodydevices_web.py +++ b/server/sql_app/api/bodydevices_web.py @@ -87,10 +87,15 @@ async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: @body_device_web.get("/body-device-license/{device_id}", response_class=HTMLResponse) -async def connect_dev_lic(request: Request, device_id: int, db: Session = Depends(get_db)): +async def connect_dev_lic(request: Request, device_id: int, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Returns template with one body device and all available licenses that can be assigned to it. """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) device = crud.get_body_device(db, device_id) dev_licenses = crud.get_bodydevice_license(db, device_id) lic_names = [] @@ -109,20 +114,30 @@ async def connect_dev_lic(request: Request, device_id: int, db: Session = Depend @body_device_web.post("/body-devices-web/{device_id}") -async def connect_post(device_id: int, lic: str = Form(...), db: Session = Depends(get_db)): +async def connect_post(device_id: int, lic: str = Form(...), db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Endpoint called from template for connecting body device with license. Adds entry to bodydevices_licenses table and redirects to body-devices-web endpoint """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) crud.create_body_device_license(db, device_id, int(lic), datetime.now()) return RedirectResponse(url=f"/body-devices-web", status_code=303) @body_device_web.post("/body-devices-web-del/{device_id}") -async def delete_post(device_id: int, b_lic: str = Form(...), db: Session = Depends(get_db)): +async def delete_post(device_id: int, b_lic: str = Form(...), db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Endpoint called from template for connecting body device with license. Adds entry to devices_licenses table and redirects to body-devices-web endpoint """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) crud.delete_bodydevice_license(db, device_id, int(b_lic)) return RedirectResponse(url=f"/body-devices-web", status_code=303) \ No newline at end of file diff --git a/server/sql_app/api/devices_web.py b/server/sql_app/api/devices_web.py index 97c38a5..0d82a6b 100644 --- a/server/sql_app/api/devices_web.py +++ b/server/sql_app/api/devices_web.py @@ -87,10 +87,15 @@ async def filter_devices(request: Request, skip: int = 0, limit: int = 100, lic: @device_web.get("/device-license/{device_id}", response_class=HTMLResponse) -async def connect_dev_lic(request: Request, device_id: int, db: Session = Depends(get_db)): +async def connect_dev_lic(request: Request, device_id: int, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Returns template with one device and all available licenses that can be assigned to it. """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) device = crud.get_device(db, device_id) dev_licenses = crud.get_device_licenses(db, device_id) lic_names = [] @@ -109,20 +114,30 @@ async def connect_dev_lic(request: Request, device_id: int, db: Session = Depend @device_web.post("/devices-web/{device_id}") -async def connect_post(device_id: int, lic: str = Form(...), db: Session = Depends(get_db)): +async def connect_post(device_id: int, lic: str = Form(...), db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Endpoint called from template for connecting device with license. Adds entry to devices_licenses table and redirects to devices-web endpoint """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) crud.create_device_license(db, device_id, int(lic), datetime.now()) return RedirectResponse(url=f"/devices-web", status_code=303) @device_web.post("/devices-web-del/{device_id}") -async def delete_post(device_id: int, lic_del: str = Form(...), db: Session = Depends(get_db)): +async def delete_post(device_id: int, lic_del: str = Form(...), db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Endpoint called from template for deleting device-license connection. Adds entry to bodydevices_licenses table and redirects to devices-web endpoint """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) crud.delete_device_license(db, device_id, int(lic_del)) return RedirectResponse(url=f"/devices-web", status_code=303) diff --git a/server/sql_app/api/licenses_web.py b/server/sql_app/api/licenses_web.py index 24de037..f402a1b 100644 --- a/server/sql_app/api/licenses_web.py +++ b/server/sql_app/api/licenses_web.py @@ -7,6 +7,7 @@ from sql_app import crud, models, schemas from ..database import SessionLocal, engine from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse, RedirectResponse +from fastapi_jwt_auth import AuthJWT from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates @@ -30,28 +31,50 @@ def get_db(): @licenses_web.get("/license-create", response_class=HTMLResponse) -async def licenses_create_web(request: Request): +async def licenses_create_web(request: Request, Authorize: AuthJWT = Depends()): """ Returns template with Form for creating new license. """ - return templates.TemplateResponse("license_create.html", {"request": request}) + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) + return templates.TemplateResponse("license_create.html", {"request": request, "minimum_date": date.today()}) @licenses_web.get("/licenses-web", response_class=HTMLResponse) -async def read_licenses_web(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): +async def read_licenses_web(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Returns template with all licenses currently saved in database """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() licenses = crud.get_licenses(db, skip=skip, limit=limit) - return templates.TemplateResponse("licenses.html", {"request": request, "licenses": licenses}) - + if current_user == "admin": + return templates.TemplateResponse("licenses.html", {"request": request, "licenses": licenses, + "user": current_user}) + else: + current_user = "guest" + return templates.TemplateResponse("licenses_normal.html", {"request": request, "licenses": licenses, + "user": current_user}) @licenses_web.post("/licenses-web") -def create_license(name: str = Form(...), expdate: date = Form(...), db: Session = Depends(get_db)): +def create_license(name: str = Form(...), expdate: date = Form(...), db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Endpoint called from create license form. Creates new license and redirects to devices-web endpoint """ - db_license = crud.create_license(db, name, expdate) - if db_license is None: - print("something went wrong") + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) + licenses = crud.get_licenses(db, 0, 100) + licenses_names = [] + for l in licenses: + licenses_names.append(l.name) + if name not in licenses_names: + db_license = crud.create_license(db, name, expdate) + if db_license is None: + print("something went wrong") return RedirectResponse(url=f"/devices-web", status_code=303) diff --git a/server/sql_app/api/pcs_web.py b/server/sql_app/api/pcs_web.py index 02303ab..2779e46 100644 --- a/server/sql_app/api/pcs_web.py +++ b/server/sql_app/api/pcs_web.py @@ -44,10 +44,15 @@ async def read_pcs(request: Request, skip: int = 0, limit: int = 100, db: Sessio @pcs_web.get("/pc-team/{pc_id}", response_class=HTMLResponse) -async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(get_db)): +async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Returns template with Form for connecting pc with team """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) pc = crud.get_pc(db, pc_id) teams = crud.get_teams(db, 0, 100) return templates.TemplateResponse("pcteam.html", @@ -55,9 +60,14 @@ async def connect_pc_team(request: Request, pc_id: int, db: Session = Depends(ge @pcs_web.post("/pcs-web/{pc_id}") -async def connect_post(pc_id: int, team: str = Form(...), db: Session = Depends(get_db)): +async def connect_post(pc_id: int, team: str = Form(...), db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Endpoint called from within form for connecting pc with team. Updates certain pc with new team. """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) old_pc = crud.update_pc(db, pc_id, team) return RedirectResponse(url=f"/pcs-web", status_code=303) diff --git a/server/sql_app/api/teams_web.py b/server/sql_app/api/teams_web.py index c1752a1..616c1c7 100644 --- a/server/sql_app/api/teams_web.py +++ b/server/sql_app/api/teams_web.py @@ -45,19 +45,32 @@ async def read_devices(request: Request, skip: int = 0, limit: int = 100, db: Se @teams_web.get("/team-create", response_class=HTMLResponse) -async def team_create_web(request: Request): +async def team_create_web(request: Request, Authorize: AuthJWT = Depends()): """ Returns template with form for creating new team """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) return templates.TemplateResponse("team_create.html", {"request": request}) @teams_web.post("/teams-web-con") -def create_team(name: str = Form(...), db: Session = Depends(get_db)): +def create_team(name: str = Form(...), db: Session = Depends(get_db), Authorize: AuthJWT = Depends()): """ Endpoint called from within form for creating new team. Creates new team and returns all teams in database """ - team = crud.create_team(db, name) - if team is None: - print("something went wrong") + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) + teams = crud.get_teams(db, 0, 100) + teams_names = [] + for t in teams: + teams_names.append(t.name) + if name not in teams_names: + team = crud.create_team(db, name) + if team is None: + print("something went wrong") return RedirectResponse(url=f"/teams-web", status_code=303) diff --git a/server/sql_app/api/usb_logs_web.py b/server/sql_app/api/usb_logs_web.py index cb83443..a4f57d0 100644 --- a/server/sql_app/api/usb_logs_web.py +++ b/server/sql_app/api/usb_logs_web.py @@ -53,10 +53,12 @@ async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Sessi @usblogs_web.post("/logs-web", response_class=HTMLResponse) async def filter_logs(request: Request, pc: str = Form("all"), team: str = Form("all"), lic: str = Form("all"), skip: int = 0, limit: int = 100, - db: Session = Depends(get_db)): + db: Session = Depends(get_db), Authorize: AuthJWT = Depends()): """ Endpoint used for filtering usb logs by user given form inputs. """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() log = crud.get_filtered_logs(db, pc, team, lic) logs_ids = [] for l in log: @@ -65,6 +67,12 @@ async def filter_logs(request: Request, pc: str = Form("all"), team: str = Form( pc_obj = crud.get_pcs(db, skip=skip, limit=limit) teams = crud.get_teams(db, skip=skip, limit=limit) licenses = crud.get_licenses(db, skip=skip, limit=limit) + if current_user != "admin": + current_user = "guest" return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, - "licenses": licenses}) + "licenses": licenses, "user": current_user}) + +@usblogs_web.get("/", response_class=HTMLResponse) +async def crossroad(request: Request): + return templates.TemplateResponse("crossroad.html", {"request": request}) diff --git a/server/sql_app/main.py b/server/sql_app/main.py index a77e626..99026c6 100644 --- a/server/sql_app/main.py +++ b/server/sql_app/main.py @@ -36,5 +36,5 @@ app.include_router(auth) ''' if __name__ == "__main__": - uvicorn.run(app, host="192.168.176.1", port=8000) + uvicorn.run(app, host="192.168.0.22", port=8000) ''' diff --git a/server/templates/auth/login.html b/server/templates/auth/login.html index 49fdcdf..0def994 100644 --- a/server/templates/auth/login.html +++ b/server/templates/auth/login.html @@ -8,8 +8,8 @@ <form action="/login" method="post"> <label for="username">Username:</label><br> <input type="text" id="username" name="username"><br><br> - <label for="password">Expiration Date</label> - <input type="text" id="password" name="password"> + <label for="password">Password</label> + <input type="password" id="password" name="password"> <input type="submit" value="Submit"> </form> </body> diff --git a/server/templates/body-devices/body_devices.html b/server/templates/body-devices/body_devices.html index eb02d61..1116968 100644 --- a/server/templates/body-devices/body_devices.html +++ b/server/templates/body-devices/body_devices.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> diff --git a/server/templates/body-devices/body_devices_normal.html b/server/templates/body-devices/body_devices_normal.html index a2c3da2..d0ce81b 100644 --- a/server/templates/body-devices/body_devices_normal.html +++ b/server/templates/body-devices/body_devices_normal.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> diff --git a/server/templates/devices/devices.html b/server/templates/devices/devices.html index 93dee09..3685a70 100644 --- a/server/templates/devices/devices.html +++ b/server/templates/devices/devices.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> diff --git a/server/templates/devices/devices_normal.html b/server/templates/devices/devices_normal.html index a87c3b2..7b5d898 100644 --- a/server/templates/devices/devices_normal.html +++ b/server/templates/devices/devices_normal.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> diff --git a/server/templates/ld-logs/ldlogs.html b/server/templates/ld-logs/ldlogs.html index e6f6c27..a936ff4 100644 --- a/server/templates/ld-logs/ldlogs.html +++ b/server/templates/ld-logs/ldlogs.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> diff --git a/server/templates/licenses/license_create.html b/server/templates/licenses/license_create.html index 709fb52..861174a 100644 --- a/server/templates/licenses/license_create.html +++ b/server/templates/licenses/license_create.html @@ -9,7 +9,7 @@ <label for="name">Name:</label><br> <input type="text" id="name" name="name"><br><br> <label for="expdate">Expiration Date</label> - <input type="date" id="expdate" name="expdate"> + <input type="date" id="expdate" name="expdate" min={{minimum_date}}> <input type="submit" value="Submit"> </form> </body> diff --git a/server/templates/licenses/licenses.html b/server/templates/licenses/licenses.html index d9faf97..e66abfe 100644 --- a/server/templates/licenses/licenses.html +++ b/server/templates/licenses/licenses.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> @@ -23,9 +24,12 @@ <input type="submit" value="Login" /> </form> </div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> +</div> +<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> @@ -40,5 +44,8 @@ </TR> {% endfor %} </table> +<form action="/license-create" method="get"> + <input type="submit" value="Add"> +</form> </body> </html> \ No newline at end of file diff --git a/server/templates/licenses/licenses_normal.html b/server/templates/licenses/licenses_normal.html new file mode 100644 index 0000000..7b5b644 --- /dev/null +++ b/server/templates/licenses/licenses_normal.html @@ -0,0 +1,48 @@ +<html> +<head> + <title>Licenses Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> + <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left'> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +</div> +<h4>{{user}}</h4> +<table> + <TR> + <TH>ID</TH> + <TH>Name</TH> + <TH>Expiration Date</TH> + </TR> + {% for license in licenses %} + <TR> + <TD class="ID">{{license.id}}</TD> + <TD class="Vendor ID">{{license.name}}</TD> + <TD class="Product ID">{{license.expiration_date}}</TD> + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/pcs/pcs.html b/server/templates/pcs/pcs.html index fa268a5..79f3156 100644 --- a/server/templates/pcs/pcs.html +++ b/server/templates/pcs/pcs.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> diff --git a/server/templates/pcs/pcs_normal.html b/server/templates/pcs/pcs_normal.html index a17833a..52d9085 100644 --- a/server/templates/pcs/pcs_normal.html +++ b/server/templates/pcs/pcs_normal.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> diff --git a/server/templates/teams/teams.html b/server/templates/teams/teams.html index f9889f0..546666b 100644 --- a/server/templates/teams/teams.html +++ b/server/templates/teams/teams.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> @@ -33,11 +34,17 @@ <TR> <TH>ID</TH> <TH>Name</TH> + <TH>Members</TH> </TR> {% for team in teams %} <TR> <TD class="ID">{{team.id}}</TD> - <TD class="Vendor ID">{{team.name}}</TD> + <TD class="Name">{{team.name}}</TD> + <TD class="Members"> + {% for ppl in team.pcs %} + {{ppl.username}}<BR> + {% endfor %} + </TD> </TR> {% endfor %} </table> diff --git a/server/templates/teams/teams_normal.html b/server/templates/teams/teams_normal.html index 1e3c70c..50a7883 100644 --- a/server/templates/teams/teams_normal.html +++ b/server/templates/teams/teams_normal.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> @@ -33,11 +34,17 @@ <TR> <TH>ID</TH> <TH>Name</TH> + <TH>Members</TH> </TR> {% for team in teams %} <TR> <TD class="ID">{{team.id}}</TD> <TD class="Vendor ID">{{team.name}}</TD> + <TD class="Members"> + {% for ppl in team.pcs %} + {{ppl.username}}<BR> + {% endfor %} + </TD> </TR> {% endfor %} </table> diff --git a/server/templates/usb-logs/crossroad.html b/server/templates/usb-logs/crossroad.html new file mode 100644 index 0000000..f553dc4 --- /dev/null +++ b/server/templates/usb-logs/crossroad.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Crossroad</title> +</head> +<body> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> + <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> + </select> + <input type="submit" value="OK"> +</form> +<h3>Available endpoints are accessible from selectBox above</h3> +<h4>Endpoints are:</h4> +<table> + <TR> + <TH>URL</TH> + <TH>Purpose</TH> + </TR> + <TR> + <TD class="URL">/logs-web</TD> + <TD class="Purpose">Shows all saves Keyman logs. User can filter through license, team and user</TD> + </TR> + <TR> + <TD class="URL">/ldlogs-web</TD> + <TD class="Purpose">Shows all saves LD debugger logs. User can filter through license, team and user</TD> + </TR> + <TR> + <TD class="URL">/devices-web</TD> + <TD class="Purpose">Shows all Keyman devices saved in database and its last state (connected, disconnected)</TD> + </TR> + <TR> + <TD class="URL">/body-devices-web</TD> + <TD class="Purpose">Shows all LD Body devices saved in database and its last state (connected, disconnected)</TD> + </TR> + <TR> + <TD class="URL">/teams-web</TD> + <TD class="Purpose">Shows all teams currently saved in database and its members</TD> + </TR> + <TR> + <TD class="URL">/pcs-web</TD> + <TD class="Purpose">Shows all PCS currently saved in database and its team</TD> + </TR> + <TR> + <TD class="URL">/licenses-web</TD> + <TD class="Purpose">Shows all Licenses currently saved in database and its expiration date</TD> + </TR> +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/usb-logs/logs.html b/server/templates/usb-logs/logs.html index dc83324..e1d0a17 100644 --- a/server/templates/usb-logs/logs.html +++ b/server/templates/usb-logs/logs.html @@ -14,6 +14,7 @@ <option value="/body-devices-web">Body Devices</option> <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> </select> <input type="submit" value="OK"> </form> -- GitLab From cbd239c6c463b12d81e19d33ee2a53bd68e64c40 Mon Sep 17 00:00:00 2001 From: Matej Zeman <zeman339@gmail.com> Date: Mon, 9 May 2022 17:48:57 +0200 Subject: [PATCH 12/13] Added signup and users table in database. Passwords are hashed. Added view for changing users roles. --- server/requirements.txt | 4 +- server/sql_app/api/auth.py | 117 ++++++++++++++++-- server/sql_app/api/ld_logs_web.py | 20 ++- server/sql_app/api/usb_logs_web.py | 18 ++- server/sql_app/api/users_web.py | 59 +++++++++ server/sql_app/crud.py | 46 ++++++- server/sql_app/main.py | 2 + server/sql_app/models.py | 11 ++ server/sql_app/schemas.py | 19 +++ server/templates/auth/login.html | 4 +- server/templates/auth/signup.html | 16 +++ .../templates/body-devices/body_devices.html | 6 + .../body-devices/body_devices_normal.html | 5 + server/templates/devices/devices.html | 6 + server/templates/devices/devices_normal.html | 5 + server/templates/ld-logs/ldlogs.html | 6 + server/templates/ld-logs/ldlogs_normal.html | 91 ++++++++++++++ server/templates/licenses/licenses.html | 6 + .../templates/licenses/licenses_normal.html | 5 + server/templates/pcs/pcs.html | 6 + server/templates/pcs/pcs_normal.html | 5 + server/templates/teams/teams.html | 6 + server/templates/teams/teams_normal.html | 5 + server/templates/usb-logs/logs.html | 6 + server/templates/usb-logs/logs_normal.html | 91 ++++++++++++++ server/templates/users/users.html | 50 ++++++++ 26 files changed, 590 insertions(+), 25 deletions(-) create mode 100644 server/sql_app/api/users_web.py create mode 100644 server/templates/auth/signup.html create mode 100644 server/templates/ld-logs/ldlogs_normal.html create mode 100644 server/templates/usb-logs/logs_normal.html create mode 100644 server/templates/users/users.html diff --git a/server/requirements.txt b/server/requirements.txt index e70f09c..7d8e232 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -5,4 +5,6 @@ uvicorn==0.17.6 psycopg2-binary==2.8.6 jinja2==3.1.1 python-multipart==0.0.5 -fastapi-jwt-auth==0.5.0 \ No newline at end of file +fastapi-jwt-auth==0.5.0 +passlib==1.7.4 +bcrypt==3.2.2 \ No newline at end of file diff --git a/server/sql_app/api/auth.py b/server/sql_app/api/auth.py index f01ef83..cf8aeba 100644 --- a/server/sql_app/api/auth.py +++ b/server/sql_app/api/auth.py @@ -3,15 +3,29 @@ from fastapi import Request from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates from fastapi_jwt_auth import AuthJWT +from sqlalchemy.orm import Session +from sql_app import crud +from passlib.context import CryptContext from pydantic import BaseModel +from ..database import SessionLocal, engine # Path to html templates used in this file templates = Jinja2Templates(directory="templates/auth") +pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") + # prefix used for all endpoints in this file auth = APIRouter(prefix="") +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + class Settings(BaseModel): authjwt_secret_key: str = "secret" @@ -25,6 +39,7 @@ class Settings(BaseModel): def get_config(): return Settings() + # admin username and password fake_users_db = { "admin": { @@ -34,6 +49,72 @@ fake_users_db = { } +def verify_password(plain_password, hashed_password): + return pwd_context.verify(plain_password, hashed_password) + + +def get_hash_password(password): + return pwd_context.hash(password) + + +def auth_user(db, username: str, password: str): + user = crud.find_user(db, username) + if not user: + return None + if not verify_password(password, user.password): + return None + return user + + +@auth.get("/signup", response_class=HTMLResponse) +async def signup_get(request: Request): + """ + return html template for signup + """ + return templates.TemplateResponse("signup.html", {"request": request}) + + +@auth.post("/signup", response_class=HTMLResponse) +async def signup(username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db)): + """ + Endpoint called form signup template. Creates new user with role guest that can be changed by admin user + """ + users = crud.get_users(db, 0, 100) + users_names = [] + for u in users: + users_names.append(u.username) + if username not in users_names: + new_user = crud.create_user(db, username, get_hash_password(password), "guest") + if new_user is None: + print("something went wrong") + return """ + <html> + <head> + <title>Signup</title> + </head> + <body> + <h1>Signed in</h1> + <form action="/logs-web" method="get"> + <input type="submit" value="Back" /> + </form> + </body> + </html> + """ + else: + return """ + <html> + <head> + <title>Signup</title> + </head> + <body> + <h1>Username taken</h1> + <form action="/logs-web" method="get"> + <input type="submit" value="Back" /> + </form> + </body> + </html> + """ + @auth.get("/login", response_class=HTMLResponse) async def login_get(request: Request): """ @@ -43,22 +124,40 @@ async def login_get(request: Request): @auth.post("/login", response_class=HTMLResponse) -async def login(username: str = Form(...), password: str = Form(...), Authorize: AuthJWT = Depends()): +async def login(username: str = Form(...), password: str = Form(...), db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): """ Endpoint called from login template. Checks if given username and password aligns with admin username and password and returns token for browser according to given username and password """ - user_dict = fake_users_db.get(username) - if user_dict != None: - if user_dict["username"] == username and user_dict["password"] == password: + user = auth_user(db, username, password) + if user != None: + if user.role == "admin": access_token = Authorize.create_access_token(subject="admin", expires_time=False) refresh_token = Authorize.create_refresh_token(subject="admin", expires_time=False) else: - access_token = Authorize.create_access_token(subject="host", expires_time=False) - refresh_token = Authorize.create_refresh_token(subject="host", expires_time=False) + access_token = Authorize.create_access_token(subject="guest", expires_time=False) + refresh_token = Authorize.create_refresh_token(subject="guest", expires_time=False) else: - access_token = Authorize.create_access_token(subject="host", expires_time=False) - refresh_token = Authorize.create_refresh_token(subject="host", expires_time=False) + usr = fake_users_db.get(username) + if usr != None: + if usr["username"] == username and usr["password"] == password: + access_token = Authorize.create_access_token(subject="admin", expires_time=False) + refresh_token = Authorize.create_refresh_token(subject="admin", expires_time=False) + else: + return """ + <html> + <head> + <title>Login</title> + </head> + <body> + <h1>Wrong Username or Password</h1> + <form action="/login" method="get"> + <input type="submit" value="Back" /> + </form> + </body> + </html> + """ # Set the JWT cookies in the response Authorize.set_access_cookies(access_token) @@ -112,4 +211,4 @@ def logout(Authorize: AuthJWT = Depends()): </form> </body> </html> - """ \ No newline at end of file + """ diff --git a/server/sql_app/api/ld_logs_web.py b/server/sql_app/api/ld_logs_web.py index fbebfec..aef3733 100644 --- a/server/sql_app/api/ld_logs_web.py +++ b/server/sql_app/api/ld_logs_web.py @@ -44,10 +44,14 @@ async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Sessi pc_obj = crud.find_pcs(db, pcs) teams = crud.get_teams(db, skip=skip, limit=limit) licenses = crud.get_licenses(db, skip=skip, limit=limit) - if current_user != "admin": + if current_user == "admin": + return templates.TemplateResponse("ldlogs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) + else: current_user = "guest" - return templates.TemplateResponse("ldlogs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, - "licenses": licenses, "user": current_user}) + return templates.TemplateResponse("ldlogs_normal.html", + {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) @ldlogs_web.post("/ldlogs-web", response_class=HTMLResponse) @@ -67,7 +71,11 @@ async def filter_logs(request: Request, pc: str = Form("all"), team: str = Form( pc_obj = crud.get_pcs(db, skip=skip, limit=limit) teams = crud.get_teams(db, skip=skip, limit=limit) licenses = crud.get_licenses(db, skip=skip, limit=limit) - if current_user != "admin": + if current_user == "admin": + return templates.TemplateResponse("ldlogs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) + else: current_user = "guest" - return templates.TemplateResponse("ldlogs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, - "licenses": licenses, "user": current_user}) + return templates.TemplateResponse("ldlogs_normal.html", + {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) diff --git a/server/sql_app/api/usb_logs_web.py b/server/sql_app/api/usb_logs_web.py index a4f57d0..75ebdc6 100644 --- a/server/sql_app/api/usb_logs_web.py +++ b/server/sql_app/api/usb_logs_web.py @@ -44,10 +44,13 @@ async def read_logs(request: Request, skip: int = 0, limit: int = 100, db: Sessi pc_obj = crud.find_pcs(db, pcs) teams = crud.get_teams(db, skip=skip, limit=limit) licenses = crud.get_licenses(db, skip=skip, limit=limit) - if current_user != "admin": + if current_user == "admin": + return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) + else: current_user = "guest" - return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, - "licenses": licenses, "user": current_user}) + return templates.TemplateResponse("logs_normal.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) @usblogs_web.post("/logs-web", response_class=HTMLResponse) @@ -67,10 +70,13 @@ async def filter_logs(request: Request, pc: str = Form("all"), team: str = Form( pc_obj = crud.get_pcs(db, skip=skip, limit=limit) teams = crud.get_teams(db, skip=skip, limit=limit) licenses = crud.get_licenses(db, skip=skip, limit=limit) - if current_user != "admin": + if current_user == "admin": + return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) + else: current_user = "guest" - return templates.TemplateResponse("logs.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, - "licenses": licenses, "user": current_user}) + return templates.TemplateResponse("logs_normal.html", {"request": request, "logs": logs, "pcs": pc_obj, "teams": teams, + "licenses": licenses, "user": current_user}) @usblogs_web.get("/", response_class=HTMLResponse) diff --git a/server/sql_app/api/users_web.py b/server/sql_app/api/users_web.py new file mode 100644 index 0000000..523b22f --- /dev/null +++ b/server/sql_app/api/users_web.py @@ -0,0 +1,59 @@ +from typing import List +from fastapi import Depends, FastAPI, HTTPException, APIRouter, Form +from sqlalchemy.orm import Session +from sql_app import crud, models, schemas +from ..database import SessionLocal, engine +from fastapi import FastAPI, Request +from fastapi.responses import HTMLResponse, RedirectResponse +from fastapi_jwt_auth import AuthJWT +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +models.Base.metadata.create_all(bind=engine) + +# Path to html templates used in this file +templates = Jinja2Templates(directory="templates/users") + +# prefix used for all endpoints in this file +users = APIRouter(prefix="") + + +# Dependency +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + + +@users.get("/users-web", response_class=HTMLResponse) +async def read_usrs(request: Request, skip: int = 0, limit: int = 100, db: Session = Depends(get_db), + Authorize: AuthJWT = Depends()): + """ + Returns template with all users currently saved in database + """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + users = crud.get_users(db, skip, limit) + if current_user == "admin": + return templates.TemplateResponse("users.html", {"request": request, "users": users}) + else: + return RedirectResponse(url=f"/logs-web", status_code=303) + + +@users.get("/user-role/{usr_id}", response_class=HTMLResponse) +async def connect_pc_team(usr_id: int, db: Session = Depends(get_db), Authorize: AuthJWT = Depends()): + """ + Changes role of user to either guest or admin depending on old role. + """ + Authorize.jwt_optional() + current_user = Authorize.get_jwt_subject() + if current_user != "admin": + return RedirectResponse(url=f"/logs-web", status_code=303) + user = crud.find_user_byid(db, usr_id) + if user.role == "admin": + crud.change_role(db, usr_id, "guest") + else: + crud.change_role(db, usr_id, "admin") + return RedirectResponse(url=f"/users-web", status_code=303) \ No newline at end of file diff --git a/server/sql_app/crud.py b/server/sql_app/crud.py index cc20541..f2b3a9b 100644 --- a/server/sql_app/crud.py +++ b/server/sql_app/crud.py @@ -99,7 +99,7 @@ def get_bodydevicelicense_by_bodydevicelicense(db: Session, device_id: int, lice returns entry in bodydevices_licenses table with given body device id and license id """ return db.query(models.BodyDeviceLicense).filter(and_(models.BodyDeviceLicense.bodydevice_id == device_id, - models.BodyDeviceLicense.license_id == license_id)).first() + models.BodyDeviceLicense.license_id == license_id)).first() def get_license_bodydevice(db: Session, license_id: int): @@ -188,6 +188,18 @@ def update_pc(db: Session, pc_id: int, team: str): db.refresh(old_pc) return old_pc +def change_role(db: Session, usr_id: int, role: str): + """ + Updates team of one specific pc + """ + old_usr = find_user_byid(db, usr_id) + new = {'id': old_usr.id, 'username': old_usr.username, 'password': old_usr.password, 'role': role} + for key, value in new.items(): + setattr(old_usr, key, value) + db.commit() + db.refresh(old_usr) + return old_usr + def get_pcs(db: Session, skip: int = 0, limit: int = 100): """ @@ -482,3 +494,35 @@ def create_device_logs(db: Session, item: schemas.USBTempBase, dev_id: int, pc_i db.commit() db.refresh(db_log) return db_log + + +def get_users(db: Session, skip: int = 0, limit: int = 100): + """ + Returns all users saved in database + """ + return db.query(models.User).offset(skip).limit(limit).all() + + +def find_user(db: Session, name: str): + """ + Finds one user by given username + """ + return db.query(models.User).filter(models.User.username == name).first() + + +def find_user_byid(db: Session, id: int): + """ + Finds one user by given id + """ + return db.query(models.User).filter(models.User.id == id).first() + + +def create_user(db: Session, name: str, passw: str, rol: str): + """ + Creates new user + """ + db_user = models.User(username=name, password=passw, role=rol) + db.add(db_user) + db.commit() + db.refresh(db_user) + return db_user diff --git a/server/sql_app/main.py b/server/sql_app/main.py index 99026c6..224d136 100644 --- a/server/sql_app/main.py +++ b/server/sql_app/main.py @@ -12,6 +12,7 @@ from sql_app.api.teams_web import teams_web from sql_app.api.auth import auth from sql_app.api.ld_logs_web import ldlogs_web from sql_app.api.bodydevices_web import body_device_web +from sql_app.api.users_web import users from fastapi import FastAPI @@ -32,6 +33,7 @@ app.include_router(teams_web) app.include_router(usblogs_web) app.include_router(ldlogs_web) app.include_router(body_device_web) +app.include_router(users) app.include_router(auth) ''' diff --git a/server/sql_app/models.py b/server/sql_app/models.py index 8d62fe9..d91cfa5 100644 --- a/server/sql_app/models.py +++ b/server/sql_app/models.py @@ -165,3 +165,14 @@ class LDLog(Base): ldpc = relationship("PC", back_populates="ld_pc") head_device = relationship("HeadDevice", back_populates="h_logs") body_device = relationship("BodyDevice", back_populates="b_logs") + +class User(Base): + """ + Class defining user in database with its own role + """ + __tablename__ = "users" + + id = Column(Integer, primary_key=True, index=True) + username = Column(String, index=True, nullable=False) + password = Column(String, index=True, nullable=False) + role = Column(String, index=True, nullable=False) diff --git a/server/sql_app/schemas.py b/server/sql_app/schemas.py index c0fe099..79becdc 100644 --- a/server/sql_app/schemas.py +++ b/server/sql_app/schemas.py @@ -232,3 +232,22 @@ class LDTemp(LDTempCreate): class Config: orm_mode = True + + +class UserBase(BaseModel): + """ + Classes used for creating new User entry + """ + username: str + password: str + role: str + +class UserCreate(UserBase): + pass + + +class User(UserCreate): + id: int + + class Config: + orm_mode = True diff --git a/server/templates/auth/login.html b/server/templates/auth/login.html index 0def994..fa536c5 100644 --- a/server/templates/auth/login.html +++ b/server/templates/auth/login.html @@ -8,9 +8,9 @@ <form action="/login" method="post"> <label for="username">Username:</label><br> <input type="text" id="username" name="username"><br><br> - <label for="password">Password</label> + <label for="password">Password:</label> <input type="password" id="password" name="password"> - <input type="submit" value="Submit"> + <input type="submit" value="LogIn"> </form> </body> </html> \ No newline at end of file diff --git a/server/templates/auth/signup.html b/server/templates/auth/signup.html new file mode 100644 index 0000000..b8b19ff --- /dev/null +++ b/server/templates/auth/signup.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Sign Up</title> +</head> +<body> +<form action="/signup" method="post"> + <label for="username">Username:</label><br> + <input type="text" id="username" name="username"><br><br> + <label for="password">Password:</label> + <input type="password" id="password" name="password"> + <input type="submit" value="Signup"> +</form> +</body> +</html> \ No newline at end of file diff --git a/server/templates/body-devices/body_devices.html b/server/templates/body-devices/body_devices.html index 1116968..251afd4 100644 --- a/server/templates/body-devices/body_devices.html +++ b/server/templates/body-devices/body_devices.html @@ -15,6 +15,7 @@ <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> <option value="/licenses-web">Licenses</option> + <option value="/users-web">Users</option> </select> <input type="submit" value="OK"> </form> @@ -25,6 +26,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/body-devices/body_devices_normal.html b/server/templates/body-devices/body_devices_normal.html index d0ce81b..84db09c 100644 --- a/server/templates/body-devices/body_devices_normal.html +++ b/server/templates/body-devices/body_devices_normal.html @@ -25,6 +25,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/devices/devices.html b/server/templates/devices/devices.html index 3685a70..7457c96 100644 --- a/server/templates/devices/devices.html +++ b/server/templates/devices/devices.html @@ -15,6 +15,7 @@ <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> <option value="/licenses-web">Licenses</option> + <option value="/users-web">Users</option> </select> <input type="submit" value="OK"> </form> @@ -25,6 +26,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/devices/devices_normal.html b/server/templates/devices/devices_normal.html index 7b5d898..fe35d04 100644 --- a/server/templates/devices/devices_normal.html +++ b/server/templates/devices/devices_normal.html @@ -25,6 +25,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/ld-logs/ldlogs.html b/server/templates/ld-logs/ldlogs.html index a936ff4..d2793e1 100644 --- a/server/templates/ld-logs/ldlogs.html +++ b/server/templates/ld-logs/ldlogs.html @@ -15,6 +15,7 @@ <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> <option value="/licenses-web">Licenses</option> + <option value="/users-web">Users</option> </select> <input type="submit" value="OK"> </form> @@ -25,6 +26,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/ld-logs/ldlogs_normal.html b/server/templates/ld-logs/ldlogs_normal.html new file mode 100644 index 0000000..435b9f6 --- /dev/null +++ b/server/templates/ld-logs/ldlogs_normal.html @@ -0,0 +1,91 @@ +<html> +<head> + <title> LD Logs Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> + <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +</div> +<h4>{{user}}</h4> +<form action="/ldlogs-web" method="post"> + <label for="pc">PC:</label> + <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> + <datalist id="pcs"> + {% for pc in pcs %} + <option value="{{pc.username}}"></option> + {% endfor %} + </datalist> + <label for="team">Team:</label> + <input id="team" name="team" type="text" list="teams" value="" placeholder="all"> + <datalist id="teams"> + {% for team in teams %} + <option value="{{team.name}}"></option> + {% endfor %} + </datalist> + <label for="lic">License:</label> + <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> + <datalist id="licenses"> + {% for license in licenses %} + <option value="{{license.name}}"></option> + {% endfor %} + </datalist> + <input type="submit" value="Filter"> +</form> + <table> + <TR> + <TH>ID</TH> + <TH>PC Username</TH> + <TH>PC Hostname</TH> + <TH>Team</TH> + <TH>Timestamp</TH> + <TH>Status</TH> + <TH>Head Device Serial Number</TH> + <TH>Body Device Serial Number</TH> + </TR> + {% for log in logs %} + <TR> + <TD class="ID">{{log.id}}</TD> + <TD class="Username">{{log.ldpc.username}}</TD> + <TD class="Hostname">{{log.ldpc.hostname}}</TD> + {% if log.ldpc.team == None %} + <TD class="Team">NONE</TD> + {% else %} + <TD class="Team">{{log.ldpc.team.name}}</TD> + {% endif %} + <TD class="Timestamp">{{log.timestamp}}</TD> + <TD class="Status">{{log.status}}</TD> + <TD class="HeadDeviceSerialNumber">{{log.head_device.serial_number}}</TD> + <TD class="BodyDeviceSerialNumber">{{log.body_device.serial_number}}</TD> + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/licenses/licenses.html b/server/templates/licenses/licenses.html index e66abfe..9b2471d 100644 --- a/server/templates/licenses/licenses.html +++ b/server/templates/licenses/licenses.html @@ -15,6 +15,7 @@ <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> <option value="/licenses-web">Licenses</option> + <option value="/users-web">Users</option> </select> <input type="submit" value="OK"> </form> @@ -25,6 +26,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/licenses/licenses_normal.html b/server/templates/licenses/licenses_normal.html index 7b5b644..7b672a1 100644 --- a/server/templates/licenses/licenses_normal.html +++ b/server/templates/licenses/licenses_normal.html @@ -25,6 +25,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/pcs/pcs.html b/server/templates/pcs/pcs.html index 79f3156..f8897b7 100644 --- a/server/templates/pcs/pcs.html +++ b/server/templates/pcs/pcs.html @@ -15,6 +15,7 @@ <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> <option value="/licenses-web">Licenses</option> + <option value="/users-web">Users</option> </select> <input type="submit" value="OK"> </form> @@ -25,6 +26,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/pcs/pcs_normal.html b/server/templates/pcs/pcs_normal.html index 52d9085..3925ad0 100644 --- a/server/templates/pcs/pcs_normal.html +++ b/server/templates/pcs/pcs_normal.html @@ -25,6 +25,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/teams/teams.html b/server/templates/teams/teams.html index 546666b..6dc7168 100644 --- a/server/templates/teams/teams.html +++ b/server/templates/teams/teams.html @@ -15,6 +15,7 @@ <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> <option value="/licenses-web">Licenses</option> + <option value="/users-web">Users</option> </select> <input type="submit" value="OK"> </form> @@ -25,6 +26,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/teams/teams_normal.html b/server/templates/teams/teams_normal.html index 50a7883..6e21020 100644 --- a/server/templates/teams/teams_normal.html +++ b/server/templates/teams/teams_normal.html @@ -25,6 +25,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/usb-logs/logs.html b/server/templates/usb-logs/logs.html index e1d0a17..c69de25 100644 --- a/server/templates/usb-logs/logs.html +++ b/server/templates/usb-logs/logs.html @@ -15,6 +15,7 @@ <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> <option value="/licenses-web">Licenses</option> + <option value="/users-web">Users</option> </select> <input type="submit" value="OK"> </form> @@ -25,6 +26,11 @@ </form> </div> <div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> <form action="/logout" method="get"> <input type="submit" value="Logout" /> </form> diff --git a/server/templates/usb-logs/logs_normal.html b/server/templates/usb-logs/logs_normal.html new file mode 100644 index 0000000..1a7bf53 --- /dev/null +++ b/server/templates/usb-logs/logs_normal.html @@ -0,0 +1,91 @@ +<html> +<head> + <title>Logs Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> + <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<div style='float:left'> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +</div> +<h4>{{user}}</h4> +<form action="/logs-web" method="post"> + <label for="pc">PC:</label> + <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> + <datalist id="pcs"> + {% for pc in pcs %} + <option value="{{pc.username}}"></option> + {% endfor %} + </datalist> + <label for="team">Team:</label> + <input id="team" name="team" type="text" list="teams" value="" placeholder="all"> + <datalist id="teams"> + {% for team in teams %} + <option value="{{team.name}}"></option> + {% endfor %} + </datalist> + <label for="lic">License:</label> + <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> + <datalist id="licenses"> + {% for license in licenses %} + <option value="{{license.name}}"></option> + {% endfor %} + </datalist> + <input type="submit" value="Filter"> +</form> + <table> + <TR> + <TH>ID</TH> + <TH>PC Username</TH> + <TH>PC Hostname</TH> + <TH>Team</TH> + <TH>Timestamp</TH> + <TH>Status</TH> + <TH>Device Product ID</TH> + <TH>Device Serial Number</TH> + </TR> + {% for log in logs %} + <TR> + <TD class="ID">{{log.id}}</TD> + <TD class="Username">{{log.pc.username}}</TD> + <TD class="Hostname">{{log.pc.hostname}}</TD> + {% if log.pc.team == None %} + <TD class="Team">NONE</TD> + {% else %} + <TD class="Team">{{log.pc.team.name}}</TD> + {% endif %} + <TD class="Timestamp">{{log.timestamp}}</TD> + <TD class="Status">{{log.status}}</TD> + <TD class="DeviceProductID">{{log.device.product_id}}</TD> + <TD class="DeviceSerialNumber">{{log.device.serial_number}}</TD> + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file diff --git a/server/templates/users/users.html b/server/templates/users/users.html new file mode 100644 index 0000000..904942e --- /dev/null +++ b/server/templates/users/users.html @@ -0,0 +1,50 @@ +<html> +<head> + <title>Users Details</title> +</head> +<body> +<div style='float:left'> +<form action="" method="get"> + <label for="view">Choose view:</label> + <select id="view" name="view" onchange="this.form.action=this.value;"> + <option value=""></option> + <option value="/logs-web">Logs</option> + <option value="/ldlogs-web">LD Logs</option> + <option value="/devices-web">Devices</option> + <option value="/body-devices-web">Body Devices</option> + <option value="/teams-web">Teams</option> + <option value="/pcs-web">PCs</option> + <option value="/licenses-web">Licenses</option> + </select> + <input type="submit" value="OK"> +</form> +</div> +<div style='float:left'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> +<table> + <TR> + <TH>ID</TH> + <TH>Username</TH> + <TH>Role</TH> + </TR> + {% for user in users %} + <TR> + <TD class="ID"><a href="/user-role/{{user.id}}">{{user.id}}</a></TD> + <TD class="Username">{{user.username}}</TD> + <TD class="Role">{{user.role}}</TD> + </TR> + {% endfor %} +</table> +</body> +</html> \ No newline at end of file -- GitLab From 2552e6144a1c151f27867e95eba0d8062853fe99 Mon Sep 17 00:00:00 2001 From: Matej Zeman <zeman339@gmail.com> Date: Mon, 9 May 2022 21:04:24 +0200 Subject: [PATCH 13/13] Changed certain template looks and controls. --- server/sql_app/api/auth.py | 17 ++++++---- .../body-devices/body_device_license.html | 2 +- .../templates/body-devices/body_devices.html | 34 +++++++++---------- .../body-devices/body_devices_normal.html | 34 +++++++++---------- server/templates/devices/devices.html | 34 +++++++++---------- server/templates/devices/devices_normal.html | 34 +++++++++---------- server/templates/ld-logs/ldlogs.html | 34 +++++++++---------- server/templates/ld-logs/ldlogs_normal.html | 34 +++++++++---------- server/templates/licenses/licenses.html | 34 +++++++++---------- .../templates/licenses/licenses_normal.html | 34 +++++++++---------- server/templates/pcs/pcs.html | 34 +++++++++---------- server/templates/pcs/pcs_normal.html | 34 +++++++++---------- server/templates/teams/teams.html | 34 +++++++++---------- server/templates/teams/teams_normal.html | 34 +++++++++---------- server/templates/usb-logs/logs.html | 34 +++++++++---------- server/templates/usb-logs/logs_normal.html | 34 +++++++++---------- server/templates/users/users.html | 29 ++++++++-------- 17 files changed, 249 insertions(+), 275 deletions(-) diff --git a/server/sql_app/api/auth.py b/server/sql_app/api/auth.py index cf8aeba..a66baca 100644 --- a/server/sql_app/api/auth.py +++ b/server/sql_app/api/auth.py @@ -93,9 +93,9 @@ async def signup(username: str = Form(...), password: str = Form(...), db: Sessi <title>Signup</title> </head> <body> - <h1>Signed in</h1> + <h1>New user created. You can go back to previous page.</h1> <form action="/logs-web" method="get"> - <input type="submit" value="Back" /> + <input type="submit" value="Home Page" /> </form> </body> </html> @@ -107,9 +107,9 @@ async def signup(username: str = Form(...), password: str = Form(...), db: Sessi <title>Signup</title> </head> <body> - <h1>Username taken</h1> + <h1>Username taken. Try to choose different username.</h1> <form action="/logs-web" method="get"> - <input type="submit" value="Back" /> + <input type="submit" value="Home Page" /> </form> </body> </html> @@ -153,7 +153,10 @@ async def login(username: str = Form(...), password: str = Form(...), db: Sessio <body> <h1>Wrong Username or Password</h1> <form action="/login" method="get"> - <input type="submit" value="Back" /> + <input type="submit" value="Log again" /> + </form> + <form action="/login" method="get"> + <input type="submit" value="Home Page" /> </form> </body> </html> @@ -168,9 +171,9 @@ async def login(username: str = Form(...), password: str = Form(...), db: Sessio <title>Login</title> </head> <body> - <h1>Logged in</h1> + <h1>Now you are logged in, you can continue to previous page.</h1> <form action="/logs-web" method="get"> - <input type="submit" value="Back" /> + <input type="submit" value="Home Page" /> </form> </body> </html> diff --git a/server/templates/body-devices/body_device_license.html b/server/templates/body-devices/body_device_license.html index 9c9dee5..d0c1896 100644 --- a/server/templates/body-devices/body_device_license.html +++ b/server/templates/body-devices/body_device_license.html @@ -19,7 +19,7 @@ </form> <form action="/body-devices-web-del/{{device.id}}" method="post"> <label for="b_lic">Licenses:</label> - <select id="b_lic" name="b_lic"> + <select id="b_lic" name="b_lic" > {% for license in dev_lic %} <option value={{license.id}}>{{license.name}}</option> {% endfor %} diff --git a/server/templates/body-devices/body_devices.html b/server/templates/body-devices/body_devices.html index 251afd4..b36a923 100644 --- a/server/templates/body-devices/body_devices.html +++ b/server/templates/body-devices/body_devices.html @@ -3,7 +3,22 @@ <title>Devices Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -19,23 +34,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <form action="/body-devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> diff --git a/server/templates/body-devices/body_devices_normal.html b/server/templates/body-devices/body_devices_normal.html index 84db09c..ece156d 100644 --- a/server/templates/body-devices/body_devices_normal.html +++ b/server/templates/body-devices/body_devices_normal.html @@ -3,7 +3,22 @@ <title>Devices Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -18,23 +33,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <form action="/body-devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> diff --git a/server/templates/devices/devices.html b/server/templates/devices/devices.html index 7457c96..e2f0bb7 100644 --- a/server/templates/devices/devices.html +++ b/server/templates/devices/devices.html @@ -3,7 +3,22 @@ <title>Devices Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -19,23 +34,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <form action="/devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> diff --git a/server/templates/devices/devices_normal.html b/server/templates/devices/devices_normal.html index fe35d04..4e0813f 100644 --- a/server/templates/devices/devices_normal.html +++ b/server/templates/devices/devices_normal.html @@ -3,7 +3,22 @@ <title>Devices Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -18,23 +33,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <form action="/devices-web" method="post"> <label for="lic">License:</label> <input id="lic" name="lic" type="text" list="licenses" value="" placeholder="all"> diff --git a/server/templates/ld-logs/ldlogs.html b/server/templates/ld-logs/ldlogs.html index d2793e1..deda9b0 100644 --- a/server/templates/ld-logs/ldlogs.html +++ b/server/templates/ld-logs/ldlogs.html @@ -3,7 +3,22 @@ <title> LD Logs Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -19,23 +34,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <form action="/ldlogs-web" method="post"> <label for="pc">PC:</label> <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> diff --git a/server/templates/ld-logs/ldlogs_normal.html b/server/templates/ld-logs/ldlogs_normal.html index 435b9f6..0487981 100644 --- a/server/templates/ld-logs/ldlogs_normal.html +++ b/server/templates/ld-logs/ldlogs_normal.html @@ -3,7 +3,22 @@ <title> LD Logs Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -18,23 +33,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <form action="/ldlogs-web" method="post"> <label for="pc">PC:</label> <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> diff --git a/server/templates/licenses/licenses.html b/server/templates/licenses/licenses.html index 9b2471d..57a9b61 100644 --- a/server/templates/licenses/licenses.html +++ b/server/templates/licenses/licenses.html @@ -3,7 +3,22 @@ <title>Licenses Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -19,23 +34,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/licenses/licenses_normal.html b/server/templates/licenses/licenses_normal.html index 7b672a1..2f580d4 100644 --- a/server/templates/licenses/licenses_normal.html +++ b/server/templates/licenses/licenses_normal.html @@ -3,7 +3,22 @@ <title>Licenses Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -18,23 +33,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/pcs/pcs.html b/server/templates/pcs/pcs.html index f8897b7..72295e2 100644 --- a/server/templates/pcs/pcs.html +++ b/server/templates/pcs/pcs.html @@ -3,7 +3,22 @@ <title>Pcs Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -19,23 +34,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/pcs/pcs_normal.html b/server/templates/pcs/pcs_normal.html index 3925ad0..b6b6cd5 100644 --- a/server/templates/pcs/pcs_normal.html +++ b/server/templates/pcs/pcs_normal.html @@ -3,7 +3,22 @@ <title>Pcs Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -18,23 +33,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/teams/teams.html b/server/templates/teams/teams.html index 6dc7168..f6945e6 100644 --- a/server/templates/teams/teams.html +++ b/server/templates/teams/teams.html @@ -3,7 +3,22 @@ <title>Teams Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -19,23 +34,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/teams/teams_normal.html b/server/templates/teams/teams_normal.html index 6e21020..d25b5b9 100644 --- a/server/templates/teams/teams_normal.html +++ b/server/templates/teams/teams_normal.html @@ -3,7 +3,22 @@ <title>Teams Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -18,23 +33,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <table> <TR> <TH>ID</TH> diff --git a/server/templates/usb-logs/logs.html b/server/templates/usb-logs/logs.html index c69de25..4f1bb07 100644 --- a/server/templates/usb-logs/logs.html +++ b/server/templates/usb-logs/logs.html @@ -3,7 +3,22 @@ <title>Logs Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -19,23 +34,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <form action="/logs-web" method="post"> <label for="pc">PC:</label> <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> diff --git a/server/templates/usb-logs/logs_normal.html b/server/templates/usb-logs/logs_normal.html index 1a7bf53..aaf52e8 100644 --- a/server/templates/usb-logs/logs_normal.html +++ b/server/templates/usb-logs/logs_normal.html @@ -3,7 +3,22 @@ <title>Logs Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:20px'> +<b>Your role: {{user}}</b> +</div> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -18,23 +33,6 @@ </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<div style='float:left'> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> -</div> -<h4>{{user}}</h4> <form action="/logs-web" method="post"> <label for="pc">PC:</label> <input id="pc" name="pc" type="text" list="pcs" value="" placeholder="all"> diff --git a/server/templates/users/users.html b/server/templates/users/users.html index 904942e..dfb9e87 100644 --- a/server/templates/users/users.html +++ b/server/templates/users/users.html @@ -3,7 +3,19 @@ <title>Users Details</title> </head> <body> -<div style='float:left'> +<div style='float:left;padding-right:5px'> +<form action="/login" method="get"> + <input type="submit" value="Login" /> +</form> +</div> +<div style='float:left;padding-right:5px'> +<form action="/signup" method="get"> + <input type="submit" value="Sign Up" /> +</form> +</div> +<form action="/logout" method="get"> + <input type="submit" value="Logout" /> +</form> <form action="" method="get"> <label for="view">Choose view:</label> <select id="view" name="view" onchange="this.form.action=this.value;"> @@ -15,23 +27,10 @@ <option value="/teams-web">Teams</option> <option value="/pcs-web">PCs</option> <option value="/licenses-web">Licenses</option> + <option value="/users-web">Users</option> </select> <input type="submit" value="OK"> </form> -</div> -<div style='float:left'> -<form action="/login" method="get"> - <input type="submit" value="Login" /> -</form> -</div> -<div style='float:left'> -<form action="/signup" method="get"> - <input type="submit" value="Sign Up" /> -</form> -</div> -<form action="/logout" method="get"> - <input type="submit" value="Logout" /> -</form> <table> <TR> <TH>ID</TH> -- GitLab