Skip to content

Commit

Permalink
add dedicated edit/create pages for auth connectors
Browse files Browse the repository at this point in the history
  • Loading branch information
rudream committed Jan 6, 2025
1 parent 4ea3566 commit b93cc53
Show file tree
Hide file tree
Showing 13 changed files with 413 additions and 114 deletions.
3 changes: 3 additions & 0 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,9 @@ func (h *Handler) bindDefaultEndpoints() {

h.GET("/webapi/github", h.WithAuth(h.getGithubConnectorsHandle))
h.POST("/webapi/github", h.WithAuth(h.createGithubConnectorHandle))
// The extra "connector" in the path is to avoid a wildcard conflict with the github handlers used
// during the login flow ("github/login/web" and "github/callback").
h.GET("/webapi/github/connector/:name", h.WithAuth(h.getGithubConnectorHandle))
h.PUT("/webapi/github/:name", h.WithAuth(h.updateGithubConnectorHandle))
h.DELETE("/webapi/github/:name", h.WithAuth(h.deleteGithubConnector))

Expand Down
21 changes: 21 additions & 0 deletions lib/web/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,27 @@ func (h *Handler) getPresetRoles(w http.ResponseWriter, r *http.Request, p httpr
return ui.NewRoles(presets)
}

// getGithubConnectorHandle returns a GitHub connector by name.
func (h *Handler) getGithubConnectorHandle(w http.ResponseWriter, r *http.Request, params httprouter.Params, ctx *SessionContext) (interface{}, error) {
clt, err := ctx.GetClient()
if err != nil {
return nil, trace.Wrap(err)
}

connectorName := params.ByName("name")
connector, err := clt.GetGithubConnector(r.Context(), connectorName, true)
if err != nil {
return nil, trace.Wrap(err)
}

resource, err := ui.NewResourceItem(connector)
if err != nil {
return nil, trace.Wrap(err)
}

return resource, nil
}

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { Link as RouterLink } from 'react-router-dom';

import { Link } from 'design';
import { Alert } from 'design/Alert';
import Box from 'design/Box';
import { ButtonPrimary, ButtonSecondary } from 'design/Button';
import Flex from 'design/Flex';
import { ArrowBack } from 'design/Icon';
import { Indicator } from 'design/Indicator';
import { H1, H3 } from 'design/Text';
import { P } from 'design/Text/Text';
import TextEditor from 'shared/components/TextEditor';
import { Attempt } from 'shared/hooks/useAttemptNext';

import { DesktopDescription } from 'teleport/AuthConnectors/styles/AuthConnectors.styles';
import { FeatureBox, FeatureHeaderTitle } from 'teleport/components/Layout';

import { description } from '../AuthConnectors';

/**
* AuthConnectorEditorContent is a the content of an Auth Connector editor page.
*/
export function AuthConnectorEditorContent({
title,
content,
backButtonRoute,
isSaveDisabled,
saveAttempt,
fetchAttempt,
onSave,
onCancel,
setContent,
}: Props) {
return (
<FeatureBox>
<FeatureHeaderTitle py={3} mb={2}>
<Flex alignItems="center">
<ArrowBack
as={RouterLink}
mr={2}
size="large"
color="text.main"
to={backButtonRoute}
/>
<Flex mr={4} alignItems="baseline">
<H1>{title}</H1>
</Flex>
</Flex>
</FeatureHeaderTitle>
{fetchAttempt.status === 'failed' && (
<Alert>{fetchAttempt.statusText}</Alert>
)}
{fetchAttempt.status === 'processing' && (
<Box textAlign="center" m={10}>
<Indicator />
</Box>
)}
{fetchAttempt.status === 'success' && (
<Flex width="100%" height="100%">
<Flex
alignItems="start"
flexDirection={'column'}
height="100%"
flex={4}
>
{saveAttempt.status === 'failed' && (
<Alert>{saveAttempt.statusText}</Alert>
)}
<Flex height="600px" width="100%">
{content && (
<TextEditor
bg="levels.deep"
readOnly={false}
data={[{ content, type: 'yaml' }]}
onChange={setContent}
/>
)}
</Flex>
<Box mt={3}>
<ButtonPrimary disabled={isSaveDisabled} onClick={onSave} mr="3">
Save Changes
</ButtonPrimary>
<ButtonSecondary
disabled={saveAttempt.status === 'processing'}
onClick={onCancel}
>
Cancel
</ButtonSecondary>
</Box>
</Flex>
<DesktopDescription>
<H3 mb={3}>Auth Connectors</H3>
<P mb={3}>{description}</P>
<P mb={2}>
Please{' '}
<Link
color="text.main"
// This URL is the OSS documentation for auth connectors
href="https://goteleport.com/docs/setup/admin/github-sso/"
target="_blank"
>
view our documentation
</Link>{' '}
on how to configure a GitHub connector.
</P>
</DesktopDescription>
</Flex>
)}
</FeatureBox>
);
}

type Props = {
title: string;
content: string;
backButtonRoute: string;
isSaveDisabled: boolean;
saveAttempt: Attempt;
fetchAttempt: Attempt;
onSave: () => void;
onCancel: () => void;
setContent: (content: string) => void;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { useEffect, useState } from 'react';
import { useHistory, useParams } from 'react-router';

import useAttempt from 'shared/hooks/useAttemptNext';

import cfg from 'teleport/config';
import useTeleport from 'teleport/useTeleport';

import templates from '../templates';
import { AuthConnectorEditorContent } from './AuthConnectorEditorContent';

/**
* GitHubConnectorEditor is the edit/create page for a GitHub Auth Connector.
*/
export function GitHubConnectorEditor({ isNew = false }) {
const { connectorName } = useParams<{
connectorName: string;
}>();
const ctx = useTeleport();
const history = useHistory();

const [content, setContent] = useState(templates['github']);
const [initialContent, setInitialContent] = useState(templates['github']);

const fetchAttempt = useAttempt(isNew ? 'success' : 'processing');
const saveAttempt = useAttempt('');

const isSaveDisabled =
saveAttempt.attempt.status === 'processing' || content === initialContent;

useEffect(() => {
if (!isNew) {
fetchAttempt.run(() =>
ctx.resourceService.fetchGithubConnector(connectorName).then(res => {
setContent(res.content);
setInitialContent(res.content);
})
);
}
}, [connectorName]);

const onSave = () => {
saveAttempt.run(() => {
if (isNew) {
return ctx.resourceService.createGithubConnector(content).then(() => {
history.push(cfg.routes.sso);
});
}
return ctx.resourceService
.updateGithubConnector(connectorName, content)
.then(() => {
history.push(cfg.routes.sso);
});
});
};

const title = isNew
? 'Creating new GitHub Auth Connector: '
: `Editing Auth Connector: ${connectorName}`;

return (
<AuthConnectorEditorContent
title={title}
content={content}
backButtonRoute={cfg.routes.sso}
isSaveDisabled={isSaveDisabled}
saveAttempt={saveAttempt.attempt}
fetchAttempt={fetchAttempt.attempt}
onSave={onSave}
onCancel={() => history.push(cfg.routes.sso)}
setContent={setContent}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

export { AuthConnectorEditorContent } from './AuthConnectorEditorContent';
export { GitHubConnectorEditor } from './GitHubConnectorEditor';
Loading

0 comments on commit b93cc53

Please sign in to comment.