chore: Remove events log from settings

This commit is contained in:
Tom Moor
2020-10-26 19:32:48 -07:00
parent bfdfa3ee4b
commit bd80e8384a
6 changed files with 0 additions and 367 deletions

View File

@ -10,7 +10,6 @@ import {
GroupIcon, GroupIcon,
LinkIcon, LinkIcon,
TeamIcon, TeamIcon,
BulletedListIcon,
ExpandedIcon, ExpandedIcon,
} from "outline-icons"; } from "outline-icons";
import * as React from "react"; import * as React from "react";
@ -118,13 +117,6 @@ class SettingsSidebar extends React.Component<Props> {
icon={<LinkIcon color="currentColor" />} icon={<LinkIcon color="currentColor" />}
label="Share Links" label="Share Links"
/> />
{can.auditLog && (
<SidebarLink
to="/settings/events"
icon={<BulletedListIcon color="currentColor" />}
label="Audit Log"
/>
)}
{can.export && ( {can.export && (
<SidebarLink <SidebarLink
to="/settings/export" to="/settings/export"

View File

@ -3,7 +3,6 @@ import * as React from "react";
import { Switch, Route } from "react-router-dom"; import { Switch, Route } from "react-router-dom";
import Settings from "scenes/Settings"; import Settings from "scenes/Settings";
import Details from "scenes/Settings/Details"; import Details from "scenes/Settings/Details";
import Events from "scenes/Settings/Events";
import Export from "scenes/Settings/Export"; import Export from "scenes/Settings/Export";
import Groups from "scenes/Settings/Groups"; import Groups from "scenes/Settings/Groups";
import Notifications from "scenes/Settings/Notifications"; import Notifications from "scenes/Settings/Notifications";
@ -25,7 +24,6 @@ export default function SettingsRoutes() {
<Route exact path="/settings/groups" component={Groups} /> <Route exact path="/settings/groups" component={Groups} />
<Route exact path="/settings/shares" component={Shares} /> <Route exact path="/settings/shares" component={Shares} />
<Route exact path="/settings/tokens" component={Tokens} /> <Route exact path="/settings/tokens" component={Tokens} />
<Route exact path="/settings/events" component={Events} />
<Route exact path="/settings/notifications" component={Notifications} /> <Route exact path="/settings/notifications" component={Notifications} />
<Route exact path="/settings/integrations/slack" component={Slack} /> <Route exact path="/settings/integrations/slack" component={Slack} />
<Route exact path="/settings/integrations/zapier" component={Zapier} /> <Route exact path="/settings/integrations/zapier" component={Zapier} />

View File

@ -1,102 +0,0 @@
// @flow
import { observable, action } from "mobx";
import { observer, inject } from "mobx-react";
import * as React from "react";
import { type Match } from "react-router-dom";
import { Waypoint } from "react-waypoint";
import { DEFAULT_PAGINATION_LIMIT } from "stores/BaseStore";
import EventsStore from "stores/EventsStore";
import CenteredContent from "components/CenteredContent";
import HelpText from "components/HelpText";
import List from "components/List";
import { ListPlaceholder } from "components/LoadingPlaceholder";
import PageTitle from "components/PageTitle";
import Tab from "components/Tab";
import Tabs from "components/Tabs";
import EventListItem from "./components/EventListItem";
type Props = {
events: EventsStore,
match: Match,
};
@observer
class Events extends React.Component<Props> {
@observable isLoaded: boolean = false;
@observable isFetching: boolean = false;
@observable offset: number = 0;
@observable allowLoadMore: boolean = true;
componentDidMount() {
this.fetchResults();
}
fetchResults = async () => {
this.isFetching = true;
const limit = DEFAULT_PAGINATION_LIMIT;
const results = await this.props.events.fetchPage({
limit,
offset: this.offset,
auditLog: true,
});
if (
results &&
(results.length === 0 || results.length < DEFAULT_PAGINATION_LIMIT)
) {
this.allowLoadMore = false;
} else {
this.offset += DEFAULT_PAGINATION_LIMIT;
}
this.isLoaded = true;
this.isFetching = false;
};
@action
loadMoreResults = async () => {
// Don't paginate if there aren't more results or were in the middle of fetching
if (!this.allowLoadMore || this.isFetching) return;
await this.fetchResults();
};
render() {
const { events } = this.props;
const showLoading = events.isFetching && !events.orderedData.length;
return (
<CenteredContent>
<PageTitle title="Audit Log" />
<h1>Audit Log</h1>
<HelpText>
The audit log details the history of security related and other events
across your knowledge base.
</HelpText>
<Tabs>
<Tab to="/settings/events" exact>
Events
</Tab>
</Tabs>
<List>
{showLoading ? (
<ListPlaceholder count={5} />
) : (
<>
{events.orderedData.map((event) => (
<EventListItem event={event} key={event.id} />
))}
{this.allowLoadMore && (
<Waypoint key={this.offset} onEnter={this.loadMoreResults} />
)}
</>
)}
</List>
</CenteredContent>
);
}
}
export default inject("events")(Events);

View File

@ -1,232 +0,0 @@
// @flow
import { capitalize } from "lodash";
import * as React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
import Event from "models/Event";
import Avatar from "components/Avatar";
import ListItem from "components/List/Item";
import Time from "components/Time";
type Props = {
event: Event,
};
const description = (event) => {
switch (event.name) {
case "api_keys.create":
return (
<>
Created the API token <strong>{event.data.name}</strong>
</>
);
case "api_keys.delete":
return (
<>
Revoked the API token <strong>{event.data.name}</strong>
</>
);
case "teams.create":
return "Created the team";
case "shares.create":
case "shares.revoke":
return (
<>
{capitalize(event.verbPastTense)} a{" "}
<Link to={`/share/${event.modelId || ""}`}>share link</Link> to the{" "}
<Link to={`/doc/${event.documentId}`}>{event.data.name}</Link>{" "}
document
</>
);
case "shares.update":
return (
<>
{event.data.published ? (
<>
Published a document{" "}
<Link to={`/share/${event.modelId || ""}`}>share link</Link>
</>
) : (
<>
Unpublished a document{" "}
<Link to={`/share/${event.modelId || ""}`}>share link</Link>
</>
)}
</>
);
case "users.create":
return <>{event.data.name} created an account</>;
case "users.invite":
return (
<>
{capitalize(event.verbPastTense)} {event.data.name} (
<a href={`mailto:${event.data.email || ""}`}>
{event.data.email || ""}
</a>
)
</>
);
case "users.suspend":
return (
<>
Suspended <strong>{event.data.name}s</strong> account
</>
);
case "users.activate":
return (
<>
Unsuspended <strong>{event.data.name}s</strong> account
</>
);
case "users.promote":
return (
<>
Made <strong>{event.data.name}</strong> an admin
</>
);
case "users.demote":
return (
<>
Made <strong>{event.data.name}</strong> a member
</>
);
case "users.delete":
return "Deleted their account";
case "groups.create":
return (
<>
Created the group <strong>{event.data.name}</strong>
</>
);
case "groups.update":
return (
<>
Update the group <strong>{event.data.name}</strong>
</>
);
case "groups.delete":
return (
<>
Deleted the group <strong>{event.data.name}</strong>
</>
);
case "collections.add_user":
case "collections.add_group":
return (
<>
Granted <strong>{event.data.name}</strong> access to a{" "}
<Link to={`/collections/${event.collectionId || ""}`}>
collection
</Link>
</>
);
case "collections.remove_user":
case "collections.remove_group":
return (
<>
Revoked <strong>{event.data.name}</strong> access to a{" "}
<Link to={`/collections/${event.collectionId || ""}`}>
collection
</Link>
</>
);
default:
}
if (event.documentId) {
if (event.name === "documents.delete") {
return (
<>
Deleted the <strong>{event.data.title}</strong> document
</>
);
}
if (event.name === "documents.create") {
return (
<>
{capitalize(event.verbPastTense)} the{" "}
<Link to={`/doc/${event.documentId}`}>
{event.data.title || "Untitled"}
</Link>{" "}
document{" "}
{event.data.templateId && (
<>
from a <Link to={`/doc/${event.data.templateId}`}>template</Link>
</>
)}
</>
);
}
return (
<>
{capitalize(event.verbPastTense)} the{" "}
<Link to={`/doc/${event.documentId}`}>
{event.data.title || "Untitled"}
</Link>{" "}
document
</>
);
}
if (event.collectionId) {
if (event.name === "collections.delete") {
return (
<>
Deleted the <strong>{event.data.name}</strong> collection
</>
);
}
return (
<>
{capitalize(event.verbPastTense)} the{" "}
<Link to={`/collections/${event.collectionId || ""}`}>
{event.data.name}
</Link>{" "}
collection
</>
);
}
if (event.userId) {
return (
<>
{capitalize(event.verbPastTense)} the user {event.data.name}
</>
);
}
return "";
};
const EventListItem = ({ event }: Props) => {
return (
<ListItem
key={event.id}
title={event.actor.name}
image={<Avatar src={event.actor.avatarUrl} size={32} />}
subtitle={
<>
{description(event)} <Time dateTime={event.createdAt} /> ago &middot;{" "}
<strong>{event.name}</strong>
</>
}
actions={
event.actorIpAddress ? (
<IP>
<a
href={`http://geoiplookup.net/ip/${event.actorIpAddress}`}
target="_blank"
rel="noreferrer noopener"
>
{event.actorIpAddress}
</a>
</IP>
) : undefined
}
/>
);
};
const IP = styled("span")`
color: ${(props) => props.theme.textTertiary};
font-size: 12px;
`;
export default EventListItem;

View File

@ -1,19 +0,0 @@
// @flow
import { sortBy } from "lodash";
import { computed } from "mobx";
import Event from "models/Event";
import BaseStore from "./BaseStore";
import RootStore from "./RootStore";
export default class EventsStore extends BaseStore<Event> {
actions = ["list"];
constructor(rootStore: RootStore) {
super(rootStore, Event);
}
@computed
get orderedData(): Event[] {
return sortBy(Array.from(this.data.values()), "createdAt").reverse();
}
}

View File

@ -5,7 +5,6 @@ import CollectionGroupMembershipsStore from "./CollectionGroupMembershipsStore";
import CollectionsStore from "./CollectionsStore"; import CollectionsStore from "./CollectionsStore";
import DocumentPresenceStore from "./DocumentPresenceStore"; import DocumentPresenceStore from "./DocumentPresenceStore";
import DocumentsStore from "./DocumentsStore"; import DocumentsStore from "./DocumentsStore";
import EventsStore from "./EventsStore";
import GroupMembershipsStore from "./GroupMembershipsStore"; import GroupMembershipsStore from "./GroupMembershipsStore";
import GroupsStore from "./GroupsStore"; import GroupsStore from "./GroupsStore";
import IntegrationsStore from "./IntegrationsStore"; import IntegrationsStore from "./IntegrationsStore";
@ -24,7 +23,6 @@ export default class RootStore {
collections: CollectionsStore; collections: CollectionsStore;
collectionGroupMemberships: CollectionGroupMembershipsStore; collectionGroupMemberships: CollectionGroupMembershipsStore;
documents: DocumentsStore; documents: DocumentsStore;
events: EventsStore;
groups: GroupsStore; groups: GroupsStore;
groupMemberships: GroupMembershipsStore; groupMemberships: GroupMembershipsStore;
integrations: IntegrationsStore; integrations: IntegrationsStore;
@ -44,7 +42,6 @@ export default class RootStore {
this.collections = new CollectionsStore(this); this.collections = new CollectionsStore(this);
this.collectionGroupMemberships = new CollectionGroupMembershipsStore(this); this.collectionGroupMemberships = new CollectionGroupMembershipsStore(this);
this.documents = new DocumentsStore(this); this.documents = new DocumentsStore(this);
this.events = new EventsStore(this);
this.groups = new GroupsStore(this); this.groups = new GroupsStore(this);
this.groupMemberships = new GroupMembershipsStore(this); this.groupMemberships = new GroupMembershipsStore(this);
this.integrations = new IntegrationsStore(this); this.integrations = new IntegrationsStore(this);
@ -65,7 +62,6 @@ export default class RootStore {
this.collections.clear(); this.collections.clear();
this.collectionGroupMemberships.clear(); this.collectionGroupMemberships.clear();
this.documents.clear(); this.documents.clear();
this.events.clear();
this.groups.clear(); this.groups.clear();
this.groupMemberships.clear(); this.groupMemberships.clear();
this.integrations.clear(); this.integrations.clear();