mirror of https://github.com/coder/coder.git
feat: add minimum password entropy requirements (#6090)
* feat: add minimum password entropy requirements * Fix all the tests * Fix E2E tests
This commit is contained in:
parent
fe725f76bb
commit
2ed0eafd75
14
cli/login.go
14
cli/login.go
|
@ -19,6 +19,7 @@ import (
|
|||
|
||||
"github.com/coder/coder/cli/cliflag"
|
||||
"github.com/coder/coder/cli/cliui"
|
||||
"github.com/coder/coder/coderd/userpassword"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
|
@ -152,16 +153,19 @@ func login() *cobra.Command {
|
|||
|
||||
for !matching {
|
||||
password, err = cliui.Prompt(cmd, cliui.PromptOptions{
|
||||
Text: "Enter a " + cliui.Styles.Field.Render("password") + ":",
|
||||
Secret: true,
|
||||
Validate: cliui.ValidateNotEmpty,
|
||||
Text: "Enter a " + cliui.Styles.Field.Render("password") + ":",
|
||||
Secret: true,
|
||||
Validate: func(s string) error {
|
||||
return userpassword.Validate(s)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("specify password prompt: %w", err)
|
||||
}
|
||||
confirm, err := cliui.Prompt(cmd, cliui.PromptOptions{
|
||||
Text: "Confirm " + cliui.Styles.Field.Render("password") + ":",
|
||||
Secret: true,
|
||||
Text: "Confirm " + cliui.Styles.Field.Render("password") + ":",
|
||||
Secret: true,
|
||||
Validate: cliui.ValidateNotEmpty,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("confirm password prompt: %w", err)
|
||||
|
|
|
@ -54,8 +54,8 @@ func TestLogin(t *testing.T) {
|
|||
"first user?", "yes",
|
||||
"username", "testuser",
|
||||
"email", "user@coder.com",
|
||||
"password", "password",
|
||||
"password", "password", // Confirm.
|
||||
"password", "SomeSecurePassword!",
|
||||
"password", "SomeSecurePassword!", // Confirm.
|
||||
"trial", "yes",
|
||||
}
|
||||
for i := 0; i < len(matches); i += 2 {
|
||||
|
@ -89,8 +89,8 @@ func TestLogin(t *testing.T) {
|
|||
"first user?", "yes",
|
||||
"username", "testuser",
|
||||
"email", "user@coder.com",
|
||||
"password", "password",
|
||||
"password", "password", // Confirm.
|
||||
"password", "SomeSecurePassword!",
|
||||
"password", "SomeSecurePassword!", // Confirm.
|
||||
"trial", "yes",
|
||||
}
|
||||
for i := 0; i < len(matches); i += 2 {
|
||||
|
@ -107,7 +107,7 @@ func TestLogin(t *testing.T) {
|
|||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
doneChan := make(chan struct{})
|
||||
root, _ := clitest.New(t, "login", client.URL.String(), "--first-user-username", "testuser", "--first-user-email", "user@coder.com", "--first-user-password", "password", "--first-user-trial")
|
||||
root, _ := clitest.New(t, "login", client.URL.String(), "--first-user-username", "testuser", "--first-user-email", "user@coder.com", "--first-user-password", "SomeSecurePassword!", "--first-user-trial")
|
||||
pty := ptytest.New(t)
|
||||
root.SetIn(pty.Input())
|
||||
root.SetOut(pty.Output())
|
||||
|
@ -143,8 +143,8 @@ func TestLogin(t *testing.T) {
|
|||
"first user?", "yes",
|
||||
"username", "testuser",
|
||||
"email", "user@coder.com",
|
||||
"password", "mypass",
|
||||
"password", "wrongpass", // Confirm.
|
||||
"password", "MyFirstSecurePassword!",
|
||||
"password", "MyNonMatchingSecurePassword!", // Confirm.
|
||||
}
|
||||
for i := 0; i < len(matches); i += 2 {
|
||||
match := matches[i]
|
||||
|
@ -157,9 +157,9 @@ func TestLogin(t *testing.T) {
|
|||
pty.ExpectMatch("Passwords do not match")
|
||||
pty.ExpectMatch("Enter a " + cliui.Styles.Field.Render("password"))
|
||||
|
||||
pty.WriteLine("pass")
|
||||
pty.WriteLine("SomeSecurePassword!")
|
||||
pty.ExpectMatch("Confirm")
|
||||
pty.WriteLine("pass")
|
||||
pty.WriteLine("SomeSecurePassword!")
|
||||
pty.ExpectMatch("trial")
|
||||
pty.WriteLine("yes")
|
||||
pty.ExpectMatch("Welcome to Coder")
|
||||
|
|
|
@ -50,9 +50,11 @@ func resetPassword() *cobra.Command {
|
|||
}
|
||||
|
||||
password, err := cliui.Prompt(cmd, cliui.PromptOptions{
|
||||
Text: "Enter new " + cliui.Styles.Field.Render("password") + ":",
|
||||
Secret: true,
|
||||
Validate: cliui.ValidateNotEmpty,
|
||||
Text: "Enter new " + cliui.Styles.Field.Render("password") + ":",
|
||||
Secret: true,
|
||||
Validate: func(s string) error {
|
||||
return userpassword.Validate(s)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("password prompt: %w", err)
|
||||
|
|
|
@ -28,8 +28,8 @@ func TestResetPassword(t *testing.T) {
|
|||
|
||||
const email = "some@one.com"
|
||||
const username = "example"
|
||||
const oldPassword = "password"
|
||||
const newPassword = "password2"
|
||||
const oldPassword = "MyOldPassword!"
|
||||
const newPassword = "MyNewPassword!"
|
||||
|
||||
// start postgres and coder server processes
|
||||
|
||||
|
|
|
@ -428,7 +428,7 @@ func NewExternalProvisionerDaemon(t *testing.T, client *codersdk.Client, org uui
|
|||
var FirstUserParams = codersdk.CreateFirstUserRequest{
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
Password: "SomeSecurePassword!",
|
||||
}
|
||||
|
||||
// CreateFirstUser creates a user with preset credentials and authenticates
|
||||
|
@ -455,7 +455,7 @@ func createAnotherUserRetry(t *testing.T, client *codersdk.Client, organizationI
|
|||
req := codersdk.CreateUserRequest{
|
||||
Email: namesgenerator.GetRandomName(10) + "@coder.com",
|
||||
Username: randomUsername(),
|
||||
Password: "testpass",
|
||||
Password: "SomeSecurePassword!",
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
passwordvalidator "github.com/wagslane/go-password-validator"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/xerrors"
|
||||
|
@ -125,15 +126,14 @@ func hashWithSaltAndIter(password string, salt []byte, iter int) string {
|
|||
// Validate checks that the plain text password meets the minimum password requirements.
|
||||
// It returns properly formatted errors for detailed form validation on the client.
|
||||
func Validate(password string) error {
|
||||
const (
|
||||
minLength = 8
|
||||
maxLength = 64
|
||||
)
|
||||
if len(password) < minLength {
|
||||
return xerrors.Errorf("Password must be at least %d characters.", minLength)
|
||||
// Ensure passwords are secure enough!
|
||||
// See: https://github.com/wagslane/go-password-validator#what-entropy-value-should-i-use
|
||||
err := passwordvalidator.Validate(password, 52)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(password) > maxLength {
|
||||
return xerrors.Errorf("Password must be no more than %d characters.", maxLength)
|
||||
if len(password) > 64 {
|
||||
return xerrors.Errorf("password must be no more than %d characters", 64)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -105,6 +105,18 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
err = userpassword.Validate(createUser.Password)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Password not strong enough!",
|
||||
Validations: []codersdk.ValidationError{{
|
||||
Field: "password",
|
||||
Detail: err.Error(),
|
||||
}},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
user, organizationID, err := api.CreateUser(ctx, api.Database, CreateUserRequest{
|
||||
CreateUserRequest: codersdk.CreateUserRequest{
|
||||
Email: createUser.Email,
|
||||
|
@ -316,6 +328,18 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
err = userpassword.Validate(req.Password)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Password not strong enough!",
|
||||
Validations: []codersdk.ValidationError{{
|
||||
Field: "password",
|
||||
Detail: err.Error(),
|
||||
}},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
user, _, err := api.CreateUser(ctx, api.Database, CreateUserRequest{
|
||||
CreateUserRequest: req,
|
||||
LoginType: database.LoginTypePassword,
|
||||
|
|
|
@ -49,7 +49,7 @@ func TestFirstUser(t *testing.T) {
|
|||
_, err := client.CreateFirstUser(ctx, codersdk.CreateFirstUserRequest{
|
||||
Email: "some@email.com",
|
||||
Username: "exampleuser",
|
||||
Password: "password",
|
||||
Password: "SomeSecurePassword!",
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
|
@ -78,7 +78,7 @@ func TestFirstUser(t *testing.T) {
|
|||
req := codersdk.CreateFirstUserRequest{
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
Password: "SomeSecurePassword!",
|
||||
Trial: true,
|
||||
}
|
||||
_, err := client.CreateFirstUser(ctx, req)
|
||||
|
@ -123,7 +123,7 @@ func TestPostLogin(t *testing.T) {
|
|||
req := codersdk.CreateFirstUserRequest{
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
Password: "SomeSecurePassword!",
|
||||
}
|
||||
_, err := client.CreateFirstUser(ctx, req)
|
||||
require.NoError(t, err)
|
||||
|
@ -172,7 +172,7 @@ func TestPostLogin(t *testing.T) {
|
|||
// Test a new session
|
||||
_, err = client.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
|
||||
Email: memberUser.Email,
|
||||
Password: "testpass",
|
||||
Password: "SomeSecurePassword!",
|
||||
})
|
||||
numLogs++ // add an audit log for login
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
|
@ -198,7 +198,7 @@ func TestPostLogin(t *testing.T) {
|
|||
defer cancel()
|
||||
|
||||
// With a user account.
|
||||
const password = "testpass"
|
||||
const password = "SomeSecurePassword!"
|
||||
user, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "test+user-@coder.com",
|
||||
Username: "user",
|
||||
|
@ -245,7 +245,7 @@ func TestPostLogin(t *testing.T) {
|
|||
req := codersdk.CreateFirstUserRequest{
|
||||
Email: "testuser@coder.com",
|
||||
Username: "testuser",
|
||||
Password: "testpass",
|
||||
Password: "SomeSecurePassword!",
|
||||
}
|
||||
_, err := client.CreateFirstUser(ctx, req)
|
||||
require.NoError(t, err)
|
||||
|
@ -309,7 +309,7 @@ func TestDeleteUser(t *testing.T) {
|
|||
another, err = api.CreateUser(context.Background(), codersdk.CreateUserRequest{
|
||||
Email: another.Email,
|
||||
Username: another.Username,
|
||||
Password: "testing",
|
||||
Password: "SomeSecurePassword!",
|
||||
OrganizationID: user.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -421,7 +421,7 @@ func TestPostUsers(t *testing.T) {
|
|||
_, err = client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: me.Email,
|
||||
Username: me.Username,
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
OrganizationID: uuid.New(),
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
|
@ -441,7 +441,7 @@ func TestPostUsers(t *testing.T) {
|
|||
OrganizationID: uuid.New(),
|
||||
Email: "another@user.org",
|
||||
Username: "someone-else",
|
||||
Password: "testing",
|
||||
Password: "SomeSecurePassword!",
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
|
@ -466,7 +466,7 @@ func TestPostUsers(t *testing.T) {
|
|||
_, err = notInOrg.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "some@domain.com",
|
||||
Username: "anotheruser",
|
||||
Password: "testing",
|
||||
Password: "SomeSecurePassword!",
|
||||
OrganizationID: org.ID,
|
||||
})
|
||||
var apiErr *codersdk.Error
|
||||
|
@ -491,7 +491,7 @@ func TestPostUsers(t *testing.T) {
|
|||
OrganizationID: user.OrganizationID,
|
||||
Email: "another@user.org",
|
||||
Username: "someone-else",
|
||||
Password: "testing",
|
||||
Password: "SomeSecurePassword!",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -561,7 +561,7 @@ func TestUpdateUserProfile(t *testing.T) {
|
|||
existentUser, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "bruno@coder.com",
|
||||
Username: "bruno",
|
||||
Password: "password",
|
||||
Password: "SomeSecurePassword!",
|
||||
OrganizationID: user.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -627,18 +627,18 @@ func TestUpdateUserPassword(t *testing.T) {
|
|||
member, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "coder@coder.com",
|
||||
Username: "coder",
|
||||
Password: "password",
|
||||
Password: "SomeStrongPassword!",
|
||||
OrganizationID: admin.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err, "create member")
|
||||
err = client.UpdateUserPassword(ctx, member.ID.String(), codersdk.UpdateUserPasswordRequest{
|
||||
Password: "newpassword",
|
||||
Password: "SomeNewStrongPassword!",
|
||||
})
|
||||
require.NoError(t, err, "admin should be able to update member password")
|
||||
// Check if the member can login using the new password
|
||||
_, err = client.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
|
||||
Email: "coder@coder.com",
|
||||
Password: "newpassword",
|
||||
Password: "SomeNewStrongPassword!",
|
||||
})
|
||||
require.NoError(t, err, "member should login successfully with the new password")
|
||||
})
|
||||
|
@ -659,8 +659,8 @@ func TestUpdateUserPassword(t *testing.T) {
|
|||
defer cancel()
|
||||
|
||||
err := member.UpdateUserPassword(ctx, "me", codersdk.UpdateUserPasswordRequest{
|
||||
OldPassword: "testpass",
|
||||
Password: "newpassword",
|
||||
OldPassword: "SomeSecurePassword!",
|
||||
Password: "MyNewSecurePassword!",
|
||||
})
|
||||
numLogs++ // add an audit log for user update
|
||||
|
||||
|
@ -696,7 +696,7 @@ func TestUpdateUserPassword(t *testing.T) {
|
|||
defer cancel()
|
||||
|
||||
err := client.UpdateUserPassword(ctx, "me", codersdk.UpdateUserPasswordRequest{
|
||||
Password: "newpassword",
|
||||
Password: "MySecurePassword!",
|
||||
})
|
||||
numLogs++ // add an audit log for user update
|
||||
|
||||
|
@ -720,7 +720,7 @@ func TestUpdateUserPassword(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
err = client.UpdateUserPassword(ctx, "me", codersdk.UpdateUserPasswordRequest{
|
||||
Password: "newpassword",
|
||||
Password: "MyNewSecurePassword!",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -733,7 +733,7 @@ func TestUpdateUserPassword(t *testing.T) {
|
|||
|
||||
resp, err := client.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
|
||||
Email: coderdtest.FirstUserParams.Email,
|
||||
Password: "newpassword",
|
||||
Password: "MyNewSecurePassword!",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -1264,7 +1264,7 @@ func TestGetUsers(t *testing.T) {
|
|||
client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "alice@email.com",
|
||||
Username: "alice",
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
OrganizationID: user.OrganizationID,
|
||||
})
|
||||
// No params is all users
|
||||
|
@ -1290,7 +1290,7 @@ func TestGetUsers(t *testing.T) {
|
|||
alice, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "alice@email.com",
|
||||
Username: "alice",
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
OrganizationID: first.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -1298,7 +1298,7 @@ func TestGetUsers(t *testing.T) {
|
|||
bruno, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "bruno@email.com",
|
||||
Username: "bruno",
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
OrganizationID: first.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -1329,7 +1329,7 @@ func TestGetUsersPagination(t *testing.T) {
|
|||
_, err = client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "alice@email.com",
|
||||
Username: "alice",
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
OrganizationID: first.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -1410,13 +1410,13 @@ func TestWorkspacesByUser(t *testing.T) {
|
|||
newUser, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "test@coder.com",
|
||||
Username: "someone",
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
OrganizationID: user.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
auth, err := client.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
|
||||
Email: newUser.Email,
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -1463,7 +1463,7 @@ func TestSuspendedPagination(t *testing.T) {
|
|||
user, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: email,
|
||||
Username: username,
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
OrganizationID: orgID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
@ -1526,7 +1526,7 @@ func TestPaginatedUsers(t *testing.T) {
|
|||
newUser, err := client.CreateUser(egCtx, codersdk.CreateUserRequest{
|
||||
Email: email,
|
||||
Username: username,
|
||||
Password: "password",
|
||||
Password: "MySecurePassword!",
|
||||
OrganizationID: orgID,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -1138,7 +1138,7 @@ func TestAppSharing(t *testing.T) {
|
|||
|
||||
setup := func(t *testing.T, allowPathAppSharing, allowSiteOwnerAccess bool) (workspace codersdk.Workspace, agnt codersdk.WorkspaceAgent, user codersdk.User, ownerClient *codersdk.Client, client *codersdk.Client, clientInOtherOrg *codersdk.Client, clientWithNoAuth *codersdk.Client) {
|
||||
//nolint:gosec
|
||||
const password = "password"
|
||||
const password = "SomeSecurePassword!"
|
||||
|
||||
var port uint16
|
||||
ownerClient, _, _, port = setupProxyTest(t, &setupProxyTestOpts{
|
||||
|
|
1
go.mod
1
go.mod
|
@ -196,6 +196,7 @@ require (
|
|||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
|
||||
github.com/vmihailenco/tagparser v0.1.1 // indirect
|
||||
github.com/wagslane/go-password-validator v0.3.0 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.1 // indirect
|
||||
)
|
||||
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1878,6 +1878,8 @@ github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvC
|
|||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/wagslane/go-password-validator v0.3.0 h1:vfxOPzGHkz5S146HDpavl0cw1DSVP061Ry2PX0/ON6I=
|
||||
github.com/wagslane/go-password-validator v0.3.0/go.mod h1:TI1XJ6T5fRdRnHqHt14pvy1tNVnrwe7m3/f1f2fDphQ=
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
|
|
|
@ -3,5 +3,5 @@ export const defaultPort = 3000
|
|||
|
||||
// Credentials for the first user
|
||||
export const username = "admin"
|
||||
export const password = "password"
|
||||
export const password = "SomeSecurePassword!"
|
||||
export const email = "admin@coder.com"
|
||||
|
|
|
@ -644,8 +644,22 @@ export const putWorkspaceExtension = async (
|
|||
}
|
||||
|
||||
export const getEntitlements = async (): Promise<TypesGen.Entitlements> => {
|
||||
const response = await axios.get("/api/v2/entitlements")
|
||||
return response.data
|
||||
try {
|
||||
const response = await axios.get("/api/v2/entitlements")
|
||||
return response.data
|
||||
} catch (ex) {
|
||||
if (axios.isAxiosError(ex) && ex.response?.status === 404) {
|
||||
return {
|
||||
errors: [],
|
||||
experimental: false,
|
||||
features: withDefaultFeatures({}),
|
||||
has_license: false,
|
||||
trial: false,
|
||||
warnings: [],
|
||||
}
|
||||
}
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
export const getExperiments = async (): Promise<TypesGen.Experiment[]> => {
|
||||
|
@ -777,8 +791,20 @@ export const getFile = async (fileId: string): Promise<ArrayBuffer> => {
|
|||
}
|
||||
|
||||
export const getAppearance = async (): Promise<TypesGen.AppearanceConfig> => {
|
||||
const response = await axios.get(`/api/v2/appearance`)
|
||||
return response.data
|
||||
try {
|
||||
const response = await axios.get(`/api/v2/appearance`)
|
||||
return response.data || {}
|
||||
} catch (ex) {
|
||||
if (axios.isAxiosError(ex) && ex.response?.status === 404) {
|
||||
return {
|
||||
logo_url: "",
|
||||
service_banner: {
|
||||
enabled: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
export const updateAppearance = async (
|
||||
|
|
Loading…
Reference in New Issue