Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for readonly repositories #194

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
10 changes: 10 additions & 0 deletions plugins/cad/src/components/AddPackagePage/AddPackagePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import {
ContentSummary,
getPackageDescriptor,
getRepository,
isReadOnlyRepository,
RepositoryContentDetails,
} from '../../utils/repository';
import { sortByLabel } from '../../utils/selectItem';
Expand Down Expand Up @@ -554,6 +555,15 @@ export const AddPackagePage = ({ action }: AddPackagePageProps) => {
helperText={`The repository to create the new ${targetRepositoryPackageDescriptorLowercase} in.`}
/>

{!!targetRepository && isReadOnlyRepository(targetRepository) && (
<Alert severity="info" icon={false}>
A new {targetRepositoryPackageDescriptorLowercase} cannot be
created in the {targetRepository.metadata.name} repository
since the repository is read-only. Another destination
repository will need to be selected.
</Alert>
)}

{!!addPackageAction?.message && (
<Alert severity="info" icon={false}>
{addPackageAction.message}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import {
findRepository,
getPackageDescriptor,
isDeploymentRepository,
isReadOnlyRepository,
} from '../../utils/repository';
import {
getRepositorySummaries,
Expand Down Expand Up @@ -819,7 +820,23 @@ export const PackageRevisionPage = ({ mode }: PackageRevisionPageProps) => {
return upgradeMessage;
};

const alertMessages = isUpgradeAvailable ? [getUpgradeMessage()] : [];
const alertMessages: AlertMessage[] = [];

if (isReadOnlyRepository(repository)) {
alertMessages.push({
key: 'read-only',
message: (
<Fragment>
This {toLowerCase(packageDescriptor)} is read-only since this{' '}
{toLowerCase(packageDescriptor)} exists in a read-only repository.
</Fragment>
),
});
}

if (isUpgradeAvailable) {
alertMessages.push(getUpgradeMessage());
}

if (isLatestPublishedPackageRevision) {
const downstreamPackagesPendingUpgrade = downstreamPackageSummaries.filter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@

import { useApi, useRouteRef } from '@backstage/core-plugin-api';
import { Button } from '@material-ui/core';
import { Alert } from '@material-ui/lab';
import React, { Fragment, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { configAsDataApiRef } from '../../../apis';
import { repositoryRouteRef } from '../../../routes';
import { Repository } from '../../../types/Repository';
import { RootSync } from '../../../types/RootSync';
import {
getPackageDescriptor,
isReadOnlyRepository,
} from '../../../utils/repository';
import { toLowerCase } from '../../../utils/string';
import { ConfirmationDialog } from '../../Controls/ConfirmationDialog';

type AdvancedPackageRevisionOptionsProps = {
Expand Down Expand Up @@ -86,6 +92,15 @@ export const AdvancedPackageRevisionOptions = ({
navigate(repositoryRef({ repositoryName }));
};

if (isReadOnlyRepository(repository)) {
return (
<Alert severity="info">
Advanced options are hidden since this{' '}
{toLowerCase(getPackageDescriptor(repository))} is read-only.
</Alert>
);
}

return (
<Fragment>
<ConfirmationDialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
import {
getPackageDescriptor,
isDeploymentRepository,
isReadOnlyRepository,
RepositoryContentDetails,
} from '../../../utils/repository';
import { PackageRevisionPageMode } from '../PackageRevisionPage';
Expand Down Expand Up @@ -64,6 +65,7 @@ type PackageRevisionOptionsProps = {
};

const DraftPackageRevisionOptions = ({
repositorySummary,
packageRevision,
mode,
onClick,
Expand All @@ -76,6 +78,11 @@ const DraftPackageRevisionOptions = ({
const repositoryName = packageRevision.spec.repository;

const isEditMode = mode === PackageRevisionPageMode.EDIT;
const isViewOnly = isReadOnlyRepository(repositorySummary.repository);

if (isViewOnly) {
return <Fragment />;
}

if (isEditMode) {
return (
Expand Down Expand Up @@ -125,9 +132,16 @@ const DraftPackageRevisionOptions = ({
};

const ProposedPackageRevisionOptions = ({
repositorySummary,
onClick,
disabled,
}: PackageRevisionOptionsProps) => {
const isViewOnly = isReadOnlyRepository(repositorySummary.repository);

if (isViewOnly) {
return <Fragment />;
}

return (
<Fragment>
<MaterialButton
Expand Down Expand Up @@ -169,6 +183,7 @@ const PublishedPackageRevisionOptions = ({
const latestRevision = packageRevisions[0];
const latestPublishedRevision = findLatestPublishedRevision(packageRevisions);

const isReadOnly = isReadOnlyRepository(repositorySummary.repository);
const isLatestPublishedPackageRevision =
packageRevision && isLatestPublishedRevision(packageRevision);

Expand All @@ -179,14 +194,16 @@ const PublishedPackageRevisionOptions = ({
if (!isLatestPublishedPackageRevision) {
return (
<Fragment>
<MaterialButton
onClick={() => onClick(RevisionOption.RESTORE_REVISION)}
color="primary"
variant="outlined"
disabled={disabled}
>
Restore Revision
</MaterialButton>
{!isReadOnly && (
<MaterialButton
onClick={() => onClick(RevisionOption.RESTORE_REVISION)}
color="primary"
variant="outlined"
disabled={disabled}
>
Restore Revision
</MaterialButton>
)}

<Button
to={packageRef({
Expand All @@ -205,18 +222,23 @@ const PublishedPackageRevisionOptions = ({

const packageContentType = getPackageDescriptor(repositorySummary.repository);

const isNewerUnpublishedRevision = latestRevision !== latestPublishedRevision;

const showUpgrade =
!isReadOnly && isUpgradeAvailable && !isNewerUnpublishedRevision;
const showCreateNewRevision = !isReadOnly && !isNewerUnpublishedRevision;
const showClone =
RepositoryContentDetails[packageContentType].cloneTo.length > 0 &&
canCloneRevision(packageRevision);

const isNewerUnpublishedRevision = latestRevision !== latestPublishedRevision;

const showCreateSync =
isDeploymentRepository(repositorySummary.repository) && rootSync === null;
!isReadOnly &&
isDeploymentRepository(repositorySummary.repository) &&
rootSync === null;

return (
<Fragment>
{isUpgradeAvailable && !isNewerUnpublishedRevision && (
{showUpgrade && (
<MaterialButton
variant="outlined"
color="primary"
Expand All @@ -227,7 +249,7 @@ const PublishedPackageRevisionOptions = ({
</MaterialButton>
)}

{!isNewerUnpublishedRevision && (
{showCreateNewRevision && (
<MaterialButton
variant="outlined"
color="primary"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
getRepositoryResource,
getSecretRef,
PackageContentSummaryOrder,
RepositoryAccess,
RepositoryContentDetails,
} from '../../utils/repository';
import { getBasicAuthSecret, isBasicAuthSecret } from '../../utils/secret';
Expand Down Expand Up @@ -86,7 +87,8 @@ export const RegisterRepositoryPage = () => {
description: '',
repoBranch: '',
repoDir: '',
authType: '',
authType: AuthenticationType.GITHUB_ACCESS_TOKEN,
repositoryAccess: RepositoryAccess.FULL,
useSecret: 'new',
authSecretName: '',
authPassword: '',
Expand Down Expand Up @@ -155,6 +157,7 @@ export const RegisterRepositoryPage = () => {
}

const contentSummary = state.contentSummary as ContentSummary;
const repositoryAccess = state.repositoryAccess as RepositoryAccess;

if (contentSummary === ContentSummary.DEPLOYMENT) {
deploymentEnvironment =
Expand All @@ -165,6 +168,7 @@ export const RegisterRepositoryPage = () => {
state.name,
state.description,
contentSummary,
repositoryAccess,
gitDetails,
ociDetails,
deploymentEnvironment,
Expand Down Expand Up @@ -384,7 +388,9 @@ export const RegisterRepositoryPage = () => {
<div className={classes.stepContent}>
<Select
label="Authentication Type"
onChange={value => setState({ ...state, authType: value })}
onChange={value =>
setState({ ...state, authType: value as AuthenticationType })
}
selected={state.authType}
items={selectAuthTypeItems}
helperText="The authentication type of the repository. Select None if the repository does not require any authentication."
Expand Down Expand Up @@ -432,6 +438,28 @@ export const RegisterRepositoryPage = () => {
/>
</Fragment>
)}

<Select
label="Repository Access"
onChange={value =>
setState({
...state,
repositoryAccess: value as RepositoryAccess,
})
}
selected={state.repositoryAccess}
items={[
{
value: RepositoryAccess.FULL,
label: 'Write access',
},
{
value: RepositoryAccess.READ_ONLY,
label: 'Read-only access',
},
]}
helperText="The access anyone using the UI will have to the repository. Write access allows packages to be created and updated in the repository, whereas read-only access allows packages to be viewed. Select read-only access if the repository authentication only allows read access."
/>
</div>
</SimpleStepperStep>

Expand Down
18 changes: 11 additions & 7 deletions plugins/cad/src/components/RepositoryPage/RepositoryPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
isDeploymentRepository,
isFunctionRepository,
isPackageRepository,
isReadOnlyRepository,
} from '../../utils/repository';
import {
getRepositorySummaries,
Expand Down Expand Up @@ -167,6 +168,7 @@ export const RepositoryPage = () => {

const thisRepository = repositorySummary.repository;
const repoTitle = getRepositoryTitle(thisRepository);
const isReadOnly = isReadOnlyRepository(thisRepository);

const packageDescriptor = getPackageDescriptor(thisRepository);

Expand All @@ -178,13 +180,15 @@ export const RepositoryPage = () => {
</Breadcrumbs>

<ContentHeader title={repoTitle}>
<Button
to={addPackageRef({ repositoryName: repositoryName })}
color="primary"
variant="contained"
>
Add {packageDescriptor}
</Button>
{!isReadOnly && (
<Button
to={addPackageRef({ repositoryName: repositoryName })}
color="primary"
variant="contained"
>
Add {packageDescriptor}
</Button>
)}
</ContentHeader>

<Tabs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import { makeStyles } from '@material-ui/core';
import Alert from '@material-ui/lab/Alert';
import React, { Fragment } from 'react';
import { Function } from '../../../types/Function';
Expand All @@ -24,7 +25,9 @@ import {
isDeploymentRepository,
isFunctionRepository,
isPackageRepository,
isReadOnlyRepository,
} from '../../../utils/repository';
import { toLowerCase } from '../../../utils/string';
import { PackagesTable } from '../../PackagesTable';
import { FunctionsTable } from '../components/FunctionsTable';

Expand All @@ -35,20 +38,37 @@ type PackagesTabContentProps = {
packagesError?: Error;
};

const useStyles = makeStyles({
messageBanner: {
marginBottom: '16px',
},
});

export const PackagesTabContent = ({
repository,
packages,
functions,
packagesError,
}: PackagesTabContentProps) => {
const classes = useStyles();

const pluralPackageDescriptor = `${getPackageDescriptor(repository)}s`;
const isReadOnly = isReadOnlyRepository(repository);

if (packagesError) {
return <Alert severity="error">{packagesError.message}</Alert>;
}

return (
<Fragment>
{isReadOnly && (
<Alert className={classes.messageBanner} severity="info">
This repository is read-only. You will not be able to add or make any
changes to the {toLowerCase(pluralPackageDescriptor)} in this
repository.
</Alert>
)}

{isPackageRepository(repository) && (
<PackagesTable
title={pluralPackageDescriptor}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
getDeploymentEnvironment,
getPackageDescriptor,
isDeploymentRepository,
isReadOnlyRepository,
} from '../../../utils/repository';

type RepositoryDetailsProps = {
Expand Down Expand Up @@ -83,11 +84,14 @@ const getRepositoryStatusConditions = (repository: Repository): Metadata => {
};

const getRepositoryMetadata = (repository: Repository): Metadata => {
const isReadOnly = isReadOnlyRepository(repository);

const metadata: Metadata = {
name: repository.metadata.name,
description: repository.spec.description ?? '',
content: `${getPackageDescriptor(repository)}s`,
deploymentEnvironment: getDeploymentEnvironment(repository),
repositoryAccess: isReadOnly ? 'read-only access' : 'write access',
...getRepositoryStoreMetadata(repository),
...getRepositoryStatusConditions(repository),
};
Expand Down
Loading