Skip to content

Commit bfe4e03

Browse files
committed
Merge branch 'main' into 342-migration
2 parents 04812a2 + 392e830 commit bfe4e03

File tree

4 files changed

+71
-1
lines changed

4 files changed

+71
-1
lines changed

netbox_custom_objects/forms.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class Meta:
8888
model = CustomObjectType
8989
fields = (
9090
"name",
91+
"slug",
9192
"description",
9293
"comments",
9394
"tags",
@@ -182,6 +183,10 @@ def __init__(self, *args, **kwargs):
182183
if "related_object_type" in self.fields:
183184
self.fields["related_object_type"].disabled = True
184185

186+
# Multi-object fields may not be set unique
187+
if self.initial["type"] == CustomFieldTypeChoices.TYPE_MULTIOBJECT:
188+
self.fields["unique"].disabled = True
189+
185190
def clean_primary(self):
186191
primary_fields = self.cleaned_data["custom_object_type"].fields.filter(
187192
primary=True

netbox_custom_objects/models.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ class CustomObjectType(NetBoxModel):
199199
version = models.CharField(max_length=10, blank=True)
200200
verbose_name = models.CharField(max_length=100, blank=True)
201201
verbose_name_plural = models.CharField(max_length=100, blank=True)
202-
slug = models.SlugField(max_length=100, unique=True, db_index=True)
202+
slug = models.SlugField(max_length=100, unique=True, db_index=True, blank=False)
203203
cache_timestamp = models.DateTimeField(
204204
auto_now=True,
205205
help_text=_("Timestamp used for cache invalidation")
@@ -232,6 +232,11 @@ def __str__(self):
232232
def clean(self):
233233
super().clean()
234234

235+
if not self.slug:
236+
raise ValidationError(
237+
{"slug": _("Slug field cannot be empty.")}
238+
)
239+
235240
# Enforce max number of COTs that may be created (max_custom_object_types)
236241
if not self.pk:
237242
max_cots = get_plugin_config("netbox_custom_objects", "max_custom_object_types")

netbox_custom_objects/tests/test_api.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,58 @@ def test_graphql_list_objects(self):
237237

238238
def test_graphql_get_object(self):
239239
...
240+
241+
242+
class CustomObjectTypeAPITest(CustomObjectsTestCase):
243+
"""
244+
Test CustomObjectType API endpoint validation.
245+
"""
246+
247+
def setUp(self):
248+
"""Set up test data."""
249+
# Create a user
250+
self.user = create_test_user('testuser')
251+
252+
# Create token for API access
253+
self.token = Token.objects.create(user=self.user)
254+
self.header = {'HTTP_AUTHORIZATION': f'Token {self.token.key}'}
255+
256+
# Add object-level permission
257+
obj_perm = ObjectPermission(
258+
name='Test permission',
259+
actions=['add']
260+
)
261+
obj_perm.save()
262+
obj_perm.users.add(self.user)
263+
obj_perm.object_types.add(ObjectType.objects.get_for_model(CustomObjectType))
264+
265+
def test_create_custom_object_type_with_blank_slug(self):
266+
"""
267+
Test that creating a CustomObjectType with a blank slug returns a validation error.
268+
"""
269+
# Test with empty string slug
270+
data = {
271+
'name': 'test_blank_slug',
272+
'slug': '',
273+
}
274+
275+
url = reverse('plugins-api:netbox_custom_objects-api:customobjecttype-list')
276+
response = self.client.post(url, data, format='json', **self.header)
277+
278+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
279+
self.assertIn('slug', response.data)
280+
281+
def test_create_custom_object_type_without_slug(self):
282+
"""
283+
Test that creating a CustomObjectType without a slug field returns a validation error.
284+
"""
285+
# Test without slug field at all
286+
data = {
287+
'name': 'test_no_slug',
288+
}
289+
290+
url = reverse('plugins-api:netbox_custom_objects-api:customobjecttype-list')
291+
response = self.client.post(url, data, format='json', **self.header)
292+
293+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
294+
self.assertIn('slug', response.data)

netbox_custom_objects/views.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ class CustomJournalEntryEditView(generic.ObjectEditView):
6666
queryset = JournalEntry.objects.all()
6767
form = CustomJournalEntryForm
6868

69+
def alter_object(self, obj, request, args, kwargs):
70+
if not obj.pk:
71+
obj.created_by = request.user
72+
return obj
73+
6974
def get_return_url(self, request, instance):
7075
"""
7176
Override to return the correct URL for custom objects.

0 commit comments

Comments
 (0)