2024-04-13 11:25:10 +00:00
|
|
|
/*
|
|
|
|
GoToSocial
|
|
|
|
Copyright (C) GoToSocial Authors admin@gotosocial.org
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
|
|
|
|
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 React from "react";
|
|
|
|
|
2024-04-25 16:24:24 +00:00
|
|
|
import { useGetAccountQuery } from "../../../../lib/query/admin";
|
2024-04-24 10:12:47 +00:00
|
|
|
import FormWithData from "../../../../lib/form/form-with-data";
|
|
|
|
import FakeProfile from "../../../../components/fake-profile";
|
|
|
|
import { AdminAccount } from "../../../../lib/types/account";
|
2024-04-13 11:25:10 +00:00
|
|
|
import { AccountActions } from "./actions";
|
2024-04-24 10:12:47 +00:00
|
|
|
import { useParams } from "wouter";
|
2024-05-01 13:11:22 +00:00
|
|
|
import { useBaseUrl } from "../../../../lib/navigation/util";
|
|
|
|
import BackButton from "../../../../components/back-button";
|
|
|
|
import { UseOurInstanceAccount, yesOrNo } from "./util";
|
2024-04-13 11:25:10 +00:00
|
|
|
|
|
|
|
export default function AccountDetail() {
|
2024-04-24 10:12:47 +00:00
|
|
|
const params: { accountID: string } = useParams();
|
2024-05-01 13:11:22 +00:00
|
|
|
const baseUrl = useBaseUrl();
|
|
|
|
const backLocation: String = history.state?.backLocation ?? `~${baseUrl}`;
|
|
|
|
|
2024-04-24 10:12:47 +00:00
|
|
|
return (
|
|
|
|
<div className="account-detail">
|
2024-05-01 13:11:22 +00:00
|
|
|
<h1><BackButton to={backLocation} /> Account Details</h1>
|
2024-04-24 10:12:47 +00:00
|
|
|
<FormWithData
|
|
|
|
dataQuery={useGetAccountQuery}
|
|
|
|
queryArg={params.accountID}
|
|
|
|
DataForm={AccountDetailForm}
|
2024-05-01 13:11:22 +00:00
|
|
|
{...{ backLocation: backLocation }}
|
2024-04-24 10:12:47 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
2024-04-13 11:25:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
interface AccountDetailFormProps {
|
2024-05-01 13:11:22 +00:00
|
|
|
data: AdminAccount;
|
|
|
|
backLocation: string;
|
2024-04-13 11:25:10 +00:00
|
|
|
}
|
|
|
|
|
2024-05-01 13:11:22 +00:00
|
|
|
function AccountDetailForm({ data: adminAcct, backLocation }: AccountDetailFormProps) {
|
|
|
|
// If this is our instance account, don't
|
|
|
|
// bother returning detailed account information.
|
|
|
|
const ourInstanceAccount = UseOurInstanceAccount(adminAcct);
|
|
|
|
if (ourInstanceAccount) {
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<FakeProfile {...adminAcct.account} />
|
|
|
|
<div className="info">
|
|
|
|
<i className="fa fa-fw fa-info-circle" aria-hidden="true"></i>
|
|
|
|
<b>
|
|
|
|
This is the service account for your instance; you
|
|
|
|
cannot perform moderation actions on this account.
|
|
|
|
</b>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const local = !adminAcct.domain;
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<FakeProfile {...adminAcct.account} />
|
|
|
|
<GeneralAccountDetails adminAcct={adminAcct} />
|
|
|
|
{
|
|
|
|
// Only show local account details
|
|
|
|
// if this is a local account!
|
|
|
|
local && <LocalAccountDetails adminAcct={adminAcct} />
|
|
|
|
}
|
|
|
|
<AccountActions
|
|
|
|
account={adminAcct}
|
|
|
|
backLocation={backLocation}
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
2024-04-13 11:25:10 +00:00
|
|
|
|
2024-05-01 13:11:22 +00:00
|
|
|
function GeneralAccountDetails({ adminAcct } : { adminAcct: AdminAccount }) {
|
|
|
|
const local = !adminAcct.domain;
|
|
|
|
const created = new Date(adminAcct.created_at).toDateString();
|
|
|
|
|
2024-04-13 11:25:10 +00:00
|
|
|
let lastPosted = "never";
|
|
|
|
if (adminAcct.account.last_status_at) {
|
|
|
|
lastPosted = new Date(adminAcct.account.last_status_at).toDateString();
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h3>General Account Details</h3>
|
2024-05-01 13:11:22 +00:00
|
|
|
{ adminAcct.suspended &&
|
|
|
|
<div className="info">
|
|
|
|
<i className="fa fa-fw fa-info-circle" aria-hidden="true"></i>
|
|
|
|
<b>Account is suspended.</b>
|
|
|
|
</div>
|
2024-04-13 11:25:10 +00:00
|
|
|
}
|
|
|
|
<dl className="info-list">
|
|
|
|
{ !local &&
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Domain</dt>
|
|
|
|
<dd>{adminAcct.domain}</dd>
|
|
|
|
</div>}
|
2024-05-01 13:11:22 +00:00
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Profile URL</dt>
|
|
|
|
<dd>
|
|
|
|
<a
|
|
|
|
href={adminAcct.account.url}
|
|
|
|
target="_blank"
|
|
|
|
rel="noreferrer"
|
|
|
|
>
|
|
|
|
<i className="fa fa-fw fa-external-link" aria-hidden="true"></i> {adminAcct.account.url} (opens in a new tab)
|
|
|
|
</a>
|
|
|
|
</dd>
|
|
|
|
</div>
|
2024-04-13 11:25:10 +00:00
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Created</dt>
|
|
|
|
<dd><time dateTime={adminAcct.created_at}>{created}</time></dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Last posted</dt>
|
|
|
|
<dd>{lastPosted}</dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Suspended</dt>
|
|
|
|
<dd>{yesOrNo(adminAcct.suspended)}</dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Silenced</dt>
|
|
|
|
<dd>{yesOrNo(adminAcct.silenced)}</dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Statuses</dt>
|
|
|
|
<dd>{adminAcct.account.statuses_count}</dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Followers</dt>
|
|
|
|
<dd>{adminAcct.account.followers_count}</dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Following</dt>
|
|
|
|
<dd>{adminAcct.account.following_count}</dd>
|
|
|
|
</div>
|
|
|
|
</dl>
|
2024-05-01 13:11:22 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function LocalAccountDetails({ adminAcct }: { adminAcct: AdminAccount }) {
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h3>Local Account Details</h3>
|
|
|
|
{ !adminAcct.approved &&
|
2024-04-13 11:25:10 +00:00
|
|
|
<div className="info">
|
|
|
|
<i className="fa fa-fw fa-info-circle" aria-hidden="true"></i>
|
|
|
|
<b>Account is pending.</b>
|
|
|
|
</div>
|
2024-05-01 13:11:22 +00:00
|
|
|
}
|
|
|
|
{ !adminAcct.confirmed &&
|
2024-04-13 11:25:10 +00:00
|
|
|
<div className="info">
|
|
|
|
<i className="fa fa-fw fa-info-circle" aria-hidden="true"></i>
|
|
|
|
<b>Account email not yet confirmed.</b>
|
|
|
|
</div>
|
2024-05-01 13:11:22 +00:00
|
|
|
}
|
|
|
|
<dl className="info-list">
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Email</dt>
|
|
|
|
<dd>{adminAcct.email} {<b>{adminAcct.confirmed ? "(confirmed)" : "(not confirmed)"}</b> }</dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Disabled</dt>
|
|
|
|
<dd>{yesOrNo(adminAcct.disabled)}</dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Approved</dt>
|
|
|
|
<dd>{yesOrNo(adminAcct.approved)}</dd>
|
|
|
|
</div>
|
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Sign-Up Reason</dt>
|
|
|
|
<dd>{adminAcct.invite_request ?? <i>none provided</i>}</dd>
|
|
|
|
</div>
|
|
|
|
{ (adminAcct.ip && adminAcct.ip !== "0.0.0.0") &&
|
2024-04-13 11:25:10 +00:00
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Sign-Up IP</dt>
|
|
|
|
<dd>{adminAcct.ip}</dd>
|
|
|
|
</div> }
|
2024-05-01 13:11:22 +00:00
|
|
|
{ adminAcct.locale &&
|
2024-04-13 11:25:10 +00:00
|
|
|
<div className="info-list-entry">
|
|
|
|
<dt>Locale</dt>
|
|
|
|
<dd>{adminAcct.locale}</dd>
|
|
|
|
</div> }
|
2024-05-01 13:11:22 +00:00
|
|
|
</dl>
|
|
|
|
</>
|
2024-04-13 11:25:10 +00:00
|
|
|
);
|
|
|
|
}
|