Compare commits

...

11 Commits

Author SHA1 Message Date
Wiktor 5a76b0052e HSWRO retrofitting + OIDC 2024-08-27 22:55:16 +02:00
Dariusz Niemczyk 9983511136
fix: ignore new devcontainer files 2024-02-04 16:13:34 +01:00
Dariusz Niemczyk dad68031df
fix: readme typo 2024-02-04 16:00:22 +01:00
Dariusz Niemczyk 1dc6d8b76d
fix: correctly lock all dependencies 2024-02-01 12:49:37 +01:00
Dariusz Niemczyk 8812e6c0d3
fix: run app as spejstore user, not root 2024-02-01 12:49:36 +01:00
Dariusz Niemczyk b94ab204d8
dx: Un-ignore .vscode 2024-02-01 12:49:36 +01:00
Dariusz Niemczyk 47b682c509
feat: Add awesome devcontainer intro and better readme 2024-02-01 12:49:36 +01:00
Dariusz Niemczyk 70fc374d0d
feat: add proper devcontainer support 2024-02-01 12:49:36 +01:00
Dariusz Niemczyk 77ddd6bb45
fix: ignore .DS_Store
MacOS creates .DS_Store files that are usually ignored by mac users.
Unfortunately, this is not a default for devcontainers.
2024-02-01 12:49:35 +01:00
radex 8ddc4da3b6 Merge pull request 'fix: properly create svgs static paths' (#2) from fix/static-svgs into master
Reviewed-on: https://code.hackerspace.pl/hswaw/spejstore/pulls/2
2024-01-31 13:24:05 +00:00
Dariusz Niemczyk 23c008914b
fix: properly create svgs static paths 2024-01-31 14:22:17 +01:00
23 changed files with 181 additions and 81 deletions

2
.devcontainer/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
\.*
!.gitignore

View File

@ -1,41 +1,50 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the // For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose // README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
{ {
"name": "Existing Docker Compose (Extend)", "name": "Extend base docker-compose for development purposes",
// Update the 'dockerComposeFile' list if you have more compose files or use different names. // Update the 'dockerComposeFile' list if you have more compose files or use different names.
// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make. // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
"dockerComposeFile": ["../docker-compose.yml", "docker-compose.yml"], "dockerComposeFile": [
"../docker-compose.yml",
"docker-compose.yml"
],
// The 'service' property is the name of the service for the container that VS Code should // The 'service' property is the name of the service for the container that VS Code should
// use. Update this value and .devcontainer/docker-compose.yml to the real service name. // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "web", "service": "web",
// The optional 'workspaceFolder' property is the path VS Code should open by default when // The optional 'workspaceFolder' property is the path VS Code should open by default when
// connected. This is typically a file mount in .devcontainer/docker-compose.yml // connected. This is typically a file mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"features": { "features": {
"ghcr.io/wxw-matt/devcontainer-features/script_runner:0": {} "ghcr.io/devcontainers/features/git:1": {},
} "ghcr.io/devcontainers/features/sshd:1": {}
},
// Features to add to the dev container. More info: https://containers.dev/features. // Features to add to the dev container. More info: https://containers.dev/features.
// "features": {}, // "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally. // Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [], // "forwardPorts": [],
// Uncomment the next line if you want start specific services in your Docker Compose config. // Uncomment the next line if you want start specific services in your Docker Compose config.
// "runServices": [], // "runServices": [],
// Uncomment the next line if you want to keep your containers running after VS Code shuts down. // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
// "shutdownAction": "none", // "shutdownAction": "none",
// Uncomment the next line to run commands after the container is created. // Uncomment the next line to run commands after the container is created.
// "postCreateCommand": "cat /etc/os-release", "postStartCommand": "${containerWorkspaceFolder}/manage.py migrate",
"postCreateCommand": "${containerWorkspaceFolder}/manage.py collectstatic --no-input --clear",
// Configure tool-specific properties. "customizations": {
// "customizations": {}, "vscode": {
"settings": {
// Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root. "extensions.verifySignature": false
// "remoteUser": "devcontainer" },
"extensions": [
"ms-python.python",
"mikestead.dotenv",
"VisualStudioExptTeam.vscodeintellicode",
"ms-python.black-formatter",
"VisualStudioExptTeam.intellicode-api-usage-examples",
"ms-azuretools.vscode-docker",
"DavidAnson.vscode-markdownlint",
"yzhang.markdown-all-in-one"
]
}
},
"containerUser": "spejstore"
} }

View File

@ -1,25 +1,9 @@
version: "3" version: "3.4"
services: services:
# Update this to the name of the service you want to work with in your docker-compose.yml file
web: web:
# Uncomment if you want to override the service's Dockerfile to one in the .devcontainer
# folder. Note that the path of the Dockerfile and context is relative to the *primary*
# docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
# array). The sample below assumes your primary file is in the root of your project.
#
# build:
# context: .
# dockerfile: .devcontainer/Dockerfile
volumes: volumes:
# Update this to wherever you want VS Code to mount the folder of your project
- ..:/workspaces:cached - ..:/workspaces:cached
restart: unless-stopped
# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
# cap_add:
# - SYS_PTRACE
# security_opt:
# - seccomp:unconfined
# Overrides default command so things don't shut down after the process ends. # Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done" command: /bin/sh -c "while sleep 1000; do :; done"
@ -36,4 +20,5 @@ services:
# - SPEJSTORE_MEDIA_ROOT= # - SPEJSTORE_MEDIA_ROOT=
# - SPEJSTORE_REQUIRE_AUTH=true # - SPEJSTORE_REQUIRE_AUTH=true
- SPEJSTORE_OAUTH_REDIRECT_IS_HTTPS=false - SPEJSTORE_OAUTH_REDIRECT_IS_HTTPS=false
- SPEJSTORE_SPEJSTORE_FILE_STORAGE_TYPE="filesystem"
# - SPEJSTORE_PROXY_TRUSTED_IPS=172.21.37.1 # - SPEJSTORE_PROXY_TRUSTED_IPS=172.21.37.1

View File

@ -20,3 +20,4 @@ log
.Dockerfile .Dockerfile
.env .env
.devcontainer .devcontainer
readme

9
.gitignore vendored
View File

@ -12,6 +12,13 @@ postgres-hstore/
docker-compose.override.yml docker-compose.override.yml
build_static build_static
.venv .venv
.vscode
__pycache__ __pycache__
# Is not ignored by default in devcontainers, macs bad
.DS_Store
# Ignore vscode devcontainer files
.vscode-server
.ssh
.gitconfig

5
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"recommendations": [
"ms-vscode-remote.remote-containers"
]
}

20
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Django",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": [
"runserver",
"0.0.0.0:8000",
],
"django": true,
"justMyCode": true
}
]
}

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
}

27
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,27 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "migrate",
"type": "shell",
"command": "${workspaceFolder}/manage.py migrate"
},
{
"label": "makemigrations",
"type": "shell",
"command": "${workspaceFolder}/manage.py makemigrations"
},
{
"label": "runserver",
"type": "shell",
"command": "${workspaceFolder}/manage.py runserver"
},
{
"label": "collectstatic",
"type": "shell",
"command": "${workspaceFolder}/manage.py collectstatic"
}
]
}

View File

@ -12,6 +12,7 @@ ADD requirements.txt /code/
RUN pip install --no-cache-dir -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt
ADD . /code/ ADD . /code/
RUN python -m pip install gunicorn RUN groupadd --gid 1000 spejstore && useradd --uid 1000 --gid 1000 --home /code --shell /bin/bash spejstore
USER spejstore
CMD bash -c "python manage.py collectstatic --no-input --clear && python manage.py migrate && gunicorn --workers 1 --threads 4 -b 0.0.0.0:8000 --capture-output --error-logfile - --access-logfile - spejstore.wsgi:application" CMD bash -c "python manage.py collectstatic --no-input --clear && python manage.py migrate && gunicorn --workers 1 --threads 4 -b 0.0.0.0:8000 --capture-output --error-logfile - --access-logfile - spejstore.wsgi:application"

View File

@ -1,33 +1,47 @@
# spejstore # spejstore (AKA inventory)
The general HSWAW (and other polish hackerspaces) inventory system.
Because there is not enough general inventory software invented here yet. Because there is not enough general inventory software invented here yet.
Please use Python3, for the love of `$deity`...
## Usage ## Usage
### Quick start ### Quick start (VSCode)
1. Run: 1. Copy `.env.example` as `.env`
```sh 2. Have `docker compose` 2.0. You can identify it by having `docker compose` command instead of `docker-compose`.
ln -s docker-compose.dev-override.yml docker-compose.override.yml 3. Customize your `.env` for your specific usecase.
docker-compose up --build
```
2. Run `docker-compose run --rm web python manage.py createsuperuser` -- now you can dev authenticate w/o SSO
### Build & run #### VSCode
```sh 0. Setup environment variables
docker-compose up --build 1. Get VSCode from [here](https://code.visualstudio.com/download), *CAN NOT* be VSCodium, as the extension is a microsoft binary which does not work with VSCodium.
2. Install [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension
3. Clone the repository and open it with VSCode.
4. You should get a toast like this when re-opening directory with the cloned repository. ![Toast example](readme/toast-example.png 'Toast example')
1. If you don't get a toast, then use (CMD|Ctrl)+Shift+P to open actions menu and choose option **Rebuild Without Cache and Reopen in Container**. ![Command example](readme/command-example.png 'Command example')
5. Reopen the directory in container either via command or popup button.
6. Wait for the application and container to properly build.
1. Devcontainer's VSCode instance will be automatically configured with extensions to help your development process.
2. You might get a Toast telling you to re-open the directory due to Black not working properly. Do so for proper autoformatting support.
3. Make sure that extensions were installed in your vscode devcontainer. It might take a couple of minutes.
7. `manage.py migrate` will be run automatically after container creation, to make sure you have the latest migrations done on the development database without any need for interaction.
8. Run debug session with either command of "Start Debugging" (default hotkey F5), or with the Debug sidebar. ![Debug sidebar instructions](readme/debug-example.png 'Debug sidebar')
9. You should have automatically forwarded ports, so the only thing remaining is opening browser window with the url provided in terminal.
# if you need to reset built static files and/or postgres database: #### Everything else (docker)
docker-compose up --build --renew-anon-volumes
```
### Troubleshooting 1. Run `docker compose up`. This will create a production-ready setup with gunicorn. out of the box.
- https://askubuntu.com/q/615394/413683 ### Everything else (python)
## New docs (WIP): 1. Get python3
2. `pip install -r requirements.txt`
3. `python3 manage.py migrate`
4. `python3 manage.py collectstatic`
5. `python3 manage.py runserver 0.0.0.0:8000`
## New docs (WIP)
Spejstore is a simple inventory system made for Warsaw Hackerspace purposes. Includes some features very specific to hswaw requirements, which are: Spejstore is a simple inventory system made for Warsaw Hackerspace purposes. Includes some features very specific to hswaw requirements, which are:

View File

@ -5,10 +5,10 @@ from social_core.backends.oauth import BaseOAuth2
class HSWawOAuth2(BaseOAuth2): class HSWawOAuth2(BaseOAuth2):
"""Hackerspace OAuth authentication backend""" """Hackerspace OAuth authentication backend"""
name = "hswaw" name = "hswro"
ID_KEY = "username" ID_KEY = "username"
AUTHORIZATION_URL = "https://sso.hackerspace.pl/oauth/authorize" AUTHORIZATION_URL = "http://sso.lokal.hswro.org/oauth/authorize"
ACCESS_TOKEN_URL = "https://sso.hackerspace.pl/oauth/token" ACCESS_TOKEN_URL = "http://sso.lokal.hswro.org/oauth/token"
DEFAULT_SCOPE = ["profile:read"] DEFAULT_SCOPE = ["profile:read"]
REDIRECT_STATE = False REDIRECT_STATE = False
SCOPE_SEPARATOR = "," SCOPE_SEPARATOR = ","
@ -28,7 +28,7 @@ class HSWawOAuth2(BaseOAuth2):
def user_data(self, access_token, *args, **kwargs): def user_data(self, access_token, *args, **kwargs):
"""Loads user data from service""" """Loads user data from service"""
url = "https://sso.hackerspace.pl/api/1/profile" url = "http://sso.lokal.hswro.org/api/1/profile"
headers = {"Authorization": "Bearer {}".format(access_token)} headers = {"Authorization": "Bearer {}".format(access_token)}
return self.get_json(url, headers=headers) return self.get_json(url, headers=headers)

View File

@ -5,7 +5,7 @@ from django.contrib.auth.models import Group
def staff_me_up(backend, details, response, uid, user, *args, **kwargs): def staff_me_up(backend, details, response, uid, user, *args, **kwargs):
user.is_staff = True user.is_staff = True
try: try:
user.groups.set([Group.objects.get(name="member")]) user.groups.set([Group.objects.get(name="hsmember")])
except Group.DoesNotExist: except Group.DoesNotExist:
pass pass
user.save() user.save()

View File

@ -2,4 +2,4 @@ from django.shortcuts import redirect
def auth_redirect(request): def auth_redirect(request):
return redirect("social:begin", "hswaw") return redirect("social:begin", "hswro")

View File

@ -2,11 +2,11 @@ version: "3"
services: services:
db: db:
image: postgres:15.4 image: postgres:15.4
restart: always restart: unless-stopped
environment: volumes:
- POSTGRES_USER=postgres - /var/spejstore-pg:/var/lib/postgresql/data
- POSTGRES_PASSWORD=postgres env_file:
- POSTGRES_DB=postgres - .env.pg
healthcheck: healthcheck:
#CHANGE 1: this command checks if the database is ready, right on the source db server #CHANGE 1: this command checks if the database is ready, right on the source db server
test: ["CMD-SHELL", "pg_isready -d postgres -U postgres"] test: ["CMD-SHELL", "pg_isready -d postgres -U postgres"]
@ -16,13 +16,16 @@ services:
web: web:
build: . build: .
restart: always user: root
restart: unless-stopped
command: bash -c "python manage.py collectstatic --no-input --clear && python manage.py migrate && gunicorn --workers 1 --threads 4 -b 0.0.0.0:8000 --capture-output --error-logfile - --access-logfile - spejstore.wsgi:application" command: bash -c "python manage.py collectstatic --no-input --clear && python manage.py migrate && gunicorn --workers 1 --threads 4 -b 0.0.0.0:8000 --capture-output --error-logfile - --access-logfile - spejstore.wsgi:application"
volumes: volumes:
- .:/code - .:/code
- /code/build_static - ./build_static:/code/build_static
ports: ports:
- "8000:8000" - "8021:8000"
env_file:
- .env
depends_on: depends_on:
db: db:
condition: service_healthy condition: service_healthy

BIN
readme/command-example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
readme/debug-example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

BIN
readme/toast-example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -1,4 +1,6 @@
asgiref==3.7.2 asgiref==3.7.2
boto3==1.34.32
botocore==1.34.32
certifi==2023.5.7 certifi==2023.5.7
cffi==1.15.1 cffi==1.15.1
chardet==5.1.0 chardet==5.1.0
@ -12,12 +14,13 @@ django-appconf==1.0.5
django-hstore==1.4.2 django-hstore==1.4.2
django-markdown2==0.3.1 django-markdown2==0.3.1
django-select2==8.1.2 django-select2==8.1.2
django-storages[s3]==1.14.2 django-storages==1.14.2
# Django-tree django-tree @ https://github.com/Palid/django-tree/archive/439e9a867e789b58f0c37e34e8ceb85ce1b806dc.zip#sha256=044e6766f4993512404492d7ec76949ca6b9ed44c88619ecc3a4e5339aa27b71
https://github.com/Palid/django-tree/archive/master.zip
djangorestframework==3.14.0 djangorestframework==3.14.0
docopt==0.6.2 docopt==0.6.2
gunicorn==21.2.0
idna==3.4 idna==3.4
jmespath==1.0.1
markdown2==2.4.9 markdown2==2.4.9
oauthlib==3.2.2 oauthlib==3.2.2
packaging==23.1 packaging==23.1
@ -25,10 +28,14 @@ Pillow==10.0.0
psycopg2==2.9.6 psycopg2==2.9.6
pycparser==2.21 pycparser==2.21
PyJWT==2.7.0 PyJWT==2.7.0
python-dateutil==2.8.2
python-jose==3.3.0
python3-openid==3.2.0 python3-openid==3.2.0
pytz==2023.3 pytz==2023.3
requests==2.31.0 requests==2.31.0
requests-oauthlib==1.3.1 requests-oauthlib==1.3.1
s3transfer==0.10.0
six==1.16.0
social-auth-app-django==5.2.0 social-auth-app-django==5.2.0
social-auth-core==4.4.2 social-auth-core==4.4.2
sqlparse==0.4.4 sqlparse==0.4.4

View File

@ -17,7 +17,7 @@ PROD = os.getenv("SPEJSTORE_ENV") == "prod"
SECRET_KEY = env("SECRET_KEY", "#hjthi7_udsyt*9eeyb&nwgw5x=%pk_lnz3+u2tg9@=w3p1m*k") SECRET_KEY = env("SECRET_KEY", "#hjthi7_udsyt*9eeyb&nwgw5x=%pk_lnz3+u2tg9@=w3p1m*k")
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = not PROD DEBUG = True
ALLOWED_HOSTS = env( ALLOWED_HOSTS = env(
"ALLOWED_HOSTS", "ALLOWED_HOSTS",
@ -137,10 +137,16 @@ AUTH_PASSWORD_VALIDATORS = [
}, },
] ]
SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = 'http://sso.lokal.hswro.org/' # endpoint without /.well-known/openid-configuration
SOCIAL_AUTH_OIDC_KEY = env("CLIENT_ID")
SOCIAL_AUTH_OIDC_SECRET = env("SECRET")
AUTHENTICATION_BACKENDS = ( AUTHENTICATION_BACKENDS = (
"auth.backend.HSWawOAuth2",
"django.contrib.auth.backends.ModelBackend", # env('LOGIN_BACKEND', 'auth.backend.HSWawOAuth2'),
'auth.backend.HSWawOAuth2',
# 'social_core.backends.open_id_connect.OpenIdConnectAuth',
'django.contrib.auth.backends.ModelBackend',
) )
SOCIAL_AUTH_PIPELINE = ( SOCIAL_AUTH_PIPELINE = (
@ -259,9 +265,10 @@ REST_FRAMEWORK = {
], ],
} }
SOCIAL_AUTH_HSWAW_KEY = env("CLIENT_ID") SOCIAL_AUTH_HSWRO_KEY = env("CLIENT_ID")
SOCIAL_AUTH_HSWAW_SECRET = env("SECRET") SOCIAL_AUTH_HSWRO_SECRET = env("SECRET")
SOCIAL_AUTH_REDIRECT_IS_HTTPS = env("OAUTH_REDIRECT_IS_HTTPS", "true") == "true" #SOCIAL_AUTH_REDIRECT_IS_HTTPS = env("OAUTH_REDIRECT_IS_HTTPS", "true") == "true"
SOCIAL_AUTH_REDIRECT_IS_HTTPS = False
SOCIAL_AUTH_JSONFIELD_ENABLED = True SOCIAL_AUTH_JSONFIELD_ENABLED = True

File diff suppressed because one or more lines are too long

View File

@ -50,6 +50,9 @@
</ul> </ul>
</div> </div>
<a href="{% url 'admin:storage_item_change' item.pk %}" class="btn btn-default">Edit</a> <a href="{% url 'admin:storage_item_change' item.pk %}" class="btn btn-default">Edit</a>
{% if item.props.wiki %}
<a href="https://wiki.hswro.org/{{ item.props.wiki }}" class="btn btn-info">Wiki</a>
{% endif %}
</div> </div>
<table class="table table-hover table-striped"> <table class="table table-hover table-striped">

View File

@ -1,4 +1,5 @@
{% load static %}
{% if category and category.icon_id %} {% if category and category.icon_id %}
<div class="containericon" title="{{ category.name }}"><img src="/static/icons/{{ category.icon_id }}.svg" /> <div class="containericon" title="{{ category.name }}"><img src="{% static 'icons/' %}{{ category.icon_id }}.svg" />
</div> </div>
{% endif %} {% endif %}