Skip to content

Commit

Permalink
allow domain customisation
Browse files Browse the repository at this point in the history
  • Loading branch information
classabbyamp committed Aug 4, 2024
1 parent a6a37c0 commit 94adcf1
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 10 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ c["www"]["avatar_methods"] = [netauth, ...]

### Notes

- The plugin looks at the entity KV store key `avatar` to set the avatar. Store a URL to an image there.
- The plugin sets the email address of the user to `entity_id@netauth`.
The plugin looks at the following metadata on NetAuth entities:

- entity ID: used as an "email" in the format `entity_id@netauth`
- entity ID: used as an "email" in the format `entity_id@domain`. `domain` is the base domain of the NetAuth server, but is overridable.
- entity display name or legal name: if set, will be used for the `full_name` buildbot user property in that fallback order
- entity group membership: used for the `groups` buildbot user property and can be used for buildbot authz, for example:

Expand Down
21 changes: 14 additions & 7 deletions buildbot_netauth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from buildbot.plugins import util
from buildbot.www import resource
from buildbot.www.avatar import AvatarBase
from buildbot.www.auth import UserInfoProviderBase, bytes2unicode
from buildbot.www.auth import UserInfoProviderBase, bytes2unicode, unicode2bytes
from twisted.internet import defer
from twisted.cred.error import UnauthorizedLogin

Expand All @@ -18,24 +18,31 @@ class BuildbotNetAuth(util.CustomAuth, AvatarBase, UserInfoProviderBase):
NetAuth authentication, user info, and avatar provider
:param conf: path to a NetAuth config file, optional
:param domain: domain to use for email addresses (default: netauth server domain
with one subdomain stripped, for example: ``netauth.example.com -> example.com``)
:param kwargs: all other keyword arguments are passed to the NetAuth instance
"""

name = "netauth"

def __init__(self, *, conf: Path | None = None, **kwargs):
def __init__(self, *, conf: Path | None = None, domain: str | None = None, **kwargs):
kwargs["service_name"] = "buildbot"

if conf is not None:
self.netauth = netauth.NetAuth.with_config(conf, **kwargs)
else:
self.netauth = netauth.NetAuth(**kwargs)

if domain:
self.domain = domain
else:
self.domain = ".".join(self.netauth.server.split(".")[1:])

super().__init__(userInfoProvider=self)

def requestAvatarId(self, cred):
if self.check_credentials(cred.username, cred.password):
return defer.succeed(cred.username + b"@netauth")
return defer.succeed(cred.username + unicode2bytes(f"@{self.domain}"))
return defer.fail(UnauthorizedLogin())

def check_credentials(self, username: str, password: str) -> bool:
Expand All @@ -51,7 +58,7 @@ def getUserInfo(self, username):
if not username:
return defer.fail(ValueError("username not found"))

username = username.removesuffix("@netauth")
username = username.removesuffix(f"@{self.domain}")

try:
entity = self.netauth.entity_info(username)
Expand All @@ -60,7 +67,7 @@ def getUserInfo(self, username):
return defer.fail(ValueError("entity not found"))

id = entity.id
email = f"{id}@netauth"
email = f"{id}@{self.domain}"
if (meta := entity.meta) is not None:
full_name = meta.display_name or meta.legal_name or id
groups = meta.groups or []
Expand All @@ -80,8 +87,8 @@ def getUserInfo(self, username):

def getUserAvatar(self, email, username, size, defaultAvatarUrl):
username = bytes2unicode(username)
if username and username.endswith("@netauth"):
username = username.removesuffix("@netauth")
if username and username.endswith(f"@{self.domain}"):
username = username.removesuffix(f"@{self.domain}")
try:
kv = self.netauth.entity_kv_get(username, "avatar")
avatar = kv.get("avatar")
Expand Down

0 comments on commit 94adcf1

Please sign in to comment.