More work towards support moving/deleting instance

This commit is contained in:
Thomas Sileo 2022-09-01 20:42:20 +02:00
parent b03daf1274
commit 5f20eab3f1
7 changed files with 126 additions and 1 deletions

View file

@ -17,3 +17,7 @@ update:
.PHONY: prune-old-data .PHONY: prune-old-data
prune-old-data: prune-old-data:
-docker run --volume `pwd`/data:/app/data --volume `pwd`/app/static:/app/app/static microblogpub/microblogpub inv prune-old-data -docker run --volume `pwd`/data:/app/data --volume `pwd`/app/static:/app/app/static microblogpub/microblogpub inv prune-old-data
.PHONY: webfinger
webfinger:
-docker run --volume `pwd`/data:/app/data --volume `pwd`/app/static:/app/app/static microblogpub/microblogpub inv webfinger $(account)

View file

@ -9,6 +9,7 @@ from loguru import logger
from markdown import markdown from markdown import markdown
from app import config from app import config
from app.config import ALSO_KNOWN_AS
from app.config import AP_CONTENT_TYPE # noqa: F401 from app.config import AP_CONTENT_TYPE # noqa: F401
from app.httpsig import auth from app.httpsig import auth
from app.key import get_pubkey_as_pem from app.key import get_pubkey_as_pem
@ -126,6 +127,9 @@ ME = {
"tag": _LOCAL_ACTOR_TAGS, "tag": _LOCAL_ACTOR_TAGS,
} }
if ALSO_KNOWN_AS:
ME["alsoKnownAs"] = [ALSO_KNOWN_AS]
class NotAnObjectError(Exception): class NotAnObjectError(Exception):
def __init__(self, url: str, resp: httpx.Response | None = None) -> None: def __init__(self, url: str, resp: httpx.Response | None = None) -> None:

View file

@ -87,6 +87,7 @@ class Config(pydantic.BaseModel):
blocked_servers: list[_BlockedServer] = [] blocked_servers: list[_BlockedServer] = []
custom_footer: str | None = None custom_footer: str | None = None
emoji: str | None = None emoji: str | None = None
also_known_as: str | None = None
inbox_retention_days: int = 15 inbox_retention_days: int = 15
@ -135,6 +136,7 @@ if CONFIG.privacy_replace:
PRIVACY_REPLACE = {pr.domain: pr.replace_by for pr in CONFIG.privacy_replace} PRIVACY_REPLACE = {pr.domain: pr.replace_by for pr in CONFIG.privacy_replace}
BLOCKED_SERVERS = {blocked_server.hostname for blocked_server in CONFIG.blocked_servers} BLOCKED_SERVERS = {blocked_server.hostname for blocked_server in CONFIG.blocked_servers}
ALSO_KNOWN_AS = CONFIG.also_known_as
INBOX_RETENTION_DAYS = CONFIG.inbox_retention_days INBOX_RETENTION_DAYS = CONFIG.inbox_retention_days
CUSTOM_FOOTER = ( CUSTOM_FOOTER = (

View file

@ -251,6 +251,7 @@ async def index(
page: int | None = None, page: int | None = None,
) -> templates.TemplateResponse | ActivityPubResponse: ) -> templates.TemplateResponse | ActivityPubResponse:
if is_activitypub_requested(request): if is_activitypub_requested(request):
return ActivityPubResponse(LOCAL_ACTOR.ap_actor) return ActivityPubResponse(LOCAL_ACTOR.ap_actor)
page = page or 1 page = page or 1

View file

@ -29,6 +29,7 @@ async def webfinger(
is_404 = False is_404 = False
resp: httpx.Response | None = None
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
for i, proto in enumerate(protos): for i, proto in enumerate(protos):
try: try:
@ -59,7 +60,10 @@ async def webfinger(
if is_404: if is_404:
return None return None
if resp:
return resp.json() return resp.json()
else:
return None
async def get_remote_follow_template(resource: str) -> str | None: async def get_remote_follow_template(resource: str) -> str | None:

View file

@ -235,6 +235,42 @@ All the data generated by the server is located in the `data/` directory:
Restoring is as easy as adding your backed up `data/` directory into a fresh deployment. Restoring is as easy as adding your backed up `data/` directory into a fresh deployment.
## Moving from another instance
If you want to move followers from your existing account, ensure it is supported in your software documentation.
For [Mastodon you can look at Moving or leaving accounts](https://docs.joinmastodon.org/user/moving/).
First you need to grab the "ActivityPub actor URL" for your existing account:
### Python edition
```bash
# For a Python install
poetry run inv webfinger username@domain.tld
```
Edit the config.
### Docker edition
```bash
# For a Docker install
make account=username@domain.tld webfinger
```
Edit the config.
#### Edit the config
And add a reference to your old/existing account in `profile.toml`:
```toml
also_known_as = "my@old-account.com"
```
Restart the server, and you should be able to complete the move from your existing account.
## Tasks ## Tasks
### Pruning old data ### Pruning old data
@ -280,3 +316,48 @@ make prune-old-data
docker compose up -d docker compose up -d
rm data/microblogpub.db.bak rm data/microblogpub.db.bak
``` ```
### Moving to another instance
**This section is just a draft.**
If you want to migrate to another instance, you have the ability to move your existing followers to your new account.
Your new account should reference the existing one, refer to your software configuration (for example [Moving or leaving accounts from the Mastodon doc](https://docs.joinmastodon.org/user/moving/)).
Execute the Move task:
#### Python edition
```bash
# For a Python install
poetry run inv move username@domain.tld
```
#### Docker edition
```bash
# For a Docker install
make account=username@domain.tld move
```
### Deleting the instance
**This section is just a draft.**
You want to delete your instance, you can request other instances to delete your remote profile.
Once deleted, you won't be able to use your instance anymore.
#### Python edition
```bash
# For a Python install
poetry run inv self-destruct
```
#### Docker edition
```bash
# For a Docker install
make self-destruct
```

View file

@ -190,6 +190,35 @@ def prune_old_data(ctx):
asyncio.run(run_prune_old_data()) asyncio.run(run_prune_old_data())
@task
def webfinger(ctx, account):
# type: (Context, str) -> None
import traceback
from loguru import logger
from app.source import _MENTION_REGEX
from app.webfinger import get_actor_url
logger.disable("app")
if not account.startswith("@"):
account = f"@{account}"
if not _MENTION_REGEX.match(account):
print(f"Invalid acccount {account}")
return
print(f"Resolving {account}")
try:
maybe_actor_url = asyncio.run(get_actor_url(account))
if maybe_actor_url:
print(f"SUCCESS: {maybe_actor_url}")
else:
print(f"ERROR: Failed to resolve {account}")
except Exception as exc:
print(f"ERROR: Failed to resolve {account}")
print("".join(traceback.format_exception(exc)))
@task @task
def yunohost_config( def yunohost_config(
ctx, ctx,