- Notifications
You must be signed in to change notification settings - Fork928
feat: delete API token in /logout API#1770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
5c062df
77880f1
994a294
094498a
eb12bee
8bb5713
fd56d39
492db6a
5fa278d
2ad0fbc
fd9231d
a49b16f
9a3731d
c38a0f5
a19e092
c82c661
a76d136
84ec351
6707efa
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
package cli_test | ||
import ( | ||
"fmt" | ||
"os" | ||
"regexp" | ||
"runtime" | ||
"testing" | ||
"github.com/stretchr/testify/assert" | ||
@@ -21,7 +24,7 @@ func TestLogout(t *testing.T) { | ||
pty := ptytest.New(t) | ||
config := login(t, pty) | ||
//Ensure session files exist. | ||
require.FileExists(t, string(config.URL())) | ||
require.FileExists(t, string(config.Session())) | ||
@@ -40,7 +43,7 @@ func TestLogout(t *testing.T) { | ||
pty.ExpectMatch("Are you sure you want to logout?") | ||
pty.WriteLine("yes") | ||
pty.ExpectMatch("You are no longerloggedin. You can log in using 'coder login <url>'.") | ||
<-logoutChan | ||
}) | ||
t.Run("SkipPrompt", func(t *testing.T) { | ||
@@ -49,7 +52,7 @@ func TestLogout(t *testing.T) { | ||
pty := ptytest.New(t) | ||
config := login(t, pty) | ||
//Ensure session files exist. | ||
require.FileExists(t, string(config.URL())) | ||
require.FileExists(t, string(config.Session())) | ||
@@ -66,7 +69,7 @@ func TestLogout(t *testing.T) { | ||
assert.NoFileExists(t, string(config.Session())) | ||
}() | ||
pty.ExpectMatch("You are no longerloggedin. You can log in using 'coder login <url>'.") | ||
<-logoutChan | ||
}) | ||
t.Run("NoURLFile", func(t *testing.T) { | ||
@@ -75,7 +78,7 @@ func TestLogout(t *testing.T) { | ||
pty := ptytest.New(t) | ||
config := login(t, pty) | ||
//Ensure session files exist. | ||
require.FileExists(t, string(config.URL())) | ||
require.FileExists(t, string(config.Session())) | ||
@@ -91,14 +94,9 @@ func TestLogout(t *testing.T) { | ||
go func() { | ||
defer close(logoutChan) | ||
err := logout.Execute() | ||
assert.EqualError(t, err, "You are not logged in. Try logging in using 'coder login <url>'.") | ||
}() | ||
<-logoutChan | ||
}) | ||
t.Run("NoSessionFile", func(t *testing.T) { | ||
@@ -107,7 +105,7 @@ func TestLogout(t *testing.T) { | ||
pty := ptytest.New(t) | ||
config := login(t, pty) | ||
//Ensure session files exist. | ||
require.FileExists(t, string(config.URL())) | ||
require.FileExists(t, string(config.Session())) | ||
@@ -123,14 +121,73 @@ func TestLogout(t *testing.T) { | ||
go func() { | ||
defer close(logoutChan) | ||
err = logout.Execute() | ||
assert.EqualError(t, err, "You are not logged in. Try logging in using 'coder login <url>'.") | ||
}() | ||
<-logoutChan | ||
}) | ||
t.Run("CannotDeleteFiles", func(t *testing.T) { | ||
t.Parallel() | ||
pty := ptytest.New(t) | ||
config := login(t, pty) | ||
// Ensure session files exist. | ||
require.FileExists(t, string(config.URL())) | ||
require.FileExists(t, string(config.Session())) | ||
var ( | ||
err error | ||
urlFile *os.File | ||
sessionFile *os.File | ||
) | ||
if runtime.GOOS == "windows" { | ||
// Opening the files so Windows does not allow deleting them. | ||
urlFile, err = os.Open(string(config.URL())) | ||
require.NoError(t, err) | ||
sessionFile, err = os.Open(string(config.Session())) | ||
require.NoError(t, err) | ||
} else { | ||
// Changing the permissions to throw error during deletion. | ||
err = os.Chmod(string(config), 0500) | ||
require.NoError(t, err) | ||
} | ||
t.Cleanup(func() { | ||
if runtime.GOOS == "windows" { | ||
// Closing the opened files for cleanup. | ||
err = urlFile.Close() | ||
require.NoError(t, err) | ||
err = sessionFile.Close() | ||
require.NoError(t, err) | ||
AbhineetJain marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
} else { | ||
// Setting the permissions back for cleanup. | ||
err = os.Chmod(string(config), 0700) | ||
require.NoError(t, err) | ||
} | ||
}) | ||
logoutChan := make(chan struct{}) | ||
logout, _ := clitest.New(t, "logout", "--global-config", string(config)) | ||
logout.SetIn(pty.Input()) | ||
logout.SetOut(pty.Output()) | ||
go func() { | ||
defer close(logoutChan) | ||
err := logout.Execute() | ||
assert.NotNil(t, err) | ||
var errorMessage string | ||
if runtime.GOOS == "windows" { | ||
errorMessage = "The process cannot access the file because it is being used by another process." | ||
} else { | ||
errorMessage = "permission denied" | ||
} | ||
errRegex := regexp.MustCompile(fmt.Sprintf("Failed to log out.\n\tremove URL file: .+: %s\n\tremove session file: .+: %s", errorMessage, errorMessage)) | ||
assert.Regexp(t, errRegex, err.Error()) | ||
}() | ||
pty.ExpectMatch("Are you sure you want to logout?") | ||
pty.WriteLine("yes") | ||
<-logoutChan | ||
}) | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -104,6 +104,10 @@ func TestAuthorizeAllEndpoints(t *testing.T) { | ||
workspaceRBACObj := rbac.ResourceWorkspace.InOrg(organization.ID).WithID(workspace.ID.String()).WithOwner(workspace.OwnerID.String()) | ||
// skipRoutes allows skipping routes from being checked. | ||
skipRoutes := map[string]string{ | ||
"POST:/api/v2/users/logout": "Logging out deletes the API Key for other routes", | ||
} | ||
AbhineetJain marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
type routeCheck struct { | ||
NoAuthorize bool | ||
AssertAction rbac.Action | ||
@@ -117,7 +121,6 @@ func TestAuthorizeAllEndpoints(t *testing.T) { | ||
"GET:/api/v2/users/first": {NoAuthorize: true}, | ||
"POST:/api/v2/users/first": {NoAuthorize: true}, | ||
"POST:/api/v2/users/login": {NoAuthorize: true}, | ||
"GET:/api/v2/users/authmethods": {NoAuthorize: true}, | ||
"POST:/api/v2/csp/reports": {NoAuthorize: true}, | ||
@@ -310,8 +313,20 @@ func TestAuthorizeAllEndpoints(t *testing.T) { | ||
assertRoute[noTrailSlash] = v | ||
} | ||
for k, v := range skipRoutes { | ||
noTrailSlash := strings.TrimRight(k, "/") | ||
if _, ok := skipRoutes[noTrailSlash]; ok && noTrailSlash != k { | ||
t.Errorf("route %q & %q is declared twice", noTrailSlash, k) | ||
t.FailNow() | ||
} | ||
skipRoutes[noTrailSlash] = v | ||
} | ||
err = chi.Walk(api.Handler, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { | ||
name := method + ":" + route | ||
if _, ok := skipRoutes[strings.TrimRight(name, "/")]; ok { | ||
return nil | ||
} | ||
t.Run(name, func(t *testing.T) { | ||
authorizer.reset() | ||
routeAssertions, ok := assertRoute[strings.TrimRight(name, "/")] | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -126,6 +126,21 @@ func (q *fakeQuerier) GetAPIKeyByID(_ context.Context, id string) (database.APIK | ||
return database.APIKey{}, sql.ErrNoRows | ||
} | ||
func (q *fakeQuerier) DeleteAPIKeyByID(_ context.Context, id string) error { | ||
q.mutex.Lock() | ||
defer q.mutex.Unlock() | ||
for index, apiKey := range q.apiKeys { | ||
if apiKey.ID != id { | ||
continue | ||
} | ||
q.apiKeys[index] = q.apiKeys[len(q.apiKeys)-1] | ||
q.apiKeys = q.apiKeys[:len(q.apiKeys)-1] | ||
return nil | ||
} | ||
AbhineetJain marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
return sql.ErrNoRows | ||
} | ||
func (q *fakeQuerier) GetFileByHash(_ context.Context, hash string) (database.File, error) { | ||
q.mutex.RLock() | ||
defer q.mutex.RUnlock() | ||
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.
Uh oh!
There was an error while loading.Please reload this page.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -38,3 +38,10 @@ SET | ||
oauth_expiry = $6 | ||
WHERE | ||
id = $1; | ||
-- name: DeleteAPIKeyByID :exec | ||
DELETE | ||
FROM | ||
api_keys | ||
WHERE | ||
id = $1; |
Uh oh!
There was an error while loading.Please reload this page.