Skip to content

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

  1. The wiki_access_level=disabled field is set via ProjectFeaturesCompatibility#wiki_access_level=. wiki_access_level lives on ProjectFeature, and is a delegated property from Project.
  2. The deprecated wiki_enabled boolean property "shadows" this field, so if it is true, wiki_access_level gets set to enabled, via ProjectFeaturesCompatibility#wiki_enabled=.
  3. Both of these fields have a default_value_for specified in their models.
  4. The default value for wiki_enabled is true (based on the default config from gitlab.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.

wiki_access_gitlab

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.

Edited by Christina Lohr