internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: inventree/InvenTree

Issue:
Add settings for backups
Can we give the user (or more likely, sysadmin) a method to customize:

a) Whether backups are performed automatically or not
b) The schedule period for performing backups

__Originally posted by @SchrodingersGat in https://github.com/inventree/InvenTree/pull/3783#discussion_r996365203__


Discussion:

Resolving patch:
diff --git a/InvenTree/InvenTree/tasks.py b/InvenTree/InvenTree/tasks.py
--- a/InvenTree/InvenTree/tasks.py
+++ b/InvenTree/InvenTree/tasks.py
@@ -275,8 +275,11 @@ def update_exchange_rates():
 
 def run_backup():
     """Run the backup command."""
-    call_command("dbbackup", noinput=True, clean=True, compress=True, interactive=False)
-    call_command("mediabackup", noinput=True, clean=True, compress=True, interactive=False)
+    from common.models import InvenTreeSetting
+
+    if InvenTreeSetting.get_setting('INVENTREE_BACKUP_ENABLE'):
+        call_command("dbbackup", noinput=True, clean=True, compress=True, interactive=False)
+        call_command("mediabackup", noinput=True, clean=True, compress=True, interactive=False)
 
 
 def send_email(subject, body, recipients, from_email=None, html_message=None):
diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py
--- a/InvenTree/common/models.py
+++ b/InvenTree/common/models.py
@@ -886,6 +886,13 @@ def save(self, *args, **kwargs):
             ]
         },
 
+        'INVENTREE_BACKUP_ENABLE': {
+            'name': _('Automatic Backup'),
+            'description': _('Enable automatic backup of database and media files'),
+            'validator': bool,
+            'default': True,
+        },
+
         'BARCODE_ENABLE': {
             'name': _('Barcode Support'),
             'description': _('Enable barcode scanner support'),


Test patch:
Repository: inventree/InvenTree

Issue:
[BUG] Confirmation Email uses local ip for link URL
### Please verify that this bug has NOT been raised before.

- [X] I checked and didn't find similar issue

### Describe the bug*

When sending a verification email, it shows the local IP not the set base URL

Eg. mywebsite.com

Hello from InvenTree!

You're receiving this e-mail because user kyle has given your e-mail address to register an account on https://mywebsite.com

To confirm this is correct, go to http://192.168.1.111:83/accounts/confirm-email/MQ:1olnC0:UXQyFESkK7GxGnQOOEJcP8AXY1gkd-bbeIK02tDoxoo/

Thank you for using InvenTree!
https://mywebsite.com

### Steps to Reproduce

1. Set base URL
2. Add an email
3. Send a verification email

### Expected behavior

URL should respect the base URL setting

### Deployment Method

- [X] Docker
- [ ] Bare metal

### Version Information

# Version Information:
InvenTree-Version: 0.8.3
Django Version: 3.2.15
Commit Hash: f9d2b14
Commit Date: 2022-09-23
Database: postgresql
Debug-Mode: False
Deployed using Docker: True


### Relevant log output

_No response_


Discussion:
Can confirm.
Thanks for the excellent report @mrkylegp ! Should be an easy fix, starting work now.

Resolving patch:
diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py
--- a/InvenTree/InvenTree/forms.py
+++ b/InvenTree/InvenTree/forms.py
@@ -6,6 +6,7 @@
 from django import forms
 from django.conf import settings
 from django.contrib.auth.models import Group, User
+from django.contrib.sites.models import Site
 from django.http import HttpResponseRedirect
 from django.urls import reverse
 from django.utils.translation import gettext_lazy as _
@@ -227,7 +228,16 @@ def save_user(self, request, user, form, commit=True):
         return user
 
 
-class CustomAccountAdapter(RegistratonMixin, OTPAdapter, DefaultAccountAdapter):
+class CustomUrlMixin:
+    """Mixin to set urls."""
+
+    def get_email_confirmation_url(self, request, emailconfirmation):
+        """Custom email confirmation (activation) url."""
+        url = reverse("account_confirm_email", args=[emailconfirmation.key])
+        return Site.objects.get_current().domain + url
+
+
+class CustomAccountAdapter(CustomUrlMixin, RegistratonMixin, OTPAdapter, DefaultAccountAdapter):
     """Override of adapter to use dynamic settings."""
     def send_mail(self, template_prefix, email, context):
         """Only send mail if backend configured."""
@@ -236,7 +246,7 @@ def send_mail(self, template_prefix, email, context):
         return False
 
 
-class CustomSocialAccountAdapter(RegistratonMixin, DefaultSocialAccountAdapter):
+class CustomSocialAccountAdapter(CustomUrlMixin, RegistratonMixin, DefaultSocialAccountAdapter):
     """Override of adapter to use dynamic settings."""
 
     def is_auto_signup_allowed(self, request, sociallogin):


Test patch:
Repository: inventree/InvenTree

Issue:
[FR]Remove special character restrictions in parameter template names
### Please verify that this feature request has NOT been suggested before.

- [X] I checked and didn't find similar feature request

### Problem statement

I tried to add a parameter template with a name 'Current - Collector (Ic)' and it failed with: 'Illegal character in template name (()'
Are there any objections on removing this limitation like it was done in #3370?

### Suggested solution

Remove special characters limitation

### Describe alternatives you've considered

none

### Examples of other systems

I am working on an importer which transforms the data stored in the Arena and there the parameter names could have special characters like (-s

### Do you want to develop this?

- [X] I want to develop this.


Discussion:
@martonmiklos sure, happy for you to submit a PR on this!

Resolving patch:
diff --git a/InvenTree/part/migrations/0088_alter_partparametertemplate_name.py b/InvenTree/part/migrations/0088_alter_partparametertemplate_name.py
new file mode 100644
--- /dev/null
+++ b/InvenTree/part/migrations/0088_alter_partparametertemplate_name.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.16 on 2022-10-30 23:06
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('part', '0087_bomitem_consumable'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='partparametertemplate',
+            name='name',
+            field=models.CharField(help_text='Parameter Name', max_length=100, unique=True, verbose_name='Name'),
+        ),
+    ]
diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py
--- a/InvenTree/part/models.py
+++ b/InvenTree/part/models.py
@@ -2383,10 +2383,7 @@ def key(self):
 
 
 def validate_template_name(name):
-    """Prevent illegal characters in "name" field for PartParameterTemplate."""
-    for c in "\"\'`!?|":  # noqa: P103
-        if c in str(name):
-            raise ValidationError(_(f"Illegal character in template name ({c})"))
+    """Placeholder for legacy function used in migrations."""
 
 
 class PartParameterTemplate(models.Model):
@@ -2431,10 +2428,7 @@ def validate_unique(self, exclude=None):
         max_length=100,
         verbose_name=_('Name'),
         help_text=_('Parameter Name'),
-        unique=True,
-        validators=[
-            validate_template_name,
-        ]
+        unique=True
     )
 
     units = models.CharField(max_length=25, verbose_name=_('Units'), help_text=_('Parameter Units'), blank=True)


Test patch:
Repository: inventree/InvenTree

Issue:
Logout Redirect URL for Remote Login Configuration
### Please verify that this bug has NOT been raised before.

- [X] I checked and didn't find similar issue

### Describe the bug*

Hi,

Currently I am testing the use of Inventree behind [Authelia SSO](https://github.com/authelia/authelia) with the remote/proxy login config settings, and everything seems to be working for login. However, upon trying to logout, the logout process seems to fail (i.e. the user remains logged in, rather than returning to the Authelia SSO login page).

This issue is resolved when the `LOGOUT_REDIRECT_URL` setting is updated to the appropriate Authelia logout URL.

### Steps to Reproduce

1. Setup `remote / proxy login` settings as follows in `config.yaml`:

```yaml
remote_login_enabled: True
remote_login_header: HTTP_REMOTE_USER
```

2. Login through Authelia SSO.
3. Get redirected to [Dashboard (`/index/`)](https://demo.inventree.org/index/).
4. Click Logout.
5. Get redirected to [`/accounts/logout/`](https://demo.inventree.org/accounts/logout/)
6. Click Sign Out.
7. Get redirected to [Dashboard (`/index/`)](https://demo.inventree.org/index/) while still logged in as user.

### Expected behavior

Get redirected to Authelia logout page which handles logout process, before being redirecting to Authelia login page (no longer logged in).

### Deployment Method

- [X] Docker
- [ ] Bare metal

### Version Information

# Version Information:
InvenTree-Version: 0.8.4
Django Version: 3.2.15
Commit Hash: ca1fbf9
Commit Date: 20/10/2022
Database: postgresql
Debug-Mode: False
Deployed using Docker: True


### Relevant log output

_No response_


Discussion:

Resolving patch:
diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py
--- a/InvenTree/InvenTree/settings.py
+++ b/InvenTree/InvenTree/settings.py
@@ -584,7 +584,7 @@
 
 # database user sessions
 SESSION_ENGINE = 'user_sessions.backends.db'
-LOGOUT_REDIRECT_URL = 'index'
+LOGOUT_REDIRECT_URL = get_setting('INVENTREE_LOGOUT_REDIRECT_URL', 'logout_redirect_url', 'index')
 SILENCED_SYSTEM_CHECKS = [
     'admin.E410',
 ]


Test patch:
Repository: inventree/InvenTree

Issue:
[SSO] Separate settings for local and social signup
The "self registration" setting controls self-signup of both local (username/password) and social (SSO) accounts.

Ideally, we would have separate control for allowing (or preventing) self-reg of local accounts and / or SSO accounts.

For example, prevent users from self-registration of local accounts, but allow self-registration of SSO accounts through an external app which already restricts which user accounts have access.

Currently, enabling "self registration" (required for SSO self reg) also lets local accounts be created without restriction.


Discussion:
@matmair what do you think about this one? Can we implement with some custom django-allauth classes?
@SchrodingersGat this is rather simple, I just thought it might make the settings for SSO too complex.
I will program this in the next few days. If I touch this code I can just add the scoping checks asked for in discussions also: https://github.com/inventree/InvenTree/discussions/2619
Seems 0.10.0 is going to have a bunch of security things in it.
Nice, thanks @matmair - please also see the changes in https://github.com/inventree/InvenTree/pull/4169
See https://github.com/inventree/InvenTree/issues/4168

Resolving patch:
diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py
--- a/InvenTree/InvenTree/forms.py
+++ b/InvenTree/InvenTree/forms.py
@@ -210,8 +210,11 @@ class RegistratonMixin:
     """Mixin to check if registration should be enabled."""
 
     def is_open_for_signup(self, request, *args, **kwargs):
-        """Check if signup is enabled in settings."""
-        if settings.EMAIL_HOST and InvenTreeSetting.get_setting('LOGIN_ENABLE_REG', True):
+        """Check if signup is enabled in settings.
+
+        Configure the class variable `REGISTRATION_SETTING` to set which setting should be used, defualt: `LOGIN_ENABLE_REG`.
+        """
+        if settings.EMAIL_HOST and (InvenTreeSetting.get_setting('LOGIN_ENABLE_REG') or InvenTreeSetting.get_setting('LOGIN_ENABLE_SSO_REG')):
             return super().is_open_for_signup(request, *args, **kwargs)
         return False
 
diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py
--- a/InvenTree/common/models.py
+++ b/InvenTree/common/models.py
@@ -1347,6 +1347,13 @@ def save(self, *args, **kwargs):
             'validator': bool,
         },
 
+        'LOGIN_ENABLE_SSO_REG': {
+            'name': _('Enable SSO registration'),
+            'description': _('Enable self-registration via SSO for users on the login pages'),
+            'default': False,
+            'validator': bool,
+        },
+
         'LOGIN_MAIL_REQUIRED': {
             'name': _('Email required'),
             'description': _('Require user to supply mail on signup'),


Test patch:
Repository: inventree/InvenTree

Issue:
[BUG] :checkered_flag: Typo in Settings page
### Please verify that this bug has NOT been raised before.

- [X] I checked and didn't find similar issue

### Describe the bug*

Just a minor thing. There's a typo on the Settings page.

Settings -> Global Settings -> Server Configuration

"Delete **_Noficiations_** | User notifications will be deleted after specified number of days"





### Steps to Reproduce

Settings -> Global Settings -> Server Configuration -> Delete "Noficiations"

### Expected behavior

Delete Notifications

### Deployment Method

- [X] Docker
- [ ] Bare metal

### Version Information

# Version Information:
InvenTree-Version: 0.9.2
Django Version: 3.2.16
Commit Hash: 236ca36
Commit Date: 2023-01-04
Database: postgresql
Debug-Mode: False
Deployed using Docker: True
Active plugins: False


### Relevant log output

_No response_


Discussion:
Thank you for the report @jtrosper ! This should be fixed in the next release.

Resolving patch:
diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py
--- a/InvenTree/common/models.py
+++ b/InvenTree/common/models.py
@@ -956,7 +956,7 @@ def save(self, *args, **kwargs):
         },
 
         'INVENTREE_DELETE_NOTIFICATIONS_DAYS': {
-            'name': _('Delete Noficiations'),
+            'name': _('Delete Notifications'),
             'description': _('User notifications will be deleted after specified number of days'),
             'default': 30,
             'units': 'days',


Test patch:
Repository: inventree/InvenTree

Issue:
[BUG] Increase worker-timeout to account for install times
 I might have another instance of the same worker-timeout-loop during startup to add to the issue. My docker production installation at InvenTree:latest is running on a Raspberry Pi 3B+.
The loop occured after I had added the `inventree-brother-plugin` to `plugins.txt` - the initial plugin installation took too long during startup so that the worker processes timed out and were constantly restartet.

My "solution" was to increase the gunicorn timeout variable in the `.env` file to
```
# Options for gunicorn server
INVENTREE_GUNICORN_TIMEOUT=60
```
but maybe actions like pip installs should somehow generally not count against the worker timeout? (I'm not sure about the technical internals on this one at the moment...)

_Originally posted by @simonkuehling in https://github.com/inventree/InvenTree/issues/4180#issuecomment-1410348943_
            


Discussion:

Resolving patch:
diff --git a/docker/gunicorn.conf.py b/docker/gunicorn.conf.py
--- a/docker/gunicorn.conf.py
+++ b/docker/gunicorn.conf.py
@@ -18,8 +18,8 @@
 threads = 4
 
 
-# Worker timeout (default = 30 seconds)
-timeout = os.environ.get('INVENTREE_GUNICORN_TIMEOUT', 30)
+# Worker timeout (default = 90 seconds)
+timeout = os.environ.get('INVENTREE_GUNICORN_TIMEOUT', 90)
 
 # Number of worker processes
 workers = os.environ.get('INVENTREE_GUNICORN_WORKERS', None)


Test patch:
Repository: inventree/InvenTree

Issue:
"Install Plugin" via GUI fails to add plugin to plugins.txt correctly for first plugin
### Please verify that this bug has NOT been raised before.

- [X] I checked and didn't find a similar issue

### Describe the bug*

When trying to install a plugin via the GUI function "Install Plugin" without any prior installed plugins, the plugin is appended to the first line of the plugins.txt.

As the first line is already populated with `# InvenTree Plugins (uses PIP framework to install)` the result is e.g. `# InvenTree Plugins (uses PIP framework to install)inventree-zebra-plugin@git+https://github.com/SergeoLacruz/inventree-zebra-plugin  # Installed 2023-04-28 06:55:40.146423+00:00 by xyz` thus ignoring the plugin in a docker env restart because of the `#`.

Subsequently installed plugins are correctly placed in an empty line of the plugins.txt.

### Steps to Reproduce

1. Have a fresh install without installed plugins.
2. Go to "Settings" > "Plugin Settings" > "Plugins" > "Install Plugin"
3. Fill "Package Name" with `inventree-zebra-plugin`
4. Fill "Source URL" with `git+https://github.com/SergeoLacruz/inventree-zebra-plugin`
5. "Submit"
6. Check plugins.txt file

### Expected behaviour

The installed plugin should be added below the comment such that it actually will be parsed by the plugin management.

### Deployment Method

- [X] Docker
- [ ] Bare metal

### Version Information

# Version Information:
InvenTree-Version: 0.11.0
Django Version: 3.2.18
Commit Hash: 593a716
Commit Date: 2023-04-18
Database: postgresql
Debug-Mode: False
Deployed using Docker: True
Active plugins: [{'name': 'InvenTreeBarcode', 'slug': 'inventreebarcode', 'version': '2.0.0'}, {'name': 'InvenTreeCoreNotificationsPlugin', 'slug': 'inventreecorenotificationsplugin', 'version': '1.0.0'}]


### Relevant log output

_No response_


Discussion:

Resolving patch:
diff --git a/InvenTree/plugin/serializers.py b/InvenTree/plugin/serializers.py
--- a/InvenTree/plugin/serializers.py
+++ b/InvenTree/plugin/serializers.py
@@ -154,7 +154,13 @@ def save(self):
 
         # save plugin to plugin_file if installed successfull
         if success:
+            # Read content of plugin file
+            plg_lines = open(settings.PLUGIN_FILE).readlines()
             with open(settings.PLUGIN_FILE, "a") as plugin_file:
+                # Check if last line has a newline
+                if plg_lines[-1][-1:] != '\n':
+                    plugin_file.write('\n')
+                # Write new plugin to file
                 plugin_file.write(f'{" ".join(install_name)}  # Installed {timezone.now()} by {str(self.context["request"].user)}\n')
 
         # Check for migrations


Test patch:
Repository: inventree/InvenTree

Issue:
PanelMixin get_custom_panels not getting called for part list view
### Please verify that this bug has NOT been raised before.

- [X] I checked and didn't find a similar issue

### Describe the bug*

I want to add a custom part import panel, for that I'm trying to use the PanelMixin for my plugin.
But I realized the part list view "http://inventree_server/part/" ignores the plugin and doesn't call the get_custom_panels method.

### Steps to Reproduce

create plugin with PanelMixin that always returns a test panel.
open part list, the panel doesn't show

### Expected behaviour

The panel should show

### Deployment Method

- [ ] Docker
- [X] Bare metal

### Version Information

# Version Information:
InvenTree-Version: 0.10.0
Django Version: 3.2.16


Database: sqlite3
Debug-Mode: False
Deployed using Docker: False
Active plugins: [{'name': 'InvenTreeBarcode', 'slug': 'inventreebarcode', 'version': '2.0.0'}, {'name': 'InvenTreeCoreNotificationsPlugin', 'slug': 'inventreecorenotificationsplugin', 'version': '1.0.0'}, {'name': 'EMEImport', 'slug': 'emeimport', 'version': '0.0.1'}]


### Relevant log output

_No response_


Discussion:
@IvoLealMCS you'll need to provide more information here - do you have a link to your plugin or a snippet of code? Otherwise not much we can help with
I think this is a feature request because the InvenTreePluginViewMixin is missing on the PartIndex view.
@wolflu05 ah, I see. I guess that makes sense to add that mixin then :)
> @IvoLealMCS you'll need to provide more information here - do you have a link to your plugin or a snippet of code? Otherwise not much we can help with

Here you have it:
`from plugin import InvenTreePlugin
from plugin.mixins import PanelMixin

from part.views import CategoryDetail


class ImportPlugin(PanelMixin, InvenTreePlugin):
    NAME = "ImportTest"
    DESCRIPTION = "Test"
    VERSION = "0.0.1"

    def get_custom_panels(self, view, request):
        with open('/etc/inventree/custom_log.txt', 'a') as f:
            f.write(str(type(view))+'\n')
        panels = []
        panels.append({
                'title': 'Test',
                'icon': 'fa-file-upload'
        })
        return panels
`

But either way I believe @wolflu05 undertood my issue correctly, and if so, sorry for the incorrect category, I believed it was a bug because in the remaing views it works
I tested adding the mixin and it works fine, will submit a PR with the fix

Resolving patch:
diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py
--- a/InvenTree/part/views.py
+++ b/InvenTree/part/views.py
@@ -27,7 +27,7 @@
 from .part import MakePartTemplate
 
 
-class PartIndex(InvenTreeRoleMixin, ListView):
+class PartIndex(InvenTreeRoleMixin, InvenTreePluginViewMixin, ListView):
     """View for displaying list of Part objects."""
 
     model = Part


Test patch:
Repository: inventree/InvenTree

Issue:
Make event test more specific
              @matmair [this CI failure](https://github.com/inventree/InvenTree/actions/runs/5259899543/jobs/9506168595?pr=4732) is the last in the current batch of weird ones. I'm seeing it on multiple PRs, about 50% of the time.

Here's the failing line:

https://github.com/inventree/InvenTree/blob/c8365ccd0c9371ea4d127fe616e0029f35b3c19c/InvenTree/plugin/samples/event/test_event_sample.py#L27

Sometimes, `cm.warning.args[0]` returns an "unclosed file object", rather than a string. Any ideas?

_Originally posted by @SchrodingersGat in https://github.com/inventree/InvenTree/issues/4732#issuecomment-1590219025_
            


Discussion:

Resolving patch:
diff --git a/InvenTree/plugin/samples/event/event_sample.py b/InvenTree/plugin/samples/event/event_sample.py
--- a/InvenTree/plugin/samples/event/event_sample.py
+++ b/InvenTree/plugin/samples/event/event_sample.py
@@ -1,12 +1,14 @@
 """Sample plugin which responds to events."""
 
-import warnings
+import logging
 
 from django.conf import settings
 
 from plugin import InvenTreePlugin
 from plugin.mixins import EventMixin
 
+logger = logging.getLogger('inventree')
+
 
 class EventPluginSample(EventMixin, InvenTreePlugin):
     """A sample plugin which provides supports for triggered events."""
@@ -23,4 +25,4 @@ def process_event(self, event, *args, **kwargs):
 
         # Issue warning that we can test for
         if settings.PLUGIN_TESTING:
-            warnings.warn(f'Event `{event}` triggered', stacklevel=2)
+            logger.debug(f'Event `{event}` triggered in sample plugin')


Test patch:
diff --git a/InvenTree/plugin/samples/event/test_event_sample.py b/InvenTree/plugin/samples/event/test_event_sample.py
--- a/InvenTree/plugin/samples/event/test_event_sample.py
+++ b/InvenTree/plugin/samples/event/test_event_sample.py
@@ -8,6 +8,8 @@
 from plugin.helpers import MixinNotImplementedError
 from plugin.mixins import EventMixin
 
+from .event_sample import logger
+
 
 class EventPluginSampleTests(TestCase):
     """Tests for EventPluginSample."""
@@ -22,9 +24,9 @@ def test_run_event(self):
         # Enable event testing
         settings.PLUGIN_TESTING_EVENTS = True
         # Check that an event is issued
-        with self.assertWarns(Warning) as cm:
+        with self.assertLogs(logger=logger, level="DEBUG") as cm:
             trigger_event('test.event')
-        self.assertEqual(cm.warning.args[0], 'Event `test.event` triggered')
+        self.assertIn('DEBUG:inventree:Event `test.event` triggered in sample plugin', cm[1])
 
         # Disable again
         settings.PLUGIN_TESTING_EVENTS = False