apache / incubator-devlake

Apache DevLake is an open-source dev data platform to ingest, analyze, and visualize the fragmented data from DevOps tools, extracting insights for engineering excellence, developer experience, and community growth.
https://devlake.apache.org/
Apache License 2.0
2.5k stars 493 forks source link

[Bug][CircleCI] It is possible to PUT a scope with an empty Id field #7651

Open jensrotne opened 1 week ago

jensrotne commented 1 week ago

Search before asking

What happened

It's possible to POST a CircleCI scope to the PUT /api/plugins/circleci/{connection_id}/scopes endpoint with an empty Id.

This causes an issue where if you forget to include the Id then it will not notify you about it being empty, and if you do this multiple times, then it will override the existing scope.

What do you expect to happen

To atleast notify you if the Id field in the PUT request body is empty.

How to reproduce

Try to PUT a CircleCI scope using the API with an empty Id field in the JSON body.

Anything else

No response

Version

v1.0.0-rc1

Are you willing to submit PR?

Code of Conduct

dosubot[bot] commented 1 week ago

Hey @jensrotne! I'm here to help you with any issues, bugs, or questions you have about the project. I can also assist you in becoming a contributor. Let me know how I can assist you!

To address the issue of allowing a PUT request with an empty Id field in the PUT /api/plugins/circleci/{connection_id}/scopes endpoint, you can add a validation check in the PutScopes function. Here is an example of how you can modify the PutScopes function to include this validation:

func PutScopes(input *plugin.ApiResourceInput) (*plugin.ApiResourceOutput, errors.Error) {
    var reqBody PutScopesReqBody
    if err := json.Unmarshal(input.Body, &reqBody); err != nil {
        return nil, errors.BadInput.Wrap(err, "failed to parse request body")
    }

    // Check if the Id field is empty
    for _, project := range reqBody.Projects {
        if project.Id == "" {
            return nil, errors.BadInput.New("Id field cannot be empty")
        }
    }

    return dsHelper.ScopeApi.PutMultiple(input)
}

In this code snippet, the PutScopes function first unmarshals the request body into a PutScopesReqBody struct. It then iterates over the projects in the request body and checks if the Id field is empty. If any Id field is found to be empty, it returns a BadInput error with a message indicating that the Id field cannot be empty [1][2][3].

Additionally, you can extend the existing unit tests to cover this new validation logic. Here is an example of how you can modify the test to include a case where the Id field is empty:

func TestScopeApiHelper_Put(t *testing.T) {
    apiHelper := createMockScopeHelper[TestFakeGithubRepo]("GithubId")
    // create a mock input, scopes, and connection
    input := &plugin.ApiResourceInput{Params: map[string]string{"connectionId": "123"}, Body: map[string]interface{}{
        "data": []map[string]interface{}{
            {
                "HTMLUrl":       "string",
                "githubId":      1,
                "cloneUrl":      "string",
                "connectionId":  1,
                "createdAt":     "string",
                "createdDate":   "string",
                "description":   "string",
                "language":      "string",
                "name":          "string",
                "owner":         "string",
                "scopeConfigId": 0,
                "updatedAt":     "string",
                "updatedDate":   "string",
            },
            {
                "HTMLUrl":       "11",
                "githubId":      2,
                "cloneUrl":      "string",
                "connectionId":  1,
                "createdAt":     "string",
                "createdDate":   "string",
                "description":   "string",
                "language":      "string",
                "name":          "string",
                "owner":         "string",
                "scopeConfigId": 0,
                "updatedAt":     "string",
                "updatedDate":   "string",
            },
            {
                "HTMLUrl":       "string",
                "githubId":      "", // Invalid Id
                "cloneUrl":      "string",
                "connectionId":  1,
                "createdAt":     "string",
                "createdDate":   "string",
                "description":   "string",
                "language":      "string",
                "name":          "string",
                "owner":         "string",
                "scopeConfigId": 0,
                "updatedAt":     "string",
                "updatedDate":   "string",
            }}}}
    // test a successful call to Put
    _, err := apiHelper.Put(input)
    assert.NoError(t, err)

    // test a call to Put with invalid Id
    input.Body["data"].([]map[string]interface{})[2]["githubId"] = ""
    _, err = apiHelper.Put(input)
    assert.Error(t, err)
}

This modification adds a new test case where the githubId is set to an empty string, which should trigger the validation logic for empty Id fields and result in an error [4].

To continue talking to Dosu, mention @dosu.