Skip to content
Snippets Groups Projects

Uses organization id on Topics GraphQL

Merged Leonardo da Rosa requested to merge 463254/3-change-graphql-for-topics-api into master

What does this MR do and why?

Uses organization to query Topics through GraphQL.

Related MRs:

Step MR
1 Add organization id to topics
2 Change app and api to support organization id on topics
3 Uses organization id on Topics GraphQL - this mr
4 Update Projects Finder when finding by Topics - TBD
5 Copy project topics to organization - TBD
6 Remove the organization_id column default - TBD

How to test

1. Setup

Click to expand
  1. Enable Organizations FF
Feature.enable(:ui_for_organizations)
  1. Create a new private organization in the console
Organizations::Organization.create!(name: 'Private Organization', path: 'private-org', visibility_level: 0)
  1. Navigate to the organization page
http://gdk.test:3000/-/organizations/private-org
  1. Create a new group for the private organization. Name it my-private-org-group
http://gdk.test:3000/-/organizations/private-org/groups/new
  1. Create a new project. Select the group you created above (my-private-org-group) and name it project-from-private-org.
http://gdk.test:3000/projects/new#blank_project
  1. Create a user called private-org-user
http://gdk.test:3000/admin/users/new
  1. Navigate to my-private-org-group page and invite the user you created above. Give a maintainer role to the user
http://gdk.test:3000/groups/my-private-org-group/-/group_members
  1. Check the organization page. You must see 1 group, 1 Project and 2 Users (Admin and the newly created one)
http://gdk.test:3000/-/organizations/private-org

2. Testing changes to searchProjectTopics query

This query is used by http://gdk.test:3000/<group>/<project>/edit page.

As Admin
Click to expand
Note: Make sure you're logged in as Administrator
  1. After the setup visit the project you created for the private organization at http://gdk.test:3000/my-private-org-group/project-from-private-org/edit

  2. Search for Project Topics. As there's no topic for the current org, the search will be empty. Let's create some topics in the console:

organization = Organizations::Organization.find_by_path('private-org')

Projects::Topic.create!(name: 'private-org-first-topic', title: 'Private Organization First Topic', organization: organization)

Try to assign the topic to the project, by searching Private Organization First Topic in the search box.

  1. In the search box, add a new topic called Private Org Second Topic and Save Changes.

  2. Check the console. The organization should have two topics, as also the project:

organization.topics

[
  #<Projects::Topic:0x0000000154d9e248 name: "private-org-first-topic", >,
  #<Projects::Topic:0x0000000154d9e108 name: "Private Org Second Topic", >
]

organization.projects.map(&:topic_list)
=> [["private-org-first-topic", "Private Org Second Topic"]]
  1. Test the query using http://gdk.test:3000/-/graphql-explorer. As admin, you'll be able to query this organization topics:
# Get the private-org global id to use in GraphQL

organization.to_global_id.to_s
{
  topics(organizationId: "gid://gitlab/Organizations::Organization/1000") {
    nodes {
      id
      name
      title
    }
  }
}
{
  "data": {
    "topics": {
      "nodes": [
        {
          "id": "gid://gitlab/Projects::Topic/1",
          "name": "private-org-first-topic",
          "title": "Private Organization First Topic"
        },
        {
          "id": "gid://gitlab/Projects::Topic/2",
          "name": "Private Org Second Topic",
          "title": "Private Org Second Topic"
        }
      ]
    }
  },
  "correlationId": "01JEP9AMZG78GRRD1P8FYNFJJ9"
}
  1. If you don't specify the organizationPath, the topics from the default org will be shown:
{
  topics {
    nodes {
      id
      name
      title
    }
  }
}
{
  "data": {
    "topics": {
      "nodes": [
        {
          "id": "gid://gitlab/Projects::Topic/3",
          "name": "ruby",
          "title": "ruby"
        },
        {
          "id": "gid://gitlab/Projects::Topic/4",
          "name": "postgres",
          "title": "postgres"
        },
        {
          "id": "gid://gitlab/Projects::Topic/5",
          "name": "rspec",
          "title": "rspec"
        },
        {
          "id": "gid://gitlab/Projects::Topic/6",
          "name": "shell",
          "title": "shell"
        }
      ]
    }
  },
  "correlationId": "01JEP9EV0AVSJ9MJ5CQECTWPD0"
}
As member of the private organization (impersonating private org user)
Click to expand
  1. Navigate to http://gdk.test:3000/admin/users/private-org-user and impersonate the user.

  2. Navigate to http://gdk.test:3000/my-private-org-group/project-from-private-org/edit to edit the project. In the search box, try to search or create topics for the private organization.

  3. Test the query using http://gdk.test:3000/-/graphql-explorer. As member of private org, you'll be able to query this organization topics:

{
  topics(organizationId: "gid://gitlab/Organizations::Organization/1000") {
    nodes {
      id
      name
      title
    }
  }
}
{
  "data": {
    "topics": {
      "nodes": [
        {
          "id": "gid://gitlab/Projects::Topic/1",
          "name": "private-org-first-topic",
          "title": "Private Organization First Topic"
        },
        {
          "id": "gid://gitlab/Projects::Topic/2",
          "name": "Private Org Second Topic",
          "title": "Private Org Second Topic"
        },
        {
          "id": "gid://gitlab/Projects::Topic/7",
          "name": "Private Org Third Topic",
          "title": "Private Org Third Topic"
        }
      ]
    }
  },
  "correlationId": "01JEP9JB0T9VP96C3KH6QS9R5S"
}
  1. As the user belongs to only one org (private-org), if you don't specify the organizationPath, the topics will be fetched from private-org anyways:

NOTE: We're setting the current org per request on https://gitlab.com/gitlab-org/gitlab/blob/a58ac8fba89b62635d6fb8e7f7e1a7879bb72adc/app/controllers/application_controller.rb#L564-564

{
  topics {
    nodes {
      id
      name
      title
    }
  }
}
{
  "data": {
    "topics": {
      "nodes": [
        {
          "id": "gid://gitlab/Projects::Topic/1",
          "name": "private-org-first-topic",
          "title": "Private Organization First Topic"
        },
        {
          "id": "gid://gitlab/Projects::Topic/2",
          "name": "Private Org Second Topic",
          "title": "Private Org Second Topic"
        },
        {
          "id": "gid://gitlab/Projects::Topic/7",
          "name": "Private Org Third Topic",
          "title": "Private Org Third Topic"
        }
      ]
    }
  },
  "correlationId": "01JEPBM9CNXD6ZYTE9N0RZF3A8"
}
  1. As we also have a default public org, the user can fetch topics from this org as well:

NOTE: In case of an unauthenticated request - the request will use the fallback organization

{
  topics(organizationId: "gid://gitlab/Organizations::Organization/1000") {
    nodes {
      id
      name
      title
    }
  }
}
{
  "data": {
    "topics": {
      "nodes": [
        {
          "id": "gid://gitlab/Projects::Topic/3",
          "name": "ruby",
          "title": "ruby"
        },
        {
          "id": "gid://gitlab/Projects::Topic/4",
          "name": "postgres",
          "title": "postgres"
        },
        {
          "id": "gid://gitlab/Projects::Topic/5",
          "name": "rspec",
          "title": "rspec"
        },
        {
          "id": "gid://gitlab/Projects::Topic/6",
          "name": "shell",
          "title": "shell"
        }
      ]
    }
  },
  "correlationId": "01JEPBXEGJ1JK968BAACW30BNR"
}
As member of the public organization only
Click to expand
  1. Stop impersonating the private-org user and navigate to http://gdk.test:3000/admin/users. Impersonate any member who doesn't belong to private-org that's not an admin.

  2. Test the query using http://gdk.test:3000/-/graphql-explorer. As this is not a member of the private org, you'll not be able to query private-org topics:

{
  topics(organizationPath: "private-org") {
    nodes {
      id
      name
      title
    }
  }
}
{
  "errors": [
    {
      "graphQLErrors": [
        {
          "message": "The resource that you are attempting to access does not exist or you don't have permission to perform this action",
          "locations": [
            {
              "line": 2,
              "column": 3
            }
          ],
          "path": [
            "topics"
          ]
        }
      ],
      "clientErrors": [],
      "networkError": null,
      "message": "The resource that you are attempting to access does not exist or you don't have permission to perform this action",
      "stack": ".."
    }
  ]
}
  1. Only topics from public org can be searched:
{
  topics {
    nodes {
      id
      name
      title
    }
  }
}

OR

{
  topics(organizationId: "gid://gitlab/Organizations::Organization/1") {
    nodes {
      id
      name
      title
    }
  }
}
{
  "data": {
    "topics": {
      "nodes": [
        {
          "id": "gid://gitlab/Projects::Topic/3",
          "name": "ruby",
          "title": "ruby"
        },
        {
          "id": "gid://gitlab/Projects::Topic/4",
          "name": "postgres",
          "title": "postgres"
        },
        {
          "id": "gid://gitlab/Projects::Topic/5",
          "name": "rspec",
          "title": "rspec"
        },
        {
          "id": "gid://gitlab/Projects::Topic/6",
          "name": "shell",
          "title": "shell"
        }
      ]
    }
  },
  "correlationId": "01JEPC9NC6B8DGWXJVHC9YD4TJ"
}
Querying without an unauthenticated user
Click to expand
  1. In a new private browser window, go to http://gdk.test:3000/-/graphql-explorer

  2. Try to query private-org topics:

{
  topics(organizationId: "gid://gitlab/Organizations::Organization/1000") {
    nodes {
      id
      name
      title
    }
  }
}
{
  "errors": [
    {
      "graphQLErrors": [
        {
          "message": "The resource that you are attempting to access does not exist or you don't have permission to perform this action",
          "locations": [
            {
              "line": 2,
              "column": 3
            }
          ],
          "path": [
            "topics"
          ]
        }
      ],
      "clientErrors": [],
      "networkError": null,
      "message": "The resource that you are attempting to access does not exist or you don't have permission to perform this action",
      "stack": ".."
    }
  ]
}
  1. Only topics from public org can be searched:
{
  topics {
    nodes {
      id
      name
      title
    }
  }
}

OR

{
  topics(organizationId: "gid://gitlab/Organizations::Organization/1") {
    nodes {
      id
      name
      title
    }
  }
}
{
  "data": {
    "topics": {
      "nodes": [
        {
          "id": "gid://gitlab/Projects::Topic/3",
          "name": "ruby",
          "title": "ruby"
        },
        {
          "id": "gid://gitlab/Projects::Topic/4",
          "name": "postgres",
          "title": "postgres"
        },
        {
          "id": "gid://gitlab/Projects::Topic/5",
          "name": "rspec",
          "title": "rspec"
        },
        {
          "id": "gid://gitlab/Projects::Topic/6",
          "name": "shell",
          "title": "shell"
        }
      ]
    }
  },
  "correlationId": "01JEPCD9AKTWD6MMYVTE7DEE1M"
}
  1. You can test the same using CURL
curl "http://gdk.test:3000/api/graphql" --header "Content-Type: application/json" --request POST --data "{\"query\": \"{ topics { nodes { id name title } } }\"}"

{"data":{"topics":{"nodes":[{"id":"gid://gitlab/Projects::Topic/3","name":"ruby","title":"ruby"},{"id":"gid://gitlab/Projects::Topic/4","name":"postgres","title":"postgres"},{"id":"gid://gitlab/Projects::Topic/5","name":"rspec","title":"rspec"},{"id":"gid://gitlab/Projects::Topic/6","name":"shell","title":"shell"}]}}}%

3. Testing Explore topics

As we can't switch organizations in the dashboard, topics from http://gdk.test:3000/explore/projects/topics will use the default organization.

Click to expand
  1. Go to http://gdk.test:3000/explore/projects/topics
  2. Check that no topics from the private-org are shown. The search only shows topics from the default org.

4. Testing Admin topics

As we can't switch organizations in the dashboard, topics shown, created or merged at http://gdk.test:3000/admin/topics will use the default organization.

Click to expand
  1. Make sure you're logged in as Admin
  2. Go to http://gdk.test:3000/admin/topics
  3. Check that no topics from the private-org are shown. The search only shows topics from the default org.
  4. Try to merge two topics. Only topics belonging to the same organization can be merged. The merge search-boxes should also show only topics from the default organization
  5. Try to create a new topic. The topic will be associated with the default organization. You can check in the console through Projects::Topic
Edited by Leonardo da Rosa

Merge request reports

Merge train pipeline #1592965462 passed

Merge train pipeline passed for b11905a6

Approval is optional

Merged by Drew BlessingDrew Blessing 3 months ago (Dec 17, 2024 6:23pm UTC)

Merge details

  • Changes merged into master with a0b93a58 (commits were squashed).
  • Deleted the source branch.
  • Auto-merge enabled

Pipeline #1592966321 passed

Pipeline passed for a0b93a58 on master

10 environments impacted.

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
  • Ghost User
  • Ghost User
  • 2 Warnings
    :warning: This MR changes code in ee/, but its Changelog commit is missing the EE: true trailer. Consider adding it to your Changelog commits.
    :warning: This merge request does not refer to an existing milestone.
    1 Message
    :book: This merge request adds or changes documentation files. A review from the Technical Writing team before you merge is recommended. Reviews can happen after you merge.

    Documentation review

    The following files require a review from a technical writer:

    The review does not need to block merging this merge request. See the:

    Multiversion compatibility

    This merge request updates GraphQL backend and frontend code.

    To prevent an incident, ensure the updated frontend code is backwards compatible.

    For more information, see the multiversion compatibility documentation.

    Reviewer roulette

    Category Reviewer Maintainer
    backend @qzhaogitlab profile link current availability (UTC+11, 14 hours ahead of author) @reprazent profile link current availability (UTC+1, 4 hours ahead of author)
    frontend @leetickett-gitlab profile link current availability (UTC+0, 3 hours ahead of author) @mfluharty profile link current availability (UTC+0, 3 hours ahead of author)
    groupauthentication Reviewer review is optional for groupauthentication @atevans profile link current availability (UTC-8, 5 hours behind author)

    Please refer to documentation page for guidance on how you can benefit from the Reviewer Roulette, or use the GitLab Review Workload Dashboard to find other available reviewers.

    If needed, you can retry the :repeat: danger-review job that generated this comment.

    Generated by :no_entry_sign: Danger

    Edited by Ghost User
  • added 1 commit

    Compare with previous version

  • Leonardo da Rosa changed the description

    changed the description

  • Leonardo da Rosa changed the description

    changed the description

  • 🤖 GitLab Bot 🤖 resolved all threads

    resolved all threads

  • Leonardo da Rosa changed the description

    changed the description

  • @fernanda.toledo, can you take the initial frontend review? :bow:

    @rutgerwessels can you take the initial backend review? :bow:

    /cc follow-up from !165066 (merged)

  • requested review from @fernanda.toledo

  • requested review from @rutgerwessels

  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Loading
  • Please register or sign in to reply
    Loading