mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Merge branch 'beta' into dev
This commit is contained in:
		| @@ -25,8 +25,6 @@ | ||||
| #   and '.env' into a folder. | ||||
| # - Run 'docker compose pull'. | ||||
| # - Run 'docker compose up -d'. | ||||
| # - Wait until the webserver has completed startup | ||||
| # - Run 'docker compose exec webserver createsuperuser' to create a user. | ||||
|  | ||||
| # | ||||
| # For more extensive installation and update instructions, refer to the | ||||
|   | ||||
| @@ -21,8 +21,6 @@ | ||||
| #   and '.env' into a folder. | ||||
| # - Run 'docker compose pull'. | ||||
| # - Run 'docker compose up -d'. | ||||
| # - Wait until the webserver has completed startup | ||||
| # - Run 'docker compose exec webserver createsuperuser' to create a user. | ||||
| # | ||||
| # For more extensive installation and update instructions, refer to the | ||||
| # documentation. | ||||
|   | ||||
| @@ -22,10 +22,6 @@ | ||||
| # - Upload 'docker-compose.env' by clicking on 'Load variables from .env file' | ||||
| # - Modify the environment variables as needed | ||||
| # - Click 'Deploy the stack' and wait for it to be deployed | ||||
| # - Open the list of containers, select paperless_webserver_1 | ||||
| # - Click 'Console' and then 'Connect' to open the command line inside the container | ||||
| # - Run 'createsuperuser' to create a user | ||||
| # - Exit the console | ||||
| # | ||||
| # For more extensive installation and update instructions, refer to the | ||||
| # documentation. | ||||
|   | ||||
| @@ -25,8 +25,6 @@ | ||||
| #   and '.env' into a folder. | ||||
| # - Run 'docker compose pull'. | ||||
| # - Run 'docker compose up -d'. | ||||
| # - Wait until the webserver has completed startup | ||||
| # - Run 'docker compose exec webserver createsuperuser' to create a user. | ||||
| # | ||||
| # For more extensive installation and update instructions, refer to the | ||||
| # documentation. | ||||
|   | ||||
| @@ -21,8 +21,6 @@ | ||||
| #   and '.env' into a folder. | ||||
| # - Run 'docker compose pull'. | ||||
| # - Run 'docker compose up -d'. | ||||
| # - Wait until the webserver has completed startup | ||||
| # - Run 'docker compose exec webserver createsuperuser' to create a user. | ||||
| # | ||||
| # For more extensive installation and update instructions, refer to the | ||||
| # documentation. | ||||
|   | ||||
| @@ -25,8 +25,6 @@ | ||||
| #   and '.env' into a folder. | ||||
| # - Run 'docker compose pull'. | ||||
| # - Run 'docker compose up -d'. | ||||
| # - Wait until the webserver has completed startup | ||||
| # - Run 'docker compose exec webserver createsuperuser' to create a user. | ||||
| # | ||||
| # For more extensive installation and update instructions, refer to the | ||||
| # documentation. | ||||
|   | ||||
| @@ -18,8 +18,6 @@ | ||||
| #   and '.env' into a folder. | ||||
| # - Run 'docker compose pull'. | ||||
| # - Run 'docker compose up -d'. | ||||
| # - Wait until the webserver has completed startup | ||||
| # - Run 'docker compose exec webserver createsuperuser' to create a user. | ||||
| # | ||||
| # For more extensive installation and update instructions, refer to the | ||||
| # documentation. | ||||
|   | ||||
| @@ -629,3 +629,11 @@ entries created prior to this are not removed. This command allows you to prune | ||||
| ```shell | ||||
| prune_audit_logs | ||||
| ``` | ||||
|  | ||||
| ### Create superuser {#create-superuser} | ||||
|  | ||||
| If you need to create a superuser, use the following command: | ||||
|  | ||||
| ```shell | ||||
| createsuperuser | ||||
| ``` | ||||
|   | ||||
| @@ -84,7 +84,7 @@ first-time setup. | ||||
|     $ uv run pre-commit install | ||||
|     ``` | ||||
|  | ||||
| 6.  Apply migrations and create a superuser for your development instance: | ||||
| 6.  Apply migrations and create a superuser (also can be done via the web UI) for your development instance: | ||||
|  | ||||
|     ```bash | ||||
|     # src/ | ||||
|   | ||||
| @@ -133,30 +133,9 @@ account. The script essentially automatically performs the steps described in [D | ||||
|  | ||||
| 6.  Run `docker compose up -d`. This will create and start the necessary containers. | ||||
|  | ||||
| 7.  Wait for the containers to complete their startup. You can monitor the logs using Docker, such as: | ||||
|  | ||||
|     ```shell-session | ||||
|     docker logs --follow webserver | ||||
|     ``` | ||||
|  | ||||
| 8.  To be able to login, you will need a "superuser". To create it, | ||||
|     execute the following command: | ||||
|  | ||||
|     ```shell-session | ||||
|     docker compose exec webserver createsuperuser | ||||
|     ``` | ||||
|  | ||||
|     or using docker exec from within the container: | ||||
|  | ||||
|     ```shell-session | ||||
|     createsuperuser | ||||
|     ``` | ||||
|  | ||||
|     This will guide you through the superuser setup. | ||||
|  | ||||
| 9.  Congratulations! Your Paperless-ngx instance should now be accessible at `http://127.0.0.1:8000` | ||||
|     (or similar, depending on your configuration). Use the superuser credentials you have | ||||
|     created in the previous step to login. | ||||
| 7.  Congratulations! Your Paperless-ngx instance should now be accessible at `http://127.0.0.1:8000` | ||||
|     (or similar, depending on your configuration). When you first access the web interface, you will be | ||||
|     prompted to create a superuser account. | ||||
|  | ||||
| ### Build the Docker image yourself {#docker_build} | ||||
|  | ||||
| @@ -392,16 +371,15 @@ are released, dependency support is confirmed, etc. | ||||
|         dependencies for Postgres or Mariadb.  You can select those extras with `--extra <EXTRA>` | ||||
|         or all with `--all-extras` | ||||
|  | ||||
| 9.  Go to `/opt/paperless/src`, and execute the following commands: | ||||
| 9.  Go to `/opt/paperless/src`, and execute the following command: | ||||
|  | ||||
|     ```bash | ||||
|     # This creates the database schema. | ||||
|     sudo -Hu paperless python3 manage.py migrate | ||||
|  | ||||
|     # This creates your first paperless user | ||||
|     sudo -Hu paperless python3 manage.py createsuperuser | ||||
|     ``` | ||||
|  | ||||
|     When you first access the web interface you will be prompted to create a superuser account. | ||||
|  | ||||
| 10. Optional: Test that paperless is working by executing | ||||
|  | ||||
|     ```bash | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| from django.conf import settings as django_settings | ||||
| from django.contrib.auth.models import User | ||||
|  | ||||
| from documents.models import Document | ||||
| from paperless.config import GeneralConfig | ||||
|  | ||||
|  | ||||
| @@ -25,4 +27,9 @@ def settings(request): | ||||
|         "domain": getattr(django_settings, "PAPERLESS_URL", request.get_host()), | ||||
|         "APP_TITLE": app_title, | ||||
|         "APP_LOGO": app_logo, | ||||
|         "FIRST_INSTALL": User.objects.exclude( | ||||
|             username__in=["consumer", "AnonymousUser"], | ||||
|         ).count() | ||||
|         == 0 | ||||
|         and Document.global_objects.count() == 0, | ||||
|     } | ||||
|   | ||||
| @@ -15,6 +15,12 @@ | ||||
| {% endblock form_top_content %} | ||||
|  | ||||
| {% block form_content %} | ||||
| 		{% if FIRST_INSTALL %} | ||||
| 			<script type="text/javascript"> | ||||
| 				// forward to the signup page if no users exist | ||||
| 				window.location.href = "{{ signup_url }}"; | ||||
| 			</script> | ||||
| 		{% endif %} | ||||
|     {% if not DISABLE_REGULAR_LOGIN %} | ||||
|         {% translate "Username" as i18n_username %} | ||||
|         {% translate "Password" as i18n_password %} | ||||
|   | ||||
| @@ -6,12 +6,19 @@ | ||||
| {% endblock head_title %} | ||||
|  | ||||
| {% block form_top_content %} | ||||
| 		{% if not FIRST_INSTALL %} | ||||
| 			<p> | ||||
| 					{% blocktrans %}Already have an account? <a href="{{ login_url }}">Sign in</a>{% endblocktrans %} | ||||
| 			</p> | ||||
| 		{% endif %} | ||||
| {% endblock form_top_content %} | ||||
|  | ||||
| {% block form_content %} | ||||
| 		{% if FIRST_INSTALL %} | ||||
| 			<p> | ||||
| 				{% blocktrans %}Note: This is the first user account for this installation and will be granted superuser privileges.{% endblocktrans %} | ||||
| 			</p> | ||||
| 		{% endif %} | ||||
|     {% translate "Username" as i18n_username %} | ||||
|     {% translate "Email (optional)" as i18n_email %} | ||||
|     {% translate "Password" as i18n_password1 %} | ||||
| @@ -42,6 +49,7 @@ | ||||
| {% endblock form_content %} | ||||
|  | ||||
| {% block after_form_content %} | ||||
| 	{% if not FIRST_INSTALL %} | ||||
| 		{% load allauth socialaccount %} | ||||
| 		{% get_providers as socialaccount_providers %} | ||||
| 		{% if socialaccount_providers %} | ||||
| @@ -67,4 +75,5 @@ | ||||
| 						{% endfor %} | ||||
| 				</ul> | ||||
| 		{% endif %} | ||||
| 	{% endif %} | ||||
| {% endblock after_form_content %} | ||||
|   | ||||
| @@ -2,7 +2,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: paperless-ngx\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2025-03-11 13:33-0700\n" | ||||
| "POT-Creation-Date: 2025-03-26 21:04-0700\n" | ||||
| "PO-Revision-Date: 2022-02-17 04:17\n" | ||||
| "Last-Translator: \n" | ||||
| "Language-Team: English\n" | ||||
| @@ -1235,28 +1235,28 @@ msgstr "" | ||||
| msgid "Don't have an account yet? <a href=\"%(signup_url)s\">Sign up</a>" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/login.html:19 | ||||
| #: documents/templates/account/signup.html:15 | ||||
| #: documents/templates/account/login.html:25 | ||||
| #: documents/templates/account/signup.html:22 | ||||
| #: documents/templates/socialaccount/signup.html:13 | ||||
| msgid "Username" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/login.html:20 | ||||
| #: documents/templates/account/signup.html:17 | ||||
| #: documents/templates/account/login.html:26 | ||||
| #: documents/templates/account/signup.html:24 | ||||
| msgid "Password" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/login.html:30 | ||||
| #: documents/templates/account/login.html:36 | ||||
| #: documents/templates/mfa/authenticate.html:23 | ||||
| msgid "Sign in" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/login.html:34 | ||||
| #: documents/templates/account/login.html:40 | ||||
| msgid "Forgot your password?" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/login.html:45 | ||||
| #: documents/templates/account/signup.html:49 | ||||
| #: documents/templates/account/login.html:51 | ||||
| #: documents/templates/account/signup.html:57 | ||||
| msgid "or sign in via" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1335,21 +1335,27 @@ msgstr "" | ||||
| msgid "Paperless-ngx sign up" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/signup.html:10 | ||||
| #: documents/templates/account/signup.html:11 | ||||
| #, python-format | ||||
| msgid "Already have an account? <a href=\"%(login_url)s\">Sign in</a>" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/signup.html:16 | ||||
| #: documents/templates/account/signup.html:19 | ||||
| msgid "" | ||||
| "Note: This is the first user account for this installation and will be " | ||||
| "granted superuser privileges." | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/signup.html:23 | ||||
| #: documents/templates/socialaccount/signup.html:14 | ||||
| msgid "Email (optional)" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/signup.html:18 | ||||
| #: documents/templates/account/signup.html:25 | ||||
| msgid "Password (again)" | ||||
| msgstr "" | ||||
|  | ||||
| #: documents/templates/account/signup.html:36 | ||||
| #: documents/templates/account/signup.html:43 | ||||
| #: documents/templates/socialaccount/signup.html:27 | ||||
| msgid "Sign up" | ||||
| msgstr "" | ||||
| @@ -1578,139 +1584,139 @@ msgstr "" | ||||
| msgid "paperless application settings" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:723 | ||||
| #: paperless/settings.py:722 | ||||
| msgid "English (US)" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:724 | ||||
| #: paperless/settings.py:723 | ||||
| msgid "Arabic" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:725 | ||||
| #: paperless/settings.py:724 | ||||
| msgid "Afrikaans" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:726 | ||||
| #: paperless/settings.py:725 | ||||
| msgid "Belarusian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:727 | ||||
| #: paperless/settings.py:726 | ||||
| msgid "Bulgarian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:728 | ||||
| #: paperless/settings.py:727 | ||||
| msgid "Catalan" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:729 | ||||
| #: paperless/settings.py:728 | ||||
| msgid "Czech" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:730 | ||||
| #: paperless/settings.py:729 | ||||
| msgid "Danish" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:731 | ||||
| #: paperless/settings.py:730 | ||||
| msgid "German" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:732 | ||||
| #: paperless/settings.py:731 | ||||
| msgid "Greek" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:733 | ||||
| #: paperless/settings.py:732 | ||||
| msgid "English (GB)" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:734 | ||||
| #: paperless/settings.py:733 | ||||
| msgid "Spanish" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:735 | ||||
| #: paperless/settings.py:734 | ||||
| msgid "Finnish" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:736 | ||||
| #: paperless/settings.py:735 | ||||
| msgid "French" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:737 | ||||
| #: paperless/settings.py:736 | ||||
| msgid "Hungarian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:738 | ||||
| #: paperless/settings.py:737 | ||||
| msgid "Italian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:739 | ||||
| #: paperless/settings.py:738 | ||||
| msgid "Japanese" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:740 | ||||
| #: paperless/settings.py:739 | ||||
| msgid "Korean" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:741 | ||||
| #: paperless/settings.py:740 | ||||
| msgid "Luxembourgish" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:742 | ||||
| #: paperless/settings.py:741 | ||||
| msgid "Norwegian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:743 | ||||
| #: paperless/settings.py:742 | ||||
| msgid "Dutch" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:744 | ||||
| #: paperless/settings.py:743 | ||||
| msgid "Polish" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:745 | ||||
| #: paperless/settings.py:744 | ||||
| msgid "Portuguese (Brazil)" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:746 | ||||
| #: paperless/settings.py:745 | ||||
| msgid "Portuguese" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:747 | ||||
| #: paperless/settings.py:746 | ||||
| msgid "Romanian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:748 | ||||
| #: paperless/settings.py:747 | ||||
| msgid "Russian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:749 | ||||
| #: paperless/settings.py:748 | ||||
| msgid "Slovak" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:750 | ||||
| #: paperless/settings.py:749 | ||||
| msgid "Slovenian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:751 | ||||
| #: paperless/settings.py:750 | ||||
| msgid "Serbian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:752 | ||||
| #: paperless/settings.py:751 | ||||
| msgid "Swedish" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:753 | ||||
| #: paperless/settings.py:752 | ||||
| msgid "Turkish" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:754 | ||||
| #: paperless/settings.py:753 | ||||
| msgid "Ukrainian" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:755 | ||||
| #: paperless/settings.py:754 | ||||
| msgid "Chinese Simplified" | ||||
| msgstr "" | ||||
|  | ||||
| #: paperless/settings.py:756 | ||||
| #: paperless/settings.py:755 | ||||
| msgid "Chinese Traditional" | ||||
| msgstr "" | ||||
|  | ||||
|   | ||||
| @@ -10,6 +10,7 @@ from django.contrib.auth.models import User | ||||
| from django.forms import ValidationError | ||||
| from django.urls import reverse | ||||
|  | ||||
| from documents.models import Document | ||||
| from paperless.signals import handle_social_account_updated | ||||
|  | ||||
| logger = logging.getLogger("paperless.auth") | ||||
| @@ -21,6 +22,13 @@ class CustomAccountAdapter(DefaultAccountAdapter): | ||||
|         Check whether the site is open for signups, which can be | ||||
|         disabled via the ACCOUNT_ALLOW_SIGNUPS setting. | ||||
|         """ | ||||
|         if ( | ||||
|             User.objects.exclude(username__in=["consumer", "AnonymousUser"]).count() | ||||
|             == 0 | ||||
|             and Document.global_objects.count() == 0 | ||||
|         ): | ||||
|             # I.e. a fresh install, allow signups | ||||
|             return True | ||||
|         allow_signups = super().is_open_for_signup(request) | ||||
|         # Override with setting, otherwise default to super. | ||||
|         return getattr(settings, "ACCOUNT_ALLOW_SIGNUPS", allow_signups) | ||||
| @@ -73,6 +81,17 @@ class CustomAccountAdapter(DefaultAccountAdapter): | ||||
|         Save the user instance. Default groups are assigned to the user, if | ||||
|         specified in the settings. | ||||
|         """ | ||||
|  | ||||
|         if ( | ||||
|             User.objects.exclude(username__in=["consumer", "AnonymousUser"]).count() | ||||
|             == 0 | ||||
|             and Document.global_objects.count() == 0 | ||||
|         ): | ||||
|             # I.e. a fresh install, make the user a superuser | ||||
|             logger.debug(f"Creating initial superuser `{user}`") | ||||
|             user.is_superuser = True | ||||
|             user.is_staff = True | ||||
|  | ||||
|         user: User = super().save_user(request, user, form, commit) | ||||
|         group_names: list[str] = settings.ACCOUNT_DEFAULT_GROUPS | ||||
|         if len(group_names) > 0: | ||||
|   | ||||
| @@ -17,6 +17,11 @@ class TestCustomAccountAdapter(TestCase): | ||||
|     def test_is_open_for_signup(self): | ||||
|         adapter = get_adapter() | ||||
|  | ||||
|         # With no accounts, signups should be allowed | ||||
|         self.assertTrue(adapter.is_open_for_signup(None)) | ||||
|  | ||||
|         User.objects.create_user("testuser") | ||||
|  | ||||
|         # Test when ACCOUNT_ALLOW_SIGNUPS is True | ||||
|         settings.ACCOUNT_ALLOW_SIGNUPS = True | ||||
|         self.assertTrue(adapter.is_open_for_signup(None)) | ||||
| @@ -101,6 +106,27 @@ class TestCustomAccountAdapter(TestCase): | ||||
|         self.assertTrue(user.groups.filter(name="group1").exists()) | ||||
|         self.assertFalse(user.groups.filter(name="group2").exists()) | ||||
|  | ||||
|     def test_fresh_install_save_creates_superuser(self): | ||||
|         adapter = get_adapter() | ||||
|         form = mock.Mock( | ||||
|             cleaned_data={ | ||||
|                 "username": "testuser", | ||||
|                 "email": "user@paperless-ngx.com", | ||||
|             }, | ||||
|         ) | ||||
|         user = adapter.save_user(HttpRequest(), User(), form, commit=True) | ||||
|         self.assertTrue(user.is_superuser) | ||||
|  | ||||
|         # Next time, it should not create a superuser | ||||
|         form = mock.Mock( | ||||
|             cleaned_data={ | ||||
|                 "username": "testuser2", | ||||
|                 "email": "user2@paperless-ngx.com", | ||||
|             }, | ||||
|         ) | ||||
|         user2 = adapter.save_user(HttpRequest(), User(), form, commit=True) | ||||
|         self.assertFalse(user2.is_superuser) | ||||
|  | ||||
|  | ||||
| class TestCustomSocialAccountAdapter(TestCase): | ||||
|     def test_is_open_for_signup(self): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 shamoon
					shamoon