Compare commits

..

16 Commits

Author SHA1 Message Date
Matthew Wild
488dc9a3f3 Merge pull request #202 from snikket-im/ka/oauthtweaks
OAuth tweaks
2025-06-05 17:55:56 +01:00
Kim Alvefur
1a65ba6150 Include a software id in oauth client registration
This is supposed to be a unique and persistent identifier for the
software itself, regardless of version or deployment instance.

Generated from the domain name in the comment using uuid_generate_sha1()
2025-06-05 17:52:04 +01:00
Kim Alvefur
9474238dee Declare as a web application in oauth client registration
It is, even if the password grant isn't restricted to that, but if ever
the authorization code flow is implemented, it'll be correct.
2025-06-05 17:52:01 +01:00
Kim Alvefur
60e663316b Declare that oauth client credentials are using POST method
Not enforced by mod_http_oauth2, but could be in the future
2025-06-05 17:50:52 +01:00
Kim Alvefur
770d05c72c Declare use of no response types, since password grant uses none
Needless restriction removed in
https://hg.prosody.im/prosody-modules/rev/ef81c67e1ae7
2025-06-05 17:50:52 +01:00
Kim Alvefur
ea75d8e832 Include requested scopes in oauth client registration
This can be used on the oauth server side to enforce that no additional
scopes are added.
2025-06-05 17:50:52 +01:00
Kim Alvefur
145dda8c19 Include web portal version in oauth client registration
This could be shown in client listings and audit logs, and checked to
ensure old versions stop being used. Not the most relevant for the web
portal as it is closely tied together with the server, but could help
answer questions about where old grants come from.
2025-06-05 17:50:52 +01:00
Matthew Wild
149a79cb2c Merge pull request #203 from snikket-im/make-lint
prosodyclient: Fixes to satisfy mypy
2025-06-05 17:48:23 +01:00
Matthew Wild
69f77020b8 prosodyclient: Fixes to satisfy mypy 2025-06-05 17:46:05 +01:00
Matthew Wild
5ac481a4b4 prosodyclient: Switch to black formatting and remove lint issues 2025-06-05 17:33:22 +01:00
Matthew Wild
56470eec01 Github: Use flake8 target 2025-06-05 17:32:34 +01:00
Matthew Wild
9b4903b230 Makefile: Add lint, format (black), flake8 and mypy targets 2025-06-05 17:29:44 +01:00
Matthew Wild
74c3946609 Bump log level of oauth errors 2025-06-02 11:36:08 +01:00
Matthew Wild
feabed6565 Register as an OAuth client and authenticate token requests
mod_http_oauth2 in prosody-modules was updated to require client
authentication for the password grant, which previously did not need
client authentication.

This means that the first request we make to Prosody will now register as a
client in order to obtain client_id and client_secret.

There is no real security gain from this approach (unlike other grant types,
the password grant does not do redirects which could be intercepted). In the
future, however, some security could be gained by having Prosody restrict
the ability to use the password grant to privileged OAuth clients. This would
prevent third-party OAuth clients from using the password grant which is not
suitable for that purpose.
2025-06-02 11:36:08 +01:00
Jonas Schäfer
af13a3cc47 Merge pull request #197 from snikket-im/z/play-badge-l10n
Serve localized Google Play badges locally
2025-04-13 08:57:16 +02:00
Kim Alvefur
466e3e79b7 Serve localized Google Play badges locally
Fixes #196

Badges downloaded from <https://play.google.com/intl/en_us/badges/> with
a bit of automation to get one per supported language.
2025-04-12 20:23:10 +02:00
17 changed files with 532 additions and 468 deletions

View File

@@ -48,7 +48,7 @@ jobs:
pip install flake8 flake8-print
- name: Linting
run: |
python -m flake8 snikket_web
make flake8
translation-check:
runs-on: ubuntu-latest

View File

@@ -5,6 +5,8 @@ generated_css_files = $(patsubst snikket_web/scss/%.scss,snikket_web/static/css/
translation_basepath = snikket_web/translations
pot_file = $(translation_basepath)/messages.pot
black_formatted_py = snikket_web/prosodyclient.py
PYTHON3 ?= python3
SCSSC ?= sassc --load-path snikket_web/scss/
@@ -34,4 +36,20 @@ compile_translations:
-pybabel compile -d $(translation_basepath)
.PHONY: lint
lint: format flake8
.PHONY: format
format:
$(PYTHON3) -m black $(black_formatted_py)
.PHONY: flake8
flake8:
$(PYTHON3) -m flake8 --exclude=$(subst $(space),$(comma),$(strip $(black_formatted_py))) snikket_web
$(PYTHON3) -m flake8 --ignore=E501,W503 $(black_formatted_py)
.PHONY: mypy
mypy:
$(PYTHON3) -m mypy --python-version 3.11 snikket_web
.PHONY: build_css clean update_translations compile_translations extract_translations force_update_translations

View File

@@ -47,10 +47,20 @@ def apple_store_badge() -> str:
return url_for("static", filename="img/apple/en.svg")
def play_store_badge() -> str:
locale = selected_locale()
filename = "{}_badge_web_generic.png".format(locale)
static_path = pathlib.Path(__file__).parent / "static" / "img" / "google"
if (static_path / filename).exists():
return url_for("static", filename="img/google/{}".format(filename))
return url_for("static", filename="img/google/en_badge_web_generic.png")
@bp.context_processor
def context() -> typing.Dict[str, typing.Any]:
return {
"apple_store_badge": apple_store_badge,
"play_store_badge": play_store_badge,
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -32,7 +32,7 @@
{%- endif -%}
<div class="install-buttons">
<ul>
<li><a href="{{ play_store_url }}"><img alt='{% trans %}Get it on Google Play{% endtrans %}' src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png' class="play"/></a></li>
<li><a href="{{ play_store_url }}"><img alt='{% trans %}Get it on Google Play{% endtrans %}' src='{{ play_store_badge() }}' class="play"/></a></li>
{%- if apple_store_url -%}
<li><a href="{{ apple_store_url }}" class="popover" data-popover-id="apple-popover"><img alt='{% trans %}Download on the App Store{% endtrans %}' src="{{ apple_store_badge() }}" class="apple"></a></li>
{%- endif -%}

View File

@@ -1,21 +1,21 @@
# Translations template for PROJECT.
# Copyright (C) 2024 ORGANIZATION
# Copyright (C) 2025 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2024.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2025.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-08-11 16:36+0200\n"
"POT-Creation-Date: 2025-04-12 20:21+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.16.0\n"
"Generated-By: Babel 2.17.0\n"
#: snikket_web/admin.py:69 snikket_web/templates/admin_delete_user.html:10
#: snikket_web/templates/admin_edit_circle.html:73
@@ -270,7 +270,7 @@ msgstr ""
msgid "Yesterday"
msgstr ""
#: snikket_web/infra.py:105
#: snikket_web/infra.py:104
#, python-format
msgid "%(time)s ago"
msgstr ""
@@ -281,59 +281,59 @@ msgid ""
"contact your Snikket operator."
msgstr ""
#: snikket_web/invite.py:114
#: snikket_web/invite.py:124
msgid "Username"
msgstr ""
#: snikket_web/invite.py:118 snikket_web/invite.py:190 snikket_web/main.py:43
#: snikket_web/invite.py:128 snikket_web/invite.py:200 snikket_web/main.py:43
msgid "Password"
msgstr ""
#: snikket_web/invite.py:126 snikket_web/invite.py:198
#: snikket_web/invite.py:136 snikket_web/invite.py:208
msgid "Confirm password"
msgstr ""
#: snikket_web/invite.py:130 snikket_web/invite.py:202
#: snikket_web/invite.py:140 snikket_web/invite.py:212
msgid "The passwords must match."
msgstr ""
#: snikket_web/invite.py:135
#: snikket_web/invite.py:145
msgid "Create account"
msgstr ""
#: snikket_web/invite.py:162
#: snikket_web/invite.py:172
msgid "That username is already taken."
msgstr ""
#: snikket_web/invite.py:166 snikket_web/invite.py:235
#: snikket_web/invite.py:176 snikket_web/invite.py:245
msgid "Registration was declined for unknown reasons."
msgstr ""
#: snikket_web/invite.py:170
#: snikket_web/invite.py:180
msgid "The username is not valid."
msgstr ""
#: snikket_web/invite.py:207 snikket_web/templates/user_home.html:37
#: snikket_web/invite.py:217 snikket_web/templates/user_home.html:37
#: snikket_web/templates/user_passwd.html:29
msgid "Change password"
msgstr ""
#: snikket_web/invite.py:254
#: snikket_web/invite.py:264
msgid "Account data file"
msgstr ""
#: snikket_web/invite.py:258
#: snikket_web/invite.py:268
msgid "Import data"
msgstr ""
#: snikket_web/invite.py:279
#: snikket_web/invite.py:289
#, python-format
msgid ""
"The account data you tried to import is in an unknown format. Please "
"upload an XML file in XEP-0227 format (provided format: %(mimetype)s)."
msgstr ""
#: snikket_web/invite.py:299 snikket_web/templates/unauth.html:18
#: snikket_web/invite.py:309 snikket_web/templates/unauth.html:18
#: snikket_web/user.py:192
msgid "Error"
msgstr ""
@@ -414,7 +414,7 @@ msgstr ""
msgid "Password changed"
msgstr ""
#: snikket_web/user.py:137
#: snikket_web/user.py:138
msgid ""
"The chosen avatar is too big. To be able to upload larger avatars, please"
" use the app."