code.gitea.io/gitea@v1.21.7/tests/integration/api_repo_get_contents_test.go (about)

     1  // Copyright 2019 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package integration
     5  
     6  import (
     7  	"io"
     8  	"net/http"
     9  	"net/url"
    10  	"testing"
    11  
    12  	auth_model "code.gitea.io/gitea/models/auth"
    13  	repo_model "code.gitea.io/gitea/models/repo"
    14  	"code.gitea.io/gitea/models/unittest"
    15  	user_model "code.gitea.io/gitea/models/user"
    16  	"code.gitea.io/gitea/modules/git"
    17  	"code.gitea.io/gitea/modules/setting"
    18  	api "code.gitea.io/gitea/modules/structs"
    19  	repo_service "code.gitea.io/gitea/services/repository"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  )
    23  
    24  func getExpectedContentsResponseForContents(ref, refType, lastCommitSHA string) *api.ContentsResponse {
    25  	treePath := "README.md"
    26  	sha := "4b4851ad51df6a7d9f25c979345979eaeb5b349f"
    27  	encoding := "base64"
    28  	content := "IyByZXBvMQoKRGVzY3JpcHRpb24gZm9yIHJlcG8x"
    29  	selfURL := setting.AppURL + "api/v1/repos/user2/repo1/contents/" + treePath + "?ref=" + ref
    30  	htmlURL := setting.AppURL + "user2/repo1/src/" + refType + "/" + ref + "/" + treePath
    31  	gitURL := setting.AppURL + "api/v1/repos/user2/repo1/git/blobs/" + sha
    32  	downloadURL := setting.AppURL + "user2/repo1/raw/" + refType + "/" + ref + "/" + treePath
    33  	return &api.ContentsResponse{
    34  		Name:          treePath,
    35  		Path:          treePath,
    36  		SHA:           sha,
    37  		LastCommitSHA: lastCommitSHA,
    38  		Type:          "file",
    39  		Size:          30,
    40  		Encoding:      &encoding,
    41  		Content:       &content,
    42  		URL:           &selfURL,
    43  		HTMLURL:       &htmlURL,
    44  		GitURL:        &gitURL,
    45  		DownloadURL:   &downloadURL,
    46  		Links: &api.FileLinksResponse{
    47  			Self:    &selfURL,
    48  			GitURL:  &gitURL,
    49  			HTMLURL: &htmlURL,
    50  		},
    51  	}
    52  }
    53  
    54  func TestAPIGetContents(t *testing.T) {
    55  	onGiteaRun(t, testAPIGetContents)
    56  }
    57  
    58  func testAPIGetContents(t *testing.T, u *url.URL) {
    59  	/*** SETUP ***/
    60  	user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})         // owner of the repo1 & repo16
    61  	org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})          // owner of the repo3, is an org
    62  	user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})         // owner of neither repos
    63  	repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})   // public repo
    64  	repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})   // public repo
    65  	repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo
    66  	treePath := "README.md"
    67  
    68  	// Get user2's token
    69  	session := loginUser(t, user2.Name)
    70  	token2 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
    71  	// Get user4's token
    72  	session = loginUser(t, user4.Name)
    73  	token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
    74  
    75  	// Get the commit ID of the default branch
    76  	gitRepo, err := git.OpenRepository(git.DefaultContext, repo1.RepoPath())
    77  	assert.NoError(t, err)
    78  	defer gitRepo.Close()
    79  
    80  	// Make a new branch in repo1
    81  	newBranch := "test_branch"
    82  	err = repo_service.CreateNewBranch(git.DefaultContext, user2, repo1, gitRepo, repo1.DefaultBranch, newBranch)
    83  	assert.NoError(t, err)
    84  
    85  	commitID, err := gitRepo.GetBranchCommitID(repo1.DefaultBranch)
    86  	assert.NoError(t, err)
    87  	// Make a new tag in repo1
    88  	newTag := "test_tag"
    89  	err = gitRepo.CreateTag(newTag, commitID)
    90  	assert.NoError(t, err)
    91  	/*** END SETUP ***/
    92  
    93  	// ref is default ref
    94  	ref := repo1.DefaultBranch
    95  	refType := "branch"
    96  	req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
    97  	resp := MakeRequest(t, req, http.StatusOK)
    98  	var contentsResponse api.ContentsResponse
    99  	DecodeJSON(t, resp, &contentsResponse)
   100  	assert.NotNil(t, contentsResponse)
   101  	lastCommit, _ := gitRepo.GetCommitByPath("README.md")
   102  	expectedContentsResponse := getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String())
   103  	assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
   104  
   105  	// No ref
   106  	refType = "branch"
   107  	req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath)
   108  	resp = MakeRequest(t, req, http.StatusOK)
   109  	DecodeJSON(t, resp, &contentsResponse)
   110  	assert.NotNil(t, contentsResponse)
   111  	expectedContentsResponse = getExpectedContentsResponseForContents(repo1.DefaultBranch, refType, lastCommit.ID.String())
   112  	assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
   113  
   114  	// ref is the branch we created above  in setup
   115  	ref = newBranch
   116  	refType = "branch"
   117  	req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
   118  	resp = MakeRequest(t, req, http.StatusOK)
   119  	DecodeJSON(t, resp, &contentsResponse)
   120  	assert.NotNil(t, contentsResponse)
   121  	branchCommit, _ := gitRepo.GetBranchCommit(ref)
   122  	lastCommit, _ = branchCommit.GetCommitByPath("README.md")
   123  	expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String())
   124  	assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
   125  
   126  	// ref is the new tag we created above in setup
   127  	ref = newTag
   128  	refType = "tag"
   129  	req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
   130  	resp = MakeRequest(t, req, http.StatusOK)
   131  	DecodeJSON(t, resp, &contentsResponse)
   132  	assert.NotNil(t, contentsResponse)
   133  	tagCommit, _ := gitRepo.GetTagCommit(ref)
   134  	lastCommit, _ = tagCommit.GetCommitByPath("README.md")
   135  	expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, lastCommit.ID.String())
   136  	assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
   137  
   138  	// ref is a commit
   139  	ref = commitID
   140  	refType = "commit"
   141  	req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
   142  	resp = MakeRequest(t, req, http.StatusOK)
   143  	DecodeJSON(t, resp, &contentsResponse)
   144  	assert.NotNil(t, contentsResponse)
   145  	expectedContentsResponse = getExpectedContentsResponseForContents(ref, refType, commitID)
   146  	assert.EqualValues(t, *expectedContentsResponse, contentsResponse)
   147  
   148  	// Test file contents a file with a bad ref
   149  	ref = "badref"
   150  	req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref)
   151  	MakeRequest(t, req, http.StatusNotFound)
   152  
   153  	// Test accessing private ref with user token that does not have access - should fail
   154  	req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4)
   155  	MakeRequest(t, req, http.StatusNotFound)
   156  
   157  	// Test access private ref of owner of token
   158  	req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/readme.md?token=%s", user2.Name, repo16.Name, token2)
   159  	MakeRequest(t, req, http.StatusOK)
   160  
   161  	// Test access of org org3 private repo file by owner user2
   162  	req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?token=%s", org3.Name, repo3.Name, treePath, token2)
   163  	MakeRequest(t, req, http.StatusOK)
   164  }
   165  
   166  func TestAPIGetContentsRefFormats(t *testing.T) {
   167  	onGiteaRun(t, func(t *testing.T, u *url.URL) {
   168  		file := "README.md"
   169  		sha := "65f1bf27bc3bf70f64657658635e66094edbcb4d"
   170  		content := "# repo1\n\nDescription for repo1"
   171  
   172  		noRef := setting.AppURL + "api/v1/repos/user2/repo1/raw/" + file
   173  		refInPath := setting.AppURL + "api/v1/repos/user2/repo1/raw/" + sha + "/" + file
   174  		refInQuery := setting.AppURL + "api/v1/repos/user2/repo1/raw/" + file + "?ref=" + sha
   175  
   176  		resp := MakeRequest(t, NewRequest(t, http.MethodGet, noRef), http.StatusOK)
   177  		raw, err := io.ReadAll(resp.Body)
   178  		assert.NoError(t, err)
   179  		assert.EqualValues(t, content, string(raw))
   180  
   181  		resp = MakeRequest(t, NewRequest(t, http.MethodGet, refInPath), http.StatusOK)
   182  		raw, err = io.ReadAll(resp.Body)
   183  		assert.NoError(t, err)
   184  		assert.EqualValues(t, content, string(raw))
   185  
   186  		resp = MakeRequest(t, NewRequest(t, http.MethodGet, refInQuery), http.StatusOK)
   187  		raw, err = io.ReadAll(resp.Body)
   188  		assert.NoError(t, err)
   189  		assert.EqualValues(t, content, string(raw))
   190  	})
   191  }