mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
chore: move app proxying code to workspaceapps pkg (#6998)
* chore: move app proxying code to workspaceapps pkg Moves path-app, subdomain-app and reconnecting PTY proxying to the new workspaceapps.WorkspaceAppServer struct. This is in preparation for external workspace proxies. Updates app logout flow to avoid redirecting to coder-logout.${app_host} on logout. Instead, all subdomain app tokens owned by the logging-out user will be deleted every time you logout for simplicity sake. Tests will remain in their original package, pending being moved to an apptest package (or similar). Co-authored-by: Steven Masley <stevenmasley@coder.com>
This commit is contained in:
@ -22,6 +22,8 @@ import (
|
||||
"github.com/coder/coder/coderd/audit"
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/database/dbgen"
|
||||
"github.com/coder/coder/coderd/database/dbtestutil"
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/coder/coder/testutil"
|
||||
)
|
||||
@ -829,6 +831,110 @@ func TestUserOIDC(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestUserLogout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Create a custom database so it's easier to make scoped tokens for
|
||||
// testing.
|
||||
db, pubSub := dbtestutil.NewDB(t)
|
||||
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
Database: db,
|
||||
Pubsub: pubSub,
|
||||
})
|
||||
firstUser := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitLong)
|
||||
|
||||
// Create a user with built-in auth.
|
||||
const (
|
||||
email = "dean.was.here@test.coder.com"
|
||||
username = "dean"
|
||||
//nolint:gosec
|
||||
password = "SomeSecurePassword123!"
|
||||
)
|
||||
newUser, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: email,
|
||||
Username: username,
|
||||
Password: password,
|
||||
OrganizationID: firstUser.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Log in with basic auth and keep the the session token (but don't use it).
|
||||
userClient := codersdk.New(client.URL)
|
||||
loginRes1, err := userClient.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
|
||||
Email: email,
|
||||
Password: password,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Log in again but actually set the token this time.
|
||||
loginRes2, err := userClient.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
|
||||
Email: email,
|
||||
Password: password,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
userClient.SetSessionToken(loginRes2.SessionToken)
|
||||
|
||||
// Add the user's second session token to the list of API keys that should
|
||||
// be deleted.
|
||||
shouldBeDeleted := map[string]string{
|
||||
"user login 2 (logging out with this)": loginRes2.SessionToken,
|
||||
}
|
||||
|
||||
// Add the user's first token, and the admin's session token to the list of
|
||||
// API keys that should not be deleted.
|
||||
shouldNotBeDeleted := map[string]string{
|
||||
"user login 1 (not logging out of)": loginRes1.SessionToken,
|
||||
"admin login": client.SessionToken(),
|
||||
}
|
||||
|
||||
// Create a few application_connect-scoped API keys that should be deleted.
|
||||
for i := 0; i < 3; i++ {
|
||||
key, _ := dbgen.APIKey(t, db, database.APIKey{
|
||||
UserID: newUser.ID,
|
||||
Scope: database.APIKeyScopeApplicationConnect,
|
||||
})
|
||||
shouldBeDeleted[fmt.Sprintf("application_connect key owned by logout user %d", i)] = key.ID
|
||||
}
|
||||
|
||||
// Create a few application_connect-scoped API keys for the admin user that
|
||||
// should not be deleted.
|
||||
for i := 0; i < 3; i++ {
|
||||
key, _ := dbgen.APIKey(t, db, database.APIKey{
|
||||
UserID: firstUser.UserID,
|
||||
Scope: database.APIKeyScopeApplicationConnect,
|
||||
})
|
||||
shouldNotBeDeleted[fmt.Sprintf("application_connect key owned by admin user %d", i)] = key.ID
|
||||
}
|
||||
|
||||
// Log out of the new user.
|
||||
err = userClient.Logout(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ensure the new user's session token is no longer valid.
|
||||
_, err = userClient.User(ctx, codersdk.Me)
|
||||
require.Error(t, err)
|
||||
var sdkErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &sdkErr)
|
||||
require.Equal(t, http.StatusUnauthorized, sdkErr.StatusCode())
|
||||
|
||||
// Check that the deleted keys are gone.
|
||||
for name, id := range shouldBeDeleted {
|
||||
id := strings.Split(id, "-")[0]
|
||||
_, err := db.GetAPIKeyByID(ctx, id)
|
||||
require.Error(t, err, name)
|
||||
}
|
||||
|
||||
// Check that the other keys are still there.
|
||||
for name, id := range shouldNotBeDeleted {
|
||||
id := strings.Split(id, "-")[0]
|
||||
_, err := db.GetAPIKeyByID(ctx, id)
|
||||
require.NoError(t, err, name)
|
||||
}
|
||||
}
|
||||
|
||||
func oauth2Callback(t *testing.T, client *codersdk.Client) *http.Response {
|
||||
client.HTTPClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
|
Reference in New Issue
Block a user