Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fac191d
Add WIP implementation of Teleport email invites
timothyb89 Aug 18, 2023
bfa7b05
Bump e ref and add new validation rule
timothyb89 Aug 22, 2023
32fcf4a
Various improvements to enable Cloud email invites
timothyb89 Sep 14, 2023
f92f373
Merge remote-tracking branch 'origin/master' into timothyb89/teleport…
timothyb89 Sep 14, 2023
8f5f9d7
Add support for Cloud collaborator invites during onboarding
timothyb89 Sep 21, 2023
8cddab0
Update e ref for the invite-collaborators branch
timothyb89 Sep 21, 2023
59c690d
Honor the `inputId` parameter if set
timothyb89 Sep 22, 2023
1f5a8e9
bump e ref
timothyb89 Sep 22, 2023
8fa63da
Improve typing for `requiredEmailLike` to add a error category
timothyb89 Oct 4, 2023
6e2c387
bump e ref
timothyb89 Oct 4, 2023
fc6a52b
Destructure the InviteCollaborators component sanely
timothyb89 Oct 9, 2023
41a5c41
Set `setDisplayInviteCollaborators` to `null` instead of `false`
timothyb89 Oct 9, 2023
1606e3b
Split `FieldSelectCreatable` into its own file
timothyb89 Oct 9, 2023
d277405
Merge remote-tracking branch 'origin/master' into timothyb89/teleport…
timothyb89 Oct 9, 2023
a9e49a1
Fix lint
timothyb89 Oct 9, 2023
36fd61f
Merge remote-tracking branch 'origin/master' into timothyb89/teleport…
timothyb89 Oct 11, 2023
b27873c
add story for SelectCreatable
timothyb89 Oct 13, 2023
ea21b51
Add tests for `requiredEmailLike`
timothyb89 Oct 13, 2023
f784af8
Rename `initial` flag to `invite`
timothyb89 Oct 13, 2023
86d0acc
Add tests for invite collaborators feedback and users rendering
timothyb89 Oct 13, 2023
79e061d
Add rendering test for the invite collaborators card
timothyb89 Oct 13, 2023
68cb212
Clean up lints
timothyb89 Oct 13, 2023
499b0f6
Rename types.tsx -> shared.tsx
timothyb89 Oct 17, 2023
c5ff2cb
Relocate invite constant to `Welcome/const.ts`
timothyb89 Oct 17, 2023
20e29c0
Split `SelectCreatable` into its own story
timothyb89 Oct 17, 2023
25323a0
Clarify SelectCreatable story
timothyb89 Oct 17, 2023
497782f
Merge remote-tracking branch 'origin/master' into timothyb89/teleport…
timothyb89 Oct 17, 2023
0df07be
Simplify story; fix lint
timothyb89 Oct 17, 2023
442c3ad
Fix type checker failure
timothyb89 Oct 18, 2023
e7032af
Rename `preset-roles` endpoint to `presetroles` to follow API convent…
timothyb89 Oct 19, 2023
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
12 changes: 9 additions & 3 deletions lib/auth/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,9 +747,10 @@ type PresetRoleManager interface {
UpsertRole(ctx context.Context, role types.Role) error
}

// createPresetRoles creates preset role resources
func createPresetRoles(ctx context.Context, rm PresetRoleManager) error {
roles := []types.Role{
// GetPresetRoles returns a list of all preset roles expected to be available on
// this cluster.
func GetPresetRoles() []types.Role {
return []types.Role{
services.NewPresetGroupAccessRole(),
services.NewPresetEditorRole(),
services.NewPresetAccessRole(),
Expand All @@ -761,6 +762,11 @@ func createPresetRoles(ctx context.Context, rm PresetRoleManager) error {
services.NewPresetDeviceEnrollRole(),
services.NewPresetRequireTrustedDeviceRole(),
}
}

// createPresetRoles creates preset role resources
func createPresetRoles(ctx context.Context, rm PresetRoleManager) error {
roles := GetPresetRoles()

g, gctx := errgroup.WithContext(ctx)
for _, role := range roles {
Expand Down
1 change: 1 addition & 0 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,7 @@ func (h *Handler) bindDefaultEndpoints() {
h.POST("/webapi/roles", h.WithAuth(h.upsertRoleHandle))
h.PUT("/webapi/roles/:name", h.WithAuth(h.upsertRoleHandle))
h.DELETE("/webapi/roles/:name", h.WithAuth(h.deleteRole))
h.GET("/webapi/presetroles", h.WithUnauthenticatedHighLimiter(h.getPresetRoles))

h.GET("/webapi/github", h.WithAuth(h.getGithubConnectorsHandle))
h.POST("/webapi/github", h.WithAuth(h.createGithubConnectorHandle))
Expand Down
10 changes: 10 additions & 0 deletions lib/web/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/gravitational/teleport/api/client/proto"
kubeproto "github.com/gravitational/teleport/api/gen/proto/go/teleport/kube/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/httplib"
Expand Down Expand Up @@ -150,6 +151,15 @@ func upsertRole(ctx context.Context, clt resourcesAPIGetter, content, httpMethod
return ui.NewResourceItem(role)
}

// getPresetRoles returns a list of preset roles expected to be available on
// this server. These are hard-coded for a given Teleport version, so this
// should have the same security implications as the Teleport version exposed
// via the public ping endpoint.
func (h *Handler) getPresetRoles(w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) {
presets := auth.GetPresetRoles()
return ui.NewRoles(presets)
Comment thread
zmb3 marked this conversation as resolved.
}

func (h *Handler) getGithubConnectorsHandle(w http.ResponseWriter, r *http.Request, params httprouter.Params, ctx *SessionContext) (interface{}, error) {
clt, err := ctx.GetClient()
if err != nil {
Expand Down
12 changes: 8 additions & 4 deletions lib/web/ui/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type ResourceItem struct {
Kind string `json:"kind"`
// Name is a resource name.
Name string `json:"name"`
// Description is an optional resource description.
Description string `json:"description,omitempty"`
// Content is resource yaml content.
Content string `json:"content"`
}
Expand All @@ -48,12 +50,14 @@ func NewResourceItem(resource types.Resource) (*ResourceItem, error) {

kind := resource.GetKind()
name := resource.GetName()
description := resource.GetMetadata().Description

return &ResourceItem{
ID: fmt.Sprintf("%v:%v", kind, name),
Kind: kind,
Name: name,
Content: string(data[:]),
ID: fmt.Sprintf("%v:%v", kind, name),
Kind: kind,
Name: name,
Description: description,
Content: string(data[:]),
}, nil

}
Expand Down
21 changes: 10 additions & 11 deletions web/packages/shared/components/FieldSelect/FieldSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ import { Box, LabelInput } from 'design';

import { useRule } from 'shared/components/Validation';

import Select, { Props as SelectProps } from './../Select';
import Select, { Props as SelectProps } from '../Select';

import { LabelTip, defaultRule } from './shared';

export default function FieldSelect({
components,
label,
labelTip,
value,
Expand All @@ -35,11 +38,13 @@ export default function FieldSelect({
isMulti,
menuPosition,
rule = defaultRule,
stylesConfig,
isSearchable = false,
isSimpleValue = false,
autoFocus = false,
isDisabled = false,
elevated = false,
inputId = 'select',
...styles
}: Props) {
const { valid, message } = useRule(rule(value));
Expand All @@ -48,13 +53,15 @@ export default function FieldSelect({
return (
<Box mb="4" {...styles}>
{label && (
<LabelInput htmlFor={'select'} hasError={hasError}>
<LabelInput htmlFor={inputId} hasError={hasError}>
{labelText}
{labelTip && <LabelTip text={labelTip} />}
</LabelInput>
)}
<Select
inputId="select"
components={components}
stylesConfig={stylesConfig}
inputId={inputId}
name={name}
menuPosition={menuPosition}
hasError={hasError}
Expand All @@ -75,14 +82,6 @@ export default function FieldSelect({
);
}

const defaultRule = () => () => ({ valid: true });

const LabelTip = ({ text }) => (
<span
css={{ fontWeight: 'normal', textTransform: 'none' }}
>{` - ${text}`}</span>
);

type Props = SelectProps & {
autoFocus?: boolean;
label?: string;
Expand Down
102 changes: 102 additions & 0 deletions web/packages/shared/components/FieldSelect/FieldSelectCreatable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
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.
*/

import React from 'react';

import { Box, LabelInput } from 'design';

import { useRule } from 'shared/components/Validation';

import {
SelectCreatable,
CreatableProps as SelectCreatableProps,
} from '../Select';

import { LabelTip, defaultRule } from './shared';

export function FieldSelectCreatable({
components,
label,
labelTip,
value,
name,
onChange,
placeholder,
maxMenuHeight,
isClearable,
isMulti,
menuIsOpen,
menuPosition,
inputValue,
onKeyDown,
onInputChange,
onBlur,
rule = defaultRule,
stylesConfig,
isSearchable = false,
isSimpleValue = false,
autoFocus = false,
isDisabled = false,
elevated = false,
inputId = 'select',
...styles
}: CreatableProps) {
const { valid, message } = useRule(rule(value));
const hasError = Boolean(!valid);
const labelText = hasError ? message : label;
return (
<Box mb="4" {...styles}>
{label && (
<LabelInput htmlFor={inputId} hasError={hasError}>
{labelText}
{labelTip && <LabelTip text={labelTip} />}
</LabelInput>
)}
<SelectCreatable
components={components}
inputId={inputId}
name={name}
menuPosition={menuPosition}
hasError={hasError}
isSimpleValue={isSimpleValue}
isSearchable={isSearchable}
isClearable={isClearable}
value={value}
onChange={onChange}
onKeyDown={onKeyDown}
onInputChange={onInputChange}
onBlur={onBlur}
inputValue={inputValue}
maxMenuHeight={maxMenuHeight}
placeholder={placeholder}
isMulti={isMulti}
autoFocus={autoFocus}
isDisabled={isDisabled}
elevated={elevated}
menuIsOpen={menuIsOpen}
stylesConfig={stylesConfig}
/>
</Box>
);
}

type CreatableProps = SelectCreatableProps & {
autoFocus?: boolean;
label?: string;
rule?: (options: unknown) => () => unknown;
// styles
[key: string]: any;
};
2 changes: 2 additions & 0 deletions web/packages/shared/components/FieldSelect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ limitations under the License.

import FieldSelect from './FieldSelect';
export default FieldSelect;

export { FieldSelectCreatable } from './FieldSelectCreatable';
23 changes: 23 additions & 0 deletions web/packages/shared/components/FieldSelect/shared.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
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.
*/

export const defaultRule = () => () => ({ valid: true });

export const LabelTip = ({ text }) => (
<span
css={{ fontWeight: 'normal', textTransform: 'none' }}
>{` - ${text}`}</span>
);
2 changes: 1 addition & 1 deletion web/packages/shared/components/Select/Select.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function SelectDark({ value, onChange, options }) {
const [selected, setSelected] = React.useState([]);

return (
<Flex flexDirection="column" width="330px">
<Flex flexDirection="column" width="330px" mr={5}>
<DarkStyledSelect mb="206px">
<Select
value={value}
Expand Down
25 changes: 23 additions & 2 deletions web/packages/shared/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,19 @@ limitations under the License.
import React from 'react';
import ReactSelect from 'react-select';
import ReactSelectAsync from 'react-select/async';
import CreatableSelect from 'react-select/creatable';
import styled from 'styled-components';
import { width, space } from 'design/system';

import { Props, AsyncProps } from './types';
import { Props, AsyncProps, CreatableProps } from './types';

export default function Select(props: Props) {
const { hasError = false, elevated = false, ...restOfProps } = props;
const {
hasError = false,
elevated = false,
stylesConfig,
...restOfProps
} = props;
return (
<StyledSelect hasError={hasError} elevated={elevated}>
<ReactSelect
Expand All @@ -34,6 +40,7 @@ export default function Select(props: Props) {
isMulti={false}
isSearchable={true}
placeholder="Select..."
styles={stylesConfig}
{...restOfProps}
/>
</StyledSelect>
Expand All @@ -59,6 +66,20 @@ export function SelectAsync(props: AsyncProps) {
);
}

export function SelectCreatable(props: CreatableProps) {
const { hasError = false, stylesConfig, ...restOfProps } = props;
return (
<StyledSelect hasError={hasError}>
<CreatableSelect
className="react-select-container"
classNamePrefix="react-select"
styles={stylesConfig}
{...restOfProps}
/>
</StyledSelect>
);
}

export const StyledSelect = styled.div`
.react-select-container {
box-sizing: border-box;
Expand Down
Loading