mirror of https://github.com/zulip/zulip.git
avatar: Use fixed avatars for system bots.
This makes a Zulip server more isolated than relying on gravatar, and avoids complex logistics if in the future we move system bots to live inside individual realms. Co-authored-by: PieterCK <pieterceka123@gmail.com>
This commit is contained in:
parent
98ac036a5d
commit
46db52dc96
Binary file not shown.
After Width: | Height: | Size: 157 KiB |
Binary file not shown.
After Width: | Height: | Size: 79 KiB |
|
@ -13,6 +13,12 @@ from zerver.lib.upload import get_avatar_url
|
||||||
from zerver.lib.url_encoding import append_url_query_string
|
from zerver.lib.url_encoding import append_url_query_string
|
||||||
from zerver.models import UserProfile
|
from zerver.models import UserProfile
|
||||||
|
|
||||||
|
SYSTEM_BOTS_AVATAR_FILES = {
|
||||||
|
settings.WELCOME_BOT: "images/welcome-bot.png",
|
||||||
|
settings.NOTIFICATION_BOT: "images/logo/zulip-icon-square.svg",
|
||||||
|
settings.EMAIL_GATEWAY_BOT: "images/email-gateway-bot.png",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def avatar_url(
|
def avatar_url(
|
||||||
user_profile: UserProfile, medium: bool = False, client_gravatar: bool = False
|
user_profile: UserProfile, medium: bool = False, client_gravatar: bool = False
|
||||||
|
@ -54,6 +60,11 @@ def get_avatar_field(
|
||||||
computing them on the server (mostly to save bandwidth).
|
computing them on the server (mostly to save bandwidth).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# System bots have hardcoded avatars
|
||||||
|
system_bot_avatar = SYSTEM_BOTS_AVATAR_FILES.get(email)
|
||||||
|
if system_bot_avatar:
|
||||||
|
return staticfiles_storage.url(system_bot_avatar)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
If our client knows how to calculate gravatar hashes, we
|
If our client knows how to calculate gravatar hashes, we
|
||||||
will return None and let the client compute the gravatar
|
will return None and let the client compute the gravatar
|
||||||
|
|
|
@ -70,6 +70,9 @@ def create_internal_realm() -> None:
|
||||||
bots = UserProfile.objects.filter(email__in=[bot_info[1] for bot_info in internal_bots])
|
bots = UserProfile.objects.filter(email__in=[bot_info[1] for bot_info in internal_bots])
|
||||||
for bot in bots:
|
for bot in bots:
|
||||||
bot.bot_owner = bot
|
bot.bot_owner = bot
|
||||||
|
# Avatars for system bots are hardcoded, so make sure gravatar
|
||||||
|
# won't be used..
|
||||||
|
bot.avatar_source = "U"
|
||||||
bot.save()
|
bot.save()
|
||||||
|
|
||||||
# Initialize the email gateway bot as able to forge senders.
|
# Initialize the email gateway bot as able to forge senders.
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Generated by Django 5.0.9 on 2024-10-14 23:22
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
|
|
||||||
|
|
||||||
|
def set_system_bot_avatar_source_user(
|
||||||
|
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
) -> None:
|
||||||
|
UserProfile = apps.get_model("zerver", "UserProfile")
|
||||||
|
UserProfile.objects.filter(
|
||||||
|
email__in=[
|
||||||
|
settings.EMAIL_GATEWAY_BOT,
|
||||||
|
settings.NOTIFICATION_BOT,
|
||||||
|
settings.WELCOME_BOT,
|
||||||
|
]
|
||||||
|
).update(avatar_source="U")
|
||||||
|
|
||||||
|
|
||||||
|
def set_system_bot_avatar_source_gravatar(
|
||||||
|
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
) -> None:
|
||||||
|
UserProfile = apps.get_model("zerver", "UserProfile")
|
||||||
|
UserProfile.objects.filter(
|
||||||
|
email__in=[
|
||||||
|
settings.EMAIL_GATEWAY_BOT,
|
||||||
|
settings.NOTIFICATION_BOT,
|
||||||
|
settings.WELCOME_BOT,
|
||||||
|
]
|
||||||
|
).update(avatar_source="G")
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0614_remove_realm_move_messages_between_streams_policy"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
set_system_bot_avatar_source_user,
|
||||||
|
elidable=True,
|
||||||
|
reverse_code=set_system_bot_avatar_source_gravatar,
|
||||||
|
),
|
||||||
|
]
|
|
@ -1256,12 +1256,12 @@ class AvatarTest(UploadSerializeMixin, ZulipTestCase):
|
||||||
# Test cross_realm_bot avatar access using email.
|
# Test cross_realm_bot avatar access using email.
|
||||||
response = self.api_get(hamlet, "/avatar/welcome-bot@zulip.com", {"foo": "bar"})
|
response = self.api_get(hamlet, "/avatar/welcome-bot@zulip.com", {"foo": "bar"})
|
||||||
redirect_url = response["Location"]
|
redirect_url = response["Location"]
|
||||||
self.assertTrue(redirect_url.endswith(str(avatar_url(cross_realm_bot)) + "&foo=bar"))
|
self.assertTrue(redirect_url.endswith(str(avatar_url(cross_realm_bot)) + "?foo=bar"))
|
||||||
|
|
||||||
# Test cross_realm_bot avatar access using id.
|
# Test cross_realm_bot avatar access using id.
|
||||||
response = self.api_get(hamlet, f"/avatar/{cross_realm_bot.id}", {"foo": "bar"})
|
response = self.api_get(hamlet, f"/avatar/{cross_realm_bot.id}", {"foo": "bar"})
|
||||||
redirect_url = response["Location"]
|
redirect_url = response["Location"]
|
||||||
self.assertTrue(redirect_url.endswith(str(avatar_url(cross_realm_bot)) + "&foo=bar"))
|
self.assertTrue(redirect_url.endswith(str(avatar_url(cross_realm_bot)) + "?foo=bar"))
|
||||||
|
|
||||||
# Without spectators enabled, no unauthenticated access.
|
# Without spectators enabled, no unauthenticated access.
|
||||||
response = self.client_get("/avatar/cordelia@zulip.com", {"foo": "bar"})
|
response = self.client_get("/avatar/cordelia@zulip.com", {"foo": "bar"})
|
||||||
|
|
Loading…
Reference in New Issue