Compare commits
92 Commits
feature-ku
...
1.5.0
Author | SHA1 | Date | |
---|---|---|---|
39e06a43a3 | |||
0ceb5a512e | |||
51a2fe1141 | |||
8332b31a1a | |||
c03b7e7d49 | |||
ed6cdaef8b | |||
5335758c70 | |||
c14ee4c4be | |||
b51ce7d513 | |||
03c39d2e2f | |||
10285bedef | |||
b9e8caecc1 | |||
afc0c66602 | |||
41ffe5b3bc | |||
e158f49a21 | |||
18bb2909a5 | |||
ca2da06d2c | |||
17f47040d6 | |||
c5faf3115d | |||
3cdd8adf38 | |||
39539a4bae | |||
5de8893330 | |||
d9b9e32019 | |||
3bce54b495 | |||
34c327b7b6 | |||
8b790b451e | |||
00bebbd8f4 | |||
cebb02de99 | |||
ebeea4f526 | |||
c91bc6ee10 | |||
625cb52dd2 | |||
497adc68f4 | |||
a10f1b3694 | |||
11abf177ab | |||
becf55e22f | |||
c57d465c5b | |||
741a149f33 | |||
f85cc0fd3d | |||
80a82605aa | |||
d9b5ec7d41 | |||
fcf3d568e4 | |||
eb3071c93d | |||
873f241d14 | |||
da5c4d76e9 | |||
8f1e61a7a6 | |||
7f46daeb54 | |||
6291510ba4 | |||
871cdc6b5d | |||
9e78aa5940 | |||
4df7e57ca7 | |||
b80d8a5c64 | |||
f3ef3be883 | |||
250ba96c84 | |||
df5234e8d3 | |||
c4459bd21f | |||
702644adc5 | |||
c9caa96f98 | |||
eb4a132f39 | |||
cb636fff01 | |||
f8338ff6f0 | |||
47898d7e1d | |||
2be5819839 | |||
c0d5bfad45 | |||
cadb3bcac0 | |||
089f8beef2 | |||
d5771401c8 | |||
a32d942db6 | |||
2ef5124ccc | |||
b54d710c50 | |||
fd3bd7f04e | |||
61f6996f5e | |||
2b2c719e69 | |||
f13bdf5a05 | |||
6010973c3b | |||
85face7cc6 | |||
38ba86b8b5 | |||
d0118e1f6f | |||
827fe14369 | |||
6ed4db0502 | |||
75cf55fe6a | |||
b160c034e5 | |||
deb93378b0 | |||
1904c2e28c | |||
aaf2d23c53 | |||
7c9320a84b | |||
c8b6a31cd4 | |||
22615e46ef | |||
4ae965603c | |||
e4ce1b539e | |||
cee396da3f | |||
0786977633 | |||
1093c55c19 |
2
.cz.yaml
2
.cz.yaml
@ -17,5 +17,5 @@ commitizen:
|
||||
prerelease_offset: 1
|
||||
tag_format: $version
|
||||
update_changelog_on_bump: false
|
||||
version: 1.3.1
|
||||
version: 1.5.0
|
||||
version_scheme: semver
|
||||
|
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
@ -20,6 +20,9 @@
|
||||
|
||||
<!-- dont remove tasks below strike through including the checkbox by enclosing in double tidle '~~' -->
|
||||
|
||||
- [ ] **Feature Release ONLY** :red_square: Squash migration files :red_square:
|
||||
_Multiple migration files created as part of this release are to be sqauashed into a few files as possible so as to limit the number of migrations_
|
||||
|
||||
- [ ] :firecracker: Contains breaking-change Any Breaking change(s)?
|
||||
|
||||
_Breaking Change must also be notated in the commit that introduces it and in [Conventional Commit Format](https://www.conventionalcommits.org/en/v1.0.0/)._
|
||||
|
709
CHANGELOG.md
709
CHANGELOG.md
@ -1,3 +1,712 @@
|
||||
## 1.5.0 (2024-12-09)
|
||||
|
||||
### feat
|
||||
|
||||
- **python**: update django 5.1.2 -> 5.1.4
|
||||
- **api**: If global organization defined, filter from ALL organization fields
|
||||
- **api**: Add nav menu permission checks for settings
|
||||
- **api**: When fething an items url dueing metadata creation, used named parameters
|
||||
- **access**: Modify Admin User panel by removing perms and adding teams
|
||||
- **access**: filter permissions available
|
||||
- **api**: Filter navigation menu by user permissions
|
||||
- **api**: Add API version details to the metadata
|
||||
- **access**: add `back` and `return_url` urls to team user metadata
|
||||
- **access**: add `back` and `return_url` urls to team metadata
|
||||
- **api**: Add `back` url to metadata
|
||||
- **api**: Add `return_url` to metadata
|
||||
|
||||
### Fixes
|
||||
|
||||
- **settings**: Add missing `get_url` function to user_settings model
|
||||
- **settings**: Add missing `get_url` function to app_settings model
|
||||
- **core**: correctr the required parameters for related ticket serializer when fetching own url
|
||||
- **core**: Remove requirement that ticket be specified for related tickets `get_url`
|
||||
- **access**: Add missing `table_fields` attribute to team users model
|
||||
- **api**: during metadata navigation permission checks, cater for non-existant keys
|
||||
- **core**: Remove superfluous check from ticket viewset
|
||||
- **access**: Team permissions is not a required field
|
||||
- **core**: History query must also be for self, not just children
|
||||
- **access**: correct team users table to correct data key
|
||||
|
||||
### Refactoring
|
||||
|
||||
- **access**: Settings must be an available permissions when setting team permissions
|
||||
- **itam**: set deviceoperatingsystem model, device field to be type `onetoone`
|
||||
- **assistance**: make content the first tab for kb articles
|
||||
- **api**: move metadata url_return -> urls.self
|
||||
|
||||
### Tests
|
||||
|
||||
- **api**: Nav menu permission checks for settings
|
||||
- **api**: Nav menu permission checks
|
||||
- **core**: Correct `url.self`checks to use list view
|
||||
- **core**: Dont test History for table view
|
||||
- **settings**: Dont test user settings for table view
|
||||
- **steeings**: Dont test app settings for table view
|
||||
- **core**: Dont test related ticket for table or detail view
|
||||
- **api**: Refactor test so that endpoints not expected to have an endpoint or be rendered in a table wont be tested for it.
|
||||
- **settings**: API Metadata checks for user settings
|
||||
- **settings**: API Metadata checks for external links
|
||||
- **settings**: API Metadata checks for app settings
|
||||
- **project_management**: API Metadata checks for project type
|
||||
- **project_management**: API Metadata checks for project task
|
||||
- **project_management**: API Metadata checks for project state
|
||||
- **project_management**: API Metadata checks for project milestone
|
||||
- **project_management**: API Metadata checks for project
|
||||
- **itim**: API Metadata checks for problem ticket
|
||||
- **itim**: API Metadata checks for incident ticket
|
||||
- **itim**: API Metadata checks for change ticket
|
||||
- **itim**: API Metadata checks for service
|
||||
- **itim**: API Metadata checks for port
|
||||
- **itim**: API Metadata checks for cluster type
|
||||
- **itim**: API Metadata checks for cluster
|
||||
- **itam**: API Metadata checks for software version
|
||||
- **itam**: API Metadata checks for software category
|
||||
- **itam**: API Metadata checks for software
|
||||
- **itam**: API Metadata checks for operating system version
|
||||
- **itam**: API Metadata checks for operating system
|
||||
- **itam**: API Metadata checks for software
|
||||
- **itam**: API Metadata checks for operating system
|
||||
- **itam**: API Metadata checks for device type
|
||||
- **itam**: API Metadata checks for device OS
|
||||
- **itam**: API Metadata checks for device model
|
||||
- **itam**: API Metadata checks for device
|
||||
- **core**: API Metadata checks for ticket comment category
|
||||
- **core**: API Metadata checks for ticket comment
|
||||
- **core**: API Metadata checks for ticket category
|
||||
- **core**: API Metadata checks for history
|
||||
- **core**: API Metadata checks for related tickets
|
||||
- **core**: API Metadata checks for manufacturers
|
||||
- **config_management**: API Metadata checks for config group software
|
||||
- **config_management**: API Metadata checks for config groups
|
||||
- **access**: API Metadata checks for request ticket
|
||||
- **access**: API Metadata checks for kb category
|
||||
- **access**: API Metadata checks for kb
|
||||
- **api**: correct metadata testcases
|
||||
- **access**: API Metadata checks for organization
|
||||
- **api**: API Metadata test cases for navigation menu rendering
|
||||
- **api**: correct logic for test class attribute fetching
|
||||
- **access**: API Metadata checks for Team User model
|
||||
- **access**: API Metadata checks for Team model
|
||||
- **api**: API Metadata functional Test Cases
|
||||
|
||||
## 1.4.1 (2024-11-30)
|
||||
|
||||
### Fixes
|
||||
|
||||
- **itam**: When validating device config, only do so if there is config defined
|
||||
|
||||
## 1.4.0 (2024-11-28)
|
||||
|
||||
### feat
|
||||
|
||||
- **project_management**: add project completed field
|
||||
- **api**: Implement Sanity error handling for uncaught exceptions
|
||||
- **itam**: Split device software serializer to include seperate software installs serializer
|
||||
- **itam**: Add Operating System Installs API v2 endpoint
|
||||
- **itam**: based off of the request kwaargs, adjust device serializer fields accordingly
|
||||
- **itam**: Add Software installs endpoint
|
||||
- **itim**: add cluster and device to Services in new UI
|
||||
- **config_management**: add hosts to new UI
|
||||
- **api**: add ticket icons
|
||||
- **itim**: Add nodes and devices to detail view
|
||||
- **api**: return_url to default to list view
|
||||
- **base**: move setting `SECURE_SSL_REDIRECT = True` to etc/settings
|
||||
- **base**: use senisible settings for SSL
|
||||
- **itam**: Add device operating system API v2 endpoint
|
||||
- **api**: Add return URL to metadata if model has attribute `get_url`
|
||||
- **config_management**: Add field child group count to table fields for groups
|
||||
- **itam**: Add `page_layout` to SoftwareVersion model
|
||||
- **itam**: Add `page_layout` to OperatingSystemVersion model
|
||||
- **project_management**: Add `page_layout` to Milestone model
|
||||
- **settings**: Add `page_layout` to AppSettings model
|
||||
- **access**: render team_name field as anchor
|
||||
- **api**: Support setting char field as an anchor field using .urls._self
|
||||
- **api**: Added abilty to specify a css class for markdown field
|
||||
- Add timezone support
|
||||
- **api**: Add a Common Model serializer to be inherited by all model serializers
|
||||
- **core**: new field type markdown
|
||||
- **core**: new field type char
|
||||
- **core**: add RElated Items choices to metadata
|
||||
- **itam**: Add Inventory API v2 endpoint
|
||||
- **api**: Depreciate API V1 endpoint /api/config
|
||||
- **core**: New signal for cleaning linked ticket items when the item is deleted
|
||||
- **core**: Show milestone using base serializer for all ticket types
|
||||
- **core**: Show project using base serializer for all ticket types
|
||||
- **core**: Add Parse error to exceptions
|
||||
- **core**: Ticket serializer to ensure user who opens ticket is subscribed to it
|
||||
- **core**: Ticket serializer to validate milestone
|
||||
- **core**: Ticket serializer to validate organization
|
||||
- **itim**: Add Project Task API v2 endpoint
|
||||
- **itim**: Add Problem Ticket API v2 endpoint
|
||||
- **itim**: Add Incident Ticket API v2 endpoint
|
||||
- **itim**: Add Change Ticket API v2 endpoint
|
||||
- **api**: Depreciate v1 API Endpoint Assistance
|
||||
- **api**: Depreciate v1 API Endpoint Request Ticket
|
||||
- **api**: Depreciate v1 API Endpoint Assistance
|
||||
- **api**: Depreciate v1 API Endpoint Ticket Comments
|
||||
- **api**: Depreciate v1 API Endpoint Ticket Comment Categories
|
||||
- **api**: Depreciate v1 API Endpoint Ticket Categories
|
||||
- **core**: Ensure Related Tickets validate against duplicate entries
|
||||
- **core**: Add MethodNot Allowed to Centurion exceptions
|
||||
- **core**: Determine serializer from action and user permissions for Ticket Comments
|
||||
- **core**: Add custom exception class
|
||||
- **core**: Ensure ticket comment Serializer validates for existance of comment_type and ticket id
|
||||
- **core**: Ensure ticket comment Serializer is picked based off of comment_type
|
||||
- **core**: Ensure that ticket linked item validates if ticket supplied
|
||||
- **core**: Ensure that ticket comment category cant assign self as parent
|
||||
- **core**: Ensure that ticket category cant assign self as parent
|
||||
- **core**: Add Ticket Comment Category API v2 endpoint
|
||||
- **core**: Add Item Ticket API v2 endpoint
|
||||
- **core**: Add Related Ticket API v2 endpoint
|
||||
- **core**: Add Ticket Linked Item API v2 endpoint
|
||||
- **core**: Add url function to Ticket Linked Items model
|
||||
- **itim**: Add url function to Service model
|
||||
- **itim**: Add url function to Cluster model
|
||||
- **itam**: Add url function to Software model
|
||||
- **itam**: Add url function to Operating System model
|
||||
- **itam**: Add url function to Device model
|
||||
- **config_management**: Add url function to Config Groups model
|
||||
- **core**: Add Ticket Comment API v2 endpoint
|
||||
- **core**: Add Ticket Category API v2 endpoint
|
||||
- **assistance**: Add Request Ticket API v2 endpoint
|
||||
- **api**: Custom exception UnknownTicketType
|
||||
- **core**: Add Base Ticket Serializer and ViewSet
|
||||
- **api**: Setup API to be correctly versioned
|
||||
- **settings**: Add get_organization function to app settings model
|
||||
- **settings**: Add Celery Task Logs API v2 endpoint
|
||||
- **api**: Added ability to specify table fields within the viewset.
|
||||
- **settings**: Add User Settings API v2 endpoint
|
||||
- **settings**: Add App Settings API v2 endpoint
|
||||
- **project_management**: Add remaining Project base serializers for API v2
|
||||
- **project_management**: Project Validation for API v2
|
||||
- **project_management**: Add Project Type API v2 endpoint
|
||||
- **project_management**: Add Project State API v2 endpoint
|
||||
- **project_management**: Add Project Milestone API v2 endpoint
|
||||
- **project_management**: Add Project API v2 endpoint
|
||||
- **itim**: Port Serializer Validations
|
||||
- **itim**: Service Serializer Validations
|
||||
- **itim**: Ensure cluster cant assign itself as parent on api v2 endpoint
|
||||
- **itim**: Add Port API v2 endpoint
|
||||
- **itim**: Add Cluster API v2 endpoint
|
||||
- **itim**: Add Cluster Type API v2 endpoint
|
||||
- **itim**: Add Service API v2 endpoint
|
||||
- **itam**: Depreciate API v1 Software Endpoint
|
||||
- **core**: Add Operating System Version API v2 endpoint
|
||||
- **core**: Add Operating System API v2 endpoint
|
||||
- **core**: Add External Link API v2 endpoint
|
||||
- **itam**: Add Device Software API v2 endpoint
|
||||
- **itam**: Add Device API v2 endpoint
|
||||
- **itam**: Add Device Type API v2 endpoint
|
||||
- **itam**: Add Software Version API v2 endpoint
|
||||
- **itam**: Depreciate API v1 device endpoint
|
||||
- **itam**: Add Software API v2 endpoint
|
||||
- **itam**: Add Device Model API v2 endpoint
|
||||
- **itam**: Add Device API v2 endpoint
|
||||
- **itim**: Add Service Notes API v2 endpoint
|
||||
- **core**: Add Software Notes API v2 endpoint
|
||||
- **core**: Add Manufacturer API v2 endpoint
|
||||
- **itim**: Add Service base serializer
|
||||
- **itam**: Add operating system Base Serializer
|
||||
- **config_management**: Add Notes API v2 endpoint
|
||||
- **config_management**: Add History API v2 endpoint
|
||||
- **config_management**: Depreciate API v1 config endpoint
|
||||
- **config_management**: Add config groups to config api endpoint
|
||||
- **config_management**: Add Device Base Serializer
|
||||
- **itam**: Add Software Version Base Serializer
|
||||
- **itam**: Add Software Base Serializer
|
||||
- **config_management**: Add Config Group Software API v2 endpoint
|
||||
- **config_management**: Add Config Group API v2 endpoint
|
||||
- **assistance**: Ensure Knowledge Base Category cant assign self as parent category
|
||||
- **assistance**: Knowledge Base Serializer Validation method added
|
||||
- **assistance**: Add Knowledge Base Category API v2 endpoint
|
||||
- **assistance**: Add Knowledge Base API v2 endpoint
|
||||
- **api**: Depreciate API v1 permission endpoint
|
||||
- **access**: Add Team Users API endpoint
|
||||
- **access**: Depreciate Team API v1 endpoint
|
||||
- **access**: Depreciate Organization API v1 endpoint
|
||||
- **access**: Add Organization API endpoint
|
||||
- **base**: Add Team API endpoint
|
||||
- **base**: Add Permission API endpoint
|
||||
- **base**: Add Content Type API endpoint
|
||||
- **api**: Add Read Only abstract ViewSet
|
||||
- **base**: Add user API endpoint
|
||||
- **api**: add v2 endpoint
|
||||
- **project_management**: Add attribute table_fields to Project Type model
|
||||
- **project_management**: Add attribute page_layout to Project Type model
|
||||
- **project_management**: Add attribute table_fields to Project State model
|
||||
- **project_management**: Add attribute page_layout to Project State model
|
||||
- **project_management**: Add attribute page_layout to Project Milestone model
|
||||
- **project_management**: Add attribute table_fields to Project Milestone model
|
||||
- **project_management**: Add attribute table_fields to Project model
|
||||
- **project_management**: Add attribute page_layout to Project model
|
||||
- **itim**: Add attribute table_fields to Service model
|
||||
- **itim**: Add attribute page_layout to Service model
|
||||
- **itim**: Add attribute table_fields to Service Port model
|
||||
- **itim**: Add attribute page_layout to Service Port model
|
||||
- **itim**: Add attribute table_fields to Cluster Type model
|
||||
- **itim**: Add attribute page_layout to Cluster Type model
|
||||
- **itim**: Add attribute table_field to Cluster model
|
||||
- **itim**: Add attribute page_layout to Cluster model
|
||||
- **itam**: Add attribute table_field to Software Category model
|
||||
- **itam**: Add attribute table_fields to Software model
|
||||
- **itam**: Add attribute page_layout to Software model
|
||||
- **itam**: Add attribute table_fields to Operating System Version model
|
||||
- **itam**: Add attribute page_layout to Operating System Version model
|
||||
- **itam**: Add attribute table_field to Operating System model
|
||||
- **itam**: Add attribute page_layout to Operating System model
|
||||
- **itam**: Add attribute table_fields to "Device Type" model
|
||||
- **itam**: Add attribute page_layout to "Device Type" model
|
||||
- **itam**: Add attribute page_layout to "Device Software" model
|
||||
- **itam**: Add attribute table_fields to "Device Software" model
|
||||
- **itam**: Add attribute page_layout to "Device Software" model
|
||||
- **core**: Add attribute table_fields to Ticket Comment Category model
|
||||
- **core**: Add attribute page_layout to Ticket Comment Category model
|
||||
- **core**: Add attribute page_layout to Ticket comment model
|
||||
- **core**: Add attribute table_fields to Ticket Category model
|
||||
- **core**: Add attribute page_layout to Ticket Category model
|
||||
- **core**: Add attribute page_layout to Ticket model
|
||||
- **core**: Add attribute page_layout to Notes model
|
||||
- **core**: Add attribute table_fields to Manufacturer model
|
||||
- **core**: Add attribute page_layout to Manufacturer model
|
||||
- **access**: Add attribute table_fields to Config Group Software model
|
||||
- **access**: Add attribute page_layout to Config Group Software model
|
||||
- **access**: Add attribute table_fields to Config Groups model
|
||||
- **access**: Add attribute page_layout to Config Groups model
|
||||
- **access**: Add attribute table_fields to KB model
|
||||
- **access**: Add attribute page_layout to KB model
|
||||
- **access**: Add attribute table_fields to KB Category model
|
||||
- **access**: Add attribute page_layout to KB Category model
|
||||
- **access**: Add attribute table_fields to Team model
|
||||
- **access**: Add attribute page_layout to Team model
|
||||
- **core**: Add `table_fields` to Ticket Model
|
||||
- **itam**: Add v2 endpoint ITAM
|
||||
- **base**: Add User Serializer
|
||||
- **settings**: Add v2 endpoint Settings
|
||||
- **project_management**: Add v2 endpoint Project Management
|
||||
- **itim**: Add v2 endpoint ITIM
|
||||
- **config_management**: Add v2 endpoint Config Management
|
||||
- **assistance**: Add v2 endpoint Assistance
|
||||
- **access**: Add v2 endpoint Access
|
||||
- **itim**: Add `table_fields` to Service Model
|
||||
- **core**: Add `table_fields` to Device Software Model
|
||||
- **core**: Add `table_fields` to Notes Model
|
||||
- **core**: Add `table_fields` to History Model
|
||||
- **itam**: Add `table_fields` and `page_layout` to Device Model
|
||||
- **itam**: Add `table_fields` and `page_layout` to Device Model
|
||||
- **core**: Add `table_fields` to Ticket Linked Item
|
||||
- **core**: Add `table_fields` to Ticket Comment
|
||||
- **core**: Add `table_fields` to Ticket
|
||||
- **core**: Add attribute `staatus_badge` to ticket model
|
||||
- **access**: Add `table_fields` and `page_layout` to Organization
|
||||
- **api**: Add React UI metadata class
|
||||
- **api**: Add API v2 Endpoint
|
||||
- **api**: add API login template to use current login form
|
||||
- **api**: Update API template to use name Centurion
|
||||
- **itam**: Add category property to device software model
|
||||
- **itam**: Add action badge property to device software model
|
||||
- **itam**: Add status badge property to device model
|
||||
- **core**: Add a icon serializer field.
|
||||
- **core**: Add a badge serializer field.
|
||||
- **api**: Add common ViewSet class for inheritence
|
||||
- Add dependency django-cors-headers
|
||||
|
||||
### Fixes
|
||||
|
||||
- **project_management**: Correct All tickets query for calculating project completion
|
||||
- **core**: Prevent a ticket from being related to itself
|
||||
- **core**: when fetching ticket serializer set org=None
|
||||
- **core**: use the view pk to filter self out for ticket category update
|
||||
- **core**: Ensure for update of ticket the correct serializer is selected
|
||||
- **core**: dont exclude self for ticket comment category if not exists
|
||||
- **itam**: Add Operating System API v2 field typo
|
||||
- **core**: Enusure project_task serializer sets the project_id
|
||||
- **itam**: device os serializer not to show org and device
|
||||
- **core**: ticket comment to use model serializer for meta
|
||||
- **core**: add kwargs to notes
|
||||
- **core**: correct get_url function notes
|
||||
- **core**: add missing dep to notes
|
||||
- **access**: correct team users get_url
|
||||
- **access**: correct team get_url requires kwargs
|
||||
- **core**: correct notes get_url
|
||||
- **access**: correct team get_url
|
||||
- **core**: ticket model url requires kwargs
|
||||
- **core**: ticket comment model url requires kwargs
|
||||
- **core**: dont attempt to fetch org for ticket comment if no data supplied
|
||||
- **core**: Always set the organization to the ticket org when adding a ticket comment when org not specified.
|
||||
- **api**: Ensure queryset filters to actual item if pk is defined
|
||||
- **core**: Automagic fetch data for fields and only require ticket id to link item to ticket
|
||||
- **core**: Always set the organization to the ticket org when adding a ticket comment.
|
||||
- **config_management**: show parent groups only on index
|
||||
- **core**: Set notes _self url to empty val then attempt to sset
|
||||
- **core**: Ensure API v1 Ticket sets the ticket type prior to validation
|
||||
- **core**: Dont attempt to use ticket instance organization if it's a new ticket being created
|
||||
- **access**: Ensure organization is a mandatory field
|
||||
- **core**: Ensure ticket and comment bodies are set to required
|
||||
- **core**: correct navigation metadata
|
||||
- **task**: Ensure if inventory RX is a string, serialize it
|
||||
- **access**: Team User serializer not to capture exceptions
|
||||
- **access**: Team User team and user fields required when creating, don't use default value.
|
||||
- **access**: Team name required when creating, don't use default value.
|
||||
- **access**: Dont capture exceptions within team serializer
|
||||
- **core**: Ensure import user can set field `opened_by` when importing tickets
|
||||
- **core**: Correct duration slash command regex
|
||||
- **core**: When an item that may be linked to a ticket is deleted, remove the ticket link
|
||||
- **core**: Related ticket slash command requires model to be imported
|
||||
- **core**: correct missing or incomplete ticket model fields
|
||||
- **core**: When creating a ticket, by default give it a status of new
|
||||
- **core**: Ensure that when creating a ticket an organization is specified
|
||||
- **core**: Correct Ticket read-only fields
|
||||
- **core**: Correct inheritence order for ticket serializers
|
||||
- **core**: Ensure Organization can be set when creating a ticket
|
||||
- **core**: Ensure that when fetching ticket permission, spaces are replaced with '_'
|
||||
- **core**: Ticket serializer org validator to access correct data
|
||||
- **core**: Add project URL to all Ticket Types
|
||||
- **core**: Add Ticket Category URL to all Ticket Types
|
||||
- **core**: When obtaining ticket type use it's enum value
|
||||
- **core**: Ensure triage and import permissions are catered for Tickets
|
||||
- **core**: Ensure Ticket Linked Item slash command works for ticket comments
|
||||
- **core**: Only use Import Serializer on Ticket Comment Create if user has perms
|
||||
- **core**: Ensure related ticket slash command works for ticket comments
|
||||
- **api**: Ensure `METHOD_NOT_ALLOWED` exception is thrown
|
||||
- **core**: Correct serializer item field to be for view serializer ONLY
|
||||
- **config_management**: Correct ticket url in group serializer
|
||||
- **core**: Add missing ticket comment category url
|
||||
- **core**: Add missing permissions function to ticket viewset
|
||||
- **core**: Ensure that when checking linked ticket class name, spaces are replaced
|
||||
- **core**: Ensure item tickets class can have underscore in name
|
||||
- Dont attempt to access request within serializers when no context is present
|
||||
- **core**: Add Ticket Category API v2 endpoint to urls
|
||||
- **core**: Correct ticket comment model name
|
||||
- **api**: Ensure read-only fields have choices added to metadata
|
||||
- **api**: Correct inheritance order for ModelViewSet
|
||||
- **settings**: Populate user_settings Meta
|
||||
- **settings**: Populate app_settings Meta
|
||||
- **project_management**: For Project use a separate Import Serializer
|
||||
- **project_management**: use the post data dict for fetching edit organisation
|
||||
- **project_management**: use the post data or existing object for fetching edit organisation
|
||||
- **project_management**: Dont use init to adjust read_only_fields for project
|
||||
- **project_management**: if user not hav org specified dont attempt to access
|
||||
- **project_management**: for project serializer (api v1) ensure org is id
|
||||
- **itim**: Ensure service config from template is not gathered if not defined
|
||||
- **itim**: Ensure params passed to super when validating cluster
|
||||
- **itim**: Correct Device Service API v2 endpoint
|
||||
- **itam**: Don't attempt to include manufacturer in name for Device Model if not defined
|
||||
- **itam**: Ensure software version model has page_layout field
|
||||
- **core**: notes field must be mandatory
|
||||
- **core**: Add missing attributes name to history model
|
||||
- **config_management**: ensure validation uses software.id for config group software serializer
|
||||
- **config_management**: Config Groups Serializer Validation checks
|
||||
- **assistance**: Correct Knowledge Base Category serializer Validation
|
||||
- **itam**: Correct inventory validation response data
|
||||
- **itam**: Correct inventory api upload to use API exceptions instead of django base
|
||||
- **assistance**: Add missing fields `display_name` and `model_notes` to Knowledge Base Category serializer
|
||||
- **assistance**: correct KB category serializer validation
|
||||
- **assistance**: Correct Knowledge Base serialaizer Validation
|
||||
- **api**: on permission check error, return authorized=false
|
||||
- **access**: Add missing parameters to Team User fields
|
||||
- **api**: Add missing organization url routes
|
||||
- **access**: ensure org id is an integer during permission checks
|
||||
- **access**: if permission_required attribute doesn't exist during permission check, return empty list
|
||||
- Ensure all Model fields are created with attributes `help_text` and `verbose_name`
|
||||
- **api**: correct logic for permission check to use either queryset or get_queryset
|
||||
- **settings**: Add attribute table_fields to External Links model
|
||||
- **settings**: Add attribute page_layout to External Links model
|
||||
- **settings**: Add missing attribute Meta.verbose_name to External Links model
|
||||
- **settingns**: Add missing attribute Meta.ordering to External Links model
|
||||
- **itam**: Add missing attribute Meta.verbose_name to Software Category model
|
||||
- **itam**: Add missing attribute Meta.ordering to Software Category model
|
||||
- **itam**: Add missing attribute Meta.verbose_name to Software model
|
||||
- **itam**: Add missing attribute Meta.ordering to Software model
|
||||
- **itam**: Add missing attribute Meta.verbose_name to Operating System Version model
|
||||
- **itam**: Add missing attribute Meta.ordering to Operating System Version model
|
||||
- **itam**: Add missing attribute Meta.verbose_name to Operating System model
|
||||
- **itam**: Add missing attribute Meta.ordering to Operating System model
|
||||
- **itam**: Add missing attribute Meta.verbose_name to "Device Type" model
|
||||
- **itam**: Add missing attribute Meta.ordering to "Device Software" model
|
||||
- **itam**: Add missing attribute Meta.verbose_name to "Device Software" model
|
||||
- **itam**: Add missing attribute Meta.verbose_name to "Device Software" model
|
||||
- **itam**: Add missing attribute Meta.ordering to "Device Software" model
|
||||
- **itama**: Add missing attribute Meta.verbose_name to "Device Model" model
|
||||
- **core**: Add missing attribute Meta.verbose_name to Notes model
|
||||
- **core**: Add missing attribute Meta.verbose_name to Manufacturer model
|
||||
- **access**: Add missing attribute Meta.verbos_name to Config Group Software model
|
||||
- **access**: Add missing attribute Meta.verbos_name to Config Groups model
|
||||
- **access**: Add missing attribute Meta.ordering Config Groups model
|
||||
- **access**: Add missing meta field verbose_name to Team model
|
||||
- **api**: during permission checking if request is HTTP/Options and user is authenticated, allow access
|
||||
- **api**: during permission checking dont attempt to access view obj if it doesn't exist
|
||||
- **itam**: Add missing model.Meta attributes ordering and verbose_name
|
||||
|
||||
### Refactoring
|
||||
|
||||
- **itam**: update device software serializer validator
|
||||
- **itam**: update device software serializer validator
|
||||
- **itam**: ensure device is unique for device os model
|
||||
- ensure filed organization is required
|
||||
- **config_management**: config_group ref to use full model name
|
||||
- update serializers to use model `get_url` function
|
||||
- **core**: ticket comment url name updated to match model name
|
||||
- Add function `get_url` to tenancy models
|
||||
- **api**: set fields that are for markdown to use the markdown field
|
||||
- **task**: Adjust inventory to use API v2 serializer
|
||||
- **core**: Move ticket validation from is_valid -> validate method
|
||||
- **core**: Ensure Ticket Linked Serializer works for Item Tickets
|
||||
- **core**: Ticket Linked Item slash command to use serializer
|
||||
- **core**: Related ticket slash command to use serializer
|
||||
- **core**: Ticket Comments to use a single API Endpoint
|
||||
- **core**: Adjust action choices to be integer
|
||||
- **config_management**: Adjust rendered config str -> dict
|
||||
- **itam**: Software Action field changed char -> integer
|
||||
- **itam**: rename dir viewset -> viewsets
|
||||
- **config_management**: move config_group_hosts to related table
|
||||
- update model fields
|
||||
- **config_management**: update serializer dir name
|
||||
- **access**: add name to modified field
|
||||
- **api**: Adjust viewset common so that page_layout is available for base
|
||||
- **assistance**: Correct viewset dir name to viwsets
|
||||
- **itam**: Cleanup Device Software model field names.
|
||||
- **core**: Change history fields after and before to be JSON fields
|
||||
- **api**: Split common ViewSet class into index/model classes
|
||||
- **itam**: remove requirement to specify the pk when fetching config
|
||||
|
||||
### Tests
|
||||
|
||||
- **project_management**: Ensure that project field completed exists when API v2 is rendere
|
||||
- **core**: Ensure a ticket cant be related to itself
|
||||
- **itam**: correct test setup for device note viewset
|
||||
- **settings**: Ensure items returned are from users orgs only for API v2 endpoints
|
||||
- **project_management**: Ensure items returned are from users orgs only for API v2 endpoints
|
||||
- **itim**: Correct test case for ticket category returned serializer checks
|
||||
- **core**: Correct test case for ticket category returned serializer checks
|
||||
- **core**: Ensure items returned are from users orgs only for API v2 endpoints
|
||||
- **config_management**: Ensure items returned are from users orgs only for API v2 endpoints
|
||||
- **assistance**: Ensure items returned are from users orgs only for API v2 endpoints
|
||||
- **access**: Ensure items returned are from users orgs only for API v2 endpoints
|
||||
- **itam**: Ensure items returned are from users orgs only for API v2 endpoints
|
||||
- Test Case for viewsets that confirms returned results from user orgs only
|
||||
- **itam**: update device model test name Device -> DeviceModel
|
||||
- **Core**: Ticket linked items API V2 Serializer returned checks
|
||||
- **Core**: Remove duplicate test for ticket linked items
|
||||
- **assistance**: Project Taask ticket Viewset Serializer checks
|
||||
- **assistance**: Problem ticket Viewset Serializer checks
|
||||
- **assistance**: Incident ticket Viewset Serializer checks
|
||||
- **assistance**: Change ticket Viewset Serializer checks
|
||||
- **assistance**: Request ticket Viewset Serializer checks
|
||||
- **core**: Ticket Test Cases for Viewset Serializer returned
|
||||
- during delete operation dont include data
|
||||
- Add ViewSet Returned Serializer Checks to a majority of models
|
||||
- Test Cases to confirm the correct serializer is returned from ViewSet
|
||||
- Added skipped test for checking model mandatory values.
|
||||
- **itam**: Operating System Installs API v2 Field checks
|
||||
- **itam**: Software Installs API v2 Permission checks
|
||||
- **itam**: Operating_system Installs API v2 Validation checks
|
||||
- **itam**: Software Installs API v2 Permission checks
|
||||
- **itam**: Software Installs API v2 Validation checks
|
||||
- **itam**: Software Installs API v2 Field checks
|
||||
- **core**: Ticket serializer checks corrected to use project_id within mock view
|
||||
- **core**: Ticket comment serializer checks corrected to use mock view
|
||||
- **core**: Ticket comment category field checks corrected
|
||||
- **itam**: Update Device Operating System history checks to cater for unique device constratint
|
||||
- **itam**: Device Operating System API field checks checks
|
||||
- **itim**: Device Operating System API v2 ViewSet permission checks
|
||||
- **itam**: Device Operating System Serializer Validation checks
|
||||
- **core**: remove duplicate functional slash commands
|
||||
- model get_url function checks
|
||||
- **core**: move unit tests that check functionality to func test for ticket
|
||||
- **itam**: Inventory API v2 Serializer Checks
|
||||
- **core**: Ensure that when ticket is assigned it's status is updated to assigned
|
||||
- **settings**: External Link API ViewSet permission checks
|
||||
- **access**: External Link API v2 Serializer Checks
|
||||
- **functional**: Move request ticket checks from unit
|
||||
- **functional**: Move functional test cases to relevant functional test dir
|
||||
- **access**: Organization API v2 Serializer Checks, only super user can create
|
||||
- **access**: Team User API v2 Serializer Checks
|
||||
- **access**: Team API v2 Serializer Checks
|
||||
- **access**: Organization API v2 Serializer Checks
|
||||
- **project_management**: Organization API v2 ViewSet permission checks
|
||||
- **core**: Ensure test setup correctly for ticket checks
|
||||
- **core**: Spend Slash command Checks.
|
||||
- **core**: Relate Slash command Checks.
|
||||
- **core**: Ensure that an item that may be linked to a ticket, when its deleted, the ticket link is removed
|
||||
- **core**: Ensure a non-existing item cant be Linked to a Ticket.
|
||||
- **core**: Action command Related Item Ticket Slash command checks.
|
||||
- **core**: Blocked by Slash command Checks.
|
||||
- **core**: Blocks Slash command Checks.
|
||||
- **core**: Related Item Ticket Slash command checks.
|
||||
- **project_management**: Project Task API v2 Serializer Checks
|
||||
- **itim**: Incident Ticket API v2 Serializer Checks
|
||||
- **itim**: Problem Ticket API v2 Serializer Checks
|
||||
- **itim**: Change Ticket API v2 Serializer Checks
|
||||
- **core**: Request Ticket API v2 Serializer Checks
|
||||
- **core**: Common Ticket Test Cases for API v2 serializers
|
||||
- **project_management**: Project Task API field checks
|
||||
- **itim**: Problem Ticket API field checks
|
||||
- **itim**: Incident Ticket API field checks
|
||||
- **itim**: Change Ticket API field checks
|
||||
- **assistance**: Update request field checks to cater for project and milestone as dicts
|
||||
- **project_management**: Ensure ticket assigned project for all API v2 ViewSet permission checks
|
||||
- **project_management**: PRoject_task API v2 ViewSet permission checks
|
||||
- **itim**: Problem Ticket API v2 ViewSet permission checks
|
||||
- **itim**: Incident Ticket API v2 ViewSet permission checks
|
||||
- **itim**: Change Ticket API v2 ViewSet permission checks
|
||||
- **core**: fix broken tests from 8b701785b3489db567f5ae08c58e28ae76529881 changes
|
||||
- **core**: Item Ticket API v2 Serializer checks
|
||||
- **core**: Item Linked Ticket API v2 ViewSet permission checks
|
||||
- **core**: Related Ticket API v2 Serializer checks
|
||||
- **core**: Related Ticket API v2 ViewSet permission checks
|
||||
- **core**: Ticket Comment API v2 Serializer checks
|
||||
- **core**: Ticket Linked Item API v2 Serializer checks
|
||||
- **core**: Ticket Comment Category API v2 Serializer checks
|
||||
- **core**: Ticket Category API v2 Serializer checks
|
||||
- **itim**: Ticket Linked Item API field checks
|
||||
- **itim**: Service Ticket URL API field checks
|
||||
- **itim**: Cluster Ticket URL API field checks
|
||||
- **itam**: Software Ticket URL API field checks
|
||||
- **itam**: Operating System Ticket URL API field checks
|
||||
- **itam**: Device Ticket URL API field checks
|
||||
- **config_management**: Group Ticket URL API field checks
|
||||
- **core**: Ticket Comment API v2 ViewSet permission checks
|
||||
- **core**: Ticket Comment Category API v2 ViewSet permission checks
|
||||
- **core**: Ticket Category API v2 ViewSet permission checks
|
||||
- **assistance**: Request Ticket API v2 ViewSet permission checks
|
||||
- **core**: Ticket Common API v2 ViewSet permission checks
|
||||
- **core**: Ticket Comment Category API field checks
|
||||
- **core**: Related Tickets API field checks
|
||||
- **itim**: Service Linked Tickets API field checks
|
||||
- **itim**: Cluster Linked Tickets API field checks
|
||||
- **itam**: Software Linked Tickets API field checks
|
||||
- **itam**: Operating System Linked Tickets API field checks
|
||||
- **itam**: device Linked Tickets API field checks
|
||||
- **core**: Config Group Linked Tickets API field checks
|
||||
- **core**: Linked Ticket Common API field checks
|
||||
- **core**: Ticket Linked Items API field checks
|
||||
- **core**: Ticket Comment API field checks
|
||||
- **core**: Ticket Category API field checks
|
||||
- **assistance**: Request Ticket API field checks
|
||||
- **core**: Ticket Common API field checks
|
||||
- **settings**: Celery Log API v2 ViewSet permission checks
|
||||
- **settings**: Celery Log API field checks
|
||||
- **settings**: User Settings API v2 ViewSet permission checks
|
||||
- **settings**: User Settings API field checks
|
||||
- **settings**: App Settings API v2 ViewSet permission checks
|
||||
- **settings**: App Settings API field checks
|
||||
- **project_management**: Project API v2 ViewSet permission checks for import user
|
||||
- **project_management**: Project Serializer Validation clean up
|
||||
- **project_management**: Project Type API v2 ViewSet permission checks
|
||||
- **project_management**: Project Type Serializer Validation checks
|
||||
- **project_management**: Project Type API field checks
|
||||
- **project_management**: Project State API v2 ViewSet permission checks
|
||||
- **project_management**: Project state Serializer Validation checks
|
||||
- **project_management**: Project state API field checks
|
||||
- **project_management**: Project Milestone API v2 ViewSet permission checks
|
||||
- **project_management**: Project milestone Serializer Validation checks
|
||||
- **project_management**: add trace output to Project serializer
|
||||
- **project_management**: Project Milestone API field checks
|
||||
- **project_management**: Project API v2 ViewSet permission checks
|
||||
- **project_management**: Project Serializer Validation checks
|
||||
- **project_management**: Project API field checks
|
||||
- **itim**: Port API v2 ViewSet permission checks
|
||||
- **itim**: Port API field checks
|
||||
- **itim**: Service API v2 ViewSet permission checks
|
||||
- **itim**: Service Serializer Validation checks
|
||||
- **itim**: Service API field checks
|
||||
- **itim**: Cluster Type API v2 ViewSet permission checks
|
||||
- **itim**: Cluster Type Serializer Validation checks
|
||||
- **itam**: Cluster Type API field checks
|
||||
- **itim**: Cluster API ViewSet permission checks
|
||||
- **itim**: Cluster Serializer Validation checks
|
||||
- **itam**: Cluster API field checks
|
||||
- **itam**: remove Device Ticket API field checks
|
||||
- **itam**: Device Service API field checks
|
||||
- **itam**: Device Software API ViewSet permission checks
|
||||
- **itam**: Device Software Serializer Validation checks
|
||||
- **itam**: Device Software API field checks
|
||||
- **itam**: Device Model API ViewSet permission checks
|
||||
- **itam**: Device Model Serializer Validation checks
|
||||
- **itam**: Device Model API field checks
|
||||
- **itam**: Device Type API ViewSet permission checks
|
||||
- **itam**: Device Type Serializer Validation checks
|
||||
- **itam**: Device Type API field checks
|
||||
- **itam**: Software Version Tenancy Model Checks
|
||||
- **itam**: Software Version API ViewSet permission checks
|
||||
- **itam**: Software Version Serializer Validation checks
|
||||
- **itam**: Software Version API field checks
|
||||
- **itam**: Software Category Version API ViewSet permission checks
|
||||
- **itam**: Software Category Serializer Validation checks
|
||||
- **itam**: Software Category Version API field checks
|
||||
- **itam**: Operating System Version API ViewSet permission checks
|
||||
- **itam**: Operating System Version Serializer Validation checks
|
||||
- **itam**: Operating System Version API field checks
|
||||
- **itam**: Software API ViewSet permission checks
|
||||
- **itam**: Software Serializer Validation checks
|
||||
- **itam**: Software API field checks
|
||||
- **itam**: Operating System Serializer Validation checks
|
||||
- **itam**: Operating_system API ViewSet permission checks
|
||||
- **itam**: Operating System API field checks
|
||||
- **itam**: Device API field checks
|
||||
- **itam**: Device Serializer Validation checks
|
||||
- **core**: Device API ViewSet permission checks
|
||||
- enure correct type checks for url
|
||||
- **core**: Manufacturer API ViewSet permission checks
|
||||
- **core**: Manufacturer Serializer Validation checks
|
||||
- **assistance**: Manufacturer API field checks
|
||||
- **assistance**: Notes API field checks
|
||||
- **core**: Notes Serializer Validation checks
|
||||
- **itim**: Service Note API ViewSet permission checks
|
||||
- **itam**: Softwaare Note API ViewSet permission checks
|
||||
- **itam**: Operating System Note API ViewSet permission checks
|
||||
- **config_management**: Device Note API ViewSet permission checks
|
||||
- Adjust tests to cater for action choices now being an integer
|
||||
- **config_management**: Config Groups Note API ViewSet permission checks
|
||||
- **config_management**: History API ViewSet permission checks
|
||||
- **config_management**: Config Groups Software API ViewSet permission checks
|
||||
- **config_management**: Config Groups Software Serializer Validation checks
|
||||
- **config_management**: Config Groups Software Serializer Validation checks
|
||||
- **config_management**: Config Groups Serializer Validation checks
|
||||
- **config_management**: Config Groups API ViewSet permission checks
|
||||
- **assistance**: Config Group API field checks
|
||||
- **assistance**: Knowledge Base Category Serializer Validation checks
|
||||
- **assistance**: ensure is_valid raises exceptions for Knowledge Base Serializer Validation checks
|
||||
- **assistance**: Knowledge Base Serializer Validation checks
|
||||
- **assistance**: Knowledge Base Category API field checks
|
||||
- **assistance**: Knowledge Base API field checks
|
||||
- **access**: correct organization permission checks to have HTTP/403 not HTTP/405
|
||||
- **assistance**: Knowledge Base Category API ViewSet permission checks
|
||||
- **assistance**: Knowledge Base API ViewSet permission checks
|
||||
- **base**: User API ViewSet permission checks
|
||||
- **base**: Permission API ViewSet permission checks
|
||||
- **base**: Content Type API ViewSet permission checks
|
||||
- **access**: Add missing test cases to Team Users Model
|
||||
- **access**: Team Users API v2 field checks
|
||||
- **access**: Team User API ViewSet permission checks
|
||||
- **access**: Team API v2 field checks
|
||||
- **api**: API Response Field checks Abstract Class added
|
||||
- **access**: Organization API v2 field checks
|
||||
- **access**: Team API ViewSet permission checks
|
||||
- **access**: Organization API ViewSet permission checks
|
||||
- **api**: API Permission ViewSet Abstract Class added
|
||||
- **access**: Team custom tests to ensure that during model field creation, attribute verbose_name is defined and not empty
|
||||
- **itim**: port placeholder test for invalid port number
|
||||
- use correct logic when testin field parameters as not being empty or none
|
||||
- Ensure that during model field creation, attribute verbose_name is defined and not empty
|
||||
- Ensure that during model field creation, attribute help_text is defined and not empty
|
||||
- **api**: Ensure models have `Meta.ordering` set and not empty
|
||||
- **api**: viewset documentation attr check
|
||||
- **api**: fix index import to correct viewset
|
||||
- **itam**: Add index viewset checks
|
||||
- **Settings**: Add index viewset checks
|
||||
- **project_management**: Add index viewset checks
|
||||
- **itim**: Add index viewset checks
|
||||
- **config_management**: Add index viewset checks
|
||||
- **assistance**: Add index viewset checks
|
||||
- **access**: Add index viewset checks
|
||||
- **api**: Add API v2 Endpoint
|
||||
- **api**: ViewSet checks
|
||||
- Ensure Models have attribute `page_layout`
|
||||
- Ensure Models have attribute `table_fields`
|
||||
- Ensure Models have meta attribute `verbose_name`
|
||||
|
||||
## 1.3.1 (2024-11-27)
|
||||
|
||||
### Fixes
|
||||
|
@ -1,3 +1,11 @@
|
||||
## Version 1.5.0
|
||||
|
||||
- When v1.4.0 was release the migrations were not merged. As part of the work conducted on this release the v1.4 migrations have been squashed. This should not have any effect on any system that when they updated to v1.4, they ran the migrations and they **completed successfully**. Upgrading from <1.4.0 to this release should also have no difficulties as the migrations required still exist. There are less of them, however with more work per migration.
|
||||
|
||||
!!! Note
|
||||
If you require the previously squashed migrations for what ever reason. Clone the repo and go to commit 17f47040d6737905a1769eee5c45d9d15339fdbf, which is the commit prior to the squashing which is commit ca2da06d2cd393cabb7e172ad47dfb2dd922d952.
|
||||
|
||||
|
||||
## Version 1.4.0
|
||||
|
||||
API redesign in preparation for moving the UI out of centurion to it's [own project](https://github.com/nofusscomputing/centurion_erp_ui). This release introduces a **Feature freeze** to the current UI. Only bug fixes will be done for the current UI.
|
||||
|
@ -1,5 +1,6 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
|
||||
from .models import *
|
||||
|
||||
@ -25,6 +26,40 @@ class OrganizationAdmin(admin.ModelAdmin):
|
||||
list_filter = ["created"]
|
||||
search_fields = ["team_name"]
|
||||
|
||||
|
||||
admin.site.register(Organization,OrganizationAdmin)
|
||||
|
||||
|
||||
class TeamUserInline(admin.TabularInline):
|
||||
model = TeamUsers
|
||||
extra = 0
|
||||
|
||||
readonly_fields = ['created', 'modified']
|
||||
fields = ['team']
|
||||
|
||||
fk_name = 'user'
|
||||
|
||||
|
||||
admin.site.unregister(User)
|
||||
class UsrAdmin(UserAdmin):
|
||||
|
||||
fieldsets = (
|
||||
(None, {"fields": ("username", "password")}),
|
||||
("Personal info", {"fields": ("first_name", "last_name", "email")}),
|
||||
(
|
||||
"Permissions",
|
||||
{
|
||||
"fields": (
|
||||
"is_active",
|
||||
"is_staff",
|
||||
"is_superuser",
|
||||
),
|
||||
|
||||
},
|
||||
),
|
||||
("Important dates", {"fields": ("last_login", "date_joined")}),
|
||||
)
|
||||
|
||||
inlines = [TeamUserInline]
|
||||
|
||||
admin.site.register(User,UsrAdmin)
|
||||
|
||||
|
@ -23,8 +23,6 @@ def permission_queryset():
|
||||
'chordcounter',
|
||||
'comment',
|
||||
'groupresult',
|
||||
'organization'
|
||||
'settings',
|
||||
'usersettings',
|
||||
]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 15:27
|
||||
# Generated by Django 5.1.2 on 2024-12-06 06:47
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
@ -9,11 +9,23 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0002_alter_team_options'),
|
||||
('access', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='organization',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Organization', 'verbose_name_plural': 'Organizations'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='team',
|
||||
options={'ordering': ['team_name'], 'verbose_name': 'Team', 'verbose_name_plural': 'Teams'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='teamusers',
|
||||
options={'ordering': ['user'], 'verbose_name': 'Team User', 'verbose_name_plural': 'Team Users'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='organization',
|
||||
name='id',
|
||||
@ -47,11 +59,31 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='team_name',
|
||||
field=models.CharField(default='', help_text='Name to give this team', max_length=50, verbose_name='Name'),
|
||||
field=models.CharField(help_text='Name to give this team', max_length=50, verbose_name='Name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teamusers',
|
||||
name='id',
|
||||
field=models.AutoField(help_text='ID of this Team User', primary_key=True, serialize=False, unique=True, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teamusers',
|
||||
name='manager',
|
||||
field=models.BooleanField(blank=True, default=False, help_text='Is this user to be a manager of this team', verbose_name='manager'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teamusers',
|
||||
name='team',
|
||||
field=models.ForeignKey(help_text='Team user belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='team', to='access.team', verbose_name='Team'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teamusers',
|
||||
name='user',
|
||||
field=models.ForeignKey(help_text='User who will be added to the team', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User'),
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 06:42
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='team',
|
||||
options={'ordering': ['team_name'], 'verbose_name': 'Team', 'verbose_name_plural': 'Teams'},
|
||||
),
|
||||
]
|
@ -1,44 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-16 06:54
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0003_alter_organization_id_alter_organization_manager_and_more'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='organization',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Organization', 'verbose_name_plural': 'Organizations'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='teamusers',
|
||||
options={'ordering': ['user'], 'verbose_name': 'Team User', 'verbose_name_plural': 'Team Users'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teamusers',
|
||||
name='id',
|
||||
field=models.AutoField(help_text='ID of this Team User', primary_key=True, serialize=False, unique=True, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teamusers',
|
||||
name='manager',
|
||||
field=models.BooleanField(blank=True, default=False, help_text='Is this user to be a manager of this team', verbose_name='manager'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teamusers',
|
||||
name='team',
|
||||
field=models.ForeignKey(help_text='Team user belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='team', to='access.team', verbose_name='Team'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='teamusers',
|
||||
name='user',
|
||||
field=models.ForeignKey(help_text='User who will be added to the team', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User'),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-07 06:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0004_alter_organization_options_alter_teamusers_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='team_name',
|
||||
field=models.CharField(help_text='Name to give this team', max_length=50, verbose_name='Name'),
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-20 02:41
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0005_alter_team_team_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='team',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
@ -369,7 +369,7 @@ class Team(Group, TenancyObject):
|
||||
{
|
||||
"layout": "table",
|
||||
"name": "Users",
|
||||
"field": "user",
|
||||
"field": "users",
|
||||
},
|
||||
]
|
||||
},
|
||||
@ -489,7 +489,10 @@ class TeamUsers(SaveHistory):
|
||||
|
||||
page_layout: list = []
|
||||
|
||||
table_fields: list = []
|
||||
table_fields: list = [
|
||||
'user',
|
||||
'manager'
|
||||
]
|
||||
|
||||
|
||||
def delete(self, using=None, keep_parents=False):
|
||||
|
@ -4,10 +4,10 @@ from rest_framework import serializers
|
||||
|
||||
from access.models import Organization
|
||||
|
||||
from api.serializers import common
|
||||
|
||||
from app.serializers.user import UserBaseSerializer
|
||||
|
||||
from core import fields as centurion_field
|
||||
|
||||
|
||||
|
||||
class OrganizationBaseSerializer(serializers.ModelSerializer):
|
||||
@ -43,7 +43,6 @@ class OrganizationBaseSerializer(serializers.ModelSerializer):
|
||||
|
||||
|
||||
class OrganizationModelSerializer(
|
||||
common.CommonModelSerializer,
|
||||
OrganizationBaseSerializer
|
||||
):
|
||||
|
||||
@ -56,6 +55,7 @@ class OrganizationModelSerializer(
|
||||
'teams': reverse("v2:_api_v2_organization_team-list", request=self._context['view'].request, kwargs={'organization_id': item.pk}),
|
||||
}
|
||||
|
||||
model_notes = centurion_field.MarkdownField( required = False )
|
||||
|
||||
class Meta:
|
||||
|
||||
|
@ -6,9 +6,10 @@ from access.models import Team
|
||||
|
||||
from api.serializers import common
|
||||
|
||||
from access.functions.permissions import permission_queryset
|
||||
from access.serializers.organization import OrganizationBaseSerializer
|
||||
|
||||
from app.serializers.permission import PermissionBaseSerializer
|
||||
from app.serializers.permission import Permission, PermissionBaseSerializer
|
||||
|
||||
from core import fields as centurion_field
|
||||
|
||||
@ -74,6 +75,7 @@ class TeamModelSerializer(
|
||||
|
||||
team_name = centurion_field.CharField( autolink = True )
|
||||
|
||||
permissions = serializers.PrimaryKeyRelatedField(many = True, queryset=permission_queryset(), required = False)
|
||||
|
||||
class Meta:
|
||||
|
||||
|
@ -13,6 +13,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
|
||||
|
||||
@ -278,3 +279,16 @@ class OrganizationViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class OrganizationMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'access'
|
||||
|
||||
menu_entry_id = 'organization'
|
@ -6,10 +6,13 @@ import requests
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
|
||||
@ -199,3 +202,100 @@ class TeamViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TeamMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_has_key_urls_back(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned has key `urls.back`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert 'back' in response.data['urls']
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_urls_back_is_str(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data key `urls.back` is str
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert type(response.data['urls']['back']) is str
|
||||
|
||||
|
||||
|
||||
def test_method_options_request_list_data_has_key_urls_return_url(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned has key `urls.return_url`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if self.url_kwargs:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert 'return_url' in response.data['urls']
|
||||
|
||||
|
||||
def test_method_options_request_list_data_key_urls_return_url_is_str(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data key `urls.return_url` is str
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if self.url_kwargs:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert type(response.data['urls']['return_url']) is str
|
||||
|
||||
|
||||
|
@ -6,10 +6,13 @@ import requests
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser, User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
|
||||
@ -208,4 +211,99 @@ class TeamUserViewSet(
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TeamUserMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase,
|
||||
|
||||
):
|
||||
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_has_key_urls_back(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned has key `urls.back`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert 'back' in response.data['urls']
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_urls_back_is_str(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data key `urls.back` is str
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert type(response.data['urls']['back']) is str
|
||||
|
||||
|
||||
|
||||
def test_method_options_request_list_data_has_key_urls_return_url(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned has key `urls.return_url`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if self.url_kwargs:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert 'return_url' in response.data['urls']
|
||||
|
||||
|
||||
def test_method_options_request_list_data_key_urls_return_url_is_str(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data key `urls.return_url` is str
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if self.url_kwargs:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert type(response.data['urls']['return_url']) is str
|
||||
|
@ -1,5 +1,7 @@
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter, OpenApiResponse
|
||||
|
||||
from access.models import Organization
|
||||
|
||||
from access.serializers.teams import (
|
||||
Team,
|
||||
TeamModelSerializer,
|
||||
@ -124,6 +126,24 @@ class ViewSet( ModelViewSet ):
|
||||
|
||||
view_description = 'Teams belonging to a single organization'
|
||||
|
||||
|
||||
def get_back_url(self) -> str:
|
||||
|
||||
if(
|
||||
getattr(self, '_back_url', None) is None
|
||||
):
|
||||
|
||||
return_model = Organization.objects.get(
|
||||
pk = self.kwargs['organization_id']
|
||||
)
|
||||
|
||||
self._back_url = str(
|
||||
return_model.get_url( self.request )
|
||||
)
|
||||
|
||||
return self._back_url
|
||||
|
||||
|
||||
def get_queryset(self):
|
||||
|
||||
queryset = super().get_queryset()
|
||||
@ -146,3 +166,21 @@ class ViewSet( ModelViewSet ):
|
||||
|
||||
return globals()[str( self.model._meta.verbose_name) + 'ModelSerializer']
|
||||
|
||||
|
||||
def get_return_url(self) -> str:
|
||||
|
||||
if getattr(self, '_get_return_url', None):
|
||||
|
||||
return self._get_return_url
|
||||
|
||||
if self.kwargs.get('pk', None) is None:
|
||||
|
||||
return_model = Organization.objects.get(
|
||||
pk = self.kwargs['organization_id']
|
||||
)
|
||||
|
||||
self._get_return_url = return_model.get_url( self.request )
|
||||
|
||||
return self._get_return_url
|
||||
|
||||
return None
|
||||
|
@ -1,5 +1,7 @@
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter, OpenApiResponse
|
||||
|
||||
from access.models import Team
|
||||
|
||||
from access.serializers.team_user import (
|
||||
TeamUsers,
|
||||
TeamUserModelSerializer,
|
||||
@ -147,6 +149,24 @@ class ViewSet( ModelViewSet ):
|
||||
|
||||
view_description = 'Users belonging to a single team'
|
||||
|
||||
|
||||
def get_back_url(self) -> str:
|
||||
|
||||
if(
|
||||
getattr(self, '_back_url', None) is None
|
||||
):
|
||||
|
||||
return_model =Team.objects.get(
|
||||
pk = self.kwargs['team_id']
|
||||
)
|
||||
|
||||
self._back_url = str(
|
||||
return_model.get_url( self.request )
|
||||
)
|
||||
|
||||
return self._back_url
|
||||
|
||||
|
||||
def get_queryset(self):
|
||||
|
||||
queryset = super().get_queryset()
|
||||
@ -172,3 +192,21 @@ class ViewSet( ModelViewSet ):
|
||||
|
||||
return globals()[str( self.model._meta.verbose_name).replace(' ', '') + 'ModelSerializer']
|
||||
|
||||
|
||||
def get_return_url(self):
|
||||
|
||||
if getattr(self, '_get_return_url', None):
|
||||
|
||||
return self._get_return_url
|
||||
|
||||
if self.kwargs.get('pk', None) is None:
|
||||
|
||||
return_model = Team.objects.get(
|
||||
pk = self.kwargs['team_id']
|
||||
)
|
||||
|
||||
self._get_return_url = return_model.get_url( self.request )
|
||||
|
||||
return self._get_return_url
|
||||
|
||||
return None
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 15:27
|
||||
# Generated by Django 5.1.2 on 2024-12-06 06:47
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
|
@ -1,5 +1,8 @@
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
from django.contrib.auth.models import ContentType, Permission
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_framework_json_api.metadata import JSONAPIMetadata
|
||||
from rest_framework.request import clone_request
|
||||
@ -64,23 +67,39 @@ class ReactUIMetadata(OverRideJSONAPIMetadata):
|
||||
|
||||
metadata["description"] = view.get_view_description()
|
||||
|
||||
if 'pk' in view.kwargs:
|
||||
metadata['urls']: dict = {}
|
||||
|
||||
if view.kwargs['pk']:
|
||||
url_self = None
|
||||
|
||||
qs = view.get_queryset()[0]
|
||||
|
||||
if hasattr(qs, 'get_url'):
|
||||
if view.kwargs.get('pk', None) is not None:
|
||||
|
||||
qs = view.get_queryset()[0]
|
||||
|
||||
if hasattr(qs, 'get_url'):
|
||||
|
||||
url_self = qs.get_url( request=request )
|
||||
|
||||
metadata['return_url'] = qs.get_url( request )
|
||||
|
||||
elif view.kwargs:
|
||||
|
||||
metadata['return_url'] = reverse('v2:' + view.basename + '-list', request = view.request, kwargs = view.kwargs )
|
||||
url_self = reverse('v2:' + view.basename + '-list', request = view.request, kwargs = view.kwargs )
|
||||
|
||||
else:
|
||||
|
||||
metadata['return_url'] = reverse('v2:' + view.basename + '-list', request = view.request )
|
||||
url_self = reverse('v2:' + view.basename + '-list', request = view.request )
|
||||
|
||||
if url_self:
|
||||
|
||||
metadata['urls'].update({'self': url_self})
|
||||
|
||||
if view.get_back_url():
|
||||
|
||||
metadata['urls'].update({'back': view.get_back_url()})
|
||||
|
||||
if view.get_return_url():
|
||||
|
||||
metadata['urls'].update({'return_url': view.get_return_url()})
|
||||
|
||||
|
||||
metadata["renders"] = [
|
||||
@ -123,136 +142,33 @@ class ReactUIMetadata(OverRideJSONAPIMetadata):
|
||||
metadata['layout'] = view.get_page_layout()
|
||||
|
||||
|
||||
metadata['navigation'] = [
|
||||
{
|
||||
"display_name": "Access",
|
||||
"name": "access",
|
||||
"pages": [
|
||||
{
|
||||
"display_name": "Organization",
|
||||
"name": "organization",
|
||||
"link": "/access/organization"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"display_name": "Assistance",
|
||||
"name": "assistance",
|
||||
"pages": [
|
||||
{
|
||||
"display_name": "Requests",
|
||||
"name": "request",
|
||||
"icon": "ticket_request",
|
||||
"link": "/assistance/ticket/request"
|
||||
},
|
||||
{
|
||||
"display_name": "Knowledge Base",
|
||||
"name": "knowledge_base",
|
||||
"icon": "information",
|
||||
"link": "/assistance/knowledge_base"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"display_name": "ITAM",
|
||||
"name": "itam",
|
||||
"pages": [
|
||||
{
|
||||
"display_name": "Devices",
|
||||
"name": "device",
|
||||
"icon": "device",
|
||||
"link": "/itam/device"
|
||||
},
|
||||
{
|
||||
"display_name": "Operating System",
|
||||
"name": "operating_system",
|
||||
"link": "/itam/operating_system"
|
||||
},
|
||||
{
|
||||
"display_name": "Software",
|
||||
"name": "software",
|
||||
"link": "/itam/software"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"display_name": "ITIM",
|
||||
"name": "itim",
|
||||
"pages": [
|
||||
{
|
||||
"display_name": "Changes",
|
||||
"name": "ticket_change",
|
||||
"link": "/itim/ticket/change"
|
||||
},
|
||||
{
|
||||
"display_name": "Clusters",
|
||||
"name": "cluster",
|
||||
"link": "/itim/cluster"
|
||||
},
|
||||
{
|
||||
"display_name": "Incidents",
|
||||
"name": "ticket_incident",
|
||||
"link": "/itim/ticket/incident"
|
||||
},
|
||||
{
|
||||
"display_name": "Problems",
|
||||
"name": "ticket_problem",
|
||||
"link": "/itim/ticket/problem"
|
||||
},
|
||||
{
|
||||
"display_name": "Services",
|
||||
"name": "service",
|
||||
"link": "/itim/service"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"display_name": "Config Management",
|
||||
"name": "config_management",
|
||||
"icon": "ansible",
|
||||
"pages": [
|
||||
{
|
||||
"display_name": "Groups",
|
||||
"name": "group",
|
||||
"icon": 'config_management',
|
||||
"link": "/config_management/group"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"display_name": "Project Management",
|
||||
"name": "project_management",
|
||||
"icon": 'project',
|
||||
"pages": [
|
||||
{
|
||||
"display_name": "Projects",
|
||||
"name": "project",
|
||||
"icon": 'kanban',
|
||||
"link": "/project_management/project"
|
||||
}
|
||||
]
|
||||
},
|
||||
build_repo: str = None
|
||||
|
||||
{
|
||||
"display_name": "Settings",
|
||||
"name": "settings",
|
||||
"pages": [
|
||||
{
|
||||
"display_name": "System",
|
||||
"name": "setting",
|
||||
"icon": "system",
|
||||
"link": "/settings"
|
||||
},
|
||||
{
|
||||
"display_name": "Task Log",
|
||||
"name": "celery_log",
|
||||
# "icon": "settings",
|
||||
"link": "/settings/celery_log"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
if settings.BUILD_REPO:
|
||||
|
||||
build_repo = settings.BUILD_REPO
|
||||
|
||||
build_sha: str = None
|
||||
|
||||
if settings.BUILD_SHA:
|
||||
|
||||
build_sha = settings.BUILD_SHA
|
||||
|
||||
build_version: str = 'development'
|
||||
|
||||
if settings.BUILD_VERSION:
|
||||
|
||||
build_version = settings.BUILD_VERSION
|
||||
|
||||
|
||||
metadata['version']: dict = {
|
||||
'project_url': build_repo,
|
||||
'sha': build_sha,
|
||||
'version': build_version,
|
||||
}
|
||||
|
||||
|
||||
metadata['navigation'] = self.get_navigation(request.user)
|
||||
|
||||
return metadata
|
||||
|
||||
@ -334,7 +250,6 @@ class ReactUIMetadata(OverRideJSONAPIMetadata):
|
||||
field_info["children"] = self.get_serializer_info(field)
|
||||
|
||||
if (
|
||||
# not field_info.get("read_only")
|
||||
hasattr(field, "choices")
|
||||
):
|
||||
field_info["choices"] = [
|
||||
@ -353,4 +268,238 @@ class ReactUIMetadata(OverRideJSONAPIMetadata):
|
||||
field.field_name in serializer.included_serializers
|
||||
)
|
||||
|
||||
return field_info
|
||||
return field_info
|
||||
|
||||
|
||||
_nav = {
|
||||
'access': {
|
||||
"display_name": "Access",
|
||||
"name": "access",
|
||||
"pages": {
|
||||
'view_organization': {
|
||||
"display_name": "Organization",
|
||||
"name": "organization",
|
||||
"link": "/access/organization"
|
||||
}
|
||||
}
|
||||
},
|
||||
'assistance': {
|
||||
"display_name": "Assistance",
|
||||
"name": "assistance",
|
||||
"pages": {
|
||||
'core.view_ticket_request': {
|
||||
"display_name": "Requests",
|
||||
"name": "request",
|
||||
"icon": "ticket_request",
|
||||
"link": "/assistance/ticket/request"
|
||||
},
|
||||
'view_knowledgebase': {
|
||||
"display_name": "Knowledge Base",
|
||||
"name": "knowledge_base",
|
||||
"icon": "information",
|
||||
"link": "/assistance/knowledge_base"
|
||||
}
|
||||
}
|
||||
},
|
||||
'itam': {
|
||||
"display_name": "ITAM",
|
||||
"name": "itam",
|
||||
"pages": {
|
||||
'view_device': {
|
||||
"display_name": "Devices",
|
||||
"name": "device",
|
||||
"icon": "device",
|
||||
"link": "/itam/device"
|
||||
},
|
||||
'view_operatingsystem': {
|
||||
"display_name": "Operating System",
|
||||
"name": "operating_system",
|
||||
"link": "/itam/operating_system"
|
||||
},
|
||||
'view_software': {
|
||||
"display_name": "Software",
|
||||
"name": "software",
|
||||
"link": "/itam/software"
|
||||
}
|
||||
}
|
||||
},
|
||||
'itim': {
|
||||
"display_name": "ITIM",
|
||||
"name": "itim",
|
||||
"pages": {
|
||||
'core.view_ticket_change': {
|
||||
"display_name": "Changes",
|
||||
"name": "ticket_change",
|
||||
"link": "/itim/ticket/change"
|
||||
},
|
||||
'view_cluster': {
|
||||
"display_name": "Clusters",
|
||||
"name": "cluster",
|
||||
"link": "/itim/cluster"
|
||||
},
|
||||
'core.view_ticket_incident': {
|
||||
"display_name": "Incidents",
|
||||
"name": "ticket_incident",
|
||||
"link": "/itim/ticket/incident"
|
||||
},
|
||||
'core.view_ticket_problem': {
|
||||
"display_name": "Problems",
|
||||
"name": "ticket_problem",
|
||||
"link": "/itim/ticket/problem"
|
||||
},
|
||||
'view_service': {
|
||||
"display_name": "Services",
|
||||
"name": "service",
|
||||
"link": "/itim/service"
|
||||
},
|
||||
}
|
||||
},
|
||||
'config_management': {
|
||||
"display_name": "Config Management",
|
||||
"name": "config_management",
|
||||
"icon": "ansible",
|
||||
"pages": {
|
||||
'view_configgroups': {
|
||||
"display_name": "Groups",
|
||||
"name": "group",
|
||||
"icon": 'config_management',
|
||||
"link": "/config_management/group"
|
||||
}
|
||||
}
|
||||
},
|
||||
'project_management': {
|
||||
"display_name": "Project Management",
|
||||
"name": "project_management",
|
||||
"icon": 'project',
|
||||
"pages": {
|
||||
'view_project': {
|
||||
"display_name": "Projects",
|
||||
"name": "project",
|
||||
"icon": 'kanban',
|
||||
"link": "/project_management/project"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'settings': {
|
||||
"display_name": "Settings",
|
||||
"name": "settings",
|
||||
"pages": {
|
||||
'all_settings': {
|
||||
"display_name": "System",
|
||||
"name": "setting",
|
||||
"icon": "system",
|
||||
"link": "/settings"
|
||||
},
|
||||
'django_celery_results.view_taskresult': {
|
||||
"display_name": "Task Log",
|
||||
"name": "celery_log",
|
||||
# "icon": "settings",
|
||||
"link": "/settings/celery_log"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def get_navigation(self, user) -> list(dict()):
|
||||
"""Render the navigation menu
|
||||
|
||||
Check the users permissions agains `_nav`. if they have the permission, add the
|
||||
menu entry to the navigation to be rendered,
|
||||
|
||||
**No** Menu is to be rendered that contains no menu entries.
|
||||
|
||||
Args:
|
||||
user (User): User object from the request.
|
||||
|
||||
Returns:
|
||||
list(dict()): Rendered navigation menu in the format the UI requires it to be.
|
||||
"""
|
||||
|
||||
nav: list = []
|
||||
|
||||
processed_permissions: dict = {}
|
||||
|
||||
for group in user.groups.all():
|
||||
|
||||
for permission in group.permissions.all():
|
||||
|
||||
if str(permission.codename).startswith('view_'):
|
||||
|
||||
|
||||
if not processed_permissions.get(permission.content_type.app_label, None):
|
||||
|
||||
processed_permissions.update({permission.content_type.app_label: {}})
|
||||
|
||||
if permission.codename not in processed_permissions[permission.content_type.app_label]:
|
||||
|
||||
processed_permissions[permission.content_type.app_label].update({str(permission.codename): '_'})
|
||||
|
||||
view_settings: list = [
|
||||
'assistance.view_knowledgebasecategory',
|
||||
'core.view_manufacturer',
|
||||
'core.view_ticketcategory',
|
||||
'core.view_ticketcommentcategory',
|
||||
'itam.view_devicemodel',
|
||||
'itam.view_devicetype',
|
||||
'itam.view_softwarecategory',
|
||||
'itim.view_clustertype',
|
||||
'project_management.view_projectstate',
|
||||
'project_management.view_projecttype',
|
||||
'settings.view_appsettings',
|
||||
]
|
||||
|
||||
for app, entry in self._nav.items():
|
||||
|
||||
new_menu_entry: dict = {}
|
||||
|
||||
new_pages: list = []
|
||||
|
||||
# if processed_permissions.get(app, None): # doesn't cater for `.` in perm
|
||||
|
||||
for permission, page in entry['pages'].items():
|
||||
|
||||
if permission == 'all_settings':
|
||||
|
||||
for setting_permission in view_settings:
|
||||
|
||||
app_permission = str(setting_permission).split('.')
|
||||
|
||||
if processed_permissions.get(app_permission[0], None):
|
||||
|
||||
if processed_permissions[app_permission[0]].get(app_permission[1], None):
|
||||
|
||||
new_pages += [ page ]
|
||||
|
||||
break
|
||||
|
||||
|
||||
elif '.' in permission:
|
||||
|
||||
app_permission = str(permission).split('.')
|
||||
|
||||
if processed_permissions.get(app_permission[0], None):
|
||||
|
||||
if processed_permissions[app_permission[0]].get(app_permission[1], None):
|
||||
|
||||
new_pages += [ page ]
|
||||
|
||||
else:
|
||||
|
||||
if processed_permissions.get(app, None):
|
||||
|
||||
if processed_permissions[app].get(permission, None):
|
||||
|
||||
new_pages += [ page ]
|
||||
|
||||
|
||||
if len(new_pages) > 0:
|
||||
|
||||
new_menu_entry = entry.copy()
|
||||
|
||||
new_menu_entry.update({ 'pages': new_pages })
|
||||
|
||||
nav += [ new_menu_entry ]
|
||||
|
||||
return nav
|
||||
|
@ -1,8 +1,32 @@
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from access.serializers.organization import Organization, OrganizationBaseSerializer
|
||||
|
||||
from core import fields as centurion_field
|
||||
|
||||
from settings.models.app_settings import AppSettings
|
||||
|
||||
|
||||
class OrganizationField(serializers.PrimaryKeyRelatedField):
|
||||
|
||||
def get_queryset(self):
|
||||
""" Queryset Override
|
||||
|
||||
Override the base serializer and filter out the `global_organization`
|
||||
if defined.
|
||||
"""
|
||||
|
||||
app_settings = AppSettings.objects.all()
|
||||
|
||||
queryset = Organization.objects.all()
|
||||
|
||||
if getattr(app_settings[0], 'global_organization', None):
|
||||
|
||||
queryset = queryset.exclude(id=app_settings[0].global_organization.id)
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
|
||||
class CommonBaseSerializer(serializers.ModelSerializer):
|
||||
@ -12,5 +36,18 @@ class CommonBaseSerializer(serializers.ModelSerializer):
|
||||
|
||||
|
||||
class CommonModelSerializer(CommonBaseSerializer):
|
||||
"""Common Model Serializer
|
||||
|
||||
model_notes = centurion_field.MarkdownField( required = False )
|
||||
_**Note:** This serializer is not inherited by the organization Serializer_
|
||||
_`access.serializers.organization`, this is by design_
|
||||
|
||||
This serializer is included within ALL model (Tenancy Model) serilaizers and is intended to be used
|
||||
to add objects that ALL model serializers will require.
|
||||
|
||||
Args:
|
||||
CommonBaseSerializer (Class): Common base serializer
|
||||
"""
|
||||
|
||||
model_notes = centurion_field.MarkdownField( required = False )
|
||||
|
||||
organization = OrganizationField(required = False)
|
889
app/api/tests/abstract/test_metadata_functional.py
Normal file
889
app/api/tests/abstract/test_metadata_functional.py
Normal file
@ -0,0 +1,889 @@
|
||||
import pytest
|
||||
from django.test import Client
|
||||
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
|
||||
|
||||
class MetadataAttributesFunctionalBase:
|
||||
""" Functional Tests for API, HTTP/Options Method
|
||||
|
||||
These tests ensure that **ALL** serializers include the metaclass that adds the required
|
||||
data to the HTTP Options method.
|
||||
|
||||
Metaclass adds data required for the UI to function correctly.
|
||||
"""
|
||||
|
||||
app_namespace: str = None
|
||||
|
||||
url_name: str = None
|
||||
|
||||
viewset_type: str = 'list'
|
||||
|
||||
|
||||
def test_method_options_request_list_ok(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request returns `OK`.
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_method_options_request_list_data_returned(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request returns data.
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert response.data is not None
|
||||
|
||||
|
||||
def test_method_options_request_list_data_type(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned is of type `dict`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert type(response.data) is dict
|
||||
|
||||
|
||||
def test_method_options_request_detail_ok(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request returns `OK`.
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_returned(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request returns data.
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert response.data is not None
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_type(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned is of type `dict`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert type(response.data) is dict
|
||||
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_has_key_urls(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned has key `urls`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert 'urls' in response.data
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_urls_is_dict(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data key `urls` is dict
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert type(response.data['urls']) is dict
|
||||
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_has_key_urls_self(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned has key `urls.self`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert 'urls' in response.data
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_urls_self_is_str(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data key `urls.self` is a string
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert type(response.data['urls']['self']) is str
|
||||
|
||||
|
||||
@pytest.mark.skip(reason='to be written')
|
||||
def test_method_options_no_field_is_generic(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Fields are used for the UI to setup inputs correctly.
|
||||
|
||||
Ensure all fields at path `.actions.<METHOD>.<name>.type` do not have `GenericField` as the value.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class MetadataAttributesFunctionalTable:
|
||||
"""Test cases for Metadata
|
||||
|
||||
These test cases are for models that are expected to
|
||||
be rendered in a table.
|
||||
"""
|
||||
|
||||
|
||||
def test_method_options_request_list_data_has_key_table_fields(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned has key `table_fields`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert 'table_fields' in response.data
|
||||
|
||||
|
||||
def test_method_options_request_list_data_key_table_fields_is_list(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data['table_fields'] is of type `list`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
assert type(response.data['table_fields']) is list
|
||||
|
||||
|
||||
def test_method_options_request_list_data_key_table_fields_is_list_of_str(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data['table_fields'] list is of `str`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
||||
|
||||
response = client.options( url, content_type='application/json' )
|
||||
|
||||
all_string = True
|
||||
|
||||
for item in response.data['table_fields']:
|
||||
|
||||
if type(item) is not str:
|
||||
|
||||
all_string = False
|
||||
|
||||
|
||||
assert all_string
|
||||
|
||||
|
||||
|
||||
class MetadataAttributesFunctionalEndpoint:
|
||||
"""Test cases for Metadata
|
||||
|
||||
These test cases are for models that will have an
|
||||
endpoint. i.e. A Detail view
|
||||
"""
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_has_key_page_layout(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data returned has key `layout`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert 'layout' in response.data
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_page_layout_is_list(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data['layout'] is of type `list`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert type(response.data['layout']) is list
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_page_layout_is_list_of_dict(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data['layout'] list is of `dict`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
all_dict = True
|
||||
|
||||
for item in response.data['layout']:
|
||||
|
||||
if type(item) is not dict:
|
||||
|
||||
all_dict = False
|
||||
|
||||
|
||||
assert all_dict
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_page_layout_dicts_key_exists_name(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data['layout'].x has key `name`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
has_key = True
|
||||
|
||||
for item in response.data['layout']:
|
||||
|
||||
if 'name' not in item:
|
||||
|
||||
has_key = False
|
||||
|
||||
|
||||
assert has_key
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_page_layout_dicts_key_type_name(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data['layout'].x.[name] is of type `str`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
all_are_str = True
|
||||
|
||||
for item in response.data['layout']:
|
||||
|
||||
if type(item['name']) is not str:
|
||||
|
||||
all_are_str = False
|
||||
|
||||
|
||||
assert all_are_str
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_page_layout_dicts_key_exists_sections(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data['layout'].x has key `sections`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
has_key = True
|
||||
|
||||
for item in response.data['layout']:
|
||||
|
||||
if 'sections' not in item:
|
||||
|
||||
has_key = False
|
||||
|
||||
|
||||
assert has_key
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_page_layout_dicts_key_type_sections(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
Ensure the request data['layout'].x.[sections] is of type `list`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-detail',
|
||||
kwargs=self.url_view_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
all_are_str = True
|
||||
|
||||
for item in response.data['layout']:
|
||||
|
||||
if type(item['sections']) is not list:
|
||||
|
||||
all_are_str = False
|
||||
|
||||
|
||||
assert all_are_str
|
||||
|
||||
|
||||
|
||||
class MetadataAttributesFunctional(
|
||||
MetadataAttributesFunctionalEndpoint,
|
||||
MetadataAttributesFunctionalTable,
|
||||
MetadataAttributesFunctionalBase,
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class MetaDataNavigationEntriesFunctional:
|
||||
""" Test cases for the Navigation menu
|
||||
|
||||
Navigation menu is rendered as part of the API when a HTTP/OPTIONS
|
||||
request has been made. Each menu entry requires that a user has View
|
||||
permissions for that entry to be visible.
|
||||
|
||||
**No** menu entry is to be returned for **any** user whom does not
|
||||
have the corresponding view permission.
|
||||
|
||||
These test cases are for any model that has a navigation menu entry.
|
||||
|
||||
## Tests
|
||||
|
||||
- Ensure add user does not have menu entry
|
||||
- Ensure change user does not have menu entry
|
||||
- Ensure delete user does not have menu entry
|
||||
- Ensure the view user has menu entry
|
||||
- No menu to return without pages for add user
|
||||
- No menu to return without pages for change user
|
||||
- No menu to return without pages for delete user
|
||||
- No menu to return without pages for view user
|
||||
"""
|
||||
|
||||
menu_id: str = None
|
||||
""" Name of the Menu entry
|
||||
|
||||
Match for .navigation[i][name]
|
||||
"""
|
||||
|
||||
menu_entry_id: str = None
|
||||
"""Name of the menu entry
|
||||
|
||||
Match for .navigation[i][pages][i][name]
|
||||
"""
|
||||
|
||||
app_namespace:str = None
|
||||
"""application namespace"""
|
||||
|
||||
url_name: str = None
|
||||
"""url name"""
|
||||
|
||||
url_kwargs: dict = None
|
||||
"""View URL kwargs"""
|
||||
|
||||
add_user = None
|
||||
""" User with add permission"""
|
||||
|
||||
change_user = None
|
||||
""" User with change permission"""
|
||||
|
||||
delete_user = None
|
||||
""" User with delete permission"""
|
||||
|
||||
view_user = None
|
||||
""" User with view permission"""
|
||||
|
||||
|
||||
|
||||
def test_navigation_entry_add_user(self):
|
||||
"""Test HTTP/Options Method Navigation Entry
|
||||
|
||||
Ensure that a user with add permission, does not
|
||||
have the menu entry within navigation
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.add_user)
|
||||
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options(
|
||||
url,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
no_menu_entry_found: bool = True
|
||||
|
||||
for nav_menu in response.data['navigation']:
|
||||
|
||||
if nav_menu['name'] == self.menu_id:
|
||||
|
||||
for menu_entry in nav_menu['pages']:
|
||||
|
||||
if menu_entry['name'] == self.menu_entry_id:
|
||||
|
||||
no_menu_entry_found = False
|
||||
|
||||
assert no_menu_entry_found
|
||||
|
||||
|
||||
|
||||
def test_navigation_no_empty_menu_add_user(self):
|
||||
"""Test HTTP/Options Method Navigation Entry
|
||||
|
||||
Ensure that a user with add permission, does not
|
||||
have any nave menu without pages
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.add_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options(
|
||||
url,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
no_empty_menu_found: bool = True
|
||||
|
||||
for nav_menu in response.data['navigation']:
|
||||
|
||||
if len(nav_menu['pages']) == 0:
|
||||
|
||||
no_empty_menu_found = False
|
||||
|
||||
assert no_empty_menu_found
|
||||
|
||||
|
||||
|
||||
def test_navigation_entry_change_user(self):
|
||||
"""Test HTTP/Options Method Navigation Entry
|
||||
|
||||
Ensure that a user with change permission, does not
|
||||
have the menu entry within navigation
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.change_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options(
|
||||
url,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
no_menu_entry_found: bool = True
|
||||
|
||||
for nav_menu in response.data['navigation']:
|
||||
|
||||
if nav_menu['name'] == self.menu_id:
|
||||
|
||||
for menu_entry in nav_menu['pages']:
|
||||
|
||||
if menu_entry['name'] == self.menu_entry_id:
|
||||
|
||||
no_menu_entry_found = False
|
||||
|
||||
assert no_menu_entry_found
|
||||
|
||||
|
||||
|
||||
def test_navigation_no_empty_menu_change_user(self):
|
||||
"""Test HTTP/Options Method Navigation Entry
|
||||
|
||||
Ensure that a user with change permission, does not
|
||||
have any nave menu without pages
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.change_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options(
|
||||
url,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
no_empty_menu_found: bool = True
|
||||
|
||||
for nav_menu in response.data['navigation']:
|
||||
|
||||
if len(nav_menu['pages']) == 0:
|
||||
|
||||
no_empty_menu_found = False
|
||||
|
||||
assert no_empty_menu_found
|
||||
|
||||
|
||||
|
||||
def test_navigation_entry_delete_user(self):
|
||||
"""Test HTTP/Options Method Navigation Entry
|
||||
|
||||
Ensure that a user with delete permission, does not
|
||||
have the menu entry within navigation
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.delete_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options(
|
||||
url,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
no_menu_entry_found: bool = True
|
||||
|
||||
for nav_menu in response.data['navigation']:
|
||||
|
||||
if nav_menu['name'] == self.menu_id:
|
||||
|
||||
for menu_entry in nav_menu['pages']:
|
||||
|
||||
if menu_entry['name'] == self.menu_entry_id:
|
||||
|
||||
no_menu_entry_found = False
|
||||
|
||||
assert no_menu_entry_found
|
||||
|
||||
|
||||
|
||||
def test_navigation_no_empty_menu_delete_user(self):
|
||||
"""Test HTTP/Options Method Navigation Entry
|
||||
|
||||
Ensure that a user with delete permission, does not
|
||||
have any nave menu without pages
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.delete_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options(
|
||||
url,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
no_empty_menu_found: bool = True
|
||||
|
||||
for nav_menu in response.data['navigation']:
|
||||
|
||||
if len(nav_menu['pages']) == 0:
|
||||
|
||||
no_empty_menu_found = False
|
||||
|
||||
assert no_empty_menu_found
|
||||
|
||||
|
||||
|
||||
def test_navigation_entry_view_user(self):
|
||||
"""Test HTTP/Options Method Navigation Entry
|
||||
|
||||
Ensure that a user with view permission,
|
||||
has the menu entry within navigation
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options(
|
||||
url,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
menu_entry_found: bool = False
|
||||
|
||||
for nav_menu in response.data['navigation']:
|
||||
|
||||
if nav_menu['name'] == self.menu_id:
|
||||
|
||||
for menu_entry in nav_menu['pages']:
|
||||
|
||||
if menu_entry['name'] == self.menu_entry_id:
|
||||
|
||||
menu_entry_found = True
|
||||
|
||||
assert menu_entry_found
|
||||
|
||||
|
||||
|
||||
def test_navigation_no_empty_menu_view_user(self):
|
||||
"""Test HTTP/Options Method Navigation Entry
|
||||
|
||||
Ensure that a user with view permission, does not
|
||||
have any nave menu without pages
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
if getattr(self, 'url_kwargs', None):
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
||||
|
||||
else:
|
||||
|
||||
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
||||
|
||||
response = client.options(
|
||||
url,
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
no_empty_menu_found: bool = True
|
||||
|
||||
for nav_menu in response.data['navigation']:
|
||||
|
||||
if len(nav_menu['pages']) == 0:
|
||||
|
||||
no_empty_menu_found = False
|
||||
|
||||
assert no_empty_menu_found
|
||||
|
||||
|
1557
app/api/tests/unit/test_navigation_menu.py
Normal file
1557
app/api/tests/unit/test_navigation_menu.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -82,6 +82,25 @@ class CommonViewSet(
|
||||
|
||||
view_name: str = None
|
||||
|
||||
def get_back_url(self) -> str:
|
||||
"""Metadata Back URL
|
||||
|
||||
This URL is an optional URL that if required the view must
|
||||
override this method. If the URL for a back operation
|
||||
is not the models URL, then this method is used to return
|
||||
the URL that will be used.
|
||||
|
||||
Defining this URL will predominatly be for sub-models. It's
|
||||
recommended that the `reverse` function
|
||||
(rest_framework.reverse.reverse) be used with a `request`
|
||||
object.
|
||||
|
||||
Returns:
|
||||
str: Full url in format `<protocol>://<doman name>.<tld>/api/<API version>/<model url>`
|
||||
"""
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_model_documentation(self):
|
||||
|
||||
@ -115,6 +134,26 @@ class CommonViewSet(
|
||||
return self.page_layout
|
||||
|
||||
|
||||
def get_return_url(self) -> str:
|
||||
"""Metadata return URL
|
||||
|
||||
This URL is an optional URL that if required the view must
|
||||
override this method. If the URL for a cancel operation
|
||||
is not the models URL, then this method is used to return
|
||||
the URL that will be used.
|
||||
|
||||
Defining this URL will predominatly be for sub-models. It's
|
||||
recommended that the `reverse` function
|
||||
(rest_framework.reverse.reverse) be used with a `request`
|
||||
object.
|
||||
|
||||
Returns:
|
||||
str: Full url in format `<protocol>://<doman name>.<tld>/api/<API version>/<model url>`
|
||||
"""
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_table_fields(self):
|
||||
|
||||
if len(self.table_fields) < 1:
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 15:27
|
||||
# Generated by Django 5.1.2 on 2024-12-06 06:47
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
@ -8,11 +8,19 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0003_alter_organization_id_alter_organization_manager_and_more'),
|
||||
('access', '0002_alter_organization_options_alter_team_options_and_more'),
|
||||
('assistance', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='knowledgebase',
|
||||
options={'ordering': ['title'], 'verbose_name': 'Knowledge Base', 'verbose_name_plural': 'Knowledge Base Articles'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='knowledgebasecategory',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Knowledge Base Category', 'verbose_name_plural': 'Knowledge Base Categories'},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='knowledgebasecategory',
|
||||
name='slug',
|
||||
@ -30,7 +38,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='knowledgebase',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='knowledgebasecategory',
|
||||
@ -50,6 +58,6 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='knowledgebasecategory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-16 06:54
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assistance', '0002_remove_knowledgebasecategory_slug_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='knowledgebase',
|
||||
options={'ordering': ['title'], 'verbose_name': 'Knowledge Base', 'verbose_name_plural': 'Knowledge Base Articles'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='knowledgebasecategory',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Knowledge Base Category', 'verbose_name_plural': 'Knowledge Base Categories'},
|
||||
),
|
||||
]
|
@ -1,27 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-20 02:41
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0006_alter_team_organization'),
|
||||
('assistance', '0003_alter_knowledgebase_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='knowledgebase',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='knowledgebasecategory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(default=None, help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -250,6 +250,24 @@ class KnowledgeBase(TenancyObject):
|
||||
|
||||
|
||||
page_layout: dict = [
|
||||
{
|
||||
"name": "Content",
|
||||
"slug": "content",
|
||||
"sections": [
|
||||
{
|
||||
"layout": "single",
|
||||
"fields": [
|
||||
'summary',
|
||||
]
|
||||
},
|
||||
{
|
||||
"layout": "single",
|
||||
"fields": [
|
||||
'content',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Details",
|
||||
"slug": "details",
|
||||
|
@ -12,6 +12,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
from assistance.models.knowledge_base import KnowledgeBase
|
||||
|
||||
@ -211,4 +212,17 @@ class KnowledgeBaseViewSet(
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class KnowledgeBaseMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'assistance'
|
||||
|
||||
menu_entry_id = 'knowledge_base'
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from assistance.models.knowledge_base import KnowledgeBaseCategory
|
||||
|
||||
@ -206,3 +207,13 @@ class KnowledgeBaseCategoryViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class KnowledgeBaseCategoryMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -1,5 +1,7 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
from core.tests.abstract.test_ticket_viewset import Ticket, TicketViewSetBase, TicketViewSetPermissionsAPI, TicketViewSet
|
||||
|
||||
|
||||
@ -29,3 +31,16 @@ class TicketRequestViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TicketRequestMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'assistance'
|
||||
|
||||
menu_entry_id = 'request'
|
||||
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 06:42
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('config_management', '0003_alter_configgroups_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='configgroups',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Config Group', 'verbose_name_plural': 'Config Groups'},
|
||||
),
|
||||
]
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 15:27
|
||||
# Generated by Django 5.1.2 on 2024-12-06 06:47
|
||||
|
||||
import access.models
|
||||
import config_management.models.groups
|
||||
@ -9,12 +9,25 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0003_alter_organization_id_alter_organization_manager_and_more'),
|
||||
('config_management', '0005_alter_configgroupsoftware_options'),
|
||||
('itam', '0014_alter_softwarecategory_options'),
|
||||
('access', '0002_alter_organization_options_alter_team_options_and_more'),
|
||||
('config_management', '0003_alter_configgroups_options_and_more'),
|
||||
('itam', '0004_alter_deviceoperatingsystem_device_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='configgroups',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Config Group', 'verbose_name_plural': 'Config Groups'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='configgroupsoftware',
|
||||
options={'ordering': ['-action', 'software'], 'verbose_name': 'Config Group Software', 'verbose_name_plural': 'Config Group Softwares'},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='configgroups',
|
||||
name='hosts',
|
||||
field=models.ManyToManyField(blank=True, help_text='Hosts that are part of this group', to='itam.device', verbose_name='Hosts'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='configgrouphosts',
|
||||
name='group',
|
||||
@ -43,7 +56,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='configgrouphosts',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='configgroups',
|
||||
@ -73,7 +86,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='configgroups',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='configgroups',
|
||||
@ -83,7 +96,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='configgroupsoftware',
|
||||
name='action',
|
||||
field=models.CharField(blank=True, choices=[('1', 'Install'), ('0', 'Remove')], default=None, help_text='ACtion to perform with this software', max_length=1, null=True, verbose_name='Action'),
|
||||
field=models.IntegerField(blank=True, choices=[(1, 'Install'), (0, 'Remove')], default=None, help_text='ACtion to perform with this software', null=True, verbose_name='Action'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='configgroupsoftware',
|
||||
@ -108,7 +121,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='configgroupsoftware',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='configgroupsoftware',
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 06:51
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('config_management', '0004_alter_configgroups_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='configgroupsoftware',
|
||||
options={'ordering': ['-action', 'software'], 'verbose_name': 'Config Group Software', 'verbose_name_plural': 'Config Group Softwares'},
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-16 06:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('config_management', '0006_alter_configgrouphosts_group_and_more'),
|
||||
('itam', '0015_alter_device_device_model_alter_device_device_type_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='configgroups',
|
||||
name='hosts',
|
||||
field=models.ManyToManyField(blank=True, help_text='Hosts that are part of this group', to='itam.device', verbose_name='Hosts'),
|
||||
),
|
||||
]
|
@ -1,75 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-16 06:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def migrate_to_configgroups_hosts(apps, schema_editor):
|
||||
|
||||
if schema_editor.connection.alias != "default":
|
||||
|
||||
return
|
||||
|
||||
print('')
|
||||
|
||||
ConfigGroups = apps.get_model('config_management', 'ConfigGroups')
|
||||
ConfigGroupHosts = apps.get_model('config_management', 'ConfigGroupHosts')
|
||||
|
||||
current_data = ConfigGroupHosts.objects.all()
|
||||
|
||||
for host in current_data:
|
||||
|
||||
print(f'Begin migrating host {host.host} in group {host.group}:')
|
||||
|
||||
config_group = ConfigGroups.objects.get(pk = host.group.id)
|
||||
|
||||
print(f' migrate {host.host} in group {config_group}')
|
||||
|
||||
config_group.hosts.add( host.host )
|
||||
|
||||
try:
|
||||
|
||||
was_migrated = ConfigGroups.objects.get(pk = host.group.id)
|
||||
|
||||
if host.host in was_migrated.hosts.all():
|
||||
|
||||
print(f' successfully migrated {host.id} {host.host} to new table')
|
||||
|
||||
ConfigGroupHosts.objects.get(pk = host.id).delete()
|
||||
|
||||
try:
|
||||
|
||||
ConfigGroupHosts.objects.get(pk = host.id)
|
||||
|
||||
print(f' Error Failed to remove old data for host {host.host}')
|
||||
|
||||
except ConfigGroupHosts.DoesNotExist:
|
||||
|
||||
print(f' Old data removed')
|
||||
|
||||
except ConfigGroupHosts.DoesNotExist:
|
||||
|
||||
print(f' Error, {host.host} was not migrated to new table')
|
||||
|
||||
|
||||
old_data = ConfigGroupHosts.objects.all()
|
||||
|
||||
if len(old_data) == 0:
|
||||
|
||||
print(f'Successfully migrated data to new table, removing old table')
|
||||
|
||||
migrations.DeleteModel("ConfigGroupHosts")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('config_management', '0007_configgroups_hosts'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_to_configgroups_hosts),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-17 03:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('config_management', '0008_move_data_configgroup_hosts'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='configgroupsoftware',
|
||||
name='action',
|
||||
field=models.IntegerField(blank=True, choices=[(1, 'Install'), (0, 'Remove')], default=None, help_text='ACtion to perform with this software', null=True, verbose_name='Action'),
|
||||
),
|
||||
]
|
@ -1,31 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-20 02:41
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0006_alter_team_organization'),
|
||||
('config_management', '0009_alter_configgroupsoftware_action'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='configgrouphosts',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='configgroups',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='configgroupsoftware',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
@ -12,6 +12,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
from config_management.models.groups import ConfigGroups
|
||||
|
||||
@ -207,3 +208,16 @@ class ConfigGroupsViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ConfigGroupsMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'config_management'
|
||||
|
||||
menu_entry_id = 'group'
|
||||
|
@ -12,6 +12,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from config_management.models.groups import ConfigGroups, ConfigGroupSoftware, Software, SoftwareVersion
|
||||
|
||||
@ -247,3 +248,13 @@ class ConfigGroupSoftwareViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ConfigGroupSoftwareMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -1,23 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-11 16:03
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0006_ticket_milestone_ticket_opened_by_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='history',
|
||||
name='after',
|
||||
field=models.JSONField(blank=True, default=None, help_text='JSON Object After Change', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='history',
|
||||
name='before',
|
||||
field=models.JSONField(blank=True, default=None, help_text='JSON Object before Change', null=True),
|
||||
),
|
||||
]
|
@ -1,7 +1,9 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 15:27
|
||||
# Generated by Django 5.1.2 on 2024-12-06 06:47
|
||||
|
||||
import access.fields
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
@ -9,19 +11,39 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0003_alter_organization_id_alter_organization_manager_and_more'),
|
||||
('config_management', '0006_alter_configgrouphosts_group_and_more'),
|
||||
('core', '0009_alter_notes_options'),
|
||||
('itam', '0014_alter_softwarecategory_options'),
|
||||
('itim', '0005_alter_cluster_cluster_type_alter_cluster_id_and_more'),
|
||||
('access', '0002_alter_organization_options_alter_team_options_and_more'),
|
||||
('config_management', '0004_alter_configgroups_options_and_more'),
|
||||
('core', '0006_ticket_milestone_ticket_opened_by_and_more'),
|
||||
('itam', '0004_alter_deviceoperatingsystem_device_and_more'),
|
||||
('itim', '0005_alter_port_options_alter_cluster_cluster_type_and_more'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='history',
|
||||
options={'ordering': ['-created'], 'verbose_name': 'History', 'verbose_name_plural': 'History'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='manufacturer',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Manufacturer', 'verbose_name_plural': 'Manufacturers'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='notes',
|
||||
options={'ordering': ['-created'], 'verbose_name': 'Note', 'verbose_name_plural': 'Notes'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='relatedtickets',
|
||||
options={'ordering': ['id'], 'verbose_name': 'Related Ticket', 'verbose_name_plural': 'Related Tickets'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='ticketcomment',
|
||||
options={'ordering': ['created', 'ticket', 'parent_id'], 'verbose_name': 'Ticket Comment', 'verbose_name_plural': 'Ticket Comments'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='history',
|
||||
name='action',
|
||||
field=models.IntegerField(choices=[('1', 'Create'), ('2', 'Update'), ('3', 'Delete')], default=None, help_text='History action performed', null=True, verbose_name='Action'),
|
||||
field=models.IntegerField(choices=[(1, 'Create'), (2, 'Update'), (3, 'Delete')], default=None, help_text='History action performed', null=True, verbose_name='Action'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='history',
|
||||
@ -78,6 +100,11 @@ class Migration(migrations.Migration):
|
||||
name='model_notes',
|
||||
field=models.TextField(blank=True, default=None, help_text='Tid bits of information', null=True, verbose_name='Notes'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='manufacturer',
|
||||
name='modified',
|
||||
field=access.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, help_text='Date and time of last modification', verbose_name='Modified'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='manufacturer',
|
||||
name='name',
|
||||
@ -86,7 +113,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='manufacturer',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='notes',
|
||||
@ -116,7 +143,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='notes',
|
||||
name='note',
|
||||
field=models.TextField(blank=True, default=None, help_text='The tid bit you wish to add', null=True, verbose_name='Note'),
|
||||
field=models.TextField(help_text='The tid bit you wish to add', verbose_name='Note'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='notes',
|
||||
@ -126,7 +153,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='notes',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='notes',
|
||||
@ -151,7 +178,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='relatedtickets',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
@ -161,7 +188,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketcategory',
|
||||
@ -176,12 +203,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='ticketcategory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketcomment',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketcommentcategory',
|
||||
@ -196,11 +223,11 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='ticketcommentcategory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketlinkeditem',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 06:58
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0007_alter_history_after_alter_history_before'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='manufacturer',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Manufacturer', 'verbose_name_plural': 'Manufacturers'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 07:02
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0008_alter_manufacturer_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='notes',
|
||||
options={'ordering': ['-created'], 'verbose_name': 'Note', 'verbose_name_plural': 'Notes'},
|
||||
),
|
||||
]
|
@ -1,22 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-18 03:34
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0010_alter_history_action_alter_history_after_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='history',
|
||||
options={'ordering': ['-created'], 'verbose_name': 'History', 'verbose_name_plural': 'History'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='history',
|
||||
name='action',
|
||||
field=models.IntegerField(choices=[(1, 'Create'), (2, 'Update'), (3, 'Delete')], default=None, help_text='History action performed', null=True, verbose_name='Action'),
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-19 02:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0011_alter_history_options_alter_history_action'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='notes',
|
||||
name='note',
|
||||
field=models.TextField(default='-', help_text='The tid bit you wish to add', verbose_name='Note'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
@ -1,20 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-19 03:58
|
||||
|
||||
import access.fields
|
||||
import django.utils.timezone
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0012_alter_notes_note'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='manufacturer',
|
||||
name='modified',
|
||||
field=access.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, help_text='Date and time of last modification', verbose_name='Modified'),
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-26 13:00
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0013_alter_manufacturer_modified'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='ticketcomment',
|
||||
options={'ordering': ['created', 'ticket', 'parent_id'], 'verbose_name': 'Comment', 'verbose_name_plural': 'Comments'},
|
||||
),
|
||||
]
|
@ -1,21 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-03 14:21
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0014_alter_ticketcomment_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='relatedtickets',
|
||||
options={'ordering': ['id'], 'verbose_name': 'Related Ticket', 'verbose_name_plural': 'Related Tickets'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='ticketcomment',
|
||||
options={'ordering': ['created', 'ticket', 'parent_id'], 'verbose_name': 'Ticket Comment', 'verbose_name_plural': 'Ticket Comments'},
|
||||
),
|
||||
]
|
@ -1,56 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-20 02:41
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0006_alter_team_organization'),
|
||||
('core', '0015_alter_relatedtickets_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='manufacturer',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='notes',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='relatedtickets',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketcategory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketcomment',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketcommentcategory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketlinkeditem',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
@ -1186,11 +1186,7 @@ class RelatedTickets(TenancyObject):
|
||||
]
|
||||
|
||||
|
||||
def get_url( self, ticket_id, request = None ) -> str:
|
||||
|
||||
if not ticket_id:
|
||||
|
||||
return ''
|
||||
def get_url( self, request = None ) -> str:
|
||||
|
||||
if request:
|
||||
|
||||
@ -1198,7 +1194,7 @@ class RelatedTickets(TenancyObject):
|
||||
"v2:_api_v2_ticket_related-detail",
|
||||
request = request,
|
||||
kwargs={
|
||||
'ticket_id': ticket_id,
|
||||
'ticket_id': self.from_ticket_id.id,
|
||||
'pk': self.id
|
||||
}
|
||||
)
|
||||
@ -1206,7 +1202,7 @@ class RelatedTickets(TenancyObject):
|
||||
return reverse(
|
||||
"v2:_api_v2_ticket_related-detail",
|
||||
kwargs={
|
||||
'ticket_id': ticket_id,
|
||||
'ticket_id': self.from_ticket_id.id,
|
||||
'pk': self.id
|
||||
}
|
||||
)
|
||||
|
@ -81,7 +81,7 @@ class RelatedTicketModelSerializer(RelatedTicketBaseSerializer):
|
||||
ticket_id = int(self._kwargs['context']['view'].kwargs['ticket_id'])
|
||||
|
||||
return {
|
||||
'_self': item.get_url( ticket_id = ticket_id, request = request ),
|
||||
'_self': item.get_url( request = request ),
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from core.models.manufacturer import Manufacturer
|
||||
|
||||
@ -207,3 +208,13 @@ class ManufacturerViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ManufacturerMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -15,16 +15,15 @@ from api.tests.abstract.api_permissions_viewset import (
|
||||
APIPermissionDelete,
|
||||
APIPermissionView,
|
||||
)
|
||||
from api.tests.abstract.test_metadata_functional import (
|
||||
MetadataAttributesFunctionalBase
|
||||
)
|
||||
|
||||
from core.models.ticket.ticket import Ticket, RelatedTickets
|
||||
|
||||
|
||||
|
||||
class RelatedTicketsPermissionsAPI(
|
||||
APIPermissionDelete,
|
||||
APIPermissionView,
|
||||
TestCase,
|
||||
):
|
||||
class ViewSetBase:
|
||||
|
||||
model = RelatedTickets
|
||||
|
||||
@ -209,6 +208,13 @@ class RelatedTicketsPermissionsAPI(
|
||||
|
||||
|
||||
|
||||
class RelatedTicketsPermissionsAPI(
|
||||
ViewSetBase,
|
||||
APIPermissionDelete,
|
||||
APIPermissionView,
|
||||
TestCase,
|
||||
):
|
||||
|
||||
def test_add_has_permission_post_not_allowed(self):
|
||||
""" Check correct permission for add
|
||||
|
||||
@ -273,3 +279,13 @@ class RelatedTicketsPermissionsAPI(
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class RelatedTicketsMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctionalBase,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -12,6 +12,10 @@ from django.test import Client, TestCase
|
||||
from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissionView
|
||||
from api.tests.abstract.test_metadata_functional import (
|
||||
MetadataAttributesFunctionalBase,
|
||||
MetadataAttributesFunctionalEndpoint,
|
||||
)
|
||||
|
||||
from core.models.history import History
|
||||
|
||||
@ -19,7 +23,7 @@ from itam.models.device import Device
|
||||
|
||||
|
||||
|
||||
class HistoryPermissionsAPI(APIPermissionView, TestCase):
|
||||
class ViewSetBase:
|
||||
|
||||
model = History
|
||||
|
||||
@ -218,6 +222,15 @@ class HistoryPermissionsAPI(APIPermissionView, TestCase):
|
||||
user = self.different_organization_user
|
||||
)
|
||||
|
||||
|
||||
|
||||
class HistoryPermissionsAPI(
|
||||
ViewSetBase,
|
||||
APIPermissionView,
|
||||
TestCase
|
||||
):
|
||||
|
||||
|
||||
def test_view_list_has_permission(self):
|
||||
""" Check correct permission for view
|
||||
|
||||
@ -326,3 +339,61 @@ class HistoryPermissionsAPI(APIPermissionView, TestCase):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class HistoryMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctionalEndpoint,
|
||||
MetadataAttributesFunctionalBase,
|
||||
TestCase
|
||||
):
|
||||
|
||||
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_has_key_urls_self(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
This is a custom test of a test with the same name.
|
||||
history view has no detail view, due to using a custom
|
||||
view "history",
|
||||
|
||||
Ensure the request data returned has key `urls.self`
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-list',
|
||||
kwargs=self.url_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert 'urls' in response.data
|
||||
|
||||
|
||||
def test_method_options_request_detail_data_key_urls_self_is_str(self):
|
||||
"""Test HTTP/Options Method
|
||||
|
||||
This is a custom test of a test with the same name.
|
||||
history view has no detail view, due to using a custom
|
||||
view "history",
|
||||
|
||||
Ensure the request data key `urls.self` is a string
|
||||
"""
|
||||
|
||||
client = Client()
|
||||
client.force_login(self.view_user)
|
||||
|
||||
response = client.options(
|
||||
reverse(
|
||||
self.app_namespace + ':' + self.url_name + '-list',
|
||||
kwargs=self.url_kwargs
|
||||
),
|
||||
content_type='application/json'
|
||||
)
|
||||
|
||||
assert type(response.data['urls']['self']) is str
|
||||
|
@ -12,6 +12,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from core.models.ticket.ticket_category import TicketCategory
|
||||
|
||||
@ -203,3 +204,13 @@ class TicketCategoryViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TicketCategoryMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -6,6 +6,7 @@ from django.test import Client, TestCase
|
||||
from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from core.models.ticket.ticket_comment import Ticket, TicketComment
|
||||
|
||||
@ -13,10 +14,7 @@ from settings.models.user_settings import UserSettings
|
||||
|
||||
|
||||
|
||||
class TicketCommentPermissionsAPI(
|
||||
APIPermissions,
|
||||
TestCase
|
||||
):
|
||||
class ViewSetBase:
|
||||
""" Test Cases common to ALL ticket types """
|
||||
|
||||
model = TicketComment
|
||||
@ -230,6 +228,11 @@ class TicketCommentPermissionsAPI(
|
||||
)
|
||||
|
||||
|
||||
class TicketCommentPermissionsAPI(
|
||||
ViewSetBase,
|
||||
APIPermissions,
|
||||
TestCase
|
||||
):
|
||||
def test_returned_results_only_user_orgs(self):
|
||||
"""Test not required
|
||||
|
||||
@ -238,3 +241,13 @@ class TicketCommentPermissionsAPI(
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TicketCommentMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -12,6 +12,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from core.models.ticket.ticket_comment_category import TicketCommentCategory
|
||||
|
||||
@ -203,3 +204,13 @@ class TicketCommentCategoryViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TicketCommentCategoryMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -1,3 +1,5 @@
|
||||
from django.db.models import Q
|
||||
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiResponse
|
||||
|
||||
from api.viewsets.common import ModelViewSet
|
||||
@ -46,9 +48,10 @@ class ViewSet(ModelViewSet):
|
||||
queryset = super().get_queryset()
|
||||
|
||||
self.queryset = queryset.filter(
|
||||
item_parent_class = self.kwargs['model_class'],
|
||||
item_parent_pk = self.kwargs['model_id']
|
||||
).order_by('-created')
|
||||
Q(item_pk = self.kwargs['model_id'], item_class = self.kwargs['model_class'])
|
||||
|
|
||||
Q(item_parent_pk = self.kwargs['model_id'], item_parent_class = self.kwargs['model_class'])
|
||||
)
|
||||
|
||||
return self.queryset
|
||||
|
||||
|
@ -251,17 +251,6 @@ class TicketViewSet(ModelViewSet):
|
||||
|
||||
|
||||
if (
|
||||
self.action == 'list'
|
||||
):
|
||||
|
||||
user_settings = UserSettings.objects.get(
|
||||
user = self.request.user
|
||||
)
|
||||
|
||||
organization = user_settings.default_organization.id
|
||||
|
||||
|
||||
elif (
|
||||
self.action == 'create'
|
||||
):
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 15:27
|
||||
# Generated by Django 5.1.2 on 2024-12-06 06:47
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
@ -9,11 +9,52 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0003_alter_organization_id_alter_organization_manager_and_more'),
|
||||
('itam', '0014_alter_softwarecategory_options'),
|
||||
('access', '0002_alter_organization_options_alter_team_options_and_more'),
|
||||
('core', '0007_alter_history_options_alter_manufacturer_options_and_more'),
|
||||
('itam', '0004_alter_deviceoperatingsystem_device_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='device',
|
||||
options={'ordering': ['name', 'organization'], 'verbose_name': 'Device', 'verbose_name_plural': 'Devices'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='devicemodel',
|
||||
options={'ordering': ['manufacturer', 'name'], 'verbose_name': 'Device Model', 'verbose_name_plural': 'Device Models'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='deviceoperatingsystem',
|
||||
options={'ordering': ['device'], 'verbose_name': 'Device Operating System', 'verbose_name_plural': 'Device Operating Systems'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='devicesoftware',
|
||||
options={'ordering': ['-action', 'software'], 'verbose_name': 'Device Software', 'verbose_name_plural': 'Device Softwares'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='devicetype',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Device Type', 'verbose_name_plural': 'Device Types'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='operatingsystem',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Operating System', 'verbose_name_plural': 'Operating Systems'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='operatingsystemversion',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Operating System Version', 'verbose_name_plural': 'Operating System Versions'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='software',
|
||||
options={'ordering': ['name', 'publisher__name'], 'verbose_name': 'Software', 'verbose_name_plural': 'Softwares'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='softwarecategory',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Software Category', 'verbose_name_plural': 'Software Categories'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='softwareversion',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Software Version', 'verbose_name_plural': 'Software Versions'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='device_model',
|
||||
@ -52,7 +93,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicemodel',
|
||||
@ -82,12 +123,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='devicemodel',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='deviceoperatingsystem',
|
||||
name='device',
|
||||
field=models.ForeignKey(help_text='Device for the Operating System', on_delete=django.db.models.deletion.CASCADE, to='itam.device', verbose_name='Device'),
|
||||
field=models.ForeignKey(help_text='Device for the Operating System', on_delete=django.db.models.deletion.CASCADE, to='itam.device', unique=True, verbose_name='Device'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='deviceoperatingsystem',
|
||||
@ -117,13 +158,18 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='deviceoperatingsystem',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='deviceoperatingsystem',
|
||||
name='version',
|
||||
field=models.CharField(help_text='Version detected as installed', max_length=15, verbose_name='Installed Version'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='action',
|
||||
field=models.IntegerField(blank=True, choices=[(1, 'Install'), (0, 'Remove')], default=None, help_text='Action to perform', null=True, verbose_name='Action'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='device',
|
||||
@ -134,6 +180,11 @@ class Migration(migrations.Migration):
|
||||
name='id',
|
||||
field=models.AutoField(help_text='ID of this item', primary_key=True, serialize=False, unique=True, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='installed',
|
||||
field=models.DateTimeField(blank=True, help_text='Date detected as installed', null=True, verbose_name='Date Installed'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='installedversion',
|
||||
@ -152,13 +203,18 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='software',
|
||||
field=models.ForeignKey(help_text='Software Name', on_delete=django.db.models.deletion.CASCADE, to='itam.software', verbose_name='Software'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='version',
|
||||
field=models.ForeignKey(blank=True, default=None, help_text='Version to install', null=True, on_delete=django.db.models.deletion.CASCADE, to='itam.softwareversion', verbose_name='Desired Version'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicetype',
|
||||
name='id',
|
||||
@ -182,7 +238,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='devicetype',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operatingsystem',
|
||||
@ -207,7 +263,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='operatingsystem',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operatingsystem',
|
||||
@ -237,12 +293,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='operatingsystemversion',
|
||||
name='operating_system',
|
||||
field=models.ForeignKey(help_text='Operating system this version applies to', on_delete=django.db.models.deletion.CASCADE, to='itam.operatingsystem', verbose_name='Operaating System'),
|
||||
field=models.ForeignKey(help_text='Operating system this version applies to', on_delete=django.db.models.deletion.CASCADE, to='itam.operatingsystem', verbose_name='Operating System'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operatingsystemversion',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='software',
|
||||
@ -272,7 +328,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='software',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='software',
|
||||
@ -302,7 +358,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='softwarecategory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='softwareversion',
|
||||
@ -327,7 +383,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='softwareversion',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='softwareversion',
|
@ -1,34 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-11 16:03
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0004_alter_deviceoperatingsystem_device_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='action',
|
||||
field=models.CharField(blank=True, choices=[('1', 'Install'), ('0', 'Remove')], default=None, help_text='Action to perform', max_length=1, null=True, verbose_name='Action'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='installed',
|
||||
field=models.DateTimeField(blank=True, help_text='Date detected as installed', null=True, verbose_name='Date Installed'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='installedversion',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='installedversion', to='itam.softwareversion', verbose_name='Installed Version'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='version',
|
||||
field=models.ForeignKey(blank=True, default=None, help_text='Version to install', null=True, on_delete=django.db.models.deletion.CASCADE, to='itam.softwareversion', verbose_name='Desired Version'),
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 06:42
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0005_alter_devicesoftware_action_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='device',
|
||||
options={'ordering': ['name', 'organization'], 'verbose_name': 'Device', 'verbose_name_plural': 'Devices'},
|
||||
),
|
||||
]
|
@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.1.2 on 2024-12-06 07:09
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0005_alter_device_options_alter_devicemodel_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='deviceoperatingsystem',
|
||||
name='device',
|
||||
field=models.OneToOneField(help_text='Device for the Operating System', on_delete=django.db.models.deletion.CASCADE, to='itam.device', verbose_name='Device'),
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 07:26
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0006_alter_device_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='devicemodel',
|
||||
options={'ordering': ['manufacturer', 'name'], 'verbose_name': 'Device Model', 'verbose_name_plural': 'Device Models'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 07:33
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0007_alter_devicemodel_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='deviceoperatingsystem',
|
||||
options={'ordering': ['device'], 'verbose_name': 'Device Operating System', 'verbose_name_plural': 'Device Operating Systems'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 07:39
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0008_alter_deviceoperatingsystem_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='devicesoftware',
|
||||
options={'ordering': ['-action', 'software'], 'verbose_name': 'Device Software', 'verbose_name_plural': 'Device Softwares'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 07:42
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0009_alter_devicesoftware_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='devicetype',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Device Type', 'verbose_name_plural': 'Device Types'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 07:51
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0010_alter_devicetype_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='operatingsystem',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Operating System', 'verbose_name_plural': 'Operating Systems'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 07:57
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0011_alter_operatingsystem_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='operatingsystemversion',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Operating System Version', 'verbose_name_plural': 'Operating System Versions'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 08:06
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0012_alter_operatingsystemversion_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='software',
|
||||
options={'ordering': ['name', 'publisher__name'], 'verbose_name': 'Software', 'verbose_name_plural': 'Softwares'},
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 08:15
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0013_alter_software_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='softwarecategory',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Software Category', 'verbose_name_plural': 'Software Categories'},
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-17 03:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0015_alter_device_device_model_alter_device_device_type_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='action',
|
||||
field=models.IntegerField(blank=True, choices=[(1, 'Install'), (0, 'Remove')], default=None, help_text='Action to perform', null=True, verbose_name='Action'),
|
||||
),
|
||||
]
|
@ -1,17 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-20 07:26
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0016_alter_devicesoftware_action'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='softwareversion',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Software Version', 'verbose_name_plural': 'Software Versions'},
|
||||
),
|
||||
]
|
@ -1,71 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-20 02:43
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0006_alter_team_organization'),
|
||||
('itam', '0017_alter_softwareversion_options'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='device',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicemodel',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='deviceoperatingsystem',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicesoftware',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicetype',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operatingsystem',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operatingsystemversion',
|
||||
name='operating_system',
|
||||
field=models.ForeignKey(help_text='Operating system this version applies to', on_delete=django.db.models.deletion.CASCADE, to='itam.operatingsystem', verbose_name='Operating System'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='operatingsystemversion',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='software',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='softwarecategory',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='softwareversion',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-20 02:43
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itam', '0018_alter_device_organization_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='deviceoperatingsystem',
|
||||
name='device',
|
||||
field=models.ForeignKey(help_text='Device for the Operating System', on_delete=django.db.models.deletion.CASCADE, to='itam.device', unique=True, verbose_name='Device'),
|
||||
),
|
||||
]
|
@ -116,12 +116,14 @@ class Device(DeviceCommonFieldsName, SaveHistory):
|
||||
|
||||
def validate_config_keys_not_reserved(self):
|
||||
|
||||
value: dict = self
|
||||
if self:
|
||||
|
||||
for invalid_key in Device.reserved_config_keys:
|
||||
value: dict = self
|
||||
|
||||
if invalid_key in value.keys():
|
||||
raise ValidationError(f'json key "{invalid_key}" is a reserved configuration key')
|
||||
for invalid_key in Device.reserved_config_keys:
|
||||
|
||||
if invalid_key in value.keys():
|
||||
raise ValidationError(f'json key "{invalid_key}" is a reserved configuration key')
|
||||
|
||||
|
||||
def validate_uuid_format(self):
|
||||
@ -660,7 +662,7 @@ class DeviceOperatingSystem(DeviceCommonFields, SaveHistory):
|
||||
verbose_name_plural = 'Device Operating Systems'
|
||||
|
||||
|
||||
device = models.ForeignKey(
|
||||
device = models.OneToOneField(
|
||||
Device,
|
||||
blank = False,
|
||||
help_text = 'Device for the Operating System',
|
||||
|
@ -6,9 +6,10 @@ from django.shortcuts import reverse
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from access.models import Organization, Team, TeamUsers, Permission
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
from itam.models.device import Device
|
||||
|
||||
@ -198,4 +199,17 @@ class DeviceViewSet(
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class DeviceMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'itam'
|
||||
|
||||
menu_entry_id = 'device'
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itam.models.device import DeviceModel
|
||||
|
||||
@ -199,3 +200,13 @@ class DeviceModelViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class DeviceModelMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itam.serializers.device_operating_system import Device, DeviceOperatingSystem, DeviceOperatingSystemModelSerializer
|
||||
from itam.models.operating_system import OperatingSystem, OperatingSystemVersion
|
||||
@ -257,3 +258,13 @@ class DeviceOperatingViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class DeviceOperatingMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itam.models.device import DeviceType
|
||||
|
||||
@ -198,4 +199,14 @@ class DeviceTypeViewSet(
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class DeviceTypeMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissionView
|
||||
from api.tests.abstract.api_serializer_viewset import SerializerView
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itam.serializers.device_operating_system import Device, DeviceOperatingSystem, DeviceOperatingSystemModelSerializer
|
||||
from itam.models.operating_system import OperatingSystem, OperatingSystemVersion
|
||||
@ -180,3 +181,13 @@ class OperatingSystemInstallsViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class OperatingSystemInstallsMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itam.models.device import Device, DeviceSoftware
|
||||
from itam.models.software import Software
|
||||
@ -228,4 +229,14 @@ class SoftwareInstallsViewSet(
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class SoftwareInstallsMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
from itam.models.operating_system import OperatingSystem
|
||||
|
||||
@ -198,4 +199,17 @@ class OperatingSystemViewSet(
|
||||
TestCase,
|
||||
):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class OperatingSystemMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'itam'
|
||||
|
||||
menu_entry_id = 'operating_system'
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itam.models.operating_system import OperatingSystem, OperatingSystemVersion
|
||||
|
||||
@ -205,3 +206,13 @@ class OperatingSystemVersionPermissionsAPI(ViewSetBase, APIPermissions, TestCase
|
||||
class OperatingSystemVersionViewSetBase(ViewSetBase, SerializersTestCases, TestCase):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class OperatingSystemVersionMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
from itam.models.software import Software
|
||||
|
||||
@ -191,3 +192,16 @@ class SoftwarePermissionsAPI(ViewSetBase, APIPermissions, TestCase):
|
||||
class SoftwareViewSet(ViewSetBase, SerializersTestCases, TestCase):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class SoftwareMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'itam'
|
||||
|
||||
menu_entry_id = 'software'
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itam.models.software import SoftwareCategory
|
||||
|
||||
@ -190,4 +191,14 @@ class SoftwareCategoryPermissionsAPI(ViewSetBase, APIPermissions, TestCase):
|
||||
|
||||
class SoftwareCategoryViewSet(ViewSetBase, SerializersTestCases, TestCase):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class SoftwareCategoryMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itam.models.software import Software, SoftwareVersion
|
||||
|
||||
@ -203,4 +204,14 @@ class SoftwareVersionPermissionsAPI(ViewSetBase, APIPermissions, TestCase):
|
||||
|
||||
class SoftwareVersionViewSet(ViewSetBase, SerializersTestCases, TestCase):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class SoftwareVersionMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 15:27
|
||||
# Generated by Django 5.1.2 on 2024-12-06 06:47
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
@ -8,11 +8,15 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0003_alter_organization_id_alter_organization_manager_and_more'),
|
||||
('access', '0002_alter_organization_options_alter_team_options_and_more'),
|
||||
('itim', '0004_alter_service_config_key_variable'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='port',
|
||||
options={'ordering': ['number', 'protocol'], 'verbose_name': 'Port', 'verbose_name_plural': 'Ports'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cluster',
|
||||
name='cluster_type',
|
||||
@ -36,7 +40,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='cluster',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cluster',
|
||||
@ -61,7 +65,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='clustertype',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='port',
|
||||
@ -81,7 +85,12 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='port',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='port',
|
||||
name='protocol',
|
||||
field=models.CharField(choices=[('TCP', 'TCP'), ('UDP', 'UDP')], help_text='Layer 4 Network Protocol', max_length=3, verbose_name='Protocol'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='service',
|
||||
@ -101,6 +110,6 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='service',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
@ -1,22 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-21 11:34
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('itim', '0005_alter_cluster_cluster_type_alter_cluster_id_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='port',
|
||||
options={'ordering': ['number', 'protocol'], 'verbose_name': 'Port', 'verbose_name_plural': 'Ports'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='port',
|
||||
name='protocol',
|
||||
field=models.CharField(choices=[('TCP', 'TCP'), ('UDP', 'UDP')], help_text='Layer 4 Network Protocol', max_length=3, verbose_name='Protocol'),
|
||||
),
|
||||
]
|
@ -1,36 +0,0 @@
|
||||
# Generated by Django 5.1.2 on 2024-11-20 02:41
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0006_alter_team_organization'),
|
||||
('itim', '0006_alter_port_options_alter_port_protocol'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='cluster',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='clustertype',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='port',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='service',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
from itim.models.clusters import Cluster
|
||||
|
||||
@ -190,4 +191,17 @@ class ClusterPermissionsAPI(ViewSetBase, APIPermissions, TestCase):
|
||||
|
||||
class ClusterViewSet(ViewSetBase, SerializersTestCases, TestCase):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ClusterMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'itim'
|
||||
|
||||
menu_entry_id = 'cluster'
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itim.models.clusters import ClusterType
|
||||
|
||||
@ -191,4 +192,14 @@ class ClusterTypePermissionsAPI(ViewSetBase, APIPermissions, TestCase):
|
||||
|
||||
class ClusterTypeViewSet(ViewSetBase, SerializersTestCases, TestCase):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ClusterTypeMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional
|
||||
|
||||
from itim.models.services import Port
|
||||
|
||||
@ -193,4 +194,14 @@ class PortPermissionsAPI(ViewSetBase, APIPermissions, TestCase):
|
||||
|
||||
class PortViewSet(ViewSetBase, SerializersTestCases, TestCase):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class PortMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from access.models import Organization, Team, TeamUsers, Permission
|
||||
|
||||
from api.tests.abstract.api_permissions_viewset import APIPermissions
|
||||
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
from itam.models.device import Device
|
||||
|
||||
@ -212,4 +213,17 @@ class ServicePermissionsAPI(ViewSetBase, APIPermissions, TestCase):
|
||||
|
||||
class ServiceViewSet(ViewSetBase, SerializersTestCases, TestCase):
|
||||
|
||||
pass
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ServiceMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'itim'
|
||||
|
||||
menu_entry_id = 'service'
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from core.tests.abstract.test_ticket_viewset import Ticket, TicketViewSetBase, TicketViewSetPermissionsAPI, TicketViewSet
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
|
||||
class ViewSetBase( TicketViewSetBase ):
|
||||
@ -28,3 +29,16 @@ class TicketChangeViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TicketChangeMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'itim'
|
||||
|
||||
menu_entry_id = 'ticket_change'
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from core.tests.abstract.test_ticket_viewset import Ticket, TicketViewSetBase, TicketViewSetPermissionsAPI, TicketViewSet
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
|
||||
class ViewSetBase( TicketViewSetBase ):
|
||||
@ -28,3 +29,16 @@ class TicketIncidentViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TicketIncidentMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'itim'
|
||||
|
||||
menu_entry_id = 'ticket_incident'
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from core.tests.abstract.test_ticket_viewset import Ticket, TicketViewSetBase, TicketViewSetPermissionsAPI, TicketViewSet
|
||||
from api.tests.abstract.test_metadata_functional import MetadataAttributesFunctional, MetaDataNavigationEntriesFunctional
|
||||
|
||||
|
||||
class ViewSetBase( TicketViewSetBase ):
|
||||
@ -28,3 +29,16 @@ class TicketProblemViewSet(
|
||||
):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class TicketProblemMetadata(
|
||||
ViewSetBase,
|
||||
MetadataAttributesFunctional,
|
||||
MetaDataNavigationEntriesFunctional,
|
||||
TestCase
|
||||
):
|
||||
|
||||
menu_id = 'itim'
|
||||
|
||||
menu_entry_id = 'ticket_problem'
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.2 on 2024-10-13 15:27
|
||||
# Generated by Django 5.1.2 on 2024-12-06 06:47
|
||||
|
||||
import access.models
|
||||
import django.db.models.deletion
|
||||
@ -9,7 +9,6 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0003_alter_organization_id_alter_organization_manager_and_more'),
|
||||
('project_management', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
@ -48,7 +47,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='project',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='projectmilestone',
|
||||
@ -68,7 +67,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='projectmilestone',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='projectstate',
|
||||
@ -83,7 +82,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='projectstate',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='projecttype',
|
||||
@ -98,6 +97,6 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='projecttype',
|
||||
name='organization',
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
field=models.ForeignKey(help_text='Organization this belongs to', on_delete=django.db.models.deletion.CASCADE, to='access.organization', validators=[access.models.TenancyObject.validatate_organization_exists], verbose_name='Organization'),
|
||||
),
|
||||
]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user