Compare commits

...

5 commits

Author SHA1 Message Date
Baptiste Daroussin 08f5a25d3b ldap: default domain name (#3414)
When the ldap synchronizer is look for an email address and fails at
finding one, it falls back at creating one using "localhost.local"
domain.

This new field makes this domain name configurable.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3414
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: Baptiste Daroussin <bapt@FreeBSD.org>
Co-committed-by: Baptiste Daroussin <bapt@FreeBSD.org>
2024-04-26 22:38:58 +00:00
Earl Warren 4da76d0e5f Merge pull request 'fix(Dockerfile.rootless): revert to default path for app.ini' (#3363) from gmask/forgejo:fix/container-app-ini-variable into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3363
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2024-04-26 22:36:33 +00:00
Earl Warren c4db84ad0e Merge pull request 'docs(release-notes): 7.0.1' (#3484) from earl-warren/forgejo:wip-release-notes-v7.0 into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3484
Reviewed-by: oliverpool <oliverpool@noreply.codeberg.org>
Reviewed-by: crystal <crystal@noreply.codeberg.org>
2024-04-26 22:34:25 +00:00
Earl Warren a5df622099
docs(release-notes): 7.0.1 2024-04-27 00:31:22 +02:00
Gerard Salvatella dad16cd589 fix(Dockerfile.rootless): revert to default path for app.ini
The current path of the `$GITEA_APP_INI` configuration file makes the
forgejo application reset every time the container is restarted, unless
a specific volume for this file is created. Consider the following:

* This quirk is not documented
* All configuration data resides in `/var/lib/gitea`
* The custom configuration path defaults to `/var/lib/gitea/custom/conf`
  (see `forgejo -h`)
* Containers mounting the volume `-v /foo/bar:/var/lib/gitea` already
  have this file available to modify. Another volume shouldn't be
  required
* Containers using named volumes can use `docker cp` to modify the file
  inside the volume, if desired

For these reasons, it makes more sense to use the default path for
`$GITEA_APP_INI` rather than require users to create a dedicated volume
for the file. Revert it back to its default while maintaining backwards
compatibility (users can update by simply moving the file to the new
path).
2024-04-26 21:30:10 +02:00
17 changed files with 147 additions and 22 deletions

View file

@ -100,8 +100,11 @@ ENV GITEA_CUSTOM /var/lib/gitea/custom
ENV GITEA_TEMP /tmp/gitea ENV GITEA_TEMP /tmp/gitea
ENV TMPDIR /tmp/gitea ENV TMPDIR /tmp/gitea
#TODO add to docs the ability to define the ini to load (useful to test and revert a config) # Legacy config file for backwards compatibility
ENV GITEA_APP_INI /etc/gitea/app.ini # TODO: remove on next major version release
ENV GITEA_APP_INI_LEGACY /etc/gitea/app.ini
ENV GITEA_APP_INI ${GITEA_CUSTOM}/conf/app.ini
ENV HOME "/var/lib/gitea/git" ENV HOME "/var/lib/gitea/git"
VOLUME ["/var/lib/gitea", "/etc/gitea"] VOLUME ["/var/lib/gitea", "/etc/gitea"]
WORKDIR /var/lib/gitea WORKDIR /var/lib/gitea

View file

@ -8,6 +8,19 @@ A [patch or minor release](https://semver.org/spec/v2.0.0.html) (e.g. upgrading
- [8.0.0](/release-notes/8.0.0/) - [8.0.0](/release-notes/8.0.0/)
## 7.0.1
This is a bug fix release. See the documentation for more information on the [upgrade procedure](https://forgejo.org/docs/v7.0/admin/upgrade/).
In addition to the following notable bug fixes, you can browse the [full list of commits](https://codeberg.org/forgejo/forgejo/compare/v7.0.0...v7.0.1) included in this release.
* **Bug fixes:**
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3466): LFS data corruption when running the [`forgejo doctor check --fix`](https://forgejo.org/docs/v7.0/admin/command-line/#doctor-check) CLI command or setting [`[cron.gc_lfs].ENABLED=true`](https://forgejo.org/docs/v7.0/admin/config-cheat-sheet/#cron---garbage-collect-lfs-pointers-in-repositories-crongc_lfs) (the default is `false`).
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3412): [non backward compatible change](https://codeberg.org/forgejo/forgejo/issues/3399) in the [`forgejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command.
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3448): error 500 because of an incorrect evaluation of the template when visiting the LFS settings of a repository.
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3464): `GET /repos/{owner}/{name}` API endpoint [always returns an empty string for the `object_format_name` field](https://codeberg.org/forgejo/forgejo/issues/3458).
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3444): fuzzy search [may fail with bleve](https://codeberg.org/forgejo/forgejo/issues/3443).
## 7.0.0 ## 7.0.0
The [complete list of commits](https://codeberg.org/forgejo/forgejo/commits/branch/v7.0/forgejo) included in the `Forgejo v7.0.0` release can be reviewed from the command line with: The [complete list of commits](https://codeberg.org/forgejo/forgejo/commits/branch/v7.0/forgejo) included in the `Forgejo v7.0.0` release can be reviewed from the command line with:
@ -19,7 +32,7 @@ $ git -C forgejo log --oneline --no-merges origin/v1.21/forgejo..origin/v7.0/for
* **Regressions and workarounds:** * **Regressions and workarounds:**
* Running the [`forgejo doctor check --fix`](https://forgejo.org/docs/v7.0/admin/command-line/#doctor-check) CLI command or setting [`[cron.gc_lfs].ENABLED=true`](https://forgejo.org/docs/v7.0/admin/config-cheat-sheet/#cron---garbage-collect-lfs-pointers-in-repositories-crongc_lfs) (the default is `false`) will corrupt the LFS storage. The workaround is to not run the doctor CLI command and disable the `cron.gc_lfs`. This regression will be [fixed in 7.0.1](https://codeberg.org/forgejo/forgejo/issues/3438). * Running the [`forgejo doctor check --fix`](https://forgejo.org/docs/v7.0/admin/command-line/#doctor-check) CLI command or setting [`[cron.gc_lfs].ENABLED=true`](https://forgejo.org/docs/v7.0/admin/config-cheat-sheet/#cron---garbage-collect-lfs-pointers-in-repositories-crongc_lfs) (the default is `false`) will corrupt the LFS storage. The workaround is to not run the doctor CLI command and disable the `cron.gc_lfs`. This regression will be [fixed in 7.0.1](https://codeberg.org/forgejo/forgejo/issues/3438).
* The [`fogejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command [requires a password](https://codeberg.org/forgejo/forgejo/commit/b122c6ef8b9254120432aed373cbe075331132ac) change by default when creating the first user and the `--admin` flag is not specified. The `--must-change-password=false` argument must be given to not require a password change. This regression will be [fixed in 7.0.1](https://codeberg.org/forgejo/forgejo/issues/3399). * The [`forgejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command [requires a password](https://codeberg.org/forgejo/forgejo/commit/b122c6ef8b9254120432aed373cbe075331132ac) change by default when creating the first user and the `--admin` flag is not specified. The `--must-change-password=false` argument must be given to not require a password change. This regression will be [fixed in 7.0.1](https://codeberg.org/forgejo/forgejo/issues/3399).
* **Breaking changes requiring manual intervention:** * **Breaking changes requiring manual intervention:**
* [MySQL 8.0 or PostgreSQL 12](https://codeberg.org/forgejo/forgejo/commit/e94f9fcafdcf284561e7fb33f60156a69c4ad6a5) are the minimum supported versions. The database must be migrated before upgrading. The requirements regarding SQLite did not change. * [MySQL 8.0 or PostgreSQL 12](https://codeberg.org/forgejo/forgejo/commit/e94f9fcafdcf284561e7fb33f60156a69c4ad6a5) are the minimum supported versions. The database must be migrated before upgrading. The requirements regarding SQLite did not change.
* The `per_page` parameter is [no longer a synonym for `limit`](https://codeberg.org/forgejo/forgejo/commit/0aab2d38a7d91bc8caff332e452364468ce52d9a) in the [/repos/{owner}/{repo}/releases](https://code.forgejo.org/api/swagger/#/repository/repoListReleases) API endpoint. * The `per_page` parameter is [no longer a synonym for `limit`](https://codeberg.org/forgejo/forgejo/commit/0aab2d38a7d91bc8caff332e452364468ce52d9a) in the [/repos/{owner}/{repo}/releases](https://code.forgejo.org/api/swagger/#/repository/repoListReleases) API endpoint.

View file

@ -13,5 +13,10 @@ fi
if [ $# -gt 0 ]; then if [ $# -gt 0 ]; then
exec "$@" exec "$@"
else else
# TODO: remove on next major version release
# Honour legacy config file if existing
if [ -f ${GITEA_APP_INI_LEGACY} ]; then
GITEA_APP_INI=${GITEA_APP_INI_LEGACY}
fi
exec /usr/local/bin/gitea -c ${GITEA_APP_INI} web exec /usr/local/bin/gitea -c ${GITEA_APP_INI} web
fi fi

View file

@ -11,6 +11,18 @@ mkdir -p ${GITEA_CUSTOM} && chmod 0700 ${GITEA_CUSTOM}
mkdir -p ${GITEA_TEMP} && chmod 0700 ${GITEA_TEMP} mkdir -p ${GITEA_TEMP} && chmod 0700 ${GITEA_TEMP}
if [ ! -w ${GITEA_TEMP} ]; then echo "${GITEA_TEMP} is not writable"; exit 1; fi if [ ! -w ${GITEA_TEMP} ]; then echo "${GITEA_TEMP} is not writable"; exit 1; fi
# TODO: remove on next major version release
# Honour legacy config file if existing, but inform the user
if [ -f ${GITEA_APP_INI_LEGACY} ] && [ ${GITEA_APP_INI} != ${GITEA_APP_INI_LEGACY} ]; then
GITEA_APP_INI_DEFAULT=/var/lib/gitea/custom/conf/app.ini
echo -e \
"\033[33mWARNING\033[0m: detected configuration file in deprecated default path ${GITEA_APP_INI_LEGACY}." \
"The new default is ${GITEA_APP_INI_DEFAULT}. To remove this warning, choose one of the options:\n" \
"* Move ${GITEA_APP_INI_LEGACY} to ${GITEA_APP_INI_DEFAULT} (or to \$GITEA_APP_INI if you want to override this variable)\n" \
"* Explicitly override GITEA_APP_INI=${GITEA_APP_INI_LEGACY} in the container environment"
GITEA_APP_INI=${GITEA_APP_INI_LEGACY}
fi
#Prepare config file #Prepare config file
if [ ! -f ${GITEA_APP_INI} ]; then if [ ! -f ${GITEA_APP_INI} ]; then

View file

@ -3100,6 +3100,7 @@ auths.attribute_mail = Email attribute
auths.attribute_ssh_public_key = Public SSH key attribute auths.attribute_ssh_public_key = Public SSH key attribute
auths.attribute_avatar = Avatar attribute auths.attribute_avatar = Avatar attribute
auths.attributes_in_bind = Fetch attributes in bind DN context auths.attributes_in_bind = Fetch attributes in bind DN context
auths.default_domain_name = Default domain name used for the email address
auths.allow_deactivate_all = Allow an empty search result to deactivate all users auths.allow_deactivate_all = Allow an empty search result to deactivate all users
auths.use_paged_search = Use paged search auths.use_paged_search = Use paged search
auths.search_page_size = Page size auths.search_page_size = Page size

View file

@ -0,0 +1 @@
Allow to customize the domain name used as a fallback when synchronizing sources from ldap [`ldap: default domain name`](https://codeberg.org/forgejo/forgejo/pulls/3414)

View file

@ -0,0 +1,6 @@
Reverted the rootless container image path in `GITEA_APP_INI` from
`/etc/gitea/app.ini` to its default value of
`/var/lib/gitea/custom/conf/app.ini`. This allows container users to not have
to mount two separate volumes (one for the configuration data and one for the
configuration `.ini` file). A warning is issued for users with the legacy
configuration on how to update to the new path.

View file

@ -1 +0,0 @@
The regression in the [`fogejo admin user create`](https://forgejo.org/docs/v7.0/admin/command-line/#admin-user-create) CLI command [is fixed](https://codeberg.org/forgejo/forgejo/issues/3399) and it is backward compatible.

View file

@ -1 +0,0 @@
Fixed bleve indexer failing when [fuzziness exceeds the maximum 2](https://codeberg.org/forgejo/forgejo/pulls/3444)

View file

@ -1 +0,0 @@
Fixed an error 500 when visiting [the LFS settings](https://codeberg.org/forgejo/forgejo/pulls/3451) at `/{owner}/{repo}/settings/lfs/find?oid=...`.

View file

@ -129,6 +129,7 @@ func parseLDAPConfig(form forms.AuthenticationForm) *ldap.Source {
UserDN: form.UserDN, UserDN: form.UserDN,
BindPassword: form.BindPassword, BindPassword: form.BindPassword,
UserBase: form.UserBase, UserBase: form.UserBase,
DefaultDomainName: form.DefaultDomainName,
AttributeUsername: form.AttributeUsername, AttributeUsername: form.AttributeUsername,
AttributeName: form.AttributeName, AttributeName: form.AttributeName,
AttributeSurname: form.AttributeSurname, AttributeSurname: form.AttributeSurname,

View file

@ -34,6 +34,7 @@ type Source struct {
BindPassword string // Bind DN password BindPassword string // Bind DN password
UserBase string // Base search path for users UserBase string // Base search path for users
UserDN string // Template for the DN of the user for simple auth UserDN string // Template for the DN of the user for simple auth
DefaultDomainName string // DomainName used if none are in the field, default "localhost.local"
AttributeUsername string // Username attribute AttributeUsername string // Username attribute
AttributeName string // First name attribute AttributeName string // First name attribute
AttributeSurname string // Surname attribute AttributeSurname string // Surname attribute

View file

@ -105,7 +105,11 @@ func (source *Source) Sync(ctx context.Context, updateExisting bool) error {
} }
if len(su.Mail) == 0 { if len(su.Mail) == 0 {
su.Mail = fmt.Sprintf("%s@localhost.local", su.Username) domainName := source.DefaultDomainName
if len(domainName) == 0 {
domainName = "localhost.local"
}
su.Mail = fmt.Sprintf("%s@%s", su.Username, domainName)
} }
fullName := composeFullName(su.Name, su.Surname, su.Username) fullName := composeFullName(su.Name, su.Surname, su.Username)

View file

@ -26,6 +26,7 @@ type AuthenticationForm struct {
AttributeUsername string AttributeUsername string
AttributeName string AttributeName string
AttributeSurname string AttributeSurname string
DefaultDomainName string
AttributeMail string AttributeMail string
AttributeSSHPublicKey string AttributeSSHPublicKey string
AttributeAvatar string AttributeAvatar string

View file

@ -97,6 +97,10 @@
<label for="attribute_mail">{{ctx.Locale.Tr "admin.auths.attribute_mail"}}</label> <label for="attribute_mail">{{ctx.Locale.Tr "admin.auths.attribute_mail"}}</label>
<input id="attribute_mail" name="attribute_mail" value="{{$cfg.AttributeMail}}" placeholder="mail" required> <input id="attribute_mail" name="attribute_mail" value="{{$cfg.AttributeMail}}" placeholder="mail" required>
</div> </div>
<div class="field">
<label for="default_domain_name">{{ctx.Locale.Tr "admin.auths.default_domain_name"}}</label>
<input id="default_domain_name" name="default_domain_name" value="{{$cfg.DefaultDomainName}}" placeholder="localhost.local" >
</div>
<div class="field"> <div class="field">
<label for="attribute_ssh_public_key">{{ctx.Locale.Tr "admin.auths.attribute_ssh_public_key"}}</label> <label for="attribute_ssh_public_key">{{ctx.Locale.Tr "admin.auths.attribute_ssh_public_key"}}</label>
<input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{$cfg.AttributeSSHPublicKey}}" placeholder="SshPublicKey"> <input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{$cfg.AttributeSSHPublicKey}}" placeholder="SshPublicKey">

View file

@ -71,6 +71,10 @@
<label for="attribute_mail">{{ctx.Locale.Tr "admin.auths.attribute_mail"}}</label> <label for="attribute_mail">{{ctx.Locale.Tr "admin.auths.attribute_mail"}}</label>
<input id="attribute_mail" name="attribute_mail" value="{{.attribute_mail}}" placeholder="mail"> <input id="attribute_mail" name="attribute_mail" value="{{.attribute_mail}}" placeholder="mail">
</div> </div>
<div class="field">
<label for="default_domain_name">{{ctx.Locale.Tr "admin.auths.default_domain_name"}}</label>
<input id="default_domain_name" name="default_domain_name" value="{{.default_domain_name}}" placeholder="localhost.local">
</div>
<div class="field"> <div class="field">
<label for="attribute_ssh_public_key">{{ctx.Locale.Tr "admin.auths.attribute_ssh_public_key"}}</label> <label for="attribute_ssh_public_key">{{ctx.Locale.Tr "admin.auths.attribute_ssh_public_key"}}</label>
<input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{.attribute_ssh_public_key}}" placeholder="SshPublicKey"> <input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{.attribute_ssh_public_key}}" placeholder="SshPublicKey">

View file

@ -112,13 +112,17 @@ func getLDAPServerPort() string {
return port return port
} }
func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap, groupTeamMapRemoval string) map[string]string { func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, mailKeyAttribute, defaultDomainName, groupFilter, groupTeamMap, groupTeamMapRemoval string) map[string]string {
// Modify user filter to test group filter explicitly // Modify user filter to test group filter explicitly
userFilter := "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))" userFilter := "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))"
if groupFilter != "" { if groupFilter != "" {
userFilter = "(&(objectClass=inetOrgPerson)(uid=%s))" userFilter = "(&(objectClass=inetOrgPerson)(uid=%s))"
} }
if len(mailKeyAttribute) == 0 {
mailKeyAttribute = "mail"
}
return map[string]string{ return map[string]string{
"_csrf": csrf, "_csrf": csrf,
"type": "2", "type": "2",
@ -134,8 +138,9 @@ func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap
"attribute_username": "uid", "attribute_username": "uid",
"attribute_name": "givenName", "attribute_name": "givenName",
"attribute_surname": "sn", "attribute_surname": "sn",
"attribute_mail": "mail", "attribute_mail": mailKeyAttribute,
"attribute_ssh_public_key": sshKeyAttribute, "attribute_ssh_public_key": sshKeyAttribute,
"default_domain_name": defaultDomainName,
"is_sync_enabled": "on", "is_sync_enabled": "on",
"is_active": "on", "is_active": "on",
"groups_enabled": "on", "groups_enabled": "on",
@ -148,7 +153,7 @@ func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap
} }
} }
func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, groupFilter string, groupMapParams ...string) { func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, mailKeyAttribute, defaultDomainName, groupFilter string, groupMapParams ...string) {
groupTeamMapRemoval := "off" groupTeamMapRemoval := "off"
groupTeamMap := "" groupTeamMap := ""
if len(groupMapParams) == 2 { if len(groupMapParams) == 2 {
@ -157,7 +162,7 @@ func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, groupFilter string, groupM
} }
session := loginUser(t, "user1") session := loginUser(t, "user1")
csrf := GetCSRF(t, session, "/admin/auths/new") csrf := GetCSRF(t, session, "/admin/auths/new")
req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap, groupTeamMapRemoval)) req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, mailKeyAttribute, defaultDomainName, groupFilter, groupTeamMap, groupTeamMapRemoval))
session.MakeRequest(t, req, http.StatusSeeOther) session.MakeRequest(t, req, http.StatusSeeOther)
} }
@ -167,7 +172,7 @@ func TestLDAPUserSignin(t *testing.T) {
return return
} }
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "") addAuthSourceLDAP(t, "", "", "", "")
u := gitLDAPUsers[0] u := gitLDAPUsers[0]
@ -184,7 +189,7 @@ func TestLDAPUserSignin(t *testing.T) {
func TestLDAPAuthChange(t *testing.T) { func TestLDAPAuthChange(t *testing.T) {
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "") addAuthSourceLDAP(t, "", "", "", "")
session := loginUser(t, "user1") session := loginUser(t, "user1")
req := NewRequest(t, "GET", "/admin/auths") req := NewRequest(t, "GET", "/admin/auths")
@ -205,7 +210,7 @@ func TestLDAPAuthChange(t *testing.T) {
binddn, _ := doc.Find(`input[name="bind_dn"]`).Attr("value") binddn, _ := doc.Find(`input[name="bind_dn"]`).Attr("value")
assert.Equal(t, "uid=gitea,ou=service,dc=planetexpress,dc=com", binddn) assert.Equal(t, "uid=gitea,ou=service,dc=planetexpress,dc=com", binddn)
req = NewRequestWithValues(t, "POST", href, buildAuthSourceLDAPPayload(csrf, "", "", "", "off")) req = NewRequestWithValues(t, "POST", href, buildAuthSourceLDAPPayload(csrf, "", "", "", "", "", "off"))
session.MakeRequest(t, req, http.StatusSeeOther) session.MakeRequest(t, req, http.StatusSeeOther)
req = NewRequest(t, "GET", href) req = NewRequest(t, "GET", href)
@ -215,6 +220,21 @@ func TestLDAPAuthChange(t *testing.T) {
assert.Equal(t, host, getLDAPServerHost()) assert.Equal(t, host, getLDAPServerHost())
binddn, _ = doc.Find(`input[name="bind_dn"]`).Attr("value") binddn, _ = doc.Find(`input[name="bind_dn"]`).Attr("value")
assert.Equal(t, "uid=gitea,ou=service,dc=planetexpress,dc=com", binddn) assert.Equal(t, "uid=gitea,ou=service,dc=planetexpress,dc=com", binddn)
domainname, _ := doc.Find(`input[name="default_domain_name"]`).Attr("value")
assert.Equal(t, "", domainname)
req = NewRequestWithValues(t, "POST", href, buildAuthSourceLDAPPayload(csrf, "", "", "test.org", "", "", "off"))
session.MakeRequest(t, req, http.StatusSeeOther)
req = NewRequest(t, "GET", href)
resp = session.MakeRequest(t, req, http.StatusOK)
doc = NewHTMLParser(t, resp.Body)
host, _ = doc.Find(`input[name="host"]`).Attr("value")
assert.Equal(t, host, getLDAPServerHost())
binddn, _ = doc.Find(`input[name="bind_dn"]`).Attr("value")
assert.Equal(t, "uid=gitea,ou=service,dc=planetexpress,dc=com", binddn)
domainname, _ = doc.Find(`input[name="default_domain_name"]`).Attr("value")
assert.Equal(t, "test.org", domainname)
} }
func TestLDAPUserSync(t *testing.T) { func TestLDAPUserSync(t *testing.T) {
@ -223,7 +243,7 @@ func TestLDAPUserSync(t *testing.T) {
return return
} }
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "") addAuthSourceLDAP(t, "", "", "", "")
auth.SyncExternalUsers(context.Background(), true) auth.SyncExternalUsers(context.Background(), true)
// Check if users exists // Check if users exists
@ -252,7 +272,7 @@ func TestLDAPUserSyncWithEmptyUsernameAttribute(t *testing.T) {
session := loginUser(t, "user1") session := loginUser(t, "user1")
csrf := GetCSRF(t, session, "/admin/auths/new") csrf := GetCSRF(t, session, "/admin/auths/new")
payload := buildAuthSourceLDAPPayload(csrf, "", "", "", "") payload := buildAuthSourceLDAPPayload(csrf, "", "", "", "", "", "")
payload["attribute_username"] = "" payload["attribute_username"] = ""
req := NewRequestWithValues(t, "POST", "/admin/auths/new", payload) req := NewRequestWithValues(t, "POST", "/admin/auths/new", payload)
session.MakeRequest(t, req, http.StatusSeeOther) session.MakeRequest(t, req, http.StatusSeeOther)
@ -300,7 +320,7 @@ func TestLDAPUserSyncWithGroupFilter(t *testing.T) {
return return
} }
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "(cn=git)") addAuthSourceLDAP(t, "", "", "", "(cn=git)")
// Assert a user not a member of the LDAP group "cn=git" cannot login // Assert a user not a member of the LDAP group "cn=git" cannot login
// This test may look like TestLDAPUserSigninFailed but it is not. // This test may look like TestLDAPUserSigninFailed but it is not.
@ -359,7 +379,7 @@ func TestLDAPUserSigninFailed(t *testing.T) {
return return
} }
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "") addAuthSourceLDAP(t, "", "", "", "")
u := otherLDAPUsers[0] u := otherLDAPUsers[0]
testLoginFailed(t, u.UserName, u.Password, translation.NewLocale("en-US").TrString("form.username_password_incorrect")) testLoginFailed(t, u.UserName, u.Password, translation.NewLocale("en-US").TrString("form.username_password_incorrect"))
@ -371,7 +391,7 @@ func TestLDAPUserSSHKeySync(t *testing.T) {
return return
} }
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "sshPublicKey", "") addAuthSourceLDAP(t, "sshPublicKey", "", "", "")
auth.SyncExternalUsers(context.Background(), true) auth.SyncExternalUsers(context.Background(), true)
@ -404,7 +424,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) {
return return
} }
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "", "on", `{"cn=ship_crew,ou=people,dc=planetexpress,dc=com":{"org26": ["team11"]},"cn=admin_staff,ou=people,dc=planetexpress,dc=com": {"non-existent": ["non-existent"]}}`) addAuthSourceLDAP(t, "", "", "", "", "on", `{"cn=ship_crew,ou=people,dc=planetexpress,dc=com":{"org26": ["team11"]},"cn=admin_staff,ou=people,dc=planetexpress,dc=com": {"non-existent": ["non-existent"]}}`)
org, err := organization.GetOrgByName(db.DefaultContext, "org26") org, err := organization.GetOrgByName(db.DefaultContext, "org26")
assert.NoError(t, err) assert.NoError(t, err)
team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11") team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11")
@ -449,7 +469,7 @@ func TestLDAPGroupTeamSyncRemoveMember(t *testing.T) {
return return
} }
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "", "on", `{"cn=dispatch,ou=people,dc=planetexpress,dc=com": {"org26": ["team11"]}}`) addAuthSourceLDAP(t, "", "", "", "", "on", `{"cn=dispatch,ou=people,dc=planetexpress,dc=com": {"org26": ["team11"]}}`)
org, err := organization.GetOrgByName(db.DefaultContext, "org26") org, err := organization.GetOrgByName(db.DefaultContext, "org26")
assert.NoError(t, err) assert.NoError(t, err)
team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11") team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11")
@ -487,6 +507,58 @@ func TestLDAPPreventInvalidGroupTeamMap(t *testing.T) {
session := loginUser(t, "user1") session := loginUser(t, "user1")
csrf := GetCSRF(t, session, "/admin/auths/new") csrf := GetCSRF(t, session, "/admin/auths/new")
req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, "", "", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`, "off")) req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, "", "", "", "", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`, "off"))
session.MakeRequest(t, req, http.StatusOK) // StatusOK = failed, StatusSeeOther = ok session.MakeRequest(t, req, http.StatusOK) // StatusOK = failed, StatusSeeOther = ok
} }
func TestLDAPUserSyncInvalidMail(t *testing.T) {
if skipLDAPTests() {
t.Skip()
return
}
defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "nonexisting", "", "")
auth.SyncExternalUsers(context.Background(), true)
// Check if users exists
for _, gitLDAPUser := range gitLDAPUsers {
dbUser, err := user_model.GetUserByName(db.DefaultContext, gitLDAPUser.UserName)
assert.NoError(t, err)
assert.Equal(t, gitLDAPUser.UserName, dbUser.Name)
assert.Equal(t, gitLDAPUser.UserName+"@localhost.local", dbUser.Email)
assert.Equal(t, gitLDAPUser.IsAdmin, dbUser.IsAdmin)
assert.Equal(t, gitLDAPUser.IsRestricted, dbUser.IsRestricted)
}
// Check if no users exist
for _, otherLDAPUser := range otherLDAPUsers {
_, err := user_model.GetUserByName(db.DefaultContext, otherLDAPUser.UserName)
assert.True(t, user_model.IsErrUserNotExist(err))
}
}
func TestLDAPUserSyncInvalidMailDefaultDomain(t *testing.T) {
if skipLDAPTests() {
t.Skip()
return
}
defer tests.PrepareTestEnv(t)()
addAuthSourceLDAP(t, "", "nonexisting", "test.org", "")
auth.SyncExternalUsers(context.Background(), true)
// Check if users exists
for _, gitLDAPUser := range gitLDAPUsers {
dbUser, err := user_model.GetUserByName(db.DefaultContext, gitLDAPUser.UserName)
assert.NoError(t, err)
assert.Equal(t, gitLDAPUser.UserName, dbUser.Name)
assert.Equal(t, gitLDAPUser.UserName+"@test.org", dbUser.Email)
assert.Equal(t, gitLDAPUser.IsAdmin, dbUser.IsAdmin)
assert.Equal(t, gitLDAPUser.IsRestricted, dbUser.IsRestricted)
}
// Check if no users exist
for _, otherLDAPUser := range otherLDAPUsers {
_, err := user_model.GetUserByName(db.DefaultContext, otherLDAPUser.UserName)
assert.True(t, user_model.IsErrUserNotExist(err))
}
}