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