Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 2 additions & 33 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2404,15 +2404,6 @@ func createIdentityContext(login string, sessionCtx *SessionContext) (srv.Identi
}, nil
}

type UILock struct {
Name string `json:"name"`
Message string `json:"message"`
Expires string `json:"expires"`
CreatedAt string `json:"createdAt"`
CreatedBy string `json:"createdBy"`
Targets types.LockTarget `json:"targets"`
}

func (h *Handler) getClusterLocks(
w http.ResponseWriter,
r *http.Request,
Expand All @@ -2429,30 +2420,8 @@ func (h *Handler) getClusterLocks(
if err != nil {
return nil, trace.Wrap(err)
}
// Lock data structure is reformatted to save doing it on the client as the
// Table component doesn't support nested complex objects. And fails to properly
// sort or filter results.
lockList := make([]UILock, 0, len(locks))
for _, lock := range locks {
var expires, createdAt string
if lock.LockExpiry() != nil {
expires = lock.LockExpiry().Format(time.RFC3339Nano)
}

if !lock.CreatedAt().IsZero() {
createdAt = lock.CreatedAt().Format(time.RFC3339Nano)
}

lockList = append(lockList, UILock{
Name: lock.GetMetadata().Name,
Message: lock.Message(),
Expires: expires,
Targets: lock.Target(),
CreatedAt: createdAt,
CreatedBy: lock.CreatedBy(),
})
}
return lockList, nil
return ui.MakeLocks(locks), nil
}

type createLockReq struct {
Expand Down Expand Up @@ -2505,7 +2474,7 @@ func (h *Handler) createClusterLock(
return nil, trace.Wrap(err)
}

return lock, nil
return ui.MakeLock(lock), nil
}

func (h *Handler) deleteClusterLock(
Expand Down
70 changes: 70 additions & 0 deletions lib/web/ui/lock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright 2023 Gravitational, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ui

import (
"time"

"github.com/gravitational/teleport/api/types"
)

// Lock describes a lock suitable for webapp.
type Lock struct {
// Name is the name of this lock (uid).
Name string `json:"name"`
// Message is the message displayed to locked-out users.
Message string `json:"message"`
// Expires if set specifies when the lock ceases to be in force.
Expires string `json:"expires"`
// CreatedAt is the date time that the lock was created.
CreatedAt string `json:"createdAt"`
// CreatedBy is the username of the author of the lock.
CreatedBy string `json:"createdBy"`
// Target describes the set of interactions that the lock applies to.
Targets types.LockTarget `json:"targets"`
}

// MakeLock creates a custom lock object suitable for the webapp.
func MakeLock(lock types.Lock) Lock {
var expiresAt, createdAt string
if lock.LockExpiry() != nil {
expiresAt = lock.LockExpiry().Format(time.RFC3339Nano)
}
if !lock.CreatedAt().IsZero() {
createdAt = lock.CreatedAt().Format(time.RFC3339Nano)
}

return Lock{
Name: lock.GetMetadata().Name,
Message: lock.Message(),
Expires: expiresAt,
Targets: lock.Target(),
CreatedAt: createdAt,
CreatedBy: lock.CreatedBy(),
}
}

// MakeLocks makes lock objects suitable for the webapp.
func MakeLocks(locks []types.Lock) []Lock {
uiLocks := make([]Lock, 0, len(locks))

for _, lock := range locks {
uiLocks = append(uiLocks, MakeLock(lock))
}

return uiLocks
}
4 changes: 4 additions & 0 deletions lib/web/ui/usercontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ type userACL struct {
Integrations access `json:"integrations"`
// DeviceTrust defines access to device trust.
DeviceTrust access `json:"deviceTrust"`
// Locks defines access to locking resources.
Locks access `json:"lock"`
}

type authType string
Expand Down Expand Up @@ -212,6 +214,7 @@ func NewUserContext(user types.User, userRoles services.RoleSet, features proto.
license := newAccess(userRoles, ctx, types.KindLicense)
deviceTrust := newAccess(userRoles, ctx, types.KindDevice)
integrationsAccess := newAccess(userRoles, ctx, types.KindIntegration)
lockAccess := newAccess(userRoles, ctx, types.KindLock)

acl := userACL{
AccessRequests: requestAccess,
Expand Down Expand Up @@ -239,6 +242,7 @@ func NewUserContext(user types.User, userRoles services.RoleSet, features proto.
Plugins: pluginsAccess,
Integrations: integrationsAccess,
DeviceTrust: deviceTrust,
Locks: lockAccess,
}

// local user
Expand Down
1 change: 1 addition & 0 deletions lib/web/ui/usercontext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func TestNewUserContext(t *testing.T) {
require.Empty(t, cmp.Diff(userContext.ACL.AuthConnectors, allowedRW))
require.Empty(t, cmp.Diff(userContext.ACL.TrustedClusters, allowedRW))
require.Empty(t, cmp.Diff(userContext.ACL.AppServers, denied))
require.Empty(t, cmp.Diff(userContext.ACL.Locks, denied))
require.Empty(t, cmp.Diff(userContext.ACL.DBServers, denied))
require.Empty(t, cmp.Diff(userContext.ACL.KubeServers, denied))
require.Empty(t, cmp.Diff(userContext.ACL.Events, denied))
Expand Down
24 changes: 18 additions & 6 deletions web/packages/design/src/Button/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,26 @@ const themedStyles = props => {
const { colors } = props.theme;
const { kind } = props;

const style = {
'&:disabled': {
background: kind === 'text' ? 'none' : colors.buttons.bgDisabled,
color: colors.buttons.textDisabled,
cursor: 'auto',
},
let disabledStyle = {
background: kind === 'text' ? 'none' : colors.buttons.bgDisabled,
color: colors.buttons.textDisabled,
cursor: 'auto',
};

let style = {
'&:disabled': disabledStyle,
};

// Using the pseudo class `:disabled` to style disabled state
// doesn't work for non form elements (e.g. anchor). So
// we target by attribute with square brackets. Only true
// when we change the underlying type for this component (button)
// using the `as` prop (eg: a, NavLink, Link).
if (props.as && props.disabled) {
disabledStyle.pointerEvents = 'none';
style = { '&[disabled]': disabledStyle };
}

return {
...kinds(props),
...style,
Expand Down
4 changes: 2 additions & 2 deletions web/packages/teleport/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
<meta name="grv_csrf_token" content="{{ .XCSRF }}" />
<meta name="grv_bearer_token" content="{{ .Session }}" />
<meta name="robots" content="noindex" />
<link rel="icon" href="/favicon.ico">
<link rel="icon" href="/favicon.ico" />
<title></title>
</head>
<body style="overflow: hidden">
<body>
<div id="app"></div>
<script type="module" src="/src/boot.tsx"></script>
</body>
Expand Down
138 changes: 0 additions & 138 deletions web/packages/teleport/src/Locks/CreateLock.test.tsx

This file was deleted.

Loading