update doc and etc
This commit is contained in:
parent
70eba30079
commit
bea87f22be
10 changed files with 35 additions and 162 deletions
|
@ -72,8 +72,6 @@ env = environ.FileAwareEnv(
|
||||||
NEODB_EMAIL_URL=(str, ""),
|
NEODB_EMAIL_URL=(str, ""),
|
||||||
# EMAIL FROM
|
# EMAIL FROM
|
||||||
NEODB_EMAIL_FROM=(str, "🧩 NeoDB <no-reply@neodb.social>"),
|
NEODB_EMAIL_FROM=(str, "🧩 NeoDB <no-reply@neodb.social>"),
|
||||||
# ADMIN_USERS
|
|
||||||
NEODB_ADMIN_USERNAMES=(list, []),
|
|
||||||
# List of available proxies for proxy downloader, in format of http://server1?url=__URL__,http://s2?url=__URL__,...
|
# List of available proxies for proxy downloader, in format of http://server1?url=__URL__,http://s2?url=__URL__,...
|
||||||
NEODB_DOWNLOADER_PROXY_LIST=(list, []),
|
NEODB_DOWNLOADER_PROXY_LIST=(list, []),
|
||||||
# Timeout of downloader requests, in seconds
|
# Timeout of downloader requests, in seconds
|
||||||
|
@ -216,8 +214,6 @@ SITE_INFO = {
|
||||||
# "cdn_url": "https://fastly.jsdelivr.net",
|
# "cdn_url": "https://fastly.jsdelivr.net",
|
||||||
}
|
}
|
||||||
|
|
||||||
SETUP_ADMIN_USERNAMES = env("NEODB_ADMIN_USERNAMES")
|
|
||||||
|
|
||||||
INVITE_ONLY = env("NEODB_INVITE_ONLY")
|
INVITE_ONLY = env("NEODB_INVITE_ONLY")
|
||||||
|
|
||||||
# By default, NeoDB will relay with relay.neodb.net so that public user ratings/etc can be shared across instances
|
# By default, NeoDB will relay with relay.neodb.net so that public user ratings/etc can be shared across instances
|
||||||
|
|
|
@ -86,17 +86,6 @@ class Setup:
|
||||||
defaults={"json": icon},
|
defaults={"json": icon},
|
||||||
)
|
)
|
||||||
|
|
||||||
def sync_admin_user(self):
|
|
||||||
users = User.objects.filter(username__in=settings.SETUP_ADMIN_USERNAMES)
|
|
||||||
for user in users:
|
|
||||||
if user.is_superuser:
|
|
||||||
logger.debug(f"User {user.username} is already admin")
|
|
||||||
else:
|
|
||||||
user.is_superuser = True
|
|
||||||
user.save(update_fields=["is_superuser"])
|
|
||||||
TakaheUser.objects.filter(email=f"@{user.username}").update(admin=True)
|
|
||||||
logger.info(f"Updated user {user.username} as admin")
|
|
||||||
|
|
||||||
def sync_relay(self):
|
def sync_relay(self):
|
||||||
relay = TakaheRelay.objects.filter(
|
relay = TakaheRelay.objects.filter(
|
||||||
state__in=["new", "subscribing", "subscribed"],
|
state__in=["new", "subscribing", "subscribed"],
|
||||||
|
@ -131,9 +120,6 @@ class Setup:
|
||||||
# Update site name if changed
|
# Update site name if changed
|
||||||
self.sync_site_config()
|
self.sync_site_config()
|
||||||
|
|
||||||
# Create/update admin user if configured in env
|
|
||||||
self.sync_admin_user()
|
|
||||||
|
|
||||||
# Subscribe to default relay if enabled
|
# Subscribe to default relay if enabled
|
||||||
self.sync_relay()
|
self.sync_relay()
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ x-shared:
|
||||||
NEODB_SITE_DESCRIPTION:
|
NEODB_SITE_DESCRIPTION:
|
||||||
NEODB_ALTERNATIVE_DOMAINS:
|
NEODB_ALTERNATIVE_DOMAINS:
|
||||||
NEODB_PREFERRED_LANGUAGES:
|
NEODB_PREFERRED_LANGUAGES:
|
||||||
NEODB_ADMIN_USERNAMES:
|
|
||||||
NEODB_INVITE_ONLY:
|
NEODB_INVITE_ONLY:
|
||||||
NEODB_LOGIN_MASTODON_WHITELIST:
|
NEODB_LOGIN_MASTODON_WHITELIST:
|
||||||
NEODB_MASTODON_CLIENT_SCOPE:
|
NEODB_MASTODON_CLIENT_SCOPE:
|
||||||
|
|
|
@ -33,7 +33,6 @@ if you are doing debug or development:
|
||||||
- `NEODB_INVITE_ONLY` - `False` by default, set to `True` to require invite code(generated by `neodb-manage invite --create`) to register
|
- `NEODB_INVITE_ONLY` - `False` by default, set to `True` to require invite code(generated by `neodb-manage invite --create`) to register
|
||||||
- `NEODB_ENABLE_LOCAL_ONLY` - `False` by default, set to `True` to allow user to post marks as "local public"
|
- `NEODB_ENABLE_LOCAL_ONLY` - `False` by default, set to `True` to allow user to post marks as "local public"
|
||||||
- `NEODB_LOGIN_MASTODON_WHITELIST` - a list of Mastodon instances to allow login from, comma separated
|
- `NEODB_LOGIN_MASTODON_WHITELIST` - a list of Mastodon instances to allow login from, comma separated
|
||||||
- `NEODB_ADMIN_USERNAMES` - a list of usernames to be admin, comma separated, server restart is required to apply this setting after these users are registered.
|
|
||||||
- `NEODB_EMAIL_FROM` - the email address to send email from
|
- `NEODB_EMAIL_FROM` - the email address to send email from
|
||||||
- `NEODB_EMAIL_URL` - email sender configuration, e.g.
|
- `NEODB_EMAIL_URL` - email sender configuration, e.g.
|
||||||
- `smtp://<username>:<password>@<host>:<port>`
|
- `smtp://<username>:<password>@<host>:<port>`
|
||||||
|
@ -68,6 +67,39 @@ Add alias to your shell for easier access
|
||||||
alias neodb-manage='docker-compose --profile production run shell neodb-manage'
|
alias neodb-manage='docker-compose --profile production run shell neodb-manage'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Toggle user's active, staff and super user status
|
||||||
|
|
||||||
|
```
|
||||||
|
neodb-manage user active <username>
|
||||||
|
neodb-manage user staff <username>
|
||||||
|
neodb-manage user super <username>
|
||||||
|
```
|
||||||
|
|
||||||
|
Create an invite link
|
||||||
|
|
||||||
|
```
|
||||||
|
neo-manage invite --create
|
||||||
|
```
|
||||||
|
|
||||||
|
Manage user tasks and cron jobs
|
||||||
|
|
||||||
|
```
|
||||||
|
neodb-manage task --list
|
||||||
|
neodb-manage cron --list
|
||||||
|
```
|
||||||
|
|
||||||
|
Manage search index
|
||||||
|
```
|
||||||
|
neo-manage index --reindex
|
||||||
|
```
|
||||||
|
|
||||||
|
Crawl links
|
||||||
|
```
|
||||||
|
neodb-manage cat [--save] <url> # parse / save a supported link
|
||||||
|
neodb-manage crawl <url> # crawl all recognizable links from a page
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Run without Docker
|
## Run without Docker
|
||||||
|
|
||||||
It's currently possible but quite cumbersome to run without Docker, hence not recommended. However it's possible to only use docker to run neodb server but reuse existing PostgresQL/Redis/Typesense servers with `compose.override.yml`, an example for reference:
|
It's currently possible but quite cumbersome to run without Docker, hence not recommended. However it's possible to only use docker to run neodb server but reuse existing PostgresQL/Redis/Typesense servers with `compose.override.yml`, an example for reference:
|
||||||
|
|
|
@ -81,24 +81,10 @@ You should see the same JSON response as above, and the site is now accessible t
|
||||||
|
|
||||||
## Register an account and make it admin
|
## Register an account and make it admin
|
||||||
|
|
||||||
If you have email sender properly configured, use this command to create an admin with a verified email (use any password as it won't be saved)
|
Open `https://yourdomain.tld` in your browser and register an account, assuming username `admin`, run the following command to make it super user
|
||||||
|
|
||||||
```
|
```
|
||||||
docker compose --profile production run --rm shell neodb-manage createsuperuser
|
docker compose --profile production run --rm shell neodb-manage user --super admin
|
||||||
```
|
|
||||||
|
|
||||||
Now open `https://yourdomain.tld` in your browser and register an account, assuming username `admin`
|
|
||||||
|
|
||||||
add the following line to `.env` to make it an admin account:
|
|
||||||
|
|
||||||
```
|
|
||||||
NEODB_ADMIN_USERS=admin
|
|
||||||
```
|
|
||||||
|
|
||||||
now restart the cluster to make it effective:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose --profile production up -d
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Now your instance should be ready to serve. More tweaks are available, see [configuration](configuration.md) for options.
|
Now your instance should be ready to serve. More tweaks are available, see [configuration](configuration.md) for options.
|
||||||
|
|
|
@ -30,9 +30,6 @@ NEODB_SITE_LINKS=@NiceDB=https://donotban.com/@testie,@NeoDB=https://mastodon.so
|
||||||
# Path to store db/media/cache/etc, must be writable
|
# Path to store db/media/cache/etc, must be writable
|
||||||
# NEODB_DATA=/var/lib/neodb
|
# NEODB_DATA=/var/lib/neodb
|
||||||
|
|
||||||
# Users with these names will be promoted to admin during next boot/migration
|
|
||||||
# NEODB_ADMIN_USERNAMES = eggplant,aubergine
|
|
||||||
|
|
||||||
# Scaling parameters
|
# Scaling parameters
|
||||||
# NEODB_WEB_WORKER_NUM=32
|
# NEODB_WEB_WORKER_NUM=32
|
||||||
# NEODB_API_WORKER_NUM=16
|
# NEODB_API_WORKER_NUM=16
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
|
||||||
from django.utils import timezone
|
|
||||||
|
|
||||||
from users.models import User
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
|
||||||
help = "disable user"
|
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
|
||||||
parser.add_argument("id", type=int, help="user id")
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
|
||||||
h = int(options["id"])
|
|
||||||
u = User.objects.get(pk=h)
|
|
||||||
u.is_active = False
|
|
||||||
u.save()
|
|
||||||
print(f"{u} disabled")
|
|
|
@ -1,77 +0,0 @@
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
from django.apps import apps
|
|
||||||
from django.core.management.base import BaseCommand
|
|
||||||
from django.utils import timezone
|
|
||||||
from tqdm import tqdm
|
|
||||||
|
|
||||||
from users.models.user import _RESERVED_USERNAMES
|
|
||||||
|
|
||||||
User = apps.get_model("users", "User")
|
|
||||||
_RESERVED_USERNAMES = [
|
|
||||||
"connect",
|
|
||||||
"oauth2_login",
|
|
||||||
"__",
|
|
||||||
"admin",
|
|
||||||
"api",
|
|
||||||
"me",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
|
||||||
help = "Generate unique username"
|
|
||||||
|
|
||||||
def process_users(self, users):
|
|
||||||
count = 0
|
|
||||||
for user in users:
|
|
||||||
if not user.is_active:
|
|
||||||
un = f"-{user.pk}-"
|
|
||||||
else:
|
|
||||||
un = user.mastodon_username
|
|
||||||
if not un:
|
|
||||||
un = f"_{user.pk}"
|
|
||||||
if un.lower() in _RESERVED_USERNAMES:
|
|
||||||
un = f"__{un}"
|
|
||||||
if User.objects.filter(username__iexact=un).exists(): # type: ignore
|
|
||||||
un = f"{un}_{user.pk}"
|
|
||||||
print(f"{user} -> {un}")
|
|
||||||
user.username = un
|
|
||||||
user.save(update_fields=["username"])
|
|
||||||
count += 1
|
|
||||||
print(f"{count} users updated")
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
|
||||||
print("Processing active users")
|
|
||||||
# recent logged in users
|
|
||||||
proactive_users = User.objects.filter( # type: ignore
|
|
||||||
username__isnull=True,
|
|
||||||
is_active=True,
|
|
||||||
last_login__gt=timezone.now() - timedelta(days=30),
|
|
||||||
).order_by("date_joined")
|
|
||||||
# users with mastodon token still active
|
|
||||||
active_users = (
|
|
||||||
User.objects.filter( # type: ignore
|
|
||||||
username__isnull=True,
|
|
||||||
is_active=True,
|
|
||||||
)
|
|
||||||
.exclude(mastodon_token="")
|
|
||||||
.order_by("date_joined")
|
|
||||||
)
|
|
||||||
# users with mastodon handler still reachable
|
|
||||||
reachable_users = User.objects.filter( # type: ignore
|
|
||||||
username__isnull=True,
|
|
||||||
is_active=True,
|
|
||||||
mastodon_last_reachable__gt=timezone.now() - timedelta(days=7),
|
|
||||||
).order_by("date_joined")
|
|
||||||
# all other users
|
|
||||||
users = User.objects.filter( # type: ignore
|
|
||||||
username__isnull=True,
|
|
||||||
).order_by("date_joined")
|
|
||||||
print(f"{proactive_users.count()} proactive users")
|
|
||||||
self.process_users(proactive_users)
|
|
||||||
print(f"{active_users.count()} active users")
|
|
||||||
self.process_users(active_users)
|
|
||||||
print(f"{reachable_users.count()} reachable users")
|
|
||||||
self.process_users(reachable_users)
|
|
||||||
print(f"{users.count()} other users")
|
|
||||||
self.process_users(users)
|
|
|
@ -1,26 +0,0 @@
|
||||||
from django.conf import settings
|
|
||||||
from django.core.management.base import BaseCommand
|
|
||||||
from loguru import logger
|
|
||||||
from tqdm import tqdm
|
|
||||||
|
|
||||||
from users.models import Preference, User
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
|
||||||
help = "Manage import tasks"
|
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
|
||||||
parser.add_argument(
|
|
||||||
"--reset",
|
|
||||||
action="store_true",
|
|
||||||
)
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
|
||||||
if options["reset"]:
|
|
||||||
count = 0
|
|
||||||
for user in tqdm(User.objects.all()):
|
|
||||||
if user.preference.import_status.get("douban_pending"):
|
|
||||||
user.preference.import_status["douban_pending"] = False
|
|
||||||
user.preference.save(update_fields=["import_status"])
|
|
||||||
count += 1
|
|
||||||
self.stdout.write(self.style.SUCCESS(f"{count} users reset"))
|
|
Loading…
Add table
Reference in a new issue