allow alternative hostnames

This commit is contained in:
Your Name 2024-04-06 11:53:31 -04:00 committed by Henri Dickson
parent f2abc7a7c0
commit d2d755d7f6
16 changed files with 73 additions and 196 deletions

View file

@ -1,5 +1,5 @@
# 🧩 NeoDB
_mark the things you love._
_mark the things you love_
![](https://github.com/neodb-social/neodb/actions/workflows/check.yml/badge.svg?branch=main)
![](https://github.com/neodb-social/neodb/actions/workflows/tests.yml/badge.svg?branch=main)

View file

@ -41,6 +41,8 @@ env = environ.FileAwareEnv(
),
# Links in site footer
NEODB_SITE_LINKS=(dict, {}),
# Alternative domains
NEODB_ALTERNATIVE_DOMAINS=(list, []),
# Default language
NEODB_LANGUAGE=(str, "zh-hans"),
# Invite only mode
@ -200,12 +202,9 @@ ALLOW_EMAIL_ONLY_ACCOUNT = env.bool(
# Allow user to login via any Mastodon/Pleroma sites
MASTODON_ALLOW_ANY_SITE = len(MASTODON_ALLOWED_SITES) == 0
REDIRECT_URIS = env(
"NEODB_LOGIN_MASTODON_REDIRECT_URI",
default=SITE_INFO["site_url"] + "/account/login/oauth",
)
# for sites migrated from previous version, either wipe mastodon client ids or use:
# REDIRECT_URIS = f'{SITE_INFO["site_url"]}/users/OAuth2_login/'
ALTERNATIVE_DOMAINS = env("NEODB_ALTERNATIVE_DOMAINS", default=[]) # type: ignore
SITE_DOMAINS = [SITE_DOMAIN] + ALTERNATIVE_DOMAINS
ENABLE_LOCAL_ONLY = env("NEODB_ENABLE_LOCAL_ONLY")

View file

@ -126,7 +126,7 @@ def search(request):
if keywords.find("://") > 0:
host = keywords.split("://")[1].split("/")[0]
if host == settings.SITE_INFO["site_domain"]:
if host in settings.SITE_DOMAINS:
return redirect(keywords)
site = SiteManager.get_site_by_url(keywords)
if site:

View file

@ -51,10 +51,7 @@ class FediverseInstance(AbstractSite):
val = URLValidator()
try:
val(url)
if (
url.split("://", 1)[1].split("/", 1)[0].lower()
== settings.SITE_INFO["site_domain"]
):
if url.split("://", 1)[1].split("/", 1)[0].lower() in settings.SITE_DOMAINS:
# disallow local instance URLs
return False
return cls.get_json_from_url(url) is not None

View file

@ -23,7 +23,7 @@
<div class="item">
<div class="cover">
<a href="{{ item.url }}">
<img src="{{ item.cover_image_url }}" alt="cover" />
<img src="{{ item.cover_image_url|relative_uri }}" alt="cover" />
</a>
</div>
<div>

View file

@ -18,7 +18,7 @@
<meta property="og:title"
content="{{ site_name }}{% trans item.category.label %} - {{ item.display_title }}">
<meta property="og:type" content="{{ item.category }}">
<meta property="og:url" content="{{ request.build_absolute_uri }}">
<meta property="og:url" content="{{ item.absolute_url }}">
{% if item.has_cover %}<meta property="og:image" content="{{ item.cover_image_url }}">{% endif %}
<meta property="og:site_name" content="{{ site_name }}">
<meta property="og:description" content="{{ item.brief }}">
@ -48,7 +48,7 @@
</span>
</div>
<div id="item-cover" class="left">
<img src="{{ item.cover_image_url|default:item.cover.url }}"
<img src="{{ item.cover_image_url|default:item.cover.url|relative_uri }}"
alt="{{ item.title }}">
</div>
{% if request.user.is_authenticated and not mark.shelf_type %}

View file

@ -15,6 +15,9 @@
rel="noopener"
href="https://github.com/neodb-social">源代码</a>
</div>
<div class="hide_unless_alter_domain" style="padding-top: 1em;">
这是{{ site_name }}的临时镜像,请尽可能使用<a href="{{ site_url }}{{ request.get_full_path }}">原始站点</a>
</div>
</footer>
<div class="player"></div>
<script>

View file

@ -7,6 +7,7 @@
{% load thumb %}
{% load collection %}
{% load bleach_tags %}
{% load duration %}
<aside class="grid__aside sidebar">
{% if request.user.unread_announcements %}
<section class="announcement">
@ -40,7 +41,7 @@
<div class="avatar">
<a href="{{ identity.url }}" onclick="window.location = this.href;">
{% comment %} onclick to workaround webkit issue with <a /> in <summary /> {% endcomment %}
<img src="{{ identity.avatar }}" alt="">
<img src="{{ identity.avatar|relative_uri }}" alt="">
</a>
</div>
<div>
@ -127,7 +128,7 @@
data-position="0"
href="{{ item.url }}"
title="{{ item.title }}">
<img src="{{ item.cover_image_url | default:item.cover.url }}"
<img src="{{ item.cover_image_url|default:item.cover.url|relative_uri }}"
alt="{{ item.title }}"
loading="lazy">
<div class="card-title">

View file

@ -51,4 +51,9 @@
<link rel="apple-touch-icon" href="{{ site_logo }}">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="{{ site_name }}">
{% if request.META.HTTP_HOST == site_domain %}
<style type="text/css">.hide_unless_alter_domain{display:none;}</style>
{% else %}
<meta name="robots" content="noindex">
{% endif %}
{{ site_head|safe }}

View file

@ -54,6 +54,12 @@ def rating_star(value):
return mark_safe(html)
@register.filter()
@stringfilter
def relative_uri(value: str) -> str:
return str(value).replace(settings.SITE_INFO["site_url"], "")
@register.filter
def make_range(number):
return range(1, number + 1)

View file

@ -26,6 +26,8 @@ x-shared:
NEODB_USER_ICON:
NEODB_SITE_LINKS:
NEODB_SITE_DESCRIPTION:
NEODB_ALTERNATIVE_DOMAINS:
NEODB_LANGUAGE:
NEODB_ADMIN_USERNAMES:
NEODB_INVITE_ONLY:
NEODB_LOGIN_ENABLE_EMAIL_ONLY:

View file

@ -8,7 +8,6 @@ most settings resides in `settings.py`, a few notable ones:
- `SECRET_KEY` must use your own, back it up well somewhere
- `SITE_INFO` change by you need
- `REDIRECT_URIS` this should be `SITE_INFO["site_url"] + "/account/login/oauth"` . It used to be multiple urls separated by `\n` , but now it must be only one url, bc not all Fediverse software support >1 urls very well. Also note changing this later may invalidate app token granted previously
- `MASTODON_ALLOW_ANY_SITE` set to `True` so that user can login via any Mastodon API compatible sites (e.g. Mastodon/Pleroma)
- `MASTODON_CLIENT_SCOPE` change it later may invalidate app token granted previously
- `ADMIN_URL` admin page url, keep it private
@ -20,3 +19,19 @@ Settings for Scrapers
---------------------
TBA
Other maintenance tasks
-----------------------
Add alias to your shell for easier access
```
alias neodb-manage='docker-compose --profile production run shell neodb-manage'
```
Enable Developer Console
```
neodb-manage createapplication --client-id NEODB_DEVELOPER_CONSOLE --skip-authorization --name 'NeoDB Developer Console' --redirect-uris 'https://example.org/lol' confidential authorization-code
```

View file

@ -1,156 +1,6 @@
NiceDB / NeoDB - Getting Start
==============================
This is a very basic guide with limited detail, contributions welcomed
## Table of Contents
- [Run in Docker](#0-run-in-docker)
- [1 Install](#1-manual-install)
* [1.1 Database](#11-database)
* [1.2 Configuration](#12-configuration)
* [1.3 Packages and Build](#13-packages-and-build)
- [2 Start services](#2-start-services)
- [3 Migrate from an earlier version](#3-migrate-from-an-earlier-version)
- [4 Add Cron Jobs (optional)](#4-add-cron-jobs-optional)
- [5 Index and Search (optional)](#5-index-and-search-optional)
- [6 Other maintenance tasks (optional)](#6-other-maintenance-tasks-optional)
- [7 Frequently Asked Questions](#7-frequently-asked-questions)
see [Docker Installation](install-docker.md)
0 Run in Docker
---------------
Recommended, see [Docker Installation](install-docker.md)
*Manual installation are no longer recommended and the doc below may be outdated*
1 Manual Install
----------------
Install PostgreSQL, Redis and Python (3.10 or above) if not yet
### 1.1 Database
Setup database
```
CREATE ROLE neodb with LOGIN ENCRYPTED PASSWORD 'abadface';
CREATE DATABASE neodb ENCODING 'UTF8' LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' TEMPLATE template0;
GRANT ALL ON DATABASE neodb TO neodb;
```
### 1.2 Configuration
Create and edit your own configuration file (optional but very much recommended)
```
mkdir mysite && cp boofilsic/settings.py mysite/
export DJANGO_SETTINGS_MODULE=mysite.settings
```
Alternatively you can have a configuration file import `boofilsic/settings.py` then override it:
```
from boofilsic.settings import *
SECRET_KEY = "my_key"
```
The most important configurations to setup are:
- `MASTODON_ALLOW_ANY_SITE` set to `True` so that user can login via any Mastodon API compatible sites (e.g. Mastodon/Pleroma)
- `REDIRECT_URIS` should be `SITE_INFO["site_url"] + "/account/login/oauth"`. If you want to run **on local**, `SITE_INFO["site_url"]` should be set to `"http://localhost/"`
More details on `settings.py` in [configuration.md](configuration.md)
### 1.3 Packages and Build
Create and use `venv` as you normally would, then install packages
```
python3 -m pip install -r requirements.txt
```
Quick check
```
python3 manage.py check
```
Initialize database
```
python3 manage.py migrate
```
Build static assets (production only)
```
python3 manage.py compilescss
python3 manage.py collectstatic
```
2 Start services
--------------
Make sure PostgreSQL and Redis are running
Start job queue server
```
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES # required and only for macOS, otherwise it may crash
python3 manage.py rqworker --with-scheduler import export mastodon fetch crawl
```
Run web server in dev mode
```
python3 manage.py runserver
```
It should be ready to serve from here, to run web server for production, consider `gunicorn -w 8 boofilsic.wsgi` in systemd or sth similar
3 Migrate from an earlier version
-------------------------------
Update database
```
python3 manage.py migrate
```
Rebuild static assets
```
python3 manage.py compilescss
python3 manage.py collectstatic
```
4 Add Cron Jobs (optional)
-------------
add `python manage.py refresh_mastodon` to crontab to run hourly, it will refresh cached users' follow/mute/block from mastodon
5 Index and Search (optional)
----------------
Install TypeSense or Meilisearch, change `SEARCH_BACKEND` and coniguration for search server in `settings.py`
Build initial index, it may take a few minutes or hours
```
python3 manage.py index --init
python3 manage.py index --reindex
```
6 Other maintenance tasks (optional)
-----------------------
Requeue failed import jobs
```
rq requeue --all --queue import
```
Run Tests
```
coverage run --source='.' manage.py test
coverage report
```
Enable Developer Console
```
python3 manage.py createapplication --client-id NEODB_DEVELOPER_CONSOLE --skip-authorization --name 'NeoDB Developer Console' --redirect-uris 'https://example.org/lol' confidential authorization-code
```
7 Frequently Asked Questions
------
### I got Error: “无效的登录回调地址”.
Check `REDIRECT_URIS` in `settings.py`, the final value should be `"http://localhost/account/login/oauth"` or sth similar. If you are specifying a port, add the port to the localhost address.
If any change was made to `REDIRECT_URIS`, existing apps registered in Mastodon are no longer valid, so delete the app record in the database:
```
delete from mastodon_mastodonapplication;
```
*Manual installation are no longer supported*

View file

@ -8,6 +8,7 @@ from urllib.parse import quote
import django_rq
import requests
from django.conf import settings
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from loguru import logger
@ -226,29 +227,22 @@ def post_toot(
return response
def create_app(domain_name):
# naive protocal strip
is_http = False
if domain_name.startswith("https://"):
domain_name = domain_name.replace("https://", "")
elif domain_name.startswith("http://"):
is_http = True
domain_name = domain_name.replace("http://", "")
if domain_name.endswith("/"):
domain_name = domain_name[0:-1]
def _get_redirect_uris(allow_multiple=True) -> str:
u = settings.SITE_INFO["site_url"] + "/account/login/oauth"
if not allow_multiple:
return u
u2s = [f"https://{d}/account/login/oauth" for d in settings.ALTERNATIVE_DOMAINS]
return "\n".join([u] + u2s)
if not is_http:
def create_app(domain_name, allow_multiple_redir):
url = "https://" + domain_name + API_CREATE_APP
else:
url = "http://" + domain_name + API_CREATE_APP
payload = {
"client_name": settings.SITE_INFO["site_name"],
"scopes": settings.MASTODON_CLIENT_SCOPE,
"redirect_uris": settings.REDIRECT_URIS,
"redirect_uris": _get_redirect_uris(allow_multiple_redir),
"website": settings.SITE_INFO["site_url"],
}
response = post(url, data=payload, headers={"User-Agent": USER_AGENT})
return response
@ -368,12 +362,12 @@ def get_or_create_fediverse_application(login_domain):
if not settings.MASTODON_ALLOW_ANY_SITE:
logger.warning(f"Disallowed to create app for {domain}")
raise Exception("不支持其它实例登录")
if settings.SITE_DOMAIN.lower() == login_domain.lower():
if login_domain.lower() in settings.SITE_DOMAINS:
raise ValueError("必须使用其它实例登录")
domain, api_domain, server_version = detect_server_info(login_domain)
if (
settings.SITE_DOMAIN.lower() == domain.lower()
or settings.SITE_DOMAIN.lower() == api_domain.lower()
domain.lower() in settings.SITE_DOMAINS
or api_domain.lower() in settings.SITE_DOMAINS
):
raise ValueError("必须使用其它实例登录")
if "neodb/" in server_version:
@ -382,7 +376,8 @@ def get_or_create_fediverse_application(login_domain):
app = MastodonApplication.objects.filter(domain_name__iexact=domain).first()
if app:
return app
response = create_app(api_domain)
allow_multiple_redir = True # TODO detect site supports multiple redirect uris
response = create_app(api_domain, allow_multiple_redir)
if response.status_code != 200:
logger.error(
f"Error creating app for {domain} on {api_domain}: {response.status_code}"
@ -406,7 +401,7 @@ def get_or_create_fediverse_application(login_domain):
def get_mastodon_login_url(app, login_domain, request):
url = settings.REDIRECT_URIS
url = request.build_absolute_uri(reverse("users:login_oauth"))
version = app.server_version or ""
scope = (
settings.MASTODON_LEGACY_CLIENT_SCOPE
@ -429,7 +424,7 @@ def get_mastodon_login_url(app, login_domain, request):
def obtain_token(site, request, code):
"""Returns token if success else None."""
mast_app = MastodonApplication.objects.get(domain_name=site)
redirect_uri = settings.REDIRECT_URIS
redirect_uri = request.build_absolute_uri(reverse("users:login_oauth"))
payload = {
"client_id": mast_app.client_id,
"client_secret": mast_app.client_secret,

View file

@ -147,14 +147,18 @@
{% endif %}
</small>
{% endif %}
<small id="fedi-tips">如不便或尚未<a href="https://joinmastodon.org/zh/servers" target="_blank">注册联邦宇宙</a>,也可以在上方选择「电子邮件验证」注册登录本站。</small>
<small id="email-tips" style="display:none;">现有用户通过联邦宇宙登录后关联电子邮件地址,即可通过邮件登录本站;如不便使用联邦宇宙,也可在此输入邮件地址注册账号,未来再关联到联邦宇宙。</small>
</form>
{% endif %}
<small class="hide_unless_alter_domain">
<br>
这是{{ site_name }}的临时镜像,请尽可能使用<a href="{{ site_url }}{{ request.get_full_path }}">原始站点</a>
</small>
<div class="delayed">部分模块加载超时,请检查网络(翻墙)设置。</div>
</div>
</article>
<footer>
<small id="fedi-tips">如尚未<a href="https://joinmastodon.org/zh/servers" target="_blank">注册联邦宇宙</a>,也可点选「电子邮件验证」注册登录本站。</small>
<small id="email-tips" style="display:none;">现有用户通过联邦宇宙登录后关联电子邮件地址,即可通过邮件登录本站;如不便使用联邦宇宙,也可在此输入邮件地址注册账号,未来再关联到联邦宇宙。</small>
<br>
<small>继续访问或注册视为同意本站<a href="{% url 'management:retrieve_slug' 'data-policy' %}">数据方针</a>及使用cookie提供必要功能</small>
</footer>