Skip to content

Commit 6bcd746

Browse files
authored
Merge branch 'main' into main
2 parents e2a1ed4 + e2cfdb7 commit 6bcd746

40 files changed

+477
-12
lines changed

.github/workflows/deploy_docs.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
branches:
66
- main
77
paths:
8-
- '/docs/**'
8+
- 'docs/**'
99
- 'mkdocs.yml'
1010
workflow_dispatch:
1111

.github/workflows/django_check.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
on:
2+
push:
3+
branches:
4+
- main
5+
pull_request:
6+
7+
jobs:
8+
ruff:
9+
runs-on: ubuntu-latest
10+
name: Check Django
11+
steps:
12+
- name: "Checkout Repo"
13+
uses: actions/checkout@v4
14+
- name: Check Django
15+
uses: dagger/dagger-for-github@v5
16+
with:
17+
verb: call
18+
args: "linters check-django"
19+
version: "0.12.6"

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ local_settings.py
6161
db.sqlite3
6262
db.sqlite3-journal
6363
*.dump
64-
staticfiles
64+
src/staticfiles
65+
src/media
6566

6667
# Flask stuff:
6768
instance/

README.md

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Spokane Tech
22

3-
Home of [SpokaneTech.org](https://SpokaneTech.org), an online hub for Spokane's tech events and groups. It's not just a website; it's a community-driven, open-source initiative aimed at fostering learning and collaboration among aspiring and seasoned tech enthusiasts.
3+
Home of [SpokaneTech.org](https://SpokaneTech.org), an online hub for Spokane's
4+
tech events and groups. It's not just a website; it's a community-driven,
5+
open-source initiative aimed at fostering learning and collaboration among
6+
aspiring and seasoned tech enthusiasts.
7+
8+
Interested in participating? Great! Read on...
9+
10+
Here are a few things you can do to get started.
11+
12+
- Go to the site and explore. It's live at [https://spokanetech.org](https://spokanetech.org).
13+
- Look through the [open issues](https://github.com/SpokaneTech/SpokaneTech_Py/issues) and find one that interests you (issues tagged "good first issue" could be great candidates).
14+
- [Read the docs](https://docs.spokanetech.org/)! In our documentation directory we have design decisions, style guide, contributing guide and more. Feel free to familiarize yourself with these.
15+
- Clone the repo to you machine and run locally, explore the code, break things, fix things, have fun. Step-by-step instructions are in the [CONTRIBUTION doc](https://docs.spokanetech.org/CONTRIBUTING/).
16+
- Have a feature idea or found a bug? Create an issue [here](https://github.com/SpokaneTech/SpokaneTech_Py/issues/new/choose)
417

5-
Please visit our [docs](https://spokanetech.github.io/SpokaneTech_Py/) to learn how to get started working on SpokaneTech_Py!

dagger/src/linters.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from asyncio import CancelledError, TaskGroup
33

44
import dagger
5-
from dagger import object_type, function
5+
from dagger import function, object_type
66

77

88
@object_type
@@ -19,6 +19,13 @@ async def run_linter(self, cmd: list[str]) -> str:
1919
# The ExecError exposes the
2020
raise LinterError(exec_error=e)
2121

22+
@function
23+
async def check_django(self) -> str:
24+
"""
25+
Run Django system checks.
26+
"""
27+
return await self.run_linter(["src/manage.py", "check"])
28+
2229
@function
2330
async def check(self) -> str:
2431
"""
@@ -68,6 +75,7 @@ async def all(self) -> str:
6875
# Run all the linters
6976
async with TaskGroup() as tg:
7077
tasks = [
78+
tg.create_task(self.check_django()),
7179
tg.create_task(self.check()),
7280
tg.create_task(self.format()),
7381
tg.create_task(self.bandit()),

docker-compose.yml

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
services:
2+
app:
3+
image: spokanetech:latest
4+
build:
5+
context: .
6+
container_name: app
7+
ports:
8+
- "8000:8000"
9+
env_file:
10+
- .env
11+
212
worker:
313
image: spokanetech:latest
414
build:

docs/CONTRIBUTING.md

+19
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ source venv/bin/activate
4848
pip install -r requirements.dev.lock
4949
```
5050

51+
> Note: to add a new dependency see [Adding Dependencies](#adding-dependencies).
52+
5153
`python-dotenv` will automatically load values in the `.env` file when Django's `manage.py` is used. Create a `.env` file from the template (**note: `.env` should never be checked in to source control!**):
5254

5355
```shell
@@ -132,6 +134,23 @@ Quit the server with CONTROL-C.
132134

133135
</details>
134136

137+
### Adding Dependencies
138+
139+
The lock files are generated using [`uv`](https://github.com/astral-sh/uv);
140+
which is included in the development requirements. To add a file use:
141+
142+
```shell
143+
uv add [--dev] SOME-DEP
144+
uv pip compile pyproject.toml --extra dev -o requirements.dev.lock --prerelease=allow
145+
uv pip compile pyproject.toml -o requirements.lock --prerelease=allow
146+
```
147+
148+
Then make sure to sync the virtual environment with the new lock files.
149+
150+
```shell
151+
uv pip sync requirements.dev.lock
152+
```
153+
135154
### Dagger
136155

137156
[Dagger](https://dagger.io/) is used for continuous integration and

pyproject.toml

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies = [
1313
"crispy-bootstrap5>=2024.2",
1414
"discord.py>=2.3.2",
1515
"Django>=5.0.1",
16+
"django-allauth[socialaccount]>=64.2.0",
1617
"django-azure-communication-email>=1.1.0",
1718
"django-celery-beat>=2.6.0",
1819
"django-celery-results>=2.5.1",
@@ -30,6 +31,7 @@ dependencies = [
3031
"python-dotenv>=1.0.1",
3132
"sentry-sdk[celery,django]>=2.1.1",
3233
"sqlparse>=0.4.4",
34+
"pillow>=10.4.0",
3335
]
3436

3537
[project.optional-dependencies]

requirements.dev.lock

+11-2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ django==5.0.8
101101
# spokanetech (pyproject.toml)
102102
# crispy-bootstrap5
103103
# dj-database-url
104+
# django-allauth
104105
# django-azure-communication-email
105106
# django-celery-beat
106107
# django-celery-results
@@ -114,6 +115,8 @@ django==5.0.8
114115
# djangorestframework
115116
# model-bakery
116117
# sentry-sdk
118+
django-allauth==64.2.0
119+
# via spokanetech (pyproject.toml)
117120
django-azure-communication-email==1.1.0
118121
# via spokanetech (pyproject.toml)
119122
django-celery-beat==2.6.0
@@ -239,6 +242,7 @@ pbr==6.1.0
239242
# via stevedore
240243
pillow==10.4.0
241244
# via
245+
# spokanetech (pyproject.toml)
242246
# cairosvg
243247
# mkdocs-material
244248
platformdirs==4.2.2
@@ -262,7 +266,9 @@ pygments==2.18.0
262266
# mkdocs-material
263267
# rich
264268
pyjwt==2.9.0
265-
# via msal
269+
# via
270+
# django-allauth
271+
# msal
266272
pymdown-extensions==10.9
267273
# via mkdocs-material
268274
pytest==8.3.2
@@ -301,14 +307,17 @@ regex==2024.7.24
301307
requests==2.32.3
302308
# via
303309
# azure-core
310+
# django-allauth
304311
# eventbrite
305312
# mkdocs-material
306313
# msal
307314
# msrest
308315
# requests-oauthlib
309316
# responses
310317
requests-oauthlib==2.0.0
311-
# via msrest
318+
# via
319+
# django-allauth
320+
# msrest
312321
responses==0.25.3
313322
# via spokanetech (pyproject.toml)
314323
rich==13.8.0

requirements.lock

+12-2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ django==5.0.8
8484
# spokanetech (pyproject.toml)
8585
# crispy-bootstrap5
8686
# dj-database-url
87+
# django-allauth
8788
# django-azure-communication-email
8889
# django-celery-beat
8990
# django-celery-results
@@ -95,6 +96,8 @@ django==5.0.8
9596
# django-timezone-field
9697
# djangorestframework
9798
# sentry-sdk
99+
django-allauth==64.2.0
100+
# via spokanetech (pyproject.toml)
98101
django-azure-communication-email==1.1.0
99102
# via spokanetech (pyproject.toml)
100103
django-celery-beat==2.6.0
@@ -173,6 +176,8 @@ oauthlib==3.2.2
173176
# via requests-oauthlib
174177
packaging==24.1
175178
# via gunicorn
179+
pillow==10.4.0
180+
# via spokanetech (pyproject.toml)
176181
portalocker==2.10.1
177182
# via msal-extensions
178183
prometheus-client==0.20.0
@@ -186,7 +191,9 @@ psycopg-binary==3.2.1
186191
pycparser==2.22
187192
# via cffi
188193
pyjwt==2.9.0
189-
# via msal
194+
# via
195+
# django-allauth
196+
# msal
190197
python-crontab==3.2.0
191198
# via django-celery-beat
192199
python-dateutil==2.9.0.post0
@@ -203,12 +210,15 @@ redis==5.1.0b7
203210
requests==2.32.3
204211
# via
205212
# azure-core
213+
# django-allauth
206214
# eventbrite
207215
# msal
208216
# msrest
209217
# requests-oauthlib
210218
requests-oauthlib==2.0.0
211-
# via msrest
219+
# via
220+
# django-allauth
221+
# msrest
212222
sentry-sdk==2.13.0
213223
# via spokanetech (pyproject.toml)
214224
setuptools==72.2.0

src/spokanetech/settings.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import environ
1717
import dj_database_url
1818
import sentry_sdk
19+
from django.urls import reverse_lazy
1920

2021

2122
# Build paths inside the project like this: BASE_DIR / 'subdir'.
@@ -100,6 +101,10 @@
100101
"markdownify.apps.MarkdownifyConfig",
101102
"handyhelpers",
102103
"web",
104+
# django-allauth
105+
"allauth",
106+
"allauth.account",
107+
"allauth.socialaccount",
103108
]
104109

105110
if DEBUG:
@@ -113,7 +118,7 @@
113118
"django.contrib.auth.middleware.AuthenticationMiddleware",
114119
"django.contrib.messages.middleware.MessageMiddleware",
115120
"django.middleware.clickjacking.XFrameOptionsMiddleware",
116-
"web.middleware.TimezoneMiddleware",
121+
"allauth.account.middleware.AccountMiddleware",
117122
]
118123

119124
if DEBUG:
@@ -170,6 +175,13 @@
170175
},
171176
]
172177

178+
AUTHENTICATION_BACKENDS = [
179+
"django.contrib.auth.backends.ModelBackend",
180+
"allauth.account.auth_backends.AuthenticationBackend",
181+
]
182+
183+
LOGIN_REDIRECT_URL = reverse_lazy("web:index")
184+
173185

174186
# Internationalization
175187
# https://docs.djangoproject.com/en/5.0/topics/i18n/
@@ -312,3 +324,5 @@
312324
if USE_AZURE:
313325
EMAIL_BACKEND = "django_azure_communication_email.EmailBackend"
314326
AZURE_COMMUNICATION_CONNECTION_STRING = env.str("AZURE_COMMUNICATION_CONNECTION_STRING")
327+
elif DEBUG:
328+
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"

src/spokanetech/urls.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@
1616
"""
1717

1818
from django.conf import settings
19+
from django.conf.urls.static import static
1920
from django.contrib import admin
2021
from django.urls import include, path
2122

2223
urlpatterns = [
2324
path("admin/", admin.site.urls),
2425
path("handyhelpers/", include("handyhelpers.urls")),
26+
path("accounts/", include("allauth.urls")),
2527
path("", include("web.urls")),
26-
]
28+
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
2729

2830

2931
if settings.DEBUG:

src/templates/429.html

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{% extends "allauth/layouts/base.html" %}
2+
{% load allauth %}
3+
{% block head_title %}
4+
Too Many Requests
5+
{% endblock head_title %}
6+
{% block content %}
7+
{% element h1 %}
8+
Too Many Requests
9+
{% endelement %}
10+
<p>You are sending too many requests. Please wait before trying again.</p>
11+
{% endblock content %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{% load allauth %}
2+
<div class="alert alert-xs {% if attrs.level == "error" %}alert-warning{% else %}alert-info{% endif %}">
3+
{% slot message %}
4+
{% endslot %}
5+
</div>
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{% load allauth %}
2+
{% setvar variant %}
3+
{% if "warning" in attrs.tags %}
4+
warning
5+
{% elif "danger" in attrs.tags %}
6+
danger
7+
{% elif "secondary" in attrs.tags %}
8+
secondary
9+
{% elif "success" in attrs.tags %}
10+
success
11+
{% else %}
12+
primary
13+
{% endif %}
14+
{% endsetvar %}
15+
<span {% if attrs.title %}title="{{ attrs.title }}"{% endif %}
16+
class="badge text-bg-{{ variant }}">
17+
{% slot %}
18+
{% endslot %}
19+
</span>
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{% load allauth %}
2+
{% comment %} djlint:off {% endcomment %}
3+
<{% if attrs.href %}a href="{{ attrs.href }}"{% else %}button{% endif %}
4+
{% if attrs.form %}form="{{ attrs.form }}"{% endif %}
5+
{% if attrs.id %}id="{{ attrs.id }}"{% endif %}
6+
{% if attrs.name %}name="{{ attrs.name }}"{% endif %}
7+
{% if attrs.type %}type="{{ attrs.type }}"{% endif %}
8+
{% if attrs.value %}value="{{ attrs.value }}"{% endif %}
9+
class="{% block class %}
10+
btn
11+
{% if "link" in attrs.tags %}btn-link
12+
{% else %}
13+
{% if "prominent" in attrs.tags %}btn-lg{% elif "minor" in attrs.tags %}btn-sm{% endif %}
14+
btn-{% if 'outline' in attrs.tags %}outline-{% endif %}{% if "danger" in attrs.tags %}danger{% elif "secondary" in attrs.tags %}secondary{% elif "warning" in attrs.tags %}warning{% else %}primary{% endif %}
15+
{% endif %}{% endblock %}">
16+
{% if "tool" in attrs.tags %}
17+
{% if "delete" in attrs.tags %}
18+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
19+
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5Zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6Z"/>
20+
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1ZM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118ZM2.5 3h11V2h-11v1Z"/>
21+
</svg>
22+
{% elif "edit" in attrs.tags %}
23+
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16"><path fill="currentColor" d="M12.854.146a.5.5 0 0 0-.707 0L10.5 1.793L14.207 5.5l1.647-1.646a.5.5 0 0 0 0-.708zm.646 6.061L9.793 2.5L3.293 9H3.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.207zm-7.468 7.468A.5.5 0 0 1 6 13.5V13h-.5a.5.5 0 0 1-.5-.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.5-.5V10h-.5a.5.5 0 0 1-.175-.032l-.179.178a.5.5 0 0 0-.11.168l-2 5a.5.5 0 0 0 .65.65l5-2a.5.5 0 0 0 .168-.11z"/></svg>
24+
{% endif %}
25+
{% endif %}
26+
27+
{% if not "tool" in attrs.tags %}
28+
{% slot %}
29+
{% endslot %}
30+
{% endif %}
31+
</{% if attrs.href %}a{% else %}button{% endif %}>

0 commit comments

Comments
 (0)