From 9f08e6190e1c98ee2b83bfed8f6bdd09ca605d21 Mon Sep 17 00:00:00 2001 From: grumo35 Date: Mon, 31 Jan 2022 11:24:04 +0100 Subject: [PATCH 01/25] Update __init__.py Added basic proxy support from environment variables, need to add this option in parameter of patchman cli. --- util/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util/__init__.py b/util/__init__.py index ddbe63eb..bc669c1e 100644 --- a/util/__init__.py +++ b/util/__init__.py @@ -14,6 +14,7 @@ # # You should have received a copy of the GNU General Public License # along with Patchman. If not, see +from os import getenv import sys import requests @@ -33,6 +34,11 @@ from progressbar import Bar, ETA, Percentage, ProgressBar from patchman.signals import error_message +http_proxy=getenv('http_proxy') +proxies = { + 'http': http_proxy, + 'https': http_proxy, +} if ProgressBar.__dict__.get('maxval'): pbar2 = False @@ -130,7 +136,7 @@ def get_url(url): """ res = None try: - res = requests.get(url, stream=True) + res = requests.get(url,proxies=proxies, stream=True) except requests.exceptions.Timeout: error_message.send(sender=None, text='Timeout - {0!s}'.format(url)) except requests.exceptions.TooManyRedirects: From 15e9be0e972e3c4e3d8e65e5d7cd5808090736f4 Mon Sep 17 00:00:00 2001 From: Stamatis Katsaounis Date: Fri, 10 Apr 2020 13:26:46 +0300 Subject: [PATCH 02/25] Add management commands --- patchman/apps.py | 7 +++ patchman/management/__init__.py | 0 patchman/management/commands/__init__.py | 0 .../commands/createsuperuser_with_password.py | 33 ++++++++++++ .../management/commands/set_rdns_check.py | 17 ++++++ .../management/commands/set_secret_key.py | 52 +++++++++++++++++++ patchman/settings.py | 1 + 7 files changed, 110 insertions(+) create mode 100644 patchman/apps.py create mode 100644 patchman/management/__init__.py create mode 100644 patchman/management/commands/__init__.py create mode 100644 patchman/management/commands/createsuperuser_with_password.py create mode 100644 patchman/management/commands/set_rdns_check.py create mode 100644 patchman/management/commands/set_secret_key.py diff --git a/patchman/apps.py b/patchman/apps.py new file mode 100644 index 00000000..4a9c3f7b --- /dev/null +++ b/patchman/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class PatchmanConfig(AppConfig): + name = 'patchman' diff --git a/patchman/management/__init__.py b/patchman/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/patchman/management/commands/__init__.py b/patchman/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/patchman/management/commands/createsuperuser_with_password.py b/patchman/management/commands/createsuperuser_with_password.py new file mode 100644 index 00000000..63d3c721 --- /dev/null +++ b/patchman/management/commands/createsuperuser_with_password.py @@ -0,0 +1,33 @@ +from django.contrib.auth.management.commands import createsuperuser +from django.core.management import CommandError + + +class Command(createsuperuser.Command): + help = 'Crate a superuser, and allow password to be provided' + + def add_arguments(self, parser): + super(Command, self).add_arguments(parser) + parser.add_argument( + '--password', dest='password', default=None, + help='Specifies the password for the superuser.', + ) + + def handle(self, *args, **options): + password = options.get('password') + username = options.get('username') + database = options.get('database') + + if options['interactive']: + raise CommandError( + 'Command is required to run with --no-input option') + if password and not username: + raise CommandError( + '--username is required if specifying --password') + + super(Command, self).handle(*args, **options) + + if password: + user = self.UserModel._default_manager.db_manager( + database).get(username=username) + user.set_password(password) + user.save() diff --git a/patchman/management/commands/set_rdns_check.py b/patchman/management/commands/set_rdns_check.py new file mode 100644 index 00000000..0e5250a7 --- /dev/null +++ b/patchman/management/commands/set_rdns_check.py @@ -0,0 +1,17 @@ +from django.core.management.base import BaseCommand, CommandError +from hosts.models import Host + + +class Command(BaseCommand): + help = 'Enable/Disable rDNS check for hosts' + + def add_arguments(self, parser): + parser.add_argument( + '--disable', action='store_false', default=True, dest='rdns_check', + help='If set, disables rDNS check') + + def handle(self, *args, **options): + try: + Host.objects.all().update(check_dns=options['rdns_check']) + except Exception as e: + raise CommandError('Failed to update rDNS check', str(e)) diff --git a/patchman/management/commands/set_secret_key.py b/patchman/management/commands/set_secret_key.py new file mode 100644 index 00000000..870d1475 --- /dev/null +++ b/patchman/management/commands/set_secret_key.py @@ -0,0 +1,52 @@ +import os +import re +import sys +import codecs +from random import choice +from tempfile import NamedTemporaryFile +from shutil import copy + +from django.core.management.base import BaseCommand + + +class Command(BaseCommand): + help = 'Set SECRET_KEY of Patchman Application.' + + def add_arguments(self, parser): + parser.add_argument( + '--key', help=( + 'The SECRET_KEY to be used by Patchman. If not set, a random ' + 'key of length 50 will be created.')) + + @staticmethod + def get_random_key(): + chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)' + return ''.join([choice(chars) for i in range(50)]) + + def handle(self, *args, **options): + secret_key = options.get('key', self.get_random_key()) + + if sys.prefix == '/usr': + conf_path = '/etc/patchman' + else: + conf_path = os.path.join(sys.prefix, 'etc/patchman') + # if conf_path doesn't exist, try ./etc/patchman + if not os.path.isdir(conf_path): + conf_path = './etc/patchman' + local_settings = os.path.join(conf_path, 'local_settings.py') + + settings_contents = codecs.open( + local_settings, 'r', encoding='utf-8').read() + settings_contents = re.sub( + r"(?<=SECRET_KEY = ')'", secret_key + "'", settings_contents) + + f = NamedTemporaryFile(delete=False) + temp = f.name + f.close() + + fh = codecs.open(temp, 'w+b', encoding='utf-8') + fh.write(settings_contents) + fh.close() + + copy(temp, local_settings) + os.remove(temp) diff --git a/patchman/settings.py b/patchman/settings.py index 4a943a2f..fb1af58e 100644 --- a/patchman/settings.py +++ b/patchman/settings.py @@ -93,6 +93,7 @@ 'repos.apps.ReposConfig', 'reports.apps.ReportsConfig', 'util.apps.UtilConfig', + 'patchman.apps.PatchmanConfig', ] REST_FRAMEWORK = { From 726fa74c3cf4771546c50493ea5b22fca2de7cee Mon Sep 17 00:00:00 2001 From: Stamatis Katsaounis Date: Tue, 12 May 2020 13:24:44 +0300 Subject: [PATCH 03/25] Add set_site command --- patchman/management/commands/set_site.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 patchman/management/commands/set_site.py diff --git a/patchman/management/commands/set_site.py b/patchman/management/commands/set_site.py new file mode 100644 index 00000000..659bb281 --- /dev/null +++ b/patchman/management/commands/set_site.py @@ -0,0 +1,23 @@ +from django.core.management.base import BaseCommand, CommandError +from django.contrib.sites.models import Site +from django.conf import settings + + +class Command(BaseCommand): + help = 'Set Patchman Site Name' + + def add_arguments(self, parser): + parser.add_argument( + '-n', '--name', dest='site_name', help='Site name') + parser.add_argument( + '--clear-cache', action='store_true', default=False, + dest='clear_cache', help='Clear Site cache') + + def handle(self, *args, **options): + try: + Site.objects.filter(pk=settings.SITE_ID).update( + name=options['site_name'], domain=options['site_name']) + if options['claer_cache']: + Site.objects.clear_cache() + except Exception as e: + raise CommandError('Failed to update Site name', str(e)) From 6d0b4b04a577f1150b60f3e1a11b32621e5fa20a Mon Sep 17 00:00:00 2001 From: Stamatis Katsaounis Date: Thu, 21 May 2020 10:29:25 +0300 Subject: [PATCH 04/25] Fix option --- patchman/management/commands/set_site.py | 2 +- patchman/wsgi.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/patchman/management/commands/set_site.py b/patchman/management/commands/set_site.py index 659bb281..3ad97a1b 100644 --- a/patchman/management/commands/set_site.py +++ b/patchman/management/commands/set_site.py @@ -17,7 +17,7 @@ def handle(self, *args, **options): try: Site.objects.filter(pk=settings.SITE_ID).update( name=options['site_name'], domain=options['site_name']) - if options['claer_cache']: + if options['clear_cache']: Site.objects.clear_cache() except Exception as e: raise CommandError('Failed to update Site name', str(e)) diff --git a/patchman/wsgi.py b/patchman/wsgi.py index 9a9b4b7f..bae22bf9 100644 --- a/patchman/wsgi.py +++ b/patchman/wsgi.py @@ -15,7 +15,6 @@ # along with Patchman. If not, see import os - from django.core.wsgi import get_wsgi_application os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'patchman.settings') # noqa From 58d36e32d50774fd84c94944a8126357abf29a3e Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Thu, 20 Jun 2024 22:09:39 -0400 Subject: [PATCH 05/25] Update apps.py --- patchman/apps.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/patchman/apps.py b/patchman/apps.py index 4a9c3f7b..cb08e2c1 100644 --- a/patchman/apps.py +++ b/patchman/apps.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - from django.apps import AppConfig From cd577bf3fdfb77f23b44f1ca0283009dd01041ef Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Sat, 22 Mar 2025 00:48:33 -0400 Subject: [PATCH 06/25] Update __init__.py --- util/__init__.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/util/__init__.py b/util/__init__.py index f27e232a..457e6782 100644 --- a/util/__init__.py +++ b/util/__init__.py @@ -29,24 +29,23 @@ from time import time from tqdm import tqdm -from patchman.signals import error_message, info_message, debug_message - -http_proxy = getenv('http_proxy') -http_proxy = getenv('https_proxy') -proxies = { - 'http': http_proxy, - 'https': https_proxy, -} - from django.utils.timezone import make_aware from django.utils.dateparse import parse_datetime from django.conf import settings +from patchman.signals import error_message, info_message, debug_message pbar = None verbose = None Checksum = Enum('Checksum', 'md5 sha sha1 sha256 sha512') +http_proxy = getenv('http_proxy') +https_proxy = getenv('https_proxy') +proxies = { + 'http': http_proxy, + 'https': https_proxy, +} + def get_verbosity(): """ Get the global verbosity level From 80a2d60e60d9b8d947d33f5b45966c59d0158a7a Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Sat, 22 Mar 2025 00:49:38 -0400 Subject: [PATCH 07/25] Update __init__.py --- util/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/__init__.py b/util/__init__.py index 457e6782..10ee21f7 100644 --- a/util/__init__.py +++ b/util/__init__.py @@ -14,13 +14,13 @@ # # You should have received a copy of the GNU General Public License # along with Patchman. If not, see -from os import getenv import requests import bz2 import magic import zlib import lzma +import os from datetime import datetime, timezone from enum import Enum from hashlib import md5, sha1, sha256, sha512 @@ -39,8 +39,8 @@ verbose = None Checksum = Enum('Checksum', 'md5 sha sha1 sha256 sha512') -http_proxy = getenv('http_proxy') -https_proxy = getenv('https_proxy') +http_proxy = os.getenv('http_proxy') +https_proxy = os.getenv('https_proxy') proxies = { 'http': http_proxy, 'https': https_proxy, @@ -122,7 +122,7 @@ def get_url(url, headers={}, params={}): response = None try: debug_message.send(sender=None, text=f'Trying {url} headers:{headers} params:{params}') - response = requests.get(url, headers=headers, params=params, stream=True, proxies = proxies, timeout=30) + response = requests.get(url, headers=headers, params=params, stream=True, proxies=proxies, timeout=30) debug_message.send(sender=None, text=f'{response.status_code}: {response.headers}') if response.status_code in [403, 404]: return response From d44a2ce5d9ff30abb6caf3037307706cdbc4c5d5 Mon Sep 17 00:00:00 2001 From: "furlongm@gmail.com" Date: Wed, 23 Apr 2025 17:35:03 -0400 Subject: [PATCH 08/25] handle duplicate CVSSes better --- security/models.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/security/models.py b/security/models.py index a847ab02..b60acb47 100644 --- a/security/models.py +++ b/security/models.py @@ -125,19 +125,20 @@ def add_cvss_score(self, vector_string, score=None, severity=None, version=None) score = cvss_score.base_score if not severity: severity = cvss_score.severities()[0] - existing = self.cvss_scores.filter(version=version, vector_string=vector_string) - if existing: - cvss = existing.first() - else: + try: cvss, created = CVSS.objects.get_or_create( version=version, vector_string=vector_string, score=score, severity=severity, ) - cvss.score = score - cvss.severity = severity - cvss.save() + except CVSS.MultipleObjectsReturned: + matching_cvsses = CVSS.objects.filter( + version=version, + vector_string=vector_string, + ) + cvss = matching_cvsses.first() + matching_cvsses.exclude(id=cvss.id).delete() self.cvss_scores.add(cvss) def fetch_cve_data(self, fetch_nist_data=False, sleep_secs=6): From bf626c90dd697dfd7bc41f542ae55c88af296e2a Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Tue, 8 Apr 2025 15:49:31 -0400 Subject: [PATCH 09/25] reduce max charfield length for mysql --- security/migrations/0001_initial.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/migrations/0001_initial.py b/security/migrations/0001_initial.py index 5655f8b0..c22d1727 100644 --- a/security/migrations/0001_initial.py +++ b/security/migrations/0001_initial.py @@ -27,7 +27,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('cwe_id', models.CharField(max_length=255, unique=True)), ('name', models.CharField(blank=True, max_length=255, null=True)), - ('description', models.CharField(blank=True, max_length=65535, null=True)), + ('description', models.CharField(blank=True, max_length=21844, null=True)), ], ), migrations.CreateModel( @@ -36,7 +36,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('cve_id', models.CharField(max_length=255, unique=True)), ('title', models.CharField(blank=True, max_length=255, null=True)), - ('description', models.CharField(max_length=65535)), + ('description', models.CharField(max_length=21844)), ('reserved_date', models.DateTimeField(blank=True, null=True)), ('published_date', models.DateTimeField(blank=True, null=True)), ('rejected_date', models.DateTimeField(blank=True, null=True)), From 382cd29ad3aeba4481fa4d14e38ce75bcff37874 Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Fri, 18 Apr 2025 00:05:34 -0400 Subject: [PATCH 10/25] further reduce charfield size for mysql --- security/migrations/0001_initial.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/migrations/0001_initial.py b/security/migrations/0001_initial.py index c22d1727..5f922c9a 100644 --- a/security/migrations/0001_initial.py +++ b/security/migrations/0001_initial.py @@ -27,7 +27,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('cwe_id', models.CharField(max_length=255, unique=True)), ('name', models.CharField(blank=True, max_length=255, null=True)), - ('description', models.CharField(blank=True, max_length=21844, null=True)), + ('description', models.CharField(blank=True, max_length=255, null=True)), ], ), migrations.CreateModel( @@ -36,7 +36,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('cve_id', models.CharField(max_length=255, unique=True)), ('title', models.CharField(blank=True, max_length=255, null=True)), - ('description', models.CharField(max_length=21844)), + ('description', models.CharField(max_length=255)), ('reserved_date', models.DateTimeField(blank=True, null=True)), ('published_date', models.DateTimeField(blank=True, null=True)), ('rejected_date', models.DateTimeField(blank=True, null=True)), From 20a42edbe72459f2ddb70c438e283262f5a9df95 Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Tue, 29 Apr 2025 16:10:52 -0400 Subject: [PATCH 11/25] reduce URLField max_length to 765 --- errata/migrations/0001_initial.py | 2 +- security/migrations/0005_reference_cve_references.py | 2 +- security/models.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/errata/migrations/0001_initial.py b/errata/migrations/0001_initial.py index 85fe88b4..d02a7dc8 100644 --- a/errata/migrations/0001_initial.py +++ b/errata/migrations/0001_initial.py @@ -19,7 +19,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('er_type', models.CharField(max_length=255)), - ('url', models.URLField(max_length=2000)), + ('url', models.URLField(max_length=765)), ], ), migrations.CreateModel( diff --git a/security/migrations/0005_reference_cve_references.py b/security/migrations/0005_reference_cve_references.py index 97251add..f94cf7d5 100644 --- a/security/migrations/0005_reference_cve_references.py +++ b/security/migrations/0005_reference_cve_references.py @@ -15,7 +15,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('ref_type', models.CharField(max_length=255)), - ('url', models.URLField(max_length=2000)), + ('url', models.URLField(max_length=765)), ], options={ 'unique_together': {('ref_type', 'url')}, diff --git a/security/models.py b/security/models.py index b60acb47..9c097eed 100644 --- a/security/models.py +++ b/security/models.py @@ -29,7 +29,7 @@ class Reference(models.Model): ref_type = models.CharField(max_length=255) - url = models.URLField(max_length=2000) + url = models.URLField(max_length=765) class Meta: unique_together = ['ref_type', 'url'] From bf5478cf5d5374b693d2641d526db1a1e02f47e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 15:45:31 +0000 Subject: [PATCH 12/25] Bump django from 4.2.20 to 4.2.21 Bumps [django](https://github.com/django/django) from 4.2.20 to 4.2.21. - [Commits](https://github.com/django/django/compare/4.2.20...4.2.21) --- updated-dependencies: - dependency-name: django dependency-version: 4.2.21 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index dca4fe03..2f72fae5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==4.2.20 +Django==4.2.21 django-taggit==4.0.0 django-extensions==3.2.3 django-bootstrap3==23.1 From 57e5c0d4861b7c80d081e1b85a8b48f9bd1cb332 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 23:28:39 +0000 Subject: [PATCH 13/25] Bump django from 4.2.21 to 4.2.22 Bumps [django](https://github.com/django/django) from 4.2.21 to 4.2.22. - [Commits](https://github.com/django/django/compare/4.2.21...4.2.22) --- updated-dependencies: - dependency-name: django dependency-version: 4.2.22 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2f72fae5..3418b5d0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==4.2.21 +Django==4.2.22 django-taggit==4.0.0 django-extensions==3.2.3 django-bootstrap3==23.1 From 6a45e90ed63efadd4e1e7c246d174feceb91c439 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Jun 2025 08:47:24 +0000 Subject: [PATCH 14/25] Bump requests from 2.32.3 to 2.32.4 Bumps [requests](https://github.com/psf/requests) from 2.32.3 to 2.32.4. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.32.3...v2.32.4) --- updated-dependencies: - dependency-name: requests dependency-version: 2.32.4 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2f72fae5..955c7bbb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ python-debian==1.0.1 defusedxml==0.7.1 PyYAML==6.0.2 chardet==5.2.0 -requests==2.32.3 +requests==2.32.4 colorama==0.4.6 djangorestframework==3.15.2 django-filter==25.1 From 56748532f099b6bd1dfaf202e55e4a160dc9fa3f Mon Sep 17 00:00:00 2001 From: vtalos Date: Thu, 17 Jul 2025 19:33:36 +0300 Subject: [PATCH 15/25] Remove unused dependency 'chardet' from requirements.txt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 088f0870..a39eb8cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,6 @@ django-bootstrap3==23.1 python-debian==1.0.1 defusedxml==0.7.1 PyYAML==6.0.2 -chardet==5.2.0 requests==2.32.4 colorama==0.4.6 djangorestframework==3.15.2 From 94fcb04694d204c32d4098fe9981f255eb4a843e Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Tue, 5 Aug 2025 20:15:16 -0400 Subject: [PATCH 16/25] get_or_create_module only returns module --- modules/utils.py | 4 ++-- repos/repo_types/yum.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/utils.py b/modules/utils.py index 817a610c..f56a0f62 100644 --- a/modules/utils.py +++ b/modules/utils.py @@ -23,7 +23,7 @@ def get_or_create_module(name, stream, version, context, arch, repo): """ Get or create a module object - Returns the module and a boolean for created + Returns the module """ created = False m_arch, c = PackageArchitecture.objects.get_or_create(name=arch) @@ -46,7 +46,7 @@ def get_or_create_module(name, stream, version, context, arch, repo): arch=m_arch, repo=repo, ) - return module, created + return module def get_matching_modules(name, stream, version, context, arch): diff --git a/repos/repo_types/yum.py b/repos/repo_types/yum.py index d08c7393..7ac85816 100644 --- a/repos/repo_types/yum.py +++ b/repos/repo_types/yum.py @@ -91,7 +91,7 @@ def extract_module_metadata(data, url, repo): packages.add(package) from modules.utils import get_or_create_module - module, created = get_or_create_module(m_name, m_stream, m_version, m_context, arch, repo) + module = get_or_create_module(m_name, m_stream, m_version, m_context, arch, repo) package_ids = [] for package in packages: From 1480468f32ed5386c678e5fa0972eaf4c708c879 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Sep 2025 02:19:45 +0000 Subject: [PATCH 17/25] Bump django from 4.2.22 to 4.2.24 Bumps [django](https://github.com/django/django) from 4.2.22 to 4.2.24. - [Commits](https://github.com/django/django/compare/4.2.22...4.2.24) --- updated-dependencies: - dependency-name: django dependency-version: 4.2.24 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a39eb8cc..9d2baa9e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==4.2.22 +Django==4.2.24 django-taggit==4.0.0 django-extensions==3.2.3 django-bootstrap3==23.1 From b6162963e7811081eb7a4f60ef04a594d23d5866 Mon Sep 17 00:00:00 2001 From: Will Furnell Date: Fri, 12 Sep 2025 13:33:45 +0100 Subject: [PATCH 18/25] Package types are in the Package class --- packages/models.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/models.py b/packages/models.py index f4c9c59e..74a83c0c 100644 --- a/packages/models.py +++ b/packages/models.py @@ -195,11 +195,11 @@ def __str__(self): rel = f'-{self.release}' else: rel = '' - if self.packagetype == self.GENTOO: + if self.packagetype == Package.GENTOO: return f'{self.category}/{self.name}-{epo}{self.version}{rel}-{self.arch}.{self.get_packagetype_display()}' - elif self.packagetype in [self.DEB, self.ARCH]: + elif self.packagetype in [Package.DEB, Package.ARCH]: return f'{self.name}_{epo}{self.version}{rel}_{self.arch}.{self.get_packagetype_display()}' - elif self.packagetype == self.RPM: + elif self.packagetype == Package.RPM: return f'{self.name}-{epo}{self.version}{rel}-{self.arch}.{self.get_packagetype_display()}' else: return f'{self.name}-{epo}{self.version}{rel}-{self.arch}.{self.get_packagetype_display()}' From 3676e78cd0afbd0467241f8fb62f54626f2508fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 23:00:50 +0000 Subject: [PATCH 19/25] Bump django from 4.2.24 to 4.2.25 Bumps [django](https://github.com/django/django) from 4.2.24 to 4.2.25. - [Commits](https://github.com/django/django/compare/4.2.24...4.2.25) --- updated-dependencies: - dependency-name: django dependency-version: 4.2.25 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9d2baa9e..9d277d38 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==4.2.24 +Django==4.2.25 django-taggit==4.0.0 django-extensions==3.2.3 django-bootstrap3==23.1 From 1c260013c8cdb1bb5913a1151e37bde309ac438d Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Fri, 3 Oct 2025 10:54:33 -0400 Subject: [PATCH 20/25] bump redis --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9d277d38..2f264c9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,7 @@ python-magic==0.4.27 gitpython==3.1.44 tenacity==8.2.3 celery==5.4.0 -redis==5.2.1 +redis==6.4.0 django-celery-beat==2.7.0 tqdm==4.67.1 cvss==3.4 From 0f5445448421f17efb66d07d3f511b6327732440 Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Fri, 3 Oct 2025 10:59:40 -0400 Subject: [PATCH 21/25] Update license in common.py --- util/templatetags/common.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/util/templatetags/common.py b/util/templatetags/common.py index 6737c438..2aea1e5e 100644 --- a/util/templatetags/common.py +++ b/util/templatetags/common.py @@ -1,12 +1,10 @@ -# Copyright 2010 VPAC -# Copyright 2013-2021 Marcus Furlong +# Copyright 2013-2025 Marcus Furlong # # This file is part of Patchman. # # Patchman is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# the Free Software Foundation, version 3 only. # # Patchman is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,7 +12,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with Patchman If not, see . +# along with Patchman. If not, see import re From ce9f4f07dc176cfdab072f425acfdd69e9b728eb Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Fri, 3 Oct 2025 11:11:25 -0400 Subject: [PATCH 22/25] fix licenses --- hosts/templatetags/report_alert.py | 7 +++---- setup.py | 2 +- util/filterspecs.py | 7 +++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/hosts/templatetags/report_alert.py b/hosts/templatetags/report_alert.py index 3a3e3a9a..a28c5058 100644 --- a/hosts/templatetags/report_alert.py +++ b/hosts/templatetags/report_alert.py @@ -1,11 +1,10 @@ -# Copyright 2016-2021 Marcus Furlong +# Copyright 2016-2025 Marcus Furlong # # This file is part of Patchman. # # Patchman is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# the Free Software Foundation, version 3 only. # # Patchman is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -13,7 +12,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with Patchman If not, see . +# along with Patchman. If not, see from datetime import timedelta diff --git a/setup.py b/setup.py index d8249a67..6ec6d974 100755 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright 2013-2021 Marcus Furlong +# Copyright 2013-2025 Marcus Furlong # # This file is part of Patchman. # diff --git a/util/filterspecs.py b/util/filterspecs.py index 1c845ff3..722b45df 100644 --- a/util/filterspecs.py +++ b/util/filterspecs.py @@ -1,12 +1,11 @@ # Copyright 2010 VPAC -# Copyright 2014-2021 Marcus Furlong +# Copyright 2014-2025 Marcus Furlong # # This file is part of Patchman. # # Patchman is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. +# the Free Software Foundation, version 3 only. # # Patchman is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,7 +13,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with Patchman If not, see . +# along with Patchman. If not, see from django.utils.safestring import mark_safe from django.db.models.query import QuerySet From c651c3f222ec7c53af47cfaedfcb5d7254b47710 Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Fri, 3 Oct 2025 11:57:40 -0400 Subject: [PATCH 23/25] use GPL-3.0-only for debian copyright --- debian/copyright | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/copyright b/debian/copyright index ab051037..5202ff0e 100644 --- a/debian/copyright +++ b/debian/copyright @@ -6,7 +6,7 @@ Source: https://github.com/furlongm/patchman Files: * Copyright: 2011-2012 VPAC http://www.vpac.org 2013-2021 Marcus Furlong -License: GPL-3.0 +License: GPL-3.0-only This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 only. From 1c7ef233720e27b9ca67431d17304a11b28f1451 Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Mon, 20 Oct 2025 21:15:01 -0400 Subject: [PATCH 24/25] Update patchman/management/commands/createsuperuser_with_password.py Co-authored-by: code-review-doctor[bot] <72320148+code-review-doctor[bot]@users.noreply.github.com> --- patchman/management/commands/createsuperuser_with_password.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patchman/management/commands/createsuperuser_with_password.py b/patchman/management/commands/createsuperuser_with_password.py index 63d3c721..e2d677ba 100644 --- a/patchman/management/commands/createsuperuser_with_password.py +++ b/patchman/management/commands/createsuperuser_with_password.py @@ -24,7 +24,7 @@ def handle(self, *args, **options): raise CommandError( '--username is required if specifying --password') - super(Command, self).handle(*args, **options) + super().handle(*args, **options) if password: user = self.UserModel._default_manager.db_manager( From f5b34d7e544f2c16160bd755e3406b30a0b1f3f9 Mon Sep 17 00:00:00 2001 From: Marcus Furlong Date: Mon, 20 Oct 2025 21:15:08 -0400 Subject: [PATCH 25/25] Update patchman/management/commands/createsuperuser_with_password.py Co-authored-by: code-review-doctor[bot] <72320148+code-review-doctor[bot]@users.noreply.github.com> --- patchman/management/commands/createsuperuser_with_password.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patchman/management/commands/createsuperuser_with_password.py b/patchman/management/commands/createsuperuser_with_password.py index e2d677ba..3006e25e 100644 --- a/patchman/management/commands/createsuperuser_with_password.py +++ b/patchman/management/commands/createsuperuser_with_password.py @@ -6,7 +6,7 @@ class Command(createsuperuser.Command): help = 'Crate a superuser, and allow password to be provided' def add_arguments(self, parser): - super(Command, self).add_arguments(parser) + super().add_arguments(parser) parser.add_argument( '--password', dest='password', default=None, help='Specifies the password for the superuser.',