goosebit 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. goosebit/__init__.py +8 -5
  2. goosebit/api/__init__.py +1 -1
  3. goosebit/api/devices.py +60 -36
  4. goosebit/api/download.py +28 -14
  5. goosebit/api/firmware.py +37 -44
  6. goosebit/api/helper.py +30 -0
  7. goosebit/api/rollouts.py +87 -0
  8. goosebit/api/routes.py +15 -7
  9. goosebit/auth/__init__.py +37 -21
  10. goosebit/db.py +5 -0
  11. goosebit/models.py +125 -6
  12. goosebit/permissions.py +33 -13
  13. goosebit/realtime/__init__.py +1 -1
  14. goosebit/realtime/logs.py +4 -6
  15. goosebit/settings.py +38 -29
  16. goosebit/telemetry/__init__.py +28 -0
  17. goosebit/telemetry/prometheus.py +10 -0
  18. goosebit/ui/__init__.py +1 -1
  19. goosebit/ui/routes.py +36 -39
  20. goosebit/ui/static/js/devices.js +191 -239
  21. goosebit/ui/static/js/firmware.js +234 -88
  22. goosebit/ui/static/js/index.js +83 -84
  23. goosebit/ui/static/js/logs.js +17 -10
  24. goosebit/ui/static/js/rollouts.js +198 -0
  25. goosebit/ui/static/js/util.js +66 -0
  26. goosebit/ui/templates/devices.html +75 -42
  27. goosebit/ui/templates/firmware.html +150 -34
  28. goosebit/ui/templates/index.html +9 -23
  29. goosebit/ui/templates/login.html +58 -27
  30. goosebit/ui/templates/logs.html +18 -3
  31. goosebit/ui/templates/nav.html +78 -25
  32. goosebit/ui/templates/rollouts.html +76 -0
  33. goosebit/updater/__init__.py +1 -1
  34. goosebit/updater/controller/__init__.py +1 -1
  35. goosebit/updater/controller/v1/__init__.py +1 -1
  36. goosebit/updater/controller/v1/routes.py +112 -24
  37. goosebit/updater/manager.py +237 -94
  38. goosebit/updater/routes.py +7 -8
  39. goosebit/updates/__init__.py +70 -0
  40. goosebit/updates/swdesc.py +83 -0
  41. goosebit-0.1.2.dist-info/METADATA +123 -0
  42. goosebit-0.1.2.dist-info/RECORD +51 -0
  43. goosebit/updater/download/__init__.py +0 -1
  44. goosebit/updater/download/routes.py +0 -6
  45. goosebit/updater/download/v1/__init__.py +0 -1
  46. goosebit/updater/download/v1/routes.py +0 -26
  47. goosebit/updater/misc.py +0 -69
  48. goosebit/updater/updates.py +0 -93
  49. goosebit-0.1.0.dist-info/METADATA +0 -37
  50. goosebit-0.1.0.dist-info/RECORD +0 -48
  51. {goosebit-0.1.0.dist-info → goosebit-0.1.2.dist-info}/LICENSE +0 -0
  52. {goosebit-0.1.0.dist-info → goosebit-0.1.2.dist-info}/WHEEL +0 -0
@@ -0,0 +1,123 @@
1
+ Metadata-Version: 2.1
2
+ Name: goosebit
3
+ Version: 0.1.2
4
+ Summary:
5
+ Author: Upstream Data
6
+ Author-email: brett@upstreamdata.ca
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Requires-Dist: aerich (>=0.7.2,<0.8.0)
12
+ Requires-Dist: aiocache (>=0.12.2,<0.13.0)
13
+ Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
14
+ Requires-Dist: argon2-cffi (>=23.1.0,<24.0.0)
15
+ Requires-Dist: fastapi[uvicorn] (>=0.111.0,<0.112.0)
16
+ Requires-Dist: itsdangerous (>=2.2.0,<3.0.0)
17
+ Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
18
+ Requires-Dist: joserfc (>=1.0.0,<2.0.0)
19
+ Requires-Dist: libconf (>=2.0.1,<3.0.0)
20
+ Requires-Dist: opentelemetry-distro (>=0.47b0,<0.48)
21
+ Requires-Dist: opentelemetry-exporter-prometheus (>=0.47b0,<0.48)
22
+ Requires-Dist: opentelemetry-instrumentation-fastapi (>=0.47b0,<0.48)
23
+ Requires-Dist: python-multipart (>=0.0.9,<0.0.10)
24
+ Requires-Dist: semver (>=3.0.2,<4.0.0)
25
+ Requires-Dist: tortoise-orm (>=0.21.4,<0.22.0)
26
+ Requires-Dist: websockets (>=12.0,<13.0)
27
+ Description-Content-Type: text/markdown
28
+
29
+ # gooseBit
30
+
31
+ <img src="docs/img/goosebit-logo.png" style="width: 100px; height: 100px; display: block;">
32
+
33
+ ---
34
+
35
+ A simplistic, opinionated remote update server implementing hawkBit™'s [DDI API](https://eclipse.dev/hawkbit/apis/ddi_api/).
36
+
37
+ ## Setup
38
+
39
+ To set up, install the dependencies in `pyproject.toml` with `poetry install`. Then you can run gooseBit by running `main.py`.
40
+
41
+ ## Initial Startup
42
+
43
+ The first time you start gooseBit, you should change the default username and password inside `settings.yaml`.
44
+ The default login credentials for testing are `admin@goosebit.local`, `admin`.
45
+
46
+ ## Assumptions
47
+
48
+ - [SWUpdate](https://swupdate.org) used on device side.
49
+
50
+ ## Current Feature Set
51
+
52
+ ### Firmware repository
53
+
54
+ Uploading firmware images through frontend. All files should follow the format `{model}_{revision}_{version}`, where
55
+ `version` is either a semantic version or a datetime version in the format `YYYYMMDD-HHmmSS`.
56
+
57
+ ### Automatic device registration
58
+
59
+ First time a new device connects, its configuration data is requested. `hw_model` and `hw_revision` are captured from
60
+ the configuration data (both fall back to `default` if not provided) which allows to distinguish different device
61
+ types and their revisions.
62
+
63
+ ### Automatically update device to newest firmware
64
+
65
+ Once a device is registered it will get the newest available firmware from the repository based on model and revision.
66
+
67
+ ### Manually update device to specific firmware
68
+
69
+ Frontend allows to assign specific firmware to be rolled out.
70
+
71
+ ### Firmware rollout
72
+
73
+ Rollouts allow a fine-grained assignment of firmwares to devices. The reported device model and revision is combined
74
+ with the manually set feed and flavor values on a device to determine a matching rollout.
75
+
76
+ The feed is meant to model either different environments (like: dev, qa, live) or update channels (like. candidate,
77
+ fast, stable).
78
+
79
+ The flavor can be used for different type of builds (like: debug, prod).
80
+
81
+ ### Pause updates
82
+
83
+ Device can be pinned to its current firmware.
84
+
85
+ ### Realtime update logs
86
+
87
+ While an update is running, the update logs are captured and visualized in the frontend.
88
+
89
+ ## Development
90
+
91
+ ### Code formatting and linting
92
+
93
+ Code is formatted using different tools
94
+
95
+ - black and isort for `*.py`
96
+ - biomejs for `*.js`, `*.json`
97
+ - prettier for `*.html`, `*.md`, `*.yml`, `*.yaml`
98
+
99
+ Code is linted using different tools as well
100
+
101
+ - flake8 for `*.py`
102
+ - biomejs for `*.js`
103
+
104
+ Best to have pre-commit install git hooks that run all those tools before a commit:
105
+
106
+ ```bash
107
+ poetry run pre-commit install
108
+ ```
109
+
110
+ To manually apply the hooks to all files use:
111
+
112
+ ```bash
113
+ pre-commit run --all-files
114
+ ```
115
+
116
+ ### Testing
117
+
118
+ Tests are implemented using pytest. To run all tests
119
+
120
+ ```bash
121
+ poetry run pytest
122
+ ```
123
+
@@ -0,0 +1,51 @@
1
+ goosebit/__init__.py,sha256=zoQORspnBSSDfv2MpqFWrZtE2U_pE8KLWFIpiPSZVE0,2026
2
+ goosebit/api/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
3
+ goosebit/api/devices.py,sha256=w7KVp1NjVPMeSG1lr6nbhFExiavCz2bWYhWlngIqegA,4940
4
+ goosebit/api/download.py,sha256=kyOs8iZDnSma-HXb2qB7d3CC2tqP_2EJEODXcVvmwTY,998
5
+ goosebit/api/firmware.py,sha256=AfWZy41N0LGfyPhOOZ8Y8TQVHQJSHc5YNp12GNf5GaQ,1696
6
+ goosebit/api/helper.py,sha256=ErvjXru-FKhScE_toNKaxLabFyx_uZgDRNEGBZks-60,1000
7
+ goosebit/api/rollouts.py,sha256=6WDhPtzx1iiAmhqEx7NjeIDfmi5io1yWUDPFxO7Yn44,2673
8
+ goosebit/api/routes.py,sha256=gnQGxgZBQGRXQjagAN2tAo7aNzcULClQlVfYZcsrdfk,698
9
+ goosebit/auth/__init__.py,sha256=BpneDLWS7yfW4QIjFejdTRsUP8rIOQJjC5nggC5FMsg,4222
10
+ goosebit/db.py,sha256=2jqsYhJklJQ8Zuh9D4sy9lYfcqg3E-R6bOUSAbvjpjk,984
11
+ goosebit/models.py,sha256=zrZr-bKFOnd3CxLFtgTMullwRS49614O4b51OLQX6wo,4312
12
+ goosebit/permissions.py,sha256=4WmoReDCK2oIZJQyMOU8eQvdczb-KGY1nqPn4hOf1n4,1836
13
+ goosebit/realtime/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
14
+ goosebit/realtime/logs.py,sha256=t-tYO5EM5J9PGHUrz_7VCPiyGHIr2zQ3nkObYNaS4-A,1248
15
+ goosebit/realtime/routes.py,sha256=DzL1xBsdSc4SF2FiOAeuVKmcAq3m4DYo6KqD_pCNMww,269
16
+ goosebit/settings.py,sha256=MaCmklqfDO75WSrHkVdZ978DnO-iq7nnKabqkv6MVI0,1589
17
+ goosebit/telemetry/__init__.py,sha256=Gxc2gRyX8CQy6cdHepa2Hsn6n50f07_fr-OS_OOFukY,707
18
+ goosebit/telemetry/prometheus.py,sha256=vORU7zgqlAepTk7IwTE5_vt18_tbILWlJhCfeGMwTsM,382
19
+ goosebit/ui/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
20
+ goosebit/ui/routes.py,sha256=-I0muVY2SDAhF57Vn6jR8oGMye8ouKG55f8z3wB461Y,3249
21
+ goosebit/ui/static/__init__.py,sha256=AsZiM3h9chQ_YaBbAD6TVFf0244Q9DetkDMl70q8swQ,135
22
+ goosebit/ui/static/favicon.ico,sha256=FLzKyAkMvQcMg58nzCJxQOfPFxT4yYbP7S82pdY6zng,4286
23
+ goosebit/ui/static/favicon.svg,sha256=2iEZocLSave4QTjaR3GxGVT1zaDNl6T_GtN61YHsvJU,6595
24
+ goosebit/ui/static/js/devices.js,sha256=hdGaB4_az6AyVeFs09Ah9obMaOEONgXMFeXp-VVXWm4,11686
25
+ goosebit/ui/static/js/firmware.js,sha256=cfaVeJz2It4JvO7POBd3nag1_Mc5w51vByja-04g5Ac,9062
26
+ goosebit/ui/static/js/index.js,sha256=sxguHagyK3agGqnNHMf2AbhhmawewP5YMts6IYKfGRI,5550
27
+ goosebit/ui/static/js/logs.js,sha256=e9gBfWC7WNS87sO6tBlU1c8oKIch_Ot9sVkUTta-vbU,862
28
+ goosebit/ui/static/js/rollouts.js,sha256=jzAnX-waTPWim_uY8mC99KzkIQvAP-CZOT0HNARPOqY,6619
29
+ goosebit/ui/static/js/util.js,sha256=zJJH3lUc_spskseRSAV57dCFJJPgZxpiVA3WUP0-_tk,2049
30
+ goosebit/ui/static/svg/goosebit-logo.svg,sha256=2iEZocLSave4QTjaR3GxGVT1zaDNl6T_GtN61YHsvJU,6595
31
+ goosebit/ui/templates/__init__.py,sha256=M-F9UIAOVyRdsVIjU-19cCiXh48-LZBAKvl8R4CLlkM,140
32
+ goosebit/ui/templates/devices.html,sha256=8NH9NJqtzi6quqTA8B3TTKRnydJcVvJg0jkGeqr1CNY,3899
33
+ goosebit/ui/templates/firmware.html,sha256=yBV7Jzx4cy_aXLpSQfni9DB0byQ8b44Xv1GNQ-Q0NyI,7254
34
+ goosebit/ui/templates/index.html,sha256=QxRMJwUb37dQCiLSR84ICsUOHfZmo1QuW-3mlSaPTHg,796
35
+ goosebit/ui/templates/login.html,sha256=Uql0T8JIUuTXYOzto_BNTfKRQiZAqZvyr3wPGjRjhWE,2729
36
+ goosebit/ui/templates/logs.html,sha256=rGqLPHALZoFxJzyB82_vOaWndzDbr7ZbvyAuah5nbxM,1289
37
+ goosebit/ui/templates/nav.html,sha256=njPQEUXst2tR_nKWh4reaOyslC2dfNXNOBIT8pbPnb4,4948
38
+ goosebit/ui/templates/rollouts.html,sha256=3BGmRpfj5RaRNljVAYUYgKSdMpv-Mkn88lS1-V29naE,2620
39
+ goosebit/updater/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
40
+ goosebit/updater/controller/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
41
+ goosebit/updater/controller/routes.py,sha256=8CnLb-kDuO-yFeWdu4apIyctCf9OzvJ011Az3QDGemU,123
42
+ goosebit/updater/controller/v1/__init__.py,sha256=4RRIzqC6KbCESIC9Vc6G4iAa28IWQH4KROTGd2S4AoI,41
43
+ goosebit/updater/controller/v1/routes.py,sha256=sbMJZ69vOS1P28jECHfq48HVZyct37FI7E3NJc9xst4,6585
44
+ goosebit/updater/manager.py,sha256=UIV3FOABplB0jmA4pZFSoL2yEtByX1Kw2CEydmt0g7U,11400
45
+ goosebit/updater/routes.py,sha256=B9ufgYIkSsdKniiUTeJnwYsa_MWdQtuu5m3MNmHXZQQ,717
46
+ goosebit/updates/__init__.py,sha256=uVpqyW2q3j7cf20zo9yIXzdHGaduyfWMjTWWpP4bUzY,1946
47
+ goosebit/updates/swdesc.py,sha256=wT4TQSE5S13akMLGrCGUfWWi2j1freFENhDvaC5oTx4,2545
48
+ goosebit-0.1.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
49
+ goosebit-0.1.2.dist-info/METADATA,sha256=CFvsYgfBtR0Ve4ejtAp6q-b-En6K43l3R-o0lWWx2Ec,3827
50
+ goosebit-0.1.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
51
+ goosebit-0.1.2.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- from .routes import router
@@ -1,6 +0,0 @@
1
- from fastapi import APIRouter
2
-
3
- from . import v1
4
-
5
- router = APIRouter(prefix="/download")
6
- router.include_router(v1.router)
@@ -1 +0,0 @@
1
- from .routes import router
@@ -1,26 +0,0 @@
1
- from fastapi import APIRouter, Depends
2
- from fastapi.requests import Request
3
- from fastapi.responses import FileResponse
4
-
5
- from goosebit.settings import TOKEN_SWU_DIR, UPDATES_DIR
6
- from goosebit.updater.manager import UpdateManager, get_update_manager
7
-
8
- router = APIRouter(prefix="/v1")
9
-
10
-
11
- @router.get("/{dev_id}/{file}")
12
- async def download_file(request: Request, tenant: str, dev_id: str, file: str):
13
- filename = UPDATES_DIR.joinpath(file)
14
- return FileResponse(filename, media_type="application/octet-stream")
15
-
16
-
17
- @router.get("/{dev_id}/cfd_conf/{file}")
18
- async def download_cfd_conf(
19
- request: Request,
20
- tenant: str,
21
- dev_id: str,
22
- file: str,
23
- updater: UpdateManager = Depends(get_update_manager),
24
- ):
25
- filename = TOKEN_SWU_DIR.joinpath(dev_id, file)
26
- return FileResponse(filename, media_type="application/octet-stream")
goosebit/updater/misc.py DELETED
@@ -1,69 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import datetime
4
- import hashlib
5
- from pathlib import Path
6
-
7
- from goosebit.models import Device
8
- from goosebit.settings import UPDATES_DIR
9
-
10
-
11
- def sha1_hash_file(file_path: Path):
12
- with file_path.open("rb") as f:
13
- sha1_hash = hashlib.file_digest(f, "sha1")
14
- return sha1_hash.hexdigest()
15
-
16
-
17
- def get_newest_fw() -> str:
18
- fw_files = [f for f in UPDATES_DIR.iterdir() if f.suffix == ".swu"]
19
- if len(fw_files) == 0:
20
- return ""
21
-
22
- return str(sorted(fw_files, key=lambda x: fw_sort_key(x), reverse=True)[0].name)
23
-
24
-
25
- def fw_sort_key(filename: Path) -> datetime.datetime:
26
- image_data = filename.stem.split("_")
27
- if len(image_data) == 3:
28
- tenant, date, time = image_data
29
- elif len(image_data) == 4:
30
- tenant, hw_version, date, time = image_data
31
- else:
32
- return datetime.datetime.now()
33
-
34
- return datetime.datetime.strptime(f"{date}_{time}", "%Y%m%d_%H%M%S")
35
-
36
-
37
- def get_fw_components(filename: Path) -> dict:
38
- image_data = filename.stem.split("_")
39
- if len(image_data) == 3:
40
- tenant, date, time = image_data
41
- return {
42
- "date": datetime.datetime.strptime(f"{date}_{time}", "%Y%m%d_%H%M%S"),
43
- "day": date,
44
- "time": time,
45
- "tenant": tenant,
46
- "hw_version": 0,
47
- }
48
- elif len(image_data) == 4:
49
- tenant, hw_version, date, time = image_data
50
- return {
51
- "date": datetime.datetime.strptime(f"{date}_{time}", "%Y%m%d_%H%M%S"),
52
- "day": date,
53
- "time": time,
54
- "tenant": tenant,
55
- "hw_version": int(hw_version.upper().replace("V", "")),
56
- }
57
-
58
-
59
- async def get_device_by_uuid(dev_id: str) -> Device:
60
- if dev_id == "unknown":
61
- return Device(
62
- uuid="unknown",
63
- name="Unknown",
64
- fw_file="latest",
65
- fw_version=None,
66
- last_state=None,
67
- last_log=None,
68
- )
69
- return (await Device.get_or_create(uuid=dev_id))[0]
@@ -1,93 +0,0 @@
1
- import datetime
2
- from pathlib import Path
3
- from typing import Optional
4
-
5
- from fastapi.requests import Request
6
-
7
- from goosebit.settings import TOKEN_SWU_DIR, UPDATES_DIR
8
- from goosebit.updater.misc import get_newest_fw, sha1_hash_file
9
-
10
-
11
- class FirmwareArtifact:
12
- def __init__(self, file: str = None, dev_id: str = None):
13
- if file == "latest":
14
- self.file = get_newest_fw()
15
- elif file == "pinned":
16
- self.file = None
17
- else:
18
- self.file = file
19
- self.dev_id = dev_id
20
-
21
- def __eq__(self, other):
22
- if isinstance(other, str):
23
- return self.name == other
24
- elif isinstance(other, FirmwareArtifact):
25
- return self.file == other.file
26
- return False
27
-
28
- def is_empty(self) -> bool:
29
- return self.file is None
30
-
31
- def file_exists(self) -> bool:
32
- if self.is_empty():
33
- return False
34
- if self.file == "cloudflared.swu":
35
- return True
36
- return self.path.exists()
37
-
38
- @property
39
- def name(self):
40
- if not self.is_empty():
41
- return self.file.split(".")[0]
42
-
43
- @property
44
- def version(self):
45
- if not self.is_empty():
46
- return "_".join(self.name.split("_")[2:])
47
-
48
- @property
49
- def timestamp(self):
50
- return datetime.datetime.strptime(self.version, "%Y%m%d_%H%M%S")
51
-
52
- @property
53
- def path(self) -> Optional[Path]:
54
- if not self.is_empty():
55
- if self.file == "cloudflared.swu":
56
- return TOKEN_SWU_DIR.joinpath(self.dev_id, self.file)
57
- return UPDATES_DIR.joinpath(self.file)
58
-
59
- @property
60
- def dl_endpoint(self):
61
- if self.file == "cloudflared.swu":
62
- return "download_cfd_conf"
63
- return "download_file"
64
-
65
- def generate_chunk(self, request: Request, tenant: str, dev_id: str) -> list:
66
- if not self.file_exists():
67
- return []
68
- return [
69
- {
70
- "part": "os",
71
- "version": "1",
72
- "name": self.file,
73
- "artifacts": [
74
- {
75
- "filename": self.file,
76
- "hashes": {"sha1": sha1_hash_file(self.path)},
77
- "size": self.path.stat().st_size,
78
- "_links": {
79
- "download": {
80
- "href": str(
81
- request.url_for(
82
- self.dl_endpoint,
83
- tenant=tenant,
84
- dev_id=dev_id,
85
- file=self.file,
86
- )
87
- )
88
- }
89
- },
90
- }
91
- ],
92
- }
93
- ]
@@ -1,37 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: goosebit
3
- Version: 0.1.0
4
- Summary:
5
- Author: Upstream Data
6
- Author-email: brett@upstreamdata.ca
7
- Requires-Python: >=3.12,<4.0
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: Programming Language :: Python :: 3.12
10
- Requires-Dist: aerich (>=0.7.2,<0.8.0)
11
- Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
12
- Requires-Dist: fastapi[uvicorn] (>=0.111.0,<0.112.0)
13
- Requires-Dist: itsdangerous (>=2.2.0,<3.0.0)
14
- Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
15
- Requires-Dist: passlib[bcrypt] (>=1.7.4,<2.0.0)
16
- Requires-Dist: python-jose (>=3.3.0,<4.0.0)
17
- Requires-Dist: python-multipart (>=0.0.9,<0.0.10)
18
- Requires-Dist: tortoise-orm (>=0.21.4,<0.22.0)
19
- Requires-Dist: websockets (>=12.0,<13.0)
20
- Description-Content-Type: text/markdown
21
-
22
- # goosebit
23
- <img src="docs/img/goosebit-logo.png?raw=true" style="width: 100px; height: 100px; display: block;">
24
-
25
- ---
26
-
27
- A simplistic remote update server.
28
-
29
-
30
- ## Setup
31
-
32
- To set up, install the dependencies in `pyproject.toml` with `poetry install`. Then you can run GooseBit by running `main.py`.
33
-
34
- ## Initial Startup
35
-
36
- The first time you start GooseBit, you should change the default username and password inside `goosebit/settings.py`, as well as generate a new secret key.
37
- The default login credentials for testing are `admin@goosebit.local`, `admin`.
@@ -1,48 +0,0 @@
1
- goosebit/__init__.py,sha256=hfY3hKnwkJewwVT_DDFm_FjsvSUMsVDsBECL2g1gMOQ,1837
2
- goosebit/api/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
3
- goosebit/api/devices.py,sha256=PwjYuG3omM59EDQNGwyPik4wuZ_NOwfRoLBSFHoTMBM,3219
4
- goosebit/api/download.py,sha256=I9aL3ZkT2T5hfyTsuwwR5vFF5XjqnjHV0WjK0p-oToQ,607
5
- goosebit/api/firmware.py,sha256=0bvQuDX4ReiT6Xp4OA6pYQQ7u62DkOFoAnK7soZY2OQ,1778
6
- goosebit/api/routes.py,sha256=JLXWOwvOyLGcHX2nDl9ZVJSan5wdfDueYn0XGLPQ0NA,365
7
- goosebit/auth/__init__.py,sha256=47vSo8srLG_8P1gdb0mmnrxfqsvohIwdzrQbcliEo5g,3638
8
- goosebit/db.py,sha256=lIQR3s290qZX54NL1J-85Ge6l98xbV9_oRaCO48vdTY,787
9
- goosebit/models.py,sha256=7DMMZ29XnNnMjkfOiZ_lgLNf_3j_az4PlrfxfB2PTlw,765
10
- goosebit/permissions.py,sha256=Yg90HiQLfInSiP-_tUeirXrTc4CpuNSrIsBp3QYCTYI,1166
11
- goosebit/realtime/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
12
- goosebit/realtime/logs.py,sha256=hopd4zpEmTU4_De_tJwItoyyNjk1JiN5onyM8_q07S0,1207
13
- goosebit/realtime/routes.py,sha256=DzL1xBsdSc4SF2FiOAeuVKmcAq3m4DYo6KqD_pCNMww,269
14
- goosebit/settings.py,sha256=4bryUrICSDB_GDb0mNv7ix5vGH8qmZCo5KDYHqgqZuA,1163
15
- goosebit/ui/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
16
- goosebit/ui/routes.py,sha256=Iy7B1v5_Ao_KKEe_hI10C7hiQOOIiJJxAgcnW3_CW9U,2791
17
- goosebit/ui/static/__init__.py,sha256=AsZiM3h9chQ_YaBbAD6TVFf0244Q9DetkDMl70q8swQ,135
18
- goosebit/ui/static/favicon.ico,sha256=FLzKyAkMvQcMg58nzCJxQOfPFxT4yYbP7S82pdY6zng,4286
19
- goosebit/ui/static/favicon.svg,sha256=2iEZocLSave4QTjaR3GxGVT1zaDNl6T_GtN61YHsvJU,6595
20
- goosebit/ui/static/js/devices.js,sha256=IpDhT_9nm9lELVkBriKsIpEReajGfZ7bhsHfpvRaZtE,12550
21
- goosebit/ui/static/js/firmware.js,sha256=S-a8dG6JB_Qvxw0mhG0ksYuPPzk4gLs6AIR_a7suVqk,3919
22
- goosebit/ui/static/js/index.js,sha256=9Mlf679A_P2FcGx7cYfLPi3FVWJ6Yl2_vUPUpP4bEGg,5744
23
- goosebit/ui/static/js/logs.js,sha256=ajaOBtW__CToZLOo17bxNIaY6WkPyy_TDQD0Emwh0DI,611
24
- goosebit/ui/static/svg/goosebit-logo.svg,sha256=2iEZocLSave4QTjaR3GxGVT1zaDNl6T_GtN61YHsvJU,6595
25
- goosebit/ui/templates/__init__.py,sha256=M-F9UIAOVyRdsVIjU-19cCiXh48-LZBAKvl8R4CLlkM,140
26
- goosebit/ui/templates/devices.html,sha256=RQGeBnYZxTI382DuEbUyIRDyd3ZCkxo0vie4hOM905k,3025
27
- goosebit/ui/templates/firmware.html,sha256=JW6h0LxLHcvq4KIgEMXk7qyxWE0bTTbbbpjlOK_vQgE,2059
28
- goosebit/ui/templates/index.html,sha256=hzqo3o1rAqIXw-mTDxc4ah2M35oY3BJibnYNzlSEhiw,1096
29
- goosebit/ui/templates/login.html,sha256=Ip_-p3DbRyCkIjAfEBO2MyzEynQk1m9eKVGpuPLEF3c,1862
30
- goosebit/ui/templates/logs.html,sha256=ysdE8luiO8NNpeqtW2XCZKU7_4Muo13OGh9AzlmJtDg,633
31
- goosebit/ui/templates/nav.html,sha256=0ZWCkg4hJNFM64h_khcg-xs-8VixnYo35LbNi1aiF-I,3529
32
- goosebit/updater/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
33
- goosebit/updater/controller/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
34
- goosebit/updater/controller/routes.py,sha256=8CnLb-kDuO-yFeWdu4apIyctCf9OzvJ011Az3QDGemU,123
35
- goosebit/updater/controller/v1/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
36
- goosebit/updater/controller/v1/routes.py,sha256=-5sjiIRz5_rGppV9tL13ftGKDPYqNhXhzuiY7htXiLo,2290
37
- goosebit/updater/download/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
38
- goosebit/updater/download/routes.py,sha256=HNvpdlZvEeVfpY-JLhvUKHDd9eGKCAOFjh1EN98J9T0,121
39
- goosebit/updater/download/v1/__init__.py,sha256=Pn8KJu4sVaJKSSley4e1K5D_I3PrDd8ZLpWXchouH_o,27
40
- goosebit/updater/download/v1/routes.py,sha256=cwzdseHhOzfuze6r8_YuOC-YuPyu9QDvhSs1UZE5dho,840
41
- goosebit/updater/manager.py,sha256=179DJtW0hy5ztv-uM8jhTuavgVTm4JwgMjucSHTpfUU,5896
42
- goosebit/updater/misc.py,sha256=NIYdquYoH6ibGDxnIFVLzTKbb7wwc3eOIxhHXwLR4Ew,2000
43
- goosebit/updater/routes.py,sha256=pziZ15nTUV6zCkvlrdi7r5Az9U2INq3C6X_cj0yYHDw,788
44
- goosebit/updater/updates.py,sha256=OhSeRsXQgzUPffR_SJ_UGepOqScVZREoxNWx6PrxhbA,2837
45
- goosebit-0.1.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
46
- goosebit-0.1.0.dist-info/METADATA,sha256=zta3l3gBIW3roHD4lS-ow0ypntg_lz31u9AVSVbUrEs,1287
47
- goosebit-0.1.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
48
- goosebit-0.1.0.dist-info/RECORD,,