Skip to content

Commit

Permalink
Test the Authenticate function (#38)
Browse files Browse the repository at this point in the history
* Add a test - not working

* Mock inner functions

* Add more test cases

* Add new line

* Return different values from the the 2 mocks
  • Loading branch information
kavir1698 authored May 16, 2024
1 parent 93dd6a3 commit 44c353f
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 11 deletions.
3 changes: 2 additions & 1 deletion cmd/datasetArchiver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ func main() {
inputdatasetList = args[0:]
}

user, _ := datasetUtils.Authenticate(client, APIServer, token, userpass)
auth := &datasetUtils.RealAuthenticator{}
user, _ := datasetUtils.Authenticate(auth, client, APIServer, token, userpass)

archivableDatasets := datasetUtils.GetArchivableDatasets(client, APIServer, ownerGroup, inputdatasetList, user["accessToken"])
if len(archivableDatasets) > 0 {
Expand Down
3 changes: 2 additions & 1 deletion cmd/datasetCleaner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ func main() {
return
}

user, _ := datasetUtils.Authenticate(client, APIServer, token, userpass)
auth := &datasetUtils.RealAuthenticator{}
user, _ := datasetUtils.Authenticate(auth, client, APIServer, token, userpass)

if user["username"] != "archiveManager" {
log.Fatalf("You must be archiveManager to be allowed to delete datasets\n")
Expand Down
3 changes: 2 additions & 1 deletion cmd/datasetGetProposal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ func main() {
return
}

user, accessGroups := datasetUtils.Authenticate(client, APIServer, token, userpass)
auth := &datasetUtils.RealAuthenticator{}
user, accessGroups := datasetUtils.Authenticate(auth, client, APIServer, token, userpass)
proposal := datasetUtils.GetProposal(client, APIServer, ownerGroup, user, accessGroups)
// proposal is of type map[string]interface{}

Expand Down
3 changes: 2 additions & 1 deletion cmd/datasetIngestor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ func main() {
return
}

user, accessGroups := datasetUtils.Authenticate(client, APIServer, token, userpass)
auth := &datasetUtils.RealAuthenticator{}
user, accessGroups := datasetUtils.Authenticate(auth, client, APIServer, token, userpass)

/* TODO Add info about policy settings and that autoarchive will take place or not */

Expand Down
3 changes: 2 additions & 1 deletion cmd/datasetPublishData/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ func createWebpage(urls []string, title string, doi string, datasetDetails []dat

// set value in publishedData ==============================

user, _ := datasetUtils.Authenticate(client, APIServer, token, userpass)
auth := &datasetUtils.RealAuthenticator{}
user, _ := datasetUtils.Authenticate(auth, client, APIServer, token, userpass)

type PublishedDataPart struct {
DownloadLink string `json:"downloadLink"`
Expand Down
3 changes: 2 additions & 1 deletion cmd/datasetPublishDataRetrieve/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ func main() {
return
}

user, _ := datasetUtils.Authenticate(client, APIServer, token, userpass)
auth := &datasetUtils.RealAuthenticator{}
user, _ := datasetUtils.Authenticate(auth, client, APIServer, token, userpass)

datasetList, _, _ := datasetUtils.GetDatasetsOfPublication(client, APIServer, *publishedDataId)

Expand Down
3 changes: 2 additions & 1 deletion cmd/datasetRetriever/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ func main() {
return
}

user, _ := datasetUtils.Authenticate(client, APIServer, token, userpass)
auth := &datasetUtils.RealAuthenticator{}
user, _ := datasetUtils.Authenticate(auth, client, APIServer, token, userpass)

datasetList := datasetUtils.GetAvailableDatasets(user["username"], RSYNCServer, *datasetId)

Expand Down
3 changes: 2 additions & 1 deletion cmd/waitForJobFinished/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ func main() {
return
}

user, _ := datasetUtils.Authenticate(client, APIServer, token, userpass)
auth := &datasetUtils.RealAuthenticator{}
user, _ := datasetUtils.Authenticate(auth, client, APIServer, token, userpass)

filter := `{"where":{"id":"` + *jobId + `"}}`

Expand Down
27 changes: 24 additions & 3 deletions datasetUtils/authenticate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import (
"syscall"
)

func Authenticate(httpClient *http.Client, APIServer string, token *string, userpass *string) (map[string]string, []string) {
// Authenticate handles user authentication by prompting the user for their credentials,
// validating these credentials against the authentication server,
// and returning an authentication token if the credentials are valid.
// This token can then be used for authenticated requests to the server.
// If the credentials are not valid, the function returns an error.
func Authenticate(auth Authenticator, httpClient *http.Client, APIServer string, token *string, userpass *string) (map[string]string, []string) {
user := make(map[string]string)
accessGroups := make([]string, 0)

Expand Down Expand Up @@ -37,9 +42,9 @@ func Authenticate(httpClient *http.Client, APIServer string, token *string, user
}
username = strings.Split(*userpass, ":")[0]
}
user, accessGroups = AuthenticateUser(httpClient, APIServer, username, password)
user, accessGroups = auth.AuthenticateUser(httpClient, APIServer, username, password)
} else {
user, accessGroups = GetUserInfoFromToken(httpClient, APIServer, *token)
user, accessGroups = auth.GetUserInfoFromToken(httpClient, APIServer, *token)
// extract password if defined in userpass value
u := strings.Split(*userpass, ":")
if len(u) == 2 {
Expand All @@ -48,3 +53,19 @@ func Authenticate(httpClient *http.Client, APIServer string, token *string, user
}
return user, accessGroups
}

// An interface with the methods so that we can mock them in tests
type Authenticator interface {
AuthenticateUser(httpClient *http.Client, APIServer string, username string, password string) (map[string]string, []string)
GetUserInfoFromToken(httpClient *http.Client, APIServer string, token string) (map[string]string, []string)
}

type RealAuthenticator struct{}

func (r *RealAuthenticator) AuthenticateUser(httpClient *http.Client, APIServer string, username string, password string) (map[string]string, []string) {
return AuthenticateUser(httpClient, APIServer, username, password)
}

func (r *RealAuthenticator) GetUserInfoFromToken(httpClient *http.Client, APIServer string, token string) (map[string]string, []string) {
return GetUserInfoFromToken(httpClient, APIServer, token)
}
93 changes: 93 additions & 0 deletions datasetUtils/authenticate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package datasetUtils

import (
"net/http"
"net/http/httptest"
"reflect"
"testing"
)

// Create a mock implementation of the interface
type MockAuthenticator struct{}

func (m *MockAuthenticator) AuthenticateUser(httpClient *http.Client, APIServer string, username string, password string) (map[string]string, []string) {
if username == "" && password == "" {
return map[string]string{}, []string{}
}
return map[string]string{"username": "testuser", "password": "testpass"}, []string{"group1", "group2"}
}

func (m *MockAuthenticator) GetUserInfoFromToken(httpClient *http.Client, APIServer string, token string) (map[string]string, []string) {
return map[string]string{"username": "tokenuser", "password": "tokenpass"}, []string{"group3", "group4"}
}

func TestAuthenticate(t *testing.T) {
var auth Authenticator = &MockAuthenticator{}
// Mock HTTP server
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(`{"username": "testuser", "accessGroups": ["group1", "group2"]}`))
}))
defer server.Close()

// Test cases
tests := []struct {
name string
token string
userpass string
wantUser map[string]string
wantGroup []string
}{
{
name: "Test with token",
token: "testtoken",
userpass: "",
wantUser: map[string]string{
"username": "tokenuser",
"password": "tokenpass",
},
wantGroup: []string{"group3", "group4"},
},
{
name: "Test with empty token and userpass",
token: "",
userpass: "",
wantUser: map[string]string{},
wantGroup: []string{},
},
{
name: "Test with empty token and non-empty userpass",
token: "",
userpass: "testuser:testpass",
wantUser: map[string]string{
"username": "testuser",
"password": "testpass",
},
wantGroup: []string{"group1", "group2"},
},
{
name: "Test with non-empty token and empty userpass",
token: "testtoken",
userpass: "",
wantUser: map[string]string{
"username": "tokenuser",
"password": "tokenpass",
},
wantGroup: []string{"group3", "group4"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
httpClient := server.Client()
user, group := Authenticate(auth, httpClient, server.URL, &tt.token, &tt.userpass)

if !reflect.DeepEqual(user, tt.wantUser) {
t.Errorf("got %v, want %v", user, tt.wantUser)
}

if !reflect.DeepEqual(group, tt.wantGroup) {
t.Errorf("got %v, want %v", group, tt.wantGroup)
}
})
}
}

0 comments on commit 44c353f

Please sign in to comment.