Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ mysql or postgresql instead, see the database configuration section.


## Supported Server Installation Options
- [Ubuntu 24.04](#ubuntu-2404-noble)
- [Ubuntu 26.04](#ubuntu-2604-noble)
- [Debian 13](#debian-13-trixie)
- [Rocky 10](#rocky-10)
- [virtualenv + pip](#virtualenv--pip)
- [Source](#source)


### Ubuntu 24.04 (noble)
### Ubuntu 26.04 (resolute)

```shell
curl -sS https://repo.openbytes.ie/openbytes.gpg > /usr/share/keyrings/openbytes.gpg
echo "deb [signed-by=/usr/share/keyrings/openbytes.gpg] https://repo.openbytes.ie/patchman/ubuntu noble-backports main" > /etc/apt/sources.list.d/patchman.list
echo "deb [signed-by=/usr/share/keyrings/openbytes.gpg] https://repo.openbytes.ie/patchman/ubuntu resolute main" > /etc/apt/sources.list.d/patchman.list
apt update
apt -y install python3-patchman patchman-client
patchman-manage createsuperuser
Expand Down Expand Up @@ -74,7 +74,7 @@ gunicorn patchman.wsgi -b 0.0.0.0:80

### Source

#### Ubuntu 24.04 (noble)
#### Ubuntu 26.04 (resolute)

1. Install dependencies

Expand Down
4 changes: 1 addition & 3 deletions errata/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
from errata.models import Erratum


@admin.register(Erratum)
class ErratumAdmin(admin.ModelAdmin):
readonly_fields = ('affected_packages', 'fixed_packages', 'references')


admin.site.register(Erratum, ErratumAdmin)
2 changes: 1 addition & 1 deletion hosts/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
from hosts.models import Host, HostRepo


@admin.register(Host)
class HostAdmin(admin.ModelAdmin):
readonly_fields = ('packages', 'updates')


admin.site.register(Host, HostAdmin)
admin.site.register(HostRepo)
21 changes: 21 additions & 0 deletions hosts/migrations/0013_alter_hostrepo_unique_together_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.2.28 on 2026-04-01 03:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('hosts', '0012_backfill_cached_counts'),
]

operations = [
migrations.AlterUniqueTogether(
name='hostrepo',
unique_together=set(),
),
migrations.AddConstraint(
model_name='hostrepo',
constraint=models.UniqueConstraint(fields=('host', 'repo'), name='unique_hostrepo'),
),
]
7 changes: 6 additions & 1 deletion hosts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,12 @@ class HostRepo(models.Model):
priority = models.IntegerField(default=0)

class Meta:
unique_together = ['host', 'repo']
constraints = [
models.UniqueConstraint(
fields=['host', 'repo'],
name='unique_hostrepo',
),
]
ordering = ['host', 'repo']

def __str__(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.2.28 on 2026-04-01 03:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('modules', '0006_alter_module_context_alter_module_name_and_more'),
]

operations = [
migrations.AlterUniqueTogether(
name='module',
unique_together=set(),
),
migrations.AddConstraint(
model_name='module',
constraint=models.UniqueConstraint(fields=('name', 'stream', 'version', 'context', 'arch', 'repo'), name='unique_module'),
),
]
7 changes: 6 additions & 1 deletion modules/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ class Module(models.Model):
class Meta:
verbose_name = 'Module'
verbose_name_plural = 'Modules'
unique_together = ['name', 'stream', 'version', 'context', 'arch', 'repo']
constraints = [
models.UniqueConstraint(
fields=['name', 'stream', 'version', 'context', 'arch', 'repo'],
name='unique_module',
),
]
ordering = ['name', 'stream']

def __str__(self):
Expand Down
2 changes: 1 addition & 1 deletion operatingsystems/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
from operatingsystems.models import OSRelease, OSVariant


@admin.register(OSRelease)
class OSReleaseAdmin(admin.ModelAdmin):
filter_horizontal = ('repos',)


admin.site.register(OSVariant)
admin.site.register(OSRelease, OSReleaseAdmin)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.2.28 on 2026-04-01 03:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('operatingsystems', '0011_alter_osrelease_codename_alter_osrelease_cpe_name_and_more'),
]

operations = [
migrations.AlterUniqueTogether(
name='osrelease',
unique_together=set(),
),
migrations.AddConstraint(
model_name='osrelease',
constraint=models.UniqueConstraint(fields=('name', 'codename', 'cpe_name'), name='unique_osrelease'),
),
]
7 changes: 6 additions & 1 deletion operatingsystems/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ class OSRelease(models.Model):
class Meta:
verbose_name = 'Operating System Release'
verbose_name_plural = 'Operating System Releases'
unique_together = ['name', 'codename', 'cpe_name']
constraints = [
models.UniqueConstraint(
fields=['name', 'codename', 'cpe_name'],
name='unique_osrelease',
),
]
ordering = ['name']

def __str__(self):
Expand Down
4 changes: 2 additions & 2 deletions packages/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
from packages.models import Package, PackageName, PackageUpdate


@admin.register(Package)
class PackageAdmin(admin.ModelAdmin):
readonly_fields = ('name',)


@admin.register(PackageUpdate)
class PackageUpdateAdmin(admin.ModelAdmin):
readonly_fields = ('oldpackage', 'newpackage')


admin.site.register(Package, PackageAdmin)
admin.site.register(PackageName)
admin.site.register(PackageUpdate, PackageUpdateAdmin)
29 changes: 29 additions & 0 deletions packages/migrations/0008_alter_package_unique_together_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 4.2.28 on 2026-04-01 03:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('packages', '0007_alter_package_epoch_alter_package_release_and_more'),
]

operations = [
migrations.AlterUniqueTogether(
name='package',
unique_together=set(),
),
migrations.AlterUniqueTogether(
name='packageupdate',
unique_together=set(),
),
migrations.AddConstraint(
model_name='package',
constraint=models.UniqueConstraint(fields=('name', 'epoch', 'version', 'release', 'arch', 'packagetype', 'category'), name='unique_package'),
),
migrations.AddConstraint(
model_name='packageupdate',
constraint=models.UniqueConstraint(fields=('oldpackage', 'newpackage', 'security'), name='unique_packageupdate'),
),
]
14 changes: 12 additions & 2 deletions packages/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ class Package(models.Model):

class Meta:
ordering = ['name', 'epoch', 'version', 'release', 'arch']
unique_together = ['name', 'epoch', 'version', 'release', 'arch', 'packagetype', 'category']
constraints = [
models.UniqueConstraint(
fields=['name', 'epoch', 'version', 'release', 'arch', 'packagetype', 'category'],
name='unique_package',
),
]

def __str__(self):
if self.epoch:
Expand Down Expand Up @@ -226,7 +231,12 @@ class PackageUpdate(models.Model):
security = models.BooleanField(default=False)

class Meta:
unique_together = ['oldpackage', 'newpackage', 'security']
constraints = [
models.UniqueConstraint(
fields=['oldpackage', 'newpackage', 'security'],
name='unique_packageupdate',
),
]
ordering = ['oldpackage', 'newpackage']

def __str__(self):
Expand Down
1 change: 0 additions & 1 deletion patchman/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'America/NewYork'
USE_I18N = True
USE_L10N = True
USE_TZ = True

DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
Expand Down
2 changes: 1 addition & 1 deletion patchman/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# along with If not, see <http://www.gnu.org/licenses/>

from django.conf import settings
from django.conf.urls import handler404, handler500, include # noqa
from django.urls import include
from django.contrib import admin
from django.urls import path
from django.views import static
Expand Down
4 changes: 1 addition & 3 deletions reports/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
from reports.models import Report


@admin.register(Report)
class ReportAdmin(admin.ModelAdmin):
readonly_fields = ('packages',)


admin.site.register(Report, ReportAdmin)
6 changes: 3 additions & 3 deletions reports/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ def create(self, request):
data = serializer.validated_data

# Extract client IP
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
x_real_ip = request.META.get('HTTP_X_REAL_IP')
x_forwarded_for = request.headers.get('x-forwarded-for')
x_real_ip = request.headers.get('x-real-ip')
if x_forwarded_for:
report_ip = x_forwarded_for.split(',')[0]
elif x_real_ip:
Expand Down Expand Up @@ -336,7 +336,7 @@ def create(self, request):
os=data['os'],
report_ip=report_ip,
protocol='2',
useragent=request.META.get('HTTP_USER_AGENT', ''),
useragent=request.headers.get('user-agent', ''),
packages=json.dumps(data.get('packages', [])),
repos=json.dumps(data.get('repos', [])),
modules=json.dumps(data.get('modules', [])),
Expand Down
4 changes: 2 additions & 2 deletions repos/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
from repos.models import Mirror, MirrorPackage, Repository


@admin.register(Mirror)
class MirrorAdmin(admin.ModelAdmin):
readonly_fields = ('packages',)


@admin.register(MirrorPackage)
class MirrorPackageAdmin(admin.ModelAdmin):
readonly_fields = ('package',)


admin.site.register(Repository)
admin.site.register(Mirror, MirrorAdmin)
admin.site.register(MirrorPackage, MirrorPackageAdmin)
29 changes: 29 additions & 0 deletions security/migrations/0011_alter_cvss_unique_together_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 4.2.28 on 2026-04-01 03:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('security', '0010_fix_cvss_vector_string_length'),
]

operations = [
migrations.AlterUniqueTogether(
name='cvss',
unique_together=set(),
),
migrations.AlterUniqueTogether(
name='reference',
unique_together=set(),
),
migrations.AddConstraint(
model_name='cvss',
constraint=models.UniqueConstraint(fields=('score', 'severity', 'version', 'vector_string'), name='unique_cvss'),
),
migrations.AddConstraint(
model_name='reference',
constraint=models.UniqueConstraint(fields=('ref_type', 'url'), name='unique_reference'),
),
]
14 changes: 12 additions & 2 deletions security/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ class Reference(models.Model):
url = models.URLField(max_length=512)

class Meta:
unique_together = ['ref_type', 'url']
constraints = [
models.UniqueConstraint(
fields=['ref_type', 'url'],
name='unique_reference',
),
]
ordering = ['ref_type', 'url']

def __str__(self):
Expand Down Expand Up @@ -87,7 +92,12 @@ class CVSS(models.Model):
vector_string = models.CharField(max_length=255, blank=True, null=True)

class Meta:
unique_together = ['score', 'severity', 'version', 'vector_string']
constraints = [
models.UniqueConstraint(
fields=['score', 'severity', 'version', 'vector_string'],
name='unique_cvss',
),
]

def __str__(self):
return f'{self.score} ({self.severity}) [{self.vector_string}]'
Expand Down
2 changes: 1 addition & 1 deletion security/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def test_reference_str(self):
self.assertIn('example.com', str_repr)

def test_reference_unique_together(self):
"""Test Reference unique_together constraint."""
"""Test Reference unique constraint."""
Reference.objects.create(
url='https://example.com/advisory',
ref_type='VENDOR',
Expand Down
Loading