Skip to content

Commit 1ea5048

Browse files
committed
Allow LDAP Sources to provide Avatars
Add setting to LDAP source to allow it to provide an Avatar. Currently this is required to point to the image bytes. Fix #4144 Signed-off-by: Andrew Thornton <[email protected]>
1 parent 88abb0d commit 1ea5048

File tree

12 files changed

+56
-1
lines changed

12 files changed

+56
-1
lines changed

cmd/admin_auth_ldap.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ var (
8989
Name: "public-ssh-key-attribute",
9090
Usage: "The attribute of the user’s LDAP record containing the user’s public ssh key.",
9191
},
92+
cli.StringFlag{
93+
Name: "jpeg-avatar-attribute",
94+
Usage: "The attribute of the user’s LDAP record containing the user’s avatar.",
95+
},
9296
}
9397

9498
ldapBindDnCLIFlags = append(commonLdapCLIFlags,
@@ -230,6 +234,9 @@ func parseLdapConfig(c *cli.Context, config *ldap.Source) error {
230234
if c.IsSet("public-ssh-key-attribute") {
231235
config.AttributeSSHPublicKey = c.String("public-ssh-key-attribute")
232236
}
237+
if c.IsSet("jpeg-avatar-attribute") {
238+
config.AttributeAvatarJPEG = c.String("jpeg-avatar-attribute")
239+
}
233240
if c.IsSet("page-size") {
234241
config.SearchPageSize = uint32(c.Uint("page-size"))
235242
}

cmd/admin_auth_ldap_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ func TestAddLdapBindDn(t *testing.T) {
4545
"--surname-attribute", "sn-bind full",
4646
"--email-attribute", "mail-bind full",
4747
"--public-ssh-key-attribute", "publickey-bind full",
48+
"--jpeg-avatar-attribute", "avatar-bind full",
4849
"--bind-dn", "cn=readonly,dc=full-domain-bind,dc=org",
4950
"--bind-password", "secret-bind-full",
5051
"--attributes-in-bind",
@@ -71,6 +72,7 @@ func TestAddLdapBindDn(t *testing.T) {
7172
AttributeMail: "mail-bind full",
7273
AttributesInBind: true,
7374
AttributeSSHPublicKey: "publickey-bind full",
75+
AttributeAvatarJPEG: "avatar-bind full",
7476
SearchPageSize: 99,
7577
Filter: "(memberOf=cn=user-group,ou=example,dc=full-domain-bind,dc=org)",
7678
AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-bind,dc=org)",
@@ -269,6 +271,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
269271
"--surname-attribute", "sn-simple full",
270272
"--email-attribute", "mail-simple full",
271273
"--public-ssh-key-attribute", "publickey-simple full",
274+
"--jpeg-avatar-attribute", "avatar-simple full",
272275
"--user-dn", "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
273276
},
274277
loginSource: &models.LoginSource{
@@ -288,6 +291,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
288291
AttributeSurname: "sn-simple full",
289292
AttributeMail: "mail-simple full",
290293
AttributeSSHPublicKey: "publickey-simple full",
294+
AttributeAvatarJPEG: "avatar-simple full",
291295
Filter: "(&(objectClass=posixAccount)(full-simple-cn=%s))",
292296
AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-simple,dc=org)",
293297
RestrictedFilter: "(memberOf=cn=restricted-group,ou=example,dc=full-domain-simple,dc=org)",
@@ -501,6 +505,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
501505
"--surname-attribute", "sn-bind full",
502506
"--email-attribute", "mail-bind full",
503507
"--public-ssh-key-attribute", "publickey-bind full",
508+
"--jpeg-avatar-attribute", "avatar-bind full",
504509
"--bind-dn", "cn=readonly,dc=full-domain-bind,dc=org",
505510
"--bind-password", "secret-bind-full",
506511
"--synchronize-users",
@@ -534,6 +539,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
534539
AttributeMail: "mail-bind full",
535540
AttributesInBind: false,
536541
AttributeSSHPublicKey: "publickey-bind full",
542+
AttributeAvatarJPEG: "avatar-bind full",
537543
SearchPageSize: 99,
538544
Filter: "(memberOf=cn=user-group,ou=example,dc=full-domain-bind,dc=org)",
539545
AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-bind,dc=org)",
@@ -932,6 +938,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
932938
"--surname-attribute", "sn-simple full",
933939
"--email-attribute", "mail-simple full",
934940
"--public-ssh-key-attribute", "publickey-simple full",
941+
"--jpeg-avatar-attribute", "avatar-simple full",
935942
"--user-dn", "cn=%s,ou=Users,dc=full-domain-simple,dc=org",
936943
},
937944
id: 7,
@@ -952,6 +959,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
952959
AttributeSurname: "sn-simple full",
953960
AttributeMail: "mail-simple full",
954961
AttributeSSHPublicKey: "publickey-simple full",
962+
AttributeAvatarJPEG: "avatar-simple full",
955963
Filter: "(&(objectClass=posixAccount)(full-simple-cn=%s))",
956964
AdminFilter: "(memberOf=cn=admin-group,ou=example,dc=full-domain-simple,dc=org)",
957965
RestrictedFilter: "(memberOf=cn=restricted-group,ou=example,dc=full-domain-simple,dc=org)",

docs/content/doc/usage/command-line.en-us.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ Admin operations:
152152
- `--surname-attribute value`: The attribute of the user’s LDAP record containing the user’s surname.
153153
- `--email-attribute value`: The attribute of the user’s LDAP record containing the user’s email address. Required.
154154
- `--public-ssh-key-attribute value`: The attribute of the user’s LDAP record containing the user’s public ssh key.
155+
- `--jpeg-avatar-attribute value`: The attribute of the user’s LDAP record containing the user’s avatar.
155156
- `--bind-dn value`: The DN to bind to the LDAP server with when searching for the user.
156157
- `--bind-password value`: The password for the Bind DN, if any.
157158
- `--attributes-in-bind`: Fetch attributes in bind DN context.
@@ -177,6 +178,7 @@ Admin operations:
177178
- `--surname-attribute value`: The attribute of the user’s LDAP record containing the user’s surname.
178179
- `--email-attribute value`: The attribute of the user’s LDAP record containing the user’s email address.
179180
- `--public-ssh-key-attribute value`: The attribute of the user’s LDAP record containing the user’s public ssh key.
181+
- `--jpeg-avatar-attribute value`: The attribute of the user’s LDAP record containing the user’s avatar.
180182
- `--bind-dn value`: The DN to bind to the LDAP server with when searching for the user.
181183
- `--bind-password value`: The password for the Bind DN, if any.
182184
- `--attributes-in-bind`: Fetch attributes in bind DN context.
@@ -202,6 +204,7 @@ Admin operations:
202204
- `--surname-attribute value`: The attribute of the user’s LDAP record containing the user’s surname.
203205
- `--email-attribute value`: The attribute of the user’s LDAP record containing the user’s email address. Required.
204206
- `--public-ssh-key-attribute value`: The attribute of the user’s LDAP record containing the user’s public ssh key.
207+
- `--jpeg-avatar-attribute value`: The attribute of the user’s LDAP record containing the user’s avatar.
205208
- `--user-dn value`: The user’s DN. Required.
206209
- Examples:
207210
- `gitea admin auth add-ldap-simple --name ldap --security-protocol unencrypted --host mydomain.org --port 389 --user-dn "cn=%s,ou=Users,dc=mydomain,dc=org" --user-filter "(&(objectClass=posixAccount)(cn=%s))" --email-attribute mail`
@@ -223,6 +226,7 @@ Admin operations:
223226
- `--surname-attribute value`: The attribute of the user’s LDAP record containing the user’s surname.
224227
- `--email-attribute value`: The attribute of the user’s LDAP record containing the user’s email address.
225228
- `--public-ssh-key-attribute value`: The attribute of the user’s LDAP record containing the user’s public ssh key.
229+
- `--jpeg-avatar-attribute value`: The attribute of the user’s LDAP record containing the user’s avatar.
226230
- `--user-dn value`: The user’s DN.
227231
- Examples:
228232
- `gitea admin auth update-ldap-simple --id 1 --name "my ldap auth source"`

options/locale/locale_en-US.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,6 +2416,7 @@ auths.attribute_name = First Name Attribute
24162416
auths.attribute_surname = Surname Attribute
24172417
auths.attribute_mail = Email Attribute
24182418
auths.attribute_ssh_public_key = Public SSH Key Attribute
2419+
auths.attribute_avatar_jpeg = JPEG Avatar Attribute
24192420
auths.attributes_in_bind = Fetch Attributes in Bind DN Context
24202421
auths.allow_deactivate_all = Allow an empty search result to deactivate all users
24212422
auths.use_paged_search = Use Paged Search

routers/web/admin/auths.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ func parseLDAPConfig(form forms.AuthenticationForm) *ldap.Source {
134134
AttributeMail: form.AttributeMail,
135135
AttributesInBind: form.AttributesInBind,
136136
AttributeSSHPublicKey: form.AttributeSSHPublicKey,
137+
AttributeAvatarJPEG: form.AttributeAvatarJPEG,
137138
SearchPageSize: pageSize,
138139
Filter: form.Filter,
139140
GroupsEnabled: form.GroupsEnabled,

services/auth/source/ldap/source.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type Source struct {
4141
AttributeMail string // E-mail attribute
4242
AttributesInBind bool // fetch attributes in bind context (not user)
4343
AttributeSSHPublicKey string // LDAP SSH Public Key attribute
44+
AttributeAvatarJPEG string
4445
SearchPageSize uint32 // Search with paging page size
4546
Filter string // Query filter to validate entry
4647
AdminFilter string // Query filter to check if user is admin

services/auth/source/ldap/source_authenticate.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,9 @@ func (source *Source) Authenticate(user *models.User, login, password string) (*
9595
err = models.RewriteAllPublicKeys()
9696
}
9797

98+
if err == nil && source.AttributeAvatarJPEG != "" {
99+
_ = user.UploadAvatar(sr.AvatarJPEG)
100+
}
101+
98102
return user, err
99103
}

services/auth/source/ldap/source_search.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type SearchResult struct {
2626
SSHPublicKey []string // SSH Public Key
2727
IsAdmin bool // if user is administrator
2828
IsRestricted bool // if user is restricted
29+
AvatarJPEG []byte
2930
}
3031

3132
func (ls *Source) sanitizedUserQuery(username string) (string, bool) {
@@ -295,6 +296,7 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
295296
}
296297

297298
var sshPublicKey []string
299+
var avatarJPEG []byte
298300

299301
username := sr.Entries[0].GetAttributeValue(ls.AttributeUsername)
300302
firstname := sr.Entries[0].GetAttributeValue(ls.AttributeName)
@@ -362,6 +364,10 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
362364
}
363365
}
364366

367+
if ls.AttributeAvatarJPEG != "" {
368+
avatarJPEG = sr.Entries[0].GetRawAttributeValue(ls.AttributeAvatarJPEG)
369+
}
370+
365371
return &SearchResult{
366372
Username: username,
367373
Name: firstname,
@@ -370,6 +376,7 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) *SearchResul
370376
SSHPublicKey: sshPublicKey,
371377
IsAdmin: isAdmin,
372378
IsRestricted: isRestricted,
379+
AvatarJPEG: avatarJPEG,
373380
}
374381
}
375382

@@ -440,6 +447,9 @@ func (ls *Source) SearchEntries() ([]*SearchResult, error) {
440447
if isAttributeSSHPublicKeySet {
441448
result[i].SSHPublicKey = v.GetAttributeValues(ls.AttributeSSHPublicKey)
442449
}
450+
if ls.AttributeAvatarJPEG != "" {
451+
result[i].AvatarJPEG = v.GetRawAttributeValue(ls.AttributeAvatarJPEG)
452+
}
443453
}
444454

445455
return result, nil

services/auth/source/ldap/source_sync.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,18 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
101101

102102
if err != nil {
103103
log.Error("SyncExternalUsers[%s]: Error creating user %s: %v", source.loginSource.Name, su.Username, err)
104-
} else if isAttributeSSHPublicKeySet {
104+
}
105+
106+
if err == nil && isAttributeSSHPublicKeySet {
105107
log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", source.loginSource.Name, usr.Name)
106108
if models.AddPublicKeysBySource(usr, source.loginSource, su.SSHPublicKey) {
107109
sshKeysNeedUpdate = true
108110
}
109111
}
112+
113+
if err == nil && source.AttributeAvatarJPEG != "" {
114+
_ = usr.UploadAvatar(su.AvatarJPEG)
115+
}
110116
} else if updateExisting {
111117
existingUsers = append(existingUsers, usr.ID)
112118

@@ -140,6 +146,10 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
140146
if err != nil {
141147
log.Error("SyncExternalUsers[%s]: Error updating user %s: %v", source.loginSource.Name, usr.Name, err)
142148
}
149+
150+
if err == nil && source.AttributeAvatarJPEG != "" {
151+
_ = usr.UploadAvatar(su.AvatarJPEG)
152+
}
143153
}
144154
}
145155
}

services/forms/auth_form.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type AuthenticationForm struct {
2929
AttributeSurname string
3030
AttributeMail string
3131
AttributeSSHPublicKey string
32+
AttributeAvatarJPEG string
3233
AttributesInBind bool
3334
UsePagedSearch bool
3435
SearchPageSize int

templates/admin/auth/edit.tmpl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@
104104
<label for="attribute_ssh_public_key">{{.i18n.Tr "admin.auths.attribute_ssh_public_key"}}</label>
105105
<input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{$cfg.AttributeSSHPublicKey}}" placeholder="e.g. SshPublicKey">
106106
</div>
107+
<div class="field">
108+
<label for="attribute_avatar_jpeg">{{.i18n.Tr "admin.auths.attribute_avatar_jpeg"}}</label>
109+
<input id="attribute_avatar_jpeg" name="attribute_avatar_jpeg" value="{{$cfg.AttributeAvatarJPEG}}" placeholder="e.g. jpegPhoto">
110+
</div>
107111
<div class="inline field">
108112
<div class="ui checkbox">
109113
<label for="groups_enabled"><strong>{{.i18n.Tr "admin.auths.verify_group_membership"}}</strong></label>

templates/admin/auth/source/ldap.tmpl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@
7676
<label for="attribute_ssh_public_key">{{.i18n.Tr "admin.auths.attribute_ssh_public_key"}}</label>
7777
<input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{.attribute_ssh_public_key}}" placeholder="e.g. SshPublicKey">
7878
</div>
79+
<div class="field">
80+
<label for="attribute_avatar_jpeg">{{.i18n.Tr "admin.auths.attribute_avatar_jpeg"}}</label>
81+
<input id="attribute_avatar_jpeg" name="attribute_avatar_jpeg" value="{{.attribute_avatar_jpeg}}" placeholder="e.g. jpegPhoto">
82+
</div>
7983
<div class="inline field">
8084
<div class="ui checkbox">
8185
<label for="groups_enabled"><strong>{{.i18n.Tr "admin.auths.verify_group_membership"}}</strong></label>

0 commit comments

Comments
 (0)