Files
upstream-zulip/zerver/lib/external_accounts.py
upstream-mirror 64898b2c79
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
2026-09-15 15:05:30 +05:00

195 lines
6.0 KiB
Python

"""
This module stores data for "external account" custom profile field.
"""
from dataclasses import dataclass
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _
from django.utils.translation import gettext_lazy
from django_stubs_ext import StrPromise
from zerver.lib.types import ProfileFieldData
from zerver.lib.validator import (
check_dict_only,
check_external_account_url_pattern,
check_required_string,
)
# Default external account fields are by default available
# to realm admins, where realm admin only need to select
# the default field and other values(i.e. name, url) will be
# fetch from this dictionary.
@dataclass
class ExternalAccount:
text: str # Field text for admins - custom profile field in org settings view
name: StrPromise # Field label or name - user profile in user settings view
hint: str # Field hint for realm users
url_pattern: str # Field URL linkifier
# Set url_pattern as "%(username)s" if there's no common URL pattern,
# and the user should enter the full URL of their link.
# Set url_pattern as "" to make the field a text field.
DEFAULT_EXTERNAL_ACCOUNTS = {
"atlassian": ExternalAccount(
text="Atlassian",
url_pattern="",
name=gettext_lazy("Atlassian account ID"),
hint="",
),
"behance": ExternalAccount(
text="Behance",
url_pattern="https://www.behance.net/%(username)s",
name=gettext_lazy("Behance username"),
hint="",
),
"bitbucket": ExternalAccount(
text="Bitbucket",
url_pattern="https://bitbucket.org/%(username)s",
name=gettext_lazy("Bitbucket username"),
hint="",
),
"bluesky": ExternalAccount(
text="Bluesky",
url_pattern="https://bsky.app/profile/%(username)s",
name=gettext_lazy("Bluesky handle"),
hint="",
),
"codeberg": ExternalAccount(
text="Codeberg",
url_pattern="https://codeberg.org/%(username)s",
name=gettext_lazy("Codeberg username"),
hint="",
),
"discord": ExternalAccount(
text="Discord",
url_pattern="",
name=gettext_lazy("Discord tag"),
hint="",
),
"dribbble": ExternalAccount(
text="Dribbble",
url_pattern="https://dribbble.com/%(username)s",
name=gettext_lazy("Dribbble username"),
hint="",
),
"facebook": ExternalAccount(
text="Facebook",
url_pattern="https://www.facebook.com/%(username)s",
name=gettext_lazy("Facebook username"),
hint="",
),
"github": ExternalAccount(
text="GitHub",
url_pattern="https://github.com/%(username)s",
name=gettext_lazy("GitHub username"),
hint="",
),
"gitlab": ExternalAccount(
text="GitLab",
url_pattern="https://gitlab.com/%(username)s",
name=gettext_lazy("GitLab username"),
hint="",
),
"instagram": ExternalAccount(
text="Instagram",
url_pattern="https://www.instagram.com/%(username)s",
name=gettext_lazy("Instagram username"),
hint="",
),
"linkedin": ExternalAccount(
text="LinkedIn",
url_pattern="https://www.linkedin.com/in/%(username)s",
name=gettext_lazy("LinkedIn profile name"),
hint="",
),
"mastodon": ExternalAccount(
text="Mastodon",
url_pattern="%(username)s",
name=gettext_lazy("Mastodon profile"),
hint="The full URL to your profile",
),
"medium": ExternalAccount(
text="Medium",
url_pattern="https://%(username)s.medium.com",
name=gettext_lazy("Medium username"),
hint="",
),
"pinterest": ExternalAccount(
text="Pinterest",
url_pattern="https://www.pinterest.com/%(username)s",
name=gettext_lazy("Pinterest username"),
hint="",
),
"reddit": ExternalAccount(
text="Reddit",
url_pattern="https://www.reddit.com/user/%(username)s",
name=gettext_lazy("Reddit username"),
hint="",
),
"snapchat": ExternalAccount(
text="Snapchat",
url_pattern="https://www.snapchat.com/@%(username)s",
name=gettext_lazy("Snapchat username"),
hint="",
),
"threads": ExternalAccount(
text="Threads",
url_pattern="https://www.threads.com/@%(username)s",
name=gettext_lazy("Threads username"),
hint="",
),
"tiktok": ExternalAccount(
text="TikTok",
url_pattern="https://www.tiktok.com/@%(username)s",
name=gettext_lazy("TikTok username"),
hint="",
),
"twitch": ExternalAccount(
text="Twitch",
url_pattern="https://www.twitch.tv/%(username)s",
name=gettext_lazy("Twitch username"),
hint="",
),
"x": ExternalAccount(
text="X",
url_pattern="https://x.com/%(username)s",
name=gettext_lazy("X username"),
hint="",
),
"youtube": ExternalAccount(
text="YouTube",
url_pattern="https://www.youtube.com/%(username)s",
name=gettext_lazy("YouTube handle"),
hint="",
),
}
def get_default_external_accounts() -> dict[str, dict[str, str]]:
return {
subtype: {
"text": external_account.text,
"url_pattern": external_account.url_pattern,
"name": str(external_account.name),
"hint": external_account.hint,
}
for subtype, external_account in DEFAULT_EXTERNAL_ACCOUNTS.items()
}
def validate_external_account_field_data(field_data: ProfileFieldData) -> ProfileFieldData:
field_validator = check_dict_only(
[("subtype", check_required_string)],
[("url_pattern", check_external_account_url_pattern)],
)
field_validator("field_data", field_data)
field_subtype = field_data.get("subtype")
if field_subtype not in DEFAULT_EXTERNAL_ACCOUNTS and field_subtype != "custom":
raise ValidationError(_("Invalid external account type"))
return field_data