Compare commits

..

4 commits

Author SHA1 Message Date
tobi e62f5f9dbc mmbop 2024-10-31 17:46:22 +01:00
Sqx. Flann van der Eik 49eb8f602e
[chore] Fix minor typo in About template (#3502) 2024-10-31 00:26:26 +01:00
Markus Unterwaditzer cad76b8a25
[docs] Clarify what Visibility Level means (#3500)
* Clarify what Visibility Level means

* attempt to rephrase a bunch more for consistency
2024-10-30 15:28:07 +01:00
dependabot[bot] 3b037d165c
[chore] Bump elliptic from 6.5.7 to 6.6.0 in /web/source (#3495)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.7 to 6.6.0.
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.7...v6.6.0)

---
updated-dependencies:
- dependency-name: elliptic
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-29 15:36:49 +01:00
13 changed files with 473 additions and 63 deletions

View file

@ -78,11 +78,13 @@ Some examples:
#### Visibility Level of Posts to Show on Your Profile
Using this dropdown, you can choose what visibility level(s) of posts should be shown on the public web view of your profile, and served in your RSS feed (if you have enabled RSS).
Using this dropdown, you can choose what visibility level(s) of posts should be shown on the public web views of your profile, of your statuses, and in your RSS feed (if you have enabled RSS).
**By default, GoToSocial shows only Public visibility posts on the web view of your profile, not Unlisted.** You can adjust this setting to also show Unlisted visibility posts on your profile, which is similar to the default for other ActivityPub softwares like Mastodon etc.
**By default, GoToSocial shows only Public visibility posts on its web views, not Unlisted.** You can adjust this setting to also show Unlisted visibility posts, which is similar to the default for other ActivityPub softwares like Mastodon etc.
You can also choose to show no posts at all on the web view of your profile. This allows you to write posts without having to worry about scrapers, rubberneckers, and other nosy parkers visiting your web profile and looking at your posts.
You can also choose to show no posts at all on GoToSocial's web views. This allows you to write posts without having to worry about scrapers, rubberneckers, and other nosy parkers visiting your web profile and looking at your posts.
This setting only applies to the visibility of your own posts. Other user's Unlisted posts are never shown.
This setting does not affect visibility of your posts over the ActivityPub protocol, so even if you choose to show no posts on your public web profile, others will be able to see your posts in their client if they follow you, and/or have your posts boosted onto their timeline, use a link to search a post of yours, etc.

View file

@ -20,17 +20,17 @@
import "time"
type DomainPermissionDraft struct {
ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // ID of this item in the database.
CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // Time when this item was created.
UpdatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // Time when this item was last updated.
PermissionType DomainPermissionType `bun:",notnull,unique:domain_permission_drafts_permission_type_domain_subscription_id_uniq"` // Permission type of the draft.
Domain string `bun:",nullzero,notnull,unique:domain_permission_drafts_permission_type_domain_subscription_id_uniq"` // Domain to block or allow. Eg. 'whatever.com'.
CreatedByAccountID string `bun:"type:CHAR(26),nullzero,notnull"` // Account ID of the creator of this subscription.
CreatedByAccount *Account `bun:"-"` // Account corresponding to createdByAccountID.
PrivateComment string `bun:",nullzero"` // Private comment on this perm, viewable to admins.
PublicComment string `bun:",nullzero"` // Public comment on this perm, viewable (optionally) by everyone.
Obfuscate *bool `bun:",nullzero,notnull,default:false"` // Obfuscate domain name when displaying it publicly.
SubscriptionID string `bun:"type:CHAR(26),nullzero,unique:domain_permission_drafts_permission_type_domain_subscription_id_uniq"` // ID of the subscription that created this draft, if any.
ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // ID of this item in the database.
CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // Time when this item was created.
UpdatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // Time when this item was last updated.
PermissionType DomainPermissionType `bun:",notnull,unique:domain_permission_drafts_permission_type_domain_subscription_id_uniq"` // Permission type of the draft.
Domain string `bun:",nullzero,notnull,unique:domain_permission_drafts_permission_type_domain_subscription_id_uniq"` // Domain to block or allow. Eg. 'whatever.com'.
CreatedByAccountID string `bun:"type:CHAR(26),nullzero,notnull"` // Account ID of the creator of this subscription.
CreatedByAccount *Account `bun:"-"` // Account corresponding to createdByAccountID.
PrivateComment string `bun:",nullzero"` // Private comment on this perm, viewable to admins.
PublicComment string `bun:",nullzero"` // Public comment on this perm, viewable (optionally) by everyone.
Obfuscate *bool `bun:",nullzero,notnull,default:false"` // Obfuscate domain name when displaying it publicly.
SubscriptionID string `bun:"type:CHAR(26),unique:domain_permission_drafts_permission_type_domain_subscription_id_uniq"` // ID of the subscription that created this draft, if any.
}
func (d *DomainPermissionDraft) GetID() string {

View file

@ -21,14 +21,15 @@ import { gtsApi } from "../../gts-api";
import type {
DomainPerm,
ModeratorDomainPermissionDraftSearchParams,
ModeratorDomainPermissionDraftSearchResp,
DomainPermDraftCreateParams,
DomainPermDraftSearchParams,
DomainPermDraftSearchResp,
} from "../../../types/domain-permission";
import parse from "parse-link-header";
const extended = gtsApi.injectEndpoints({
endpoints: (build) => ({
searchDomainPermissionDrafts: build.query<ModeratorDomainPermissionDraftSearchResp, ModeratorDomainPermissionDraftSearchParams>({
searchDomainPermissionDrafts: build.query<DomainPermDraftSearchResp, DomainPermDraftSearchParams>({
query: (form) => {
const params = new(URLSearchParams);
Object.entries(form).forEach(([k, v]) => {
@ -66,6 +67,17 @@ const extended = gtsApi.injectEndpoints({
{ type: 'DomainPermissionDraft', id }
],
}),
createDomainPermissionDraft: build.mutation<DomainPerm, DomainPermDraftCreateParams>({
query: (formData) => ({
method: "POST",
url: `/api/v1/admin/domain_permission_drafts`,
asForm: true,
body: formData,
discardEmpty: true
}),
invalidatesTags: [{ type: "DomainPermissionDraft", id: "TRANSFORMED" }],
}),
}),
});
@ -79,7 +91,13 @@ const useLazySearchDomainPermissionDraftsQuery = extended.useLazySearchDomainPer
*/
const useGetDomainPermissionDraftQuery = extended.useGetDomainPermissionDraftQuery;
/**
* Create a domain permission draft with the given parameters.
*/
const useCreateDomainPermissionDraftMutation = extended.useCreateDomainPermissionDraftMutation;
export {
useLazySearchDomainPermissionDraftsQuery,
useGetDomainPermissionDraftQuery,
useCreateDomainPermissionDraftMutation,
};

View file

@ -33,6 +33,8 @@ export interface DomainPerm {
private_comment?: string;
public_comment?: string;
created_at?: string;
created_by?: string;
subscription_id?: string;
// Keys that should be stripped before
// sending the domain permission (if imported).
@ -99,7 +101,7 @@ export interface ExportDomainPermsParams {
/**
* Parameters for GET to /api/v1/admin/domain_permission_drafts.
*/
export interface ModeratorDomainPermissionDraftSearchParams {
export interface DomainPermDraftSearchParams {
/**
* Show only drafts created by the given subscription ID.
*/
@ -136,7 +138,7 @@ export interface ModeratorDomainPermissionDraftSearchParams {
/**
* Parameters for POST to /api/v1/admin/domain_permission_drafts/{id}/accept.
*/
export interface ModeratorDomainPermissionDraftAcceptParams {
export interface DomainPermDraftAcceptParams {
/**
* ID of the domain permission draft.
*/
@ -151,7 +153,7 @@ export interface ModeratorDomainPermissionDraftAcceptParams {
/**
* Parameters for POST to /api/v1/admin/domain_permission_drafts/{id}/accept.
*/
export interface ModeratorDomainPermissionDraftRejectParams {
export interface DomainPermDraftRejectParams {
/**
* ID of the domain permission draft.
*/
@ -163,7 +165,34 @@ export interface ModeratorDomainPermissionDraftRejectParams {
ignore_target?: boolean;
}
export interface ModeratorDomainPermissionDraftSearchResp {
export interface DomainPermDraftSearchResp {
drafts: DomainPerm[];
links: Links | null;
}
export interface DomainPermDraftCreateParams {
/**
* Domain to create the permission draft for.
*/
domain: string;
/**
* Create a draft "allow" or a draft "block".
*/
permission_type: PermType;
/**
* Obfuscate the name of the domain when serving it publicly.
* Eg., `example.org` becomes something like `ex***e.org`.
*/
obfuscate?: boolean;
/**
* Public comment about this domain permission. This will be displayed
* alongside the domain permission if you choose to share permissions.
*/
public_comment?: string;
/**
* Private comment about this domain permission.
* Will only be shown to other admins, so this is a useful way of
* internally keeping track of why a certain domain ended up permissioned.
*/
private_comment?: string;
}

View file

@ -0,0 +1,48 @@
/*
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 isValidDomain from "is-valid-domain";
/**
* Validate the "domain" field of a form.
* @param domain
* @returns
*/
export function formDomainValidator(domain: string): string {
if (domain.length === 0) {
return "";
}
if (domain[domain.length-1] === ".") {
return "invalid domain";
}
const valid = isValidDomain(domain, {
subdomain: true,
wildcard: false,
allowUnicode: true,
topLevel: false,
});
if (valid) {
return "";
}
return "invalid domain";
}

View file

@ -1359,6 +1359,50 @@ button.tab-button {
}
}
.domain-permission-drafts-view {
.domain-permission-draft {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
&.block {
border-left: 0.3rem solid $error3;
}
&.allow {
border-left: 0.3rem solid $green1;
}
&:hover {
border-color: $fg-accent;
}
.info-list {
border: none;
.info-list-entry {
background: none;
padding: 0;
}
}
}
}
.domain-permission-draft-details {
.info-list {
margin-top: 1rem;
}
}
.domain-permission-drafts-view,
.domain-permission-draft-details {
dd.permission-type {
display: flex;
gap: 0.35rem;
align-items: center;
}
}
.instance-rules {
list-style-position: inside;
margin: 0;

View file

@ -27,7 +27,7 @@ import MutationButton from "../../../../components/form/mutation-button";
import { useLocation, useSearch } from "wouter";
import { AdminAccount } from "../../../../lib/types/account";
import Username from "../../../../components/username";
import isValidDomain from "is-valid-domain";
import { formDomainValidator } from "../../../../lib/util/formvalidators";
export function AccountSearchForm() {
const [ location, setLocation ] = useLocation();
@ -45,28 +45,7 @@ export function AccountSearchForm() {
display_name: useTextInput("display_name", { defaultValue: urlQueryParams.get("display_name") ?? ""}),
by_domain: useTextInput("by_domain", {
defaultValue: urlQueryParams.get("by_domain") ?? "",
validator: (v: string) => {
if (v.length === 0) {
return "";
}
if (v[v.length-1] === ".") {
return "invalid domain";
}
const valid = isValidDomain(v, {
subdomain: true,
wildcard: false,
allowUnicode: true,
topLevel: false,
});
if (valid) {
return "";
}
return "invalid domain";
}
validator: formDomainValidator,
}),
email: useTextInput("email", { defaultValue: urlQueryParams.get("email") ?? ""}),
ip: useTextInput("ip", { defaultValue: urlQueryParams.get("ip") ?? ""}),

View file

@ -0,0 +1,151 @@
/*
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, { useEffect, useMemo } from "react";
import { useParams } from "wouter";
import Loading from "../../../../components/loading";
import { useBaseUrl } from "../../../../lib/navigation/util";
import BackButton from "../../../../components/back-button";
import { useGetDomainPermissionDraftQuery } from "../../../../lib/query/admin/domain-permissions/drafts";
import { Error as ErrorC } from "../../../../components/error";
import Username from "../../../../components/username";
import { useLazyGetAccountQuery } from "../../../../lib/query/admin";
export default function DomainPermissionDraftDetail() {
const baseUrl = useBaseUrl();
const backLocation: String = history.state?.backLocation ?? `~${baseUrl}`;
const params = useParams();
let draftID = params.permDraftId as string | undefined;
if (!draftID) {
throw "no perm ID";
}
const {
data: permDraft,
isLoading,
isFetching,
isError,
error,
} = useGetDomainPermissionDraftQuery(draftID);
// Once we've triggered loading the perm draft,
// trigger getting the account that created it.
const [ getAccount, getAccountRes ] = useLazyGetAccountQuery();
useEffect(() => {
if (!permDraft) {
return;
}
if (!permDraft.created_by) {
return;
}
getAccount(permDraft.created_by, true);
}, [getAccount, permDraft]);
// Load the createdByAccount if possible,
// returning a username lozenge with
// a link to the account.
const createdByAccount = useMemo(() => {
const {
data: account,
isLoading: isLoadingAccount,
isFetching: isFetchingAccount,
isError: isErrorAccount,
} = getAccountRes;
// Wait for query to finish, returning
// loading spinner in the meantime.
if (isLoadingAccount || isFetchingAccount || !permDraft) {
return <Loading />;
} else if (isErrorAccount || account === undefined) {
// Fall back to account ID.
return permDraft?.created_by;
}
return (
<Username
account={account}
linkTo={`~/settings/moderation/accounts/${account.id}`}
backLocation={`~${location}`}
/>
);
}, [getAccountRes, permDraft]);
if (isLoading || isFetching) {
return <Loading />;
} else if (isError) {
return <ErrorC error={error} />;
} else if (permDraft === undefined) {
return <ErrorC error={new Error("permission draft was undefined")} />;
}
const created = permDraft.created_at ? new Date(permDraft.created_at).toDateString(): "unknown";
const domain = permDraft.domain;
const permType = permDraft.permission_type;
if (!permType) {
return <ErrorC error={new Error("permission_type was undefined")} />;
}
const publicComment = permDraft.public_comment ?? "[none]";
const privateComment = permDraft.private_comment ?? "[none]";
const subscriptionID = permDraft.subscription_id ?? "[none]";
return (
<div className="domain-permission-draft-details">
<h1><BackButton to={backLocation} /> Domain Permission Draft Detail</h1>
<dl className="info-list">
<div className="info-list-entry">
<dt>Created</dt>
<dd><time dateTime={permDraft.created_at}>{created}</time></dd>
</div>
<div className="info-list-entry">
<dt>Created By</dt>
<dd>{createdByAccount}</dd>
</div>
<div className="info-list-entry">
<dt>Domain</dt>
<dd>{domain}</dd>
</div>
<div className="info-list-entry">
<dt>Permission type</dt>
<dd className={`permission-type ${permType}`}>
<i
aria-hidden={true}
className={`fa fa-${permType === "allow" ? "check" : "close"}`}
></i>
{permType}
</dd>
</div>
<div className="info-list-entry">
<dt>Private comment</dt>
<dd>{privateComment}</dd>
</div>
<div className="info-list-entry">
<dt>Public comment</dt>
<dd>{publicComment}</dd>
</div>
<div className="info-list-entry">
<dt>Subscription ID</dt>
<dd>{subscriptionID}</dd>
</div>
</dl>
</div>
);
}

View file

@ -25,6 +25,9 @@ import MutationButton from "../../../../components/form/mutation-button";
import { useLocation, useSearch } from "wouter";
import { useLazySearchDomainPermissionDraftsQuery } from "../../../../lib/query/admin/domain-permissions/drafts";
import { DomainPerm } from "../../../../lib/types/domain-permission";
import { Error as ErrorC } from "../../../../components/error";
import { Select, TextInput } from "../../../../components/form/inputs";
import { formDomainValidator } from "../../../../lib/util/formvalidators";
export default function DomainPermissionDraftsSearch() {
return (
@ -53,7 +56,10 @@ function DomainPermissionDraftsSearchForm() {
const form = {
subscription_id: useTextInput("subscription_id", { defaultValue: urlQueryParams.get("subscription_id") ?? "" }),
domain: useTextInput("domain", { defaultValue: urlQueryParams.get("domain") ?? "" }),
domain: useTextInput("domain", {
defaultValue: urlQueryParams.get("domain") ?? "",
validator: formDomainValidator,
}),
permission_type: useTextInput("permission_type", { defaultValue: urlQueryParams.get("permission_type") ?? "" }),
limit: useTextInput("limit", { defaultValue: urlQueryParams.get("limit") ?? "20" })
};
@ -111,8 +117,8 @@ function DomainPermissionDraftsSearchForm() {
return (
<DraftListEntry
key={draft.id}
draft={draft}
linkTo={`/${draft.id}`}
permDraft={draft}
linkTo={`/drafts/${draft.id}`}
backLocation={backLocation}
/>
);
@ -126,17 +132,35 @@ function DomainPermissionDraftsSearchForm() {
// trying to fill in fields.
autoComplete="off"
>
{/* <Select
field={form.resolved}
label="Report status"
<Select
field={form.permission_type}
label="Permission type"
options={
<>
<option value="false">Unresolved only</option>
<option value="true">Resolved only</option>
<option value="">Any</option>
<option value="block">Block</option>
<option value="allow">Allow</option>
</>
}
></Select> */}
></Select>
<TextInput
field={form.domain}
label={`Domain (without "https://" prefix)`}
placeholder="example.org"
autoCapitalize="none"
spellCheck="false"
/>
<Select
field={form.limit}
label="Items per page"
options={
<>
<option value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
</>
}
></Select>
<MutationButton
disabled={false}
label={"Search"}
@ -159,17 +183,25 @@ function DomainPermissionDraftsSearchForm() {
}
interface DraftEntryProps {
draft: DomainPerm;
permDraft: DomainPerm;
linkTo: string;
backLocation: string;
}
function DraftListEntry({ draft, linkTo, backLocation }: DraftEntryProps) {
function DraftListEntry({ permDraft, linkTo, backLocation }: DraftEntryProps) {
const [ _location, setLocation ] = useLocation();
const domain = permDraft.domain;
const permType = permDraft.permission_type;
if (!permType) {
return <ErrorC error={new Error("permission_type was undefined")} />;
}
const privateComment = permDraft.private_comment ?? "[none]";
const subscriptionID = permDraft.subscription_id ?? "[none]";
return (
<span
className={`pseudolink domain-permission-draft`}
className={`pseudolink domain-permission-draft entry ${permType}`}
// aria-label={title}
// title={title}
onClick={() => {
@ -186,7 +218,28 @@ function DraftListEntry({ draft, linkTo, backLocation }: DraftEntryProps) {
tabIndex={0}
>
<dl className="info-list">
<div className="info-list-entry">
<dt>Domain:</dt>
<dd className="text-cutoff">{domain}</dd>
</div>
<div className="info-list-entry">
<dt>Permission type:</dt>
<dd className={`permission-type ${permType}`}>
<i
aria-hidden={true}
className={`fa fa-${permType === "allow" ? "check" : "close"}`}
></i>
{permType}
</dd>
</div>
<div className="info-list-entry">
<dt>Private comment:</dt>
<dd className="text-cutoff">{privateComment}</dd>
</div>
<div className="info-list-entry">
<dt>Subscription:</dt>
<dd className="text-cutoff">{subscriptionID}</dd>
</div>
</dl>
</span>
);

View file

@ -18,7 +18,91 @@
*/
import React from "react";
import useFormSubmit from "../../../../lib/form/submit";
import { useCreateDomainPermissionDraftMutation } from "../../../../lib/query/admin/domain-permissions/drafts";
import { useBoolInput, useRadioInput, useTextInput } from "../../../../lib/form";
import { formDomainValidator } from "../../../../lib/util/formvalidators";
import MutationButton from "../../../../components/form/mutation-button";
import { Checkbox, RadioGroup, TextArea, TextInput } from "../../../../components/form/inputs";
export default function DomainPermissionDraftNew() {
return <></>;
const form = {
domain: useTextInput("domain", {
validator: formDomainValidator,
}),
permission_type: useRadioInput("permission_type", {
options: {
block: "Block domain",
allow: "Allow domain",
}
}),
obfuscate: useBoolInput("obfuscate"),
public_comment: useTextInput("public_comment"),
private_comment: useTextInput("private_comment"),
};
const [formSubmit, result] = useFormSubmit(form, useCreateDomainPermissionDraftMutation());
return (
<form
onSubmit={formSubmit}
// Prevent password managers
// trying to fill in fields.
autoComplete="off"
>
<div className="form-section-docs">
<h2>New Domain Permission Draft</h2>
<p>
You can use the form below to create a new domain permission draft.
<br/>
Domain permission drafts are domain block or domain allow entries that are not yet in force.
<br/>
You can choose to accept or remove a draft.
</p>
</div>
<RadioGroup
field={form.permission_type}
/>
<TextInput
field={form.domain}
label={`Domain (without "https://" prefix)`}
placeholder="example.org"
autoCapitalize="none"
spellCheck="false"
/>
<TextArea
field={form.private_comment}
label={"Private comment"}
placeholder="This domain is like unto a clown car full of clowns, I suggest we block it forthwith."
autoCapitalize="sentences"
rows={3}
/>
<TextArea
field={form.public_comment}
label={"Public comment"}
placeholder="Bad posters"
autoCapitalize="sentences"
rows={3}
/>
<Checkbox
field={form.obfuscate}
label="Obfuscate domain in public lists"
/>
<MutationButton
label="Save"
result={result}
disabled={
!form.domain.value ||
!form.domain.valid ||
!form.permission_type.value
}
/>
</form>
);
}

View file

@ -31,6 +31,7 @@ import AccountsPending from "./accounts/pending";
import AccountDetail from "./accounts/detail";
import DomainPermissionDraftsSearch from "./domain-permissions/drafts";
import DomainPermissionDraftNew from "./domain-permissions/drafts/new";
import DomainPermissionDraftDetail from "./domain-permissions/drafts/detail";
/*
EXPORTED COMPONENTS
@ -143,6 +144,7 @@ function ModerationDomainPermsRouter() {
<Route path="/process" component={ImportExport} />
<Route path="/drafts/search" component={DomainPermissionDraftsSearch} />
<Route path="/drafts/new" component={DomainPermissionDraftNew} />
<Route path="/drafts/:permDraftId" component={DomainPermissionDraftDetail} />
<Route path="/:permType" component={DomainPermissionsOverview} />
<Route path="/:permType/:domain" component={DomainPermDetail} />
<Route><Redirect to="/blocks"/></Route>

View file

@ -3213,9 +3213,9 @@ electron-to-chromium@^1.4.668:
integrity sha512-jeWaIta2rIG2FzHaYIhSuVWqC6KJYo7oSBX4Jv7g+aVujKztfvdpf+n6MGwZdC5hQXbax4nntykLH2juIQrfPg==
elliptic@^6.5.3, elliptic@^6.5.4:
version "6.5.7"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b"
integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==
version "6.6.0"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210"
integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==
dependencies:
bn.js "^4.11.9"
brorand "^1.1.0"

View file

@ -172,7 +172,7 @@ Polls can have up to
<p>
ActivityPub instances federate with other instances by exchanging data with them over the network.
Exchanged data includes things like accounts, statuses, likes, boosts, and media attachments.
This exchange of data can prevented for instances on specific domains via a domain block created
This exchange of data can be prevented for instances on specific domains via a domain block created
by an instance admin. When an instance is domain blocked by another instance:
</p>
<ul>