Compare commits

...
Sign in to create a new pull request.

5 commits

16 changed files with 437 additions and 97 deletions

1
.dockerignore Normal file
View file

@ -0,0 +1 @@
*/__pycache__

View file

@ -1,11 +1,26 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
# This Dockerfile builds a docker image containing all dependecies to run
# a development version of the lumi application.
FROM python:3 FROM python:3
# Install dependencies # Create non-root user
ARG LUMI2_UID
ARG LUMI2_GID
ENV LUMI2_USERNAME=lumi2
ENV LUMI2_GROUPNAME=lumi2
RUN groupadd --gid ${LUMI2_GID:-1000} ${LUMI2_GROUPNAME} && \
useradd --uid ${LUMI2_UID:-1000} --gid ${LUMI2_GID:-1000} --no-create-home --shell /bin/bash ${LUMI2_USERNAME} && \
mkdir /app && chown ${LUMI2_UID:-1000}:${LUMI2_GID:-1000} /app
# Copy source files
WORKDIR /app WORKDIR /app
COPY requirements.txt /app/ COPY --chown=${LUMI2_USERNAME}:${LUMI2_GROUPNAME} requirements.txt /app/
COPY --chown=${LUMI2_USERNAME}:${LUMI2_GROUPNAME} lumi2 /app/lumi2/
COPY --chown=${LUMI2_USERNAME}:${LUMI2_GROUPNAME} tests /app/tests/
COPY --chown=${LUMI2_USERNAME}:${LUMI2_GROUPNAME} pytest.ini /app/
# Install dependencies
RUN pip install -r requirements.txt RUN pip install -r requirements.txt
# Launch WSGI server
USER ${LUMI2_UID:-1000}:${LUMI2_GID:-1000}
ENTRYPOINT ["waitress-serve", "--listen=0.0.0.0:80", "--no-ipv6", "--call", "lumi2:create_app"]

View file

@ -4,35 +4,22 @@ version: "3"
services: services:
lumi2: lumi2:
build: .
container_name: lumi2 container_name: lumi2
command: flask --app /app/lumi2 --debug run --host 0.0.0.0 --port 80 build:
context: .
args:
LUMI2_UID: 1000
LUMI2_GID: 1000
volumes: volumes:
- ./config.py/:/app/config.py:ro - ./config.py/:/app/config.py:ro
- ./lumi2/__init__.py:/app/lumi2/__init__.py:ro
- ./lumi2/auth.py:/app/lumi2/auth.py:ro
- ./lumi2/default_configuration.py:/app/lumi2/default_configuration.py:ro
- ./lumi2/exceptions.py:/app/lumi2/exceptions.py:ro
- ./lumi2/ldap.py:/app/lumi2/ldap.py:ro
- ./lumi2/logging.py:/app/lumi2/logging.py:ro
- ./lumi2/static/css:/app/lumi2/static/css:ro
- ./lumi2/static/fonts:/app/lumi2/static/fonts:ro
- ./lumi2/static/images/base:/app/lumi2/static/images/base:ro
- ./lumi2/static/images/default:/app/lumi2/static/images/default:ro
- ./lumi2/static/js:/app/lumi2/static/js:ro
- ./lumi2/templates/:/app/lumi2/templates/:ro
- ./lumi2/usermanager.py:/app/lumi2/usermanager.py:ro
- ./lumi2/usermodel.py:/app/lumi2/usermodel.py:ro
- ./lumi2/webapi.py:/app/lumi2/webapi.py:ro
- ./tests/fakedata.py/:/app/tests/fakedata.py:ro
environment: environment:
- LUMI_CONFIG=/app/config.py - LUMI2_CONFIG=/app/config.py
ports: ports:
- "8000:80" - "8000:80"
depends_on: depends_on:
- lumi2-openldap - openldap
lumi2-openldap: openldap:
container_name: lumi2-openldap container_name: openldap
image: osixia/openldap image: osixia/openldap
restart: unless-stopped restart: unless-stopped
volumes: volumes:
@ -46,18 +33,6 @@ services:
LDAP_DOMAIN: "example.com" LDAP_DOMAIN: "example.com"
LDAP_ADMIN_PASSWORD: "admin" LDAP_ADMIN_PASSWORD: "admin"
LDAP_CONFIG_PASSWORD: "admin" LDAP_CONFIG_PASSWORD: "admin"
LDAP_TLS_VERIFY_CLIENT: "allow" LDAP_TLS_VERIFY_CLIENT: "never"
lumi2-phpldapadmin:
container_name: lumi2-phpldapadmin
image: osixia/phpldapadmin
restart: unless-stopped
depends_on:
- lumi2-openldap
ports:
- "8001:80"
environment:
PHPLDAPADMIN_LDAP_HOSTS: "openldap"
PHPLDAPADMIN_HTTPS: "false"
PHPLDAPADMIN_SERVER_ADMIN: "admin"
... ...

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 KiB

BIN
docs/screenshot-index.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

BIN
docs/screenshot-user.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

BIN
docs/screenshot-users.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

View file

@ -20,7 +20,7 @@ def create_app(test_config=None):
if test_config is None: if test_config is None:
# Load the instance config, if it exists, when not testing # Load the instance config, if it exists, when not testing
app.config.from_envvar('LUMI_CONFIG', silent=True) app.config.from_envvar('LUMI2_CONFIG', silent=True)
else: else:
# Load the test config if passed in # Load the test config if passed in
app.config.from_mapping(test_config) app.config.from_mapping(test_config)

View file

@ -6046,8 +6046,6 @@ textarea.form-control-lg {
border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(-100%); transform: translateX(-100%);
} }
}
@media (max-width: 575.98px) {
.offcanvas-sm.offcanvas-end { .offcanvas-sm.offcanvas-end {
top: 0; top: 0;
right: 0; right: 0;
@ -6055,8 +6053,6 @@ textarea.form-control-lg {
border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(100%); transform: translateX(100%);
} }
}
@media (max-width: 575.98px) {
.offcanvas-sm.offcanvas-top { .offcanvas-sm.offcanvas-top {
top: 0; top: 0;
right: 0; right: 0;
@ -6066,8 +6062,6 @@ textarea.form-control-lg {
border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(-100%); transform: translateY(-100%);
} }
}
@media (max-width: 575.98px) {
.offcanvas-sm.offcanvas-bottom { .offcanvas-sm.offcanvas-bottom {
right: 0; right: 0;
left: 0; left: 0;
@ -6076,13 +6070,9 @@ textarea.form-control-lg {
border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(100%); transform: translateY(100%);
} }
}
@media (max-width: 575.98px) {
.offcanvas-sm.showing, .offcanvas-sm.show:not(.hiding) { .offcanvas-sm.showing, .offcanvas-sm.show:not(.hiding) {
transform: none; transform: none;
} }
}
@media (max-width: 575.98px) {
.offcanvas-sm.showing, .offcanvas-sm.hiding, .offcanvas-sm.show { .offcanvas-sm.showing, .offcanvas-sm.hiding, .offcanvas-sm.show {
visibility: visible; visibility: visible;
} }
@ -6134,8 +6124,6 @@ textarea.form-control-lg {
border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(-100%); transform: translateX(-100%);
} }
}
@media (max-width: 767.98px) {
.offcanvas-md.offcanvas-end { .offcanvas-md.offcanvas-end {
top: 0; top: 0;
right: 0; right: 0;
@ -6143,8 +6131,6 @@ textarea.form-control-lg {
border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(100%); transform: translateX(100%);
} }
}
@media (max-width: 767.98px) {
.offcanvas-md.offcanvas-top { .offcanvas-md.offcanvas-top {
top: 0; top: 0;
right: 0; right: 0;
@ -6154,8 +6140,6 @@ textarea.form-control-lg {
border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(-100%); transform: translateY(-100%);
} }
}
@media (max-width: 767.98px) {
.offcanvas-md.offcanvas-bottom { .offcanvas-md.offcanvas-bottom {
right: 0; right: 0;
left: 0; left: 0;
@ -6164,13 +6148,9 @@ textarea.form-control-lg {
border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(100%); transform: translateY(100%);
} }
}
@media (max-width: 767.98px) {
.offcanvas-md.showing, .offcanvas-md.show:not(.hiding) { .offcanvas-md.showing, .offcanvas-md.show:not(.hiding) {
transform: none; transform: none;
} }
}
@media (max-width: 767.98px) {
.offcanvas-md.showing, .offcanvas-md.hiding, .offcanvas-md.show { .offcanvas-md.showing, .offcanvas-md.hiding, .offcanvas-md.show {
visibility: visible; visibility: visible;
} }
@ -6222,8 +6202,6 @@ textarea.form-control-lg {
border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(-100%); transform: translateX(-100%);
} }
}
@media (max-width: 991.98px) {
.offcanvas-lg.offcanvas-end { .offcanvas-lg.offcanvas-end {
top: 0; top: 0;
right: 0; right: 0;
@ -6231,8 +6209,6 @@ textarea.form-control-lg {
border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(100%); transform: translateX(100%);
} }
}
@media (max-width: 991.98px) {
.offcanvas-lg.offcanvas-top { .offcanvas-lg.offcanvas-top {
top: 0; top: 0;
right: 0; right: 0;
@ -6242,8 +6218,6 @@ textarea.form-control-lg {
border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(-100%); transform: translateY(-100%);
} }
}
@media (max-width: 991.98px) {
.offcanvas-lg.offcanvas-bottom { .offcanvas-lg.offcanvas-bottom {
right: 0; right: 0;
left: 0; left: 0;
@ -6252,13 +6226,9 @@ textarea.form-control-lg {
border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(100%); transform: translateY(100%);
} }
}
@media (max-width: 991.98px) {
.offcanvas-lg.showing, .offcanvas-lg.show:not(.hiding) { .offcanvas-lg.showing, .offcanvas-lg.show:not(.hiding) {
transform: none; transform: none;
} }
}
@media (max-width: 991.98px) {
.offcanvas-lg.showing, .offcanvas-lg.hiding, .offcanvas-lg.show { .offcanvas-lg.showing, .offcanvas-lg.hiding, .offcanvas-lg.show {
visibility: visible; visibility: visible;
} }
@ -6310,8 +6280,6 @@ textarea.form-control-lg {
border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(-100%); transform: translateX(-100%);
} }
}
@media (max-width: 1199.98px) {
.offcanvas-xl.offcanvas-end { .offcanvas-xl.offcanvas-end {
top: 0; top: 0;
right: 0; right: 0;
@ -6319,8 +6287,6 @@ textarea.form-control-lg {
border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(100%); transform: translateX(100%);
} }
}
@media (max-width: 1199.98px) {
.offcanvas-xl.offcanvas-top { .offcanvas-xl.offcanvas-top {
top: 0; top: 0;
right: 0; right: 0;
@ -6330,8 +6296,6 @@ textarea.form-control-lg {
border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(-100%); transform: translateY(-100%);
} }
}
@media (max-width: 1199.98px) {
.offcanvas-xl.offcanvas-bottom { .offcanvas-xl.offcanvas-bottom {
right: 0; right: 0;
left: 0; left: 0;
@ -6340,13 +6304,9 @@ textarea.form-control-lg {
border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(100%); transform: translateY(100%);
} }
}
@media (max-width: 1199.98px) {
.offcanvas-xl.showing, .offcanvas-xl.show:not(.hiding) { .offcanvas-xl.showing, .offcanvas-xl.show:not(.hiding) {
transform: none; transform: none;
} }
}
@media (max-width: 1199.98px) {
.offcanvas-xl.showing, .offcanvas-xl.hiding, .offcanvas-xl.show { .offcanvas-xl.showing, .offcanvas-xl.hiding, .offcanvas-xl.show {
visibility: visible; visibility: visible;
} }
@ -6398,8 +6358,6 @@ textarea.form-control-lg {
border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(-100%); transform: translateX(-100%);
} }
}
@media (max-width: 1399.98px) {
.offcanvas-xxl.offcanvas-end { .offcanvas-xxl.offcanvas-end {
top: 0; top: 0;
right: 0; right: 0;
@ -6407,8 +6365,6 @@ textarea.form-control-lg {
border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateX(100%); transform: translateX(100%);
} }
}
@media (max-width: 1399.98px) {
.offcanvas-xxl.offcanvas-top { .offcanvas-xxl.offcanvas-top {
top: 0; top: 0;
right: 0; right: 0;
@ -6418,8 +6374,6 @@ textarea.form-control-lg {
border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(-100%); transform: translateY(-100%);
} }
}
@media (max-width: 1399.98px) {
.offcanvas-xxl.offcanvas-bottom { .offcanvas-xxl.offcanvas-bottom {
right: 0; right: 0;
left: 0; left: 0;
@ -6428,13 +6382,9 @@ textarea.form-control-lg {
border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);
transform: translateY(100%); transform: translateY(100%);
} }
}
@media (max-width: 1399.98px) {
.offcanvas-xxl.showing, .offcanvas-xxl.show:not(.hiding) { .offcanvas-xxl.showing, .offcanvas-xxl.show:not(.hiding) {
transform: none; transform: none;
} }
}
@media (max-width: 1399.98px) {
.offcanvas-xxl.showing, .offcanvas-xxl.hiding, .offcanvas-xxl.show { .offcanvas-xxl.showing, .offcanvas-xxl.hiding, .offcanvas-xxl.show {
visibility: visible; visibility: visible;
} }

File diff suppressed because one or more lines are too long

View file

@ -5,7 +5,7 @@
<img src="{{ url_for('static', filename='images/base/navbar-logo.svg') }}" <img src="{{ url_for('static', filename='images/base/navbar-logo.svg') }}"
alt="Logo for lumi2" alt="Logo for lumi2"
class="img-fluid rounded" class="img-fluid rounded"
style="max-width: 400px" style="max-width: 400px; width: 100%"
> >
</div> </div>
<h1 class="text-center display-1">Welcome</h1> <h1 class="text-center display-1">Welcome</h1>

370
package-lock.json generated
View file

@ -10,6 +10,9 @@
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"bootstrap": "^5.2.3" "bootstrap": "^5.2.3"
},
"devDependencies": {
"sass": "^1.69.7"
} }
}, },
"node_modules/@popperjs/core": { "node_modules/@popperjs/core": {
@ -22,6 +25,28 @@
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/bootstrap": { "node_modules/bootstrap": {
"version": "5.2.3", "version": "5.2.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
@ -39,6 +64,202 @@
"peerDependencies": { "peerDependencies": {
"@popperjs/core": "^2.11.6" "@popperjs/core": "^2.11.6"
} }
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/immutable": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz",
"integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==",
"dev": true
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/sass": {
"version": "1.69.7",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz",
"integrity": "sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
} }
}, },
"dependencies": { "dependencies": {
@ -48,11 +269,160 @@
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
"peer": true "peer": true
}, },
"anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
"bootstrap": { "bootstrap": {
"version": "5.2.3", "version": "5.2.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
"integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==", "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
"requires": {} "requires": {}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"requires": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"fsevents": "~2.3.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"optional": true
},
"glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"immutable": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz",
"integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==",
"dev": true
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true
},
"is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true
},
"readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"sass": {
"version": "1.69.7",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz",
"integrity": "sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
}
},
"source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
} }
} }
} }

View file

@ -4,11 +4,18 @@
"description": "A minimalistic frontend for LDAP.", "description": "A minimalistic frontend for LDAP.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "build": "sass scss/bootstrap.scss lumi2/static/css/bootstrap.css"
}, },
"author": "LUMI 2 Development Team", "author": "LUMI 2 Development Team",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"bootstrap": "^5.2.3" "bootstrap": "^5.2.3"
},
"directories": {
"doc": "docs",
"test": "tests"
},
"devDependencies": {
"sass": "^1.69.7"
} }
} }

View file

@ -1,4 +1,5 @@
Flask==2.2.2 Flask==2.2.2
Werkzeug==2.2.2
ldap3==2.9.1 ldap3==2.9.1
pytest==7.2.0 pytest==7.2.0
coverage==6.5.0 coverage==6.5.0
@ -9,3 +10,4 @@ Flask-WTF==1.0.1
Flask-RESTful==0.3.9 Flask-RESTful==0.3.9
Faker==15.3.3 Faker==15.3.3
requests==2.28.1 requests==2.28.1
waitress==2.1.2

20
shell.nix Normal file
View file

@ -0,0 +1,20 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
nativeBuildInputs = with pkgs; [
python311Packages.flask
python311Packages.ldap3
python311Packages.flask-wtf
python311Packages.wtforms
python311Packages.flask-restful
python311Packages.pytest
python311Packages.coverage
python311Packages.pillow
python311Packages.requests
python311Packages.faker
python311Packages.waitress
];
#shellHook = ''
# export MPLBACKEND=QtAgg
#'';
}

View file

@ -7,14 +7,13 @@ import requests
from PIL import Image from PIL import Image
from faker import Faker from faker import Faker
from lumi2.usermodel import User
import lumi2.ldap as ldap import lumi2.ldap as ldap
def get_random_avatar() -> Image.Image: def get_random_avatar() -> Image.Image:
"""Returns a PIL JPEG Image of an AI-generated cat.""" """Returns a PIL JPEG Image of an AI-generated cat."""
url = "https://thiscatdoesnotexist.com/" url = "https://thispersondoesnotexist.com/"
response = requests.get(url) response = requests.get(url)
if response.status_code != 200: if response.status_code != 200:
raise RuntimeError( raise RuntimeError(
@ -24,8 +23,9 @@ def get_random_avatar() -> Image.Image:
return Image.open(BytesIO(response.content)) return Image.open(BytesIO(response.content))
def generate_random_user() -> User: def generate_random_user():
"""Generates a randomized user object and returns it.""" """Generates a randomized user object and returns it."""
from lumi2.usermodel import User
faker = Faker() faker = Faker()