mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-10-30 18:15:52 +01:00
Archive repository (#1477)
This adds a flag "archived" to repositories. Repositories marked with this can no longer be modified in any way. To do this, we switch to a new version of Shiro Static Permissions (sdorra/shiro-static-permissions#4) and specify a permission guard to check for every permission request, whether the repository in question is archived or not. Further we implement checks in stores and other activies so that no writing request may be executed by mistake. Co-authored-by: Eduard Heimbuch <eduard.heimbuch@cloudogu.com>
This commit is contained in:
@@ -30,6 +30,8 @@ import { Changeset, Repository } from "@scm-manager/ui-types";
|
||||
import {
|
||||
CustomQueryFlexWrappedColumns,
|
||||
ErrorPage,
|
||||
FileControlFactory,
|
||||
JumpToFileButton,
|
||||
Loading,
|
||||
NavLink,
|
||||
Page,
|
||||
@@ -37,7 +39,9 @@ import {
|
||||
SecondaryNavigation,
|
||||
SecondaryNavigationColumn,
|
||||
StateMenuContextProvider,
|
||||
SubNavigation
|
||||
SubNavigation,
|
||||
Tooltip,
|
||||
urls,
|
||||
} from "@scm-manager/ui-components";
|
||||
import { fetchRepoByName, getFetchRepoFailure, getRepository, isFetchRepoPending } from "../modules/repos";
|
||||
import RepositoryDetails from "../components/RepositoryDetails";
|
||||
@@ -53,10 +57,9 @@ import { getLinks, getRepositoriesLink } from "../../modules/indexResource";
|
||||
import CodeOverview from "../codeSection/containers/CodeOverview";
|
||||
import ChangesetView from "./ChangesetView";
|
||||
import SourceExtensions from "../sources/containers/SourceExtensions";
|
||||
import { FileControlFactory, JumpToFileButton } from "@scm-manager/ui-components";
|
||||
import TagsOverview from "../tags/container/TagsOverview";
|
||||
import TagRoot from "../tags/container/TagRoot";
|
||||
import { urls } from "@scm-manager/ui-components";
|
||||
import styled from "styled-components";
|
||||
|
||||
type Props = RouteComponentProps &
|
||||
WithTranslation & {
|
||||
@@ -72,6 +75,15 @@ type Props = RouteComponentProps &
|
||||
fetchRepoByName: (link: string, namespace: string, name: string) => void;
|
||||
};
|
||||
|
||||
const ArchiveTag = styled.span`
|
||||
margin-left: 0.2rem;
|
||||
background-color: #9a9a9a;
|
||||
padding: 0.4rem;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
class RepositoryRoot extends React.Component<Props> {
|
||||
componentDidMount() {
|
||||
const { fetchRepoByName, namespace, name, repoLink } = this.props;
|
||||
@@ -141,7 +153,7 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
const extensionProps = {
|
||||
repository,
|
||||
url,
|
||||
indexLinks
|
||||
indexLinks,
|
||||
};
|
||||
|
||||
const redirectUrlFactory = binder.getExtension("repository.redirect", this.props);
|
||||
@@ -152,16 +164,17 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
redirectedUrl = url + "/info";
|
||||
}
|
||||
|
||||
const fileControlFactoryFactory: (changeset: Changeset) => FileControlFactory = changeset => file => {
|
||||
const fileControlFactoryFactory: (changeset: Changeset) => FileControlFactory = (changeset) => (file) => {
|
||||
const baseUrl = `${url}/code/sources`;
|
||||
const sourceLink = file.newPath && {
|
||||
url: `${baseUrl}/${changeset.id}/${file.newPath}/`,
|
||||
label: t("diff.jumpToSource")
|
||||
};
|
||||
const targetLink = file.oldPath && changeset._embedded?.parents?.length === 1 && {
|
||||
url: `${baseUrl}/${changeset._embedded.parents[0].id}/${file.oldPath}`,
|
||||
label: t("diff.jumpToTarget")
|
||||
label: t("diff.jumpToSource"),
|
||||
};
|
||||
const targetLink = file.oldPath &&
|
||||
changeset._embedded?.parents?.length === 1 && {
|
||||
url: `${baseUrl}/${changeset._embedded.parents[0].id}/${file.oldPath}`,
|
||||
label: t("diff.jumpToTarget"),
|
||||
};
|
||||
|
||||
const links = [];
|
||||
switch (file.type) {
|
||||
@@ -186,6 +199,12 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
return links ? links.map(({ url, label }) => <JumpToFileButton tooltip={label} link={url} />) : null;
|
||||
};
|
||||
|
||||
const archivedFlag = repository.archived && (
|
||||
<Tooltip message={t("archive.tooltip")}>
|
||||
<ArchiveTag className="is-size-6">{t("repository.archived")}</ArchiveTag>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
const titleComponent = (
|
||||
<>
|
||||
<Link to={`/repos/${repository.namespace}/`} className={"has-text-dark"}>
|
||||
@@ -200,7 +219,12 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
<Page
|
||||
title={titleComponent}
|
||||
documentTitle={`${repository.namespace}/${repository.name}`}
|
||||
afterTitle={<ExtensionPoint name={"repository.afterTitle"} props={{ repository }} />}
|
||||
afterTitle={
|
||||
<>
|
||||
<ExtensionPoint name={"repository.afterTitle"} props={{ repository }} />
|
||||
{archivedFlag}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<CustomQueryFlexWrappedColumns>
|
||||
<PrimaryContentColumn>
|
||||
@@ -336,7 +360,7 @@ const mapStateToProps = (state: any, ownProps: Props) => {
|
||||
loading,
|
||||
error,
|
||||
repoLink,
|
||||
indexLinks
|
||||
indexLinks,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -344,7 +368,7 @@ const mapDispatchToProps = (dispatch: any) => {
|
||||
return {
|
||||
fetchRepoByName: (link: string, namespace: string, name: string) => {
|
||||
dispatch(fetchRepoByName(link, namespace, name));
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user