Project create API does not honour access levels across multiple features
Summary
Calling the create project API with wiki_access_level=disabled
does not disable the wiki. This issue is present when setting access levels across other features as well, as described in the related issues. The fix for this should be comprehensive of all properties.
Root cause and other fields affected by this bug
This same bug also exists for the other deprecated "shadowed" fields: builds_enabled
, merge_requests_enabled
, issues_enabled
, and snippets_enabled
.
The root cause has been identified. Here's a summary of what's going on...
Recap of how to reproduce bug:
When you specify wiki_access_level=disabled
in a project create API call, it has no effect, and ends up getting set to enabled
.
Recap of relevant code
- The
wiki_access_level=disabled
field is set viaProjectFeaturesCompatibility#wiki_access_level=
.wiki_access_level
lives onProjectFeature
, and is a delegated property fromProject
. - The deprecated
wiki_enabled
boolean property "shadows" this field, so if it is true,wiki_access_level
gets set toenabled
, viaProjectFeaturesCompatibility#wiki_enabled=
. - Both of these fields have a
default_value_for
specified in their models. - The default value for
wiki_enabled
istrue
(based on the default config fromgitlab.yml
)
Cause of bug
The bug occurs because the default_value_for
for wiki_enabled
calls ProjectFeaturesCompatibility#wiki_enabled=
AFTER the specified wiki_access_level
is set based on the passed wiki_access_level=disabled
API parameter, thus overwriting the specified disabled
value and resetting it to enabled
.
Other fields affected by this bug
This same bug also exists for the other deprecated "shadowed" fields: builds_enabled
, merge_requests_enabled
, issues_enabled
, and snippets_enabled
How should we fix it?
The simplest approach seems to be to just delete all the default_value_for
declarations for the deprecated fields
This should be fine, because there's still default_value_for
entries for all the corresponding non-deprecated fields.
However, it does seem to break several tests in project_spec.rb
, so we'll have to look into whether those are real problems or just tests which need to be rewritten to account for the change.
There is an MR to work on this fix: !53204 (closed). However, it is not yet (as of 2021-02-05) clear what is the appropriate fix is - see this MR thread for a discussion of possible fixes and the associated risks and complexity.
Steps to reproduce
Using httpie(1)
run the following:
http -v POST https://gitlab.com/api/v4/projects Private-Token:XXXXXXXXXXX name=test-wiki-access-level wiki_access_level=disabled
Or using curl
:
curl --request POST --header "PRIVATE-TOKEN: XXXXXXXX" "http://localhost:3000/api/v4/projects?name=test-wiki-access-level&wiki_access_level=disabled"
Example Project
https://gitlab.com/bradwood/test-wiki-access-level (defaults to private project, but wiki access is still enabled)
What is the current bug behavior?
The project is created with the wiki_access_level
unchanged from the default of being enabled.
API response confirms this (both request and response shown below)
POST /api/v4/projects HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 67
Content-Type: application/json
Host: gitlab.com
Private-Token: XXXXXXXXXXXXXXXXXXXXXXX
User-Agent: HTTPie/2.1.0
{
"name": "test-wiki-access-level",
"wiki_access_level": "disabled"
}
HTTP/1.1 201 Created
CF-Cache-Status: DYNAMIC
CF-RAY: 59af5c7f3bb9f3e3-LHR
Cache-Control: max-age=0, private, must-revalidate
Connection: keep-alive
Content-Length: 3090
Content-Type: application/json
Date: Fri, 29 May 2020 09:59:13 GMT
Etag: W/"f60a9974058a28a3f8458b3c9b3d8174"
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
GitLab-LB: fe-08-lb-gprd
GitLab-SV: localhost
RateLimit-Limit: 600
RateLimit-Observed: 2
RateLimit-Remaining: 598
RateLimit-Reset: 1590746412
RateLimit-ResetTime: Fri, 29 May 2020 10:00:12 GMT
Referrer-Policy: strict-origin-when-cross-origin
Server: cloudflare
Set-Cookie: __cfduid=d9616937c4735355fb107ea0acde1a5081590746352; expires=Sun, 28-Jun-20 09:59:12 GMT; path=/; domain=.gitlab.com; HttpOnly; SameSite=Lax; Secure
Strict-Transport-Security: max-age=31536000
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: GwxjEzS9fC5
X-Runtime: 0.397730
cf-request-id: 03017823800000f3e3b590f200000001
{
"_links": {
"events": "https://gitlab.com/api/v4/projects/19069958/events",
"issues": "https://gitlab.com/api/v4/projects/19069958/issues",
"labels": "https://gitlab.com/api/v4/projects/19069958/labels",
"members": "https://gitlab.com/api/v4/projects/19069958/members",
"merge_requests": "https://gitlab.com/api/v4/projects/19069958/merge_requests",
"repo_branches": "https://gitlab.com/api/v4/projects/19069958/repository/branches",
"self": "https://gitlab.com/api/v4/projects/19069958"
},
"archived": false,
"auto_cancel_pending_pipelines": "enabled",
"auto_devops_deploy_strategy": "continuous",
"auto_devops_enabled": false,
"autoclose_referenced_issues": true,
"avatar_url": null,
"build_coverage_regex": null,
"build_git_strategy": "fetch",
"build_timeout": 3600,
"builds_access_level": "enabled",
"can_create_merge_request_in": true,
"ci_config_path": "",
"ci_default_git_depth": 50,
"container_expiration_policy": {
"cadence": "1d",
"enabled": true,
"keep_n": 10,
"name_regex": null,
"name_regex_keep": null,
"next_run_at": "2020-05-30T09:59:12.685Z",
"older_than": "90d"
},
"container_registry_enabled": true,
"created_at": "2020-05-29T09:59:12.660Z",
"creator_id": 747231,
"default_branch": null,
"description": null,
"emails_disabled": null,
"empty_repo": true,
"external_authorization_classification_label": "",
"forking_access_level": "enabled",
"forks_count": 0,
"http_url_to_repo": "https://gitlab.com/bradwood/test-wiki-access-level.git",
"id": 19069958,
"import_error": null,
"import_status": "none",
"issues_access_level": "enabled",
"issues_enabled": true,
"jobs_enabled": true,
"last_activity_at": "2020-05-29T09:59:12.660Z",
"lfs_enabled": true,
"merge_method": "merge",
"merge_requests_access_level": "enabled",
"merge_requests_enabled": true,
"name": "test-wiki-access-level",
"name_with_namespace": "Bradley Wood / test-wiki-access-level",
"namespace": {
"avatar_url": "/uploads/-/system/user/avatar/747231/avatar.png",
"full_path": "bradwood",
"id": 893426,
"kind": "user",
"name": "Bradley Wood",
"parent_id": null,
"path": "bradwood",
"web_url": "https://gitlab.com/bradwood"
},
"only_allow_merge_if_all_discussions_are_resolved": false,
"only_allow_merge_if_pipeline_succeeds": false,
"open_issues_count": 0,
"owner": {
"avatar_url": "https://assets.gitlab-static.net/uploads/-/system/user/avatar/747231/avatar.png",
"id": 747231,
"name": "Bradley Wood",
"state": "active",
"username": "bradwood",
"web_url": "https://gitlab.com/bradwood"
},
"pages_access_level": "private",
"path": "test-wiki-access-level",
"path_with_namespace": "bradwood/test-wiki-access-level",
"printing_merge_request_link_enabled": true,
"public_jobs": true,
"readme_url": null,
"remove_source_branch_after_merge": true,
"repository_access_level": "enabled",
"request_access_enabled": true,
"resolve_outdated_diff_discussions": false,
"runners_token": "Lyz1eodo_SXREPbysyHK",
"shared_runners_enabled": true,
"shared_with_groups": [],
"snippets_access_level": "enabled",
"snippets_enabled": true,
"ssh_url_to_repo": "git@gitlab.com:bradwood/test-wiki-access-level.git",
"star_count": 0,
"suggestion_commit_message": null,
"tag_list": [],
"visibility": "private",
"web_url": "https://gitlab.com/bradwood/test-wiki-access-level",
"wiki_access_level": "enabled",
"wiki_enabled": true
}
What is the expected correct behavior?
The wiki on the project should be disabled in the GUI and the JSON response should set both wiki_enabled
to false
and wiki_access_level
to disabled
.
Relevant logs and/or screenshots
As above
Output of checks
This happens on Gitlab.com and a hosted version of gitlab as described here
Results of GitLab environment info
N/A
Results of GitLab application Check
N/A
Possible fixes
The deprecated wiki_enabled
field does disable the wiki.
Note, I suspect this behaviour might also be exhibited for other *_access_level
fields on the create project API.