Compare commits

...

907 Commits

Author SHA1 Message Date
Jon
1b338e4c19 Merge pull request #938 from nofusscomputing/project_management-refactor-tests 2025-08-04 17:25:17 +09:30
Jon
f525411ace refactor(test): remove xfail during pytest_generate_tests before parameterizing
ref: #938
2025-08-04 16:58:17 +09:30
Jon
f5f4eb3ff2 refactor(project_management): ensure within fixtur kwargs are copied
ref: #938 #937
2025-08-04 16:38:26 +09:30
Jon
b7c68694a6 refactor(project_management): Remove old test suites no longer required model ProjectType
ref: #938 closes #937
2025-08-04 16:10:06 +09:30
Jon
363d044851 refactor(project_management): ViewSet Unit Test Suite re-written to Pytest for model ProjectType
ref: #938 #937
2025-08-04 16:09:58 +09:30
Jon
b66adb2ebe refactor(project_management): Serializer Unit Test Suite re-written to Pytest for model ProjectType
ref: #938 #937
2025-08-04 16:09:50 +09:30
Jon
4037127c39 refactor(project_management): API Fields render Functional Test Suite re-written to Pytest for model ProjectType
ref: #938 #937
2025-08-04 16:09:36 +09:30
Jon
1640910305 refactor(project_management): Model Functional Test Suite re-written to Pytest for model ProjectType
ref: #938 #937
2025-08-04 16:09:26 +09:30
Jon
d0effd582a refactor(project_management): API Metadata Functional Test Suite re-written to Pytest for model ProjectType
ref: #938 #937
2025-08-04 16:09:16 +09:30
Jon
ad175f4f7d refactor(project_management): Remove old test suites no longer required model ProjectState
ref: #938 closes #936
2025-08-04 15:46:00 +09:30
Jon
6dc42d4cdb refactor(project_management): ViewSet Unit Test Suite re-written to Pytest for model ProjectState
ref: #938 #936
2025-08-04 15:45:51 +09:30
Jon
3f08bf532f refactor(project_management): Serializer Unit Test Suite re-written to Pytest for model ProjectState
ref: #938 #936
2025-08-04 15:45:30 +09:30
Jon
9cde656450 refactor(project_management): API Fields render Functional Test Suite re-written to Pytest for model ProjectState
ref: #938 #936
2025-08-04 15:45:12 +09:30
Jon
62da0f8c7a refactor(project_management): Model Functional Test Suite re-written to Pytest for model ProjectState
ref: #938 #936
2025-08-04 15:45:02 +09:30
Jon
4045f0cffb refactor(project_management): API Metadata Functional Test Suite re-written to Pytest for model ProjectState
ref: #938 #936
2025-08-04 15:44:44 +09:30
Jon
6eb4cb12ba refactor(project_management): Remove old test suites no longer required model ProjectMilestone
ref: #938 closes #935
2025-08-04 14:58:45 +09:30
Jon
2d720032f6 refactor(project_management): ViewSet Unit Test Suite re-written to Pytest for model ProjectMilestone
ref: #938 #935
2025-08-04 14:58:34 +09:30
Jon
bb7cf9d462 refactor(project_management): Serializer Unit Test Suite re-written to Pytest for model ProjectMilestone
ref: #938 #935
2025-08-04 14:58:17 +09:30
Jon
d53eb7101d refactor(project_management): API Fields render Functional Test Suite re-written to Pytest for model ProjectMilestone
ref: #938 #935
2025-08-04 14:57:57 +09:30
Jon
0edfaef79a refactor(project_management): Model Functional Test Suite re-written to Pytest for model ProjectMilestone
ref: #938 #934
2025-08-04 14:57:32 +09:30
Jon
0c508a7e0b refactor(project_management): API Metadata Functional Test Suite re-written to Pytest for model ProjectMilestone
ref: #938 #935
2025-08-04 14:57:22 +09:30
Jon
2bdb12ed7a refactor(project_management): Remove old test suites no longer required model Project
ref: #938 closes #934
2025-08-04 14:21:04 +09:30
Jon
187f82feaf refactor(project_management): ViewSet Unit Test Suite re-written to Pytest for model Project
ref: #938 #934
2025-08-04 14:20:07 +09:30
Jon
91082b205d refactor(project_management): Serializer Unit Test Suite re-written to Pytest for model Project
ref: #938 #934
2025-08-04 14:19:47 +09:30
Jon
b7d190218c refactor(project_management): API Fields render Functional Test Suite re-written to Pytest for model Project
ref: #938 #934
2025-08-04 14:19:24 +09:30
Jon
2daf7dbb27 refactor(project_management): Model Functional Test Suite re-written to Pytest for model Project
ref: #938 #934
2025-08-04 14:19:01 +09:30
Jon
f98d2f2884 refactor(project_management): API Metadata Functional Test Suite re-written to Pytest for model Project
ref: #938 #934
2025-08-04 14:18:35 +09:30
Jon
fa0b703877 Merge pull request #932 from nofusscomputing/refactor-itim-tests 2025-08-03 15:02:19 +09:30
Jon
1b7d92e300 fix(itim): Ensure during testing, fixture vals are copied for Model Service
ref: #932 #931
2025-08-03 14:34:18 +09:30
Jon
697d375d06 refactor(itim): Remove old test suites no longer required model Service
ref: #932 closes #931
2025-08-03 14:06:00 +09:30
Jon
3726f3aee9 refactor(itim): ViewSet Unit Test Suite re-written to Pytest for model Service
ref: #932 #931
2025-08-03 14:05:52 +09:30
Jon
28cd56d9a0 refactor(itim): Serializer Unit Test Suite re-written to Pytest for model Service
ref: #932 #931
2025-08-03 14:05:39 +09:30
Jon
017f5de78a refactor(itim): API Fields render Functional Test Suite re-written to Pytest for model Service
ref: #932 #931
2025-08-03 14:05:17 +09:30
Jon
d8fa00b530 refactor(itim): Model Functional Test Suite re-written to Pytest for model Service
ref: #932 #931
2025-08-03 14:05:05 +09:30
Jon
3765113445 refactor(itim): API Metadata Functional Test Suite re-written to Pytest for model Service
ref: #932 #931
2025-08-03 14:04:57 +09:30
Jon
8f1a9966e9 refactor(itim): Remove old test suites no longer required model Port
ref: #932 closes #930
2025-08-03 12:41:00 +09:30
Jon
e3f6b3f9ad refactor(itim): ViewSet Unit Test Suite re-written to Pytest for model Port
ref: #932 #930
2025-08-03 12:40:50 +09:30
Jon
422acd64fa refactor(itim): Serializer Unit Test Suite re-written to Pytest for model Port
ref: #932 #930
2025-08-03 12:40:39 +09:30
Jon
dc01c6b0f9 refactor(itim): API Fields render Functional Test Suite re-written to Pytest for model Port
ref: #932 #930
2025-08-03 12:40:25 +09:30
Jon
e24a135616 refactor(itim): Model Functional Test Suite re-written to Pytest for model Port
ref: #932 #930
2025-08-03 12:40:12 +09:30
Jon
6f82a054cd refactor(itim): API Metadata Functional Test Suite re-written to Pytest for model Port
ref: #932 #930
2025-08-03 12:40:02 +09:30
Jon
ecafbcf830 refactor(itim): Remove old test suites no longer required model ClusterType
ref: #932 closes #929
2025-08-03 11:55:10 +09:30
Jon
1c8f641dd4 refactor(itim): ViewSet Unit Test Suite re-written to Pytest for model ClusterType
ref: #932 #929
2025-08-03 11:55:00 +09:30
Jon
a3f4299299 refactor(itim): Serializer Unit Test Suite re-written to Pytest for model ClusterType
ref: #932 #929
2025-08-03 11:54:44 +09:30
Jon
173a47d942 refactor(itim): API Fields render Functional Test Suite re-written to Pytest for model ClusterType
ref: #932 #929
2025-08-03 11:54:32 +09:30
Jon
24c4607c2d refactor(itim): Model Functional Test Suite re-written to Pytest for model ClusterType
ref: #932 #929
2025-08-03 11:54:19 +09:30
Jon
d68afd8992 refactor(itim): API Metadata Functional Test Suite re-written to Pytest for model ClusterType
ref: #932 #929
2025-08-03 11:54:05 +09:30
Jon
38c9cccf30 refactor(itim): Remove old test suites no longer required model Cluster
ref: #932 closes #928
2025-08-03 11:32:08 +09:30
Jon
c2344e95c5 refactor(itim): ViewSet Unit Test Suite re-written to Pytest for model Cluster
ref: #932 #928
2025-08-03 11:31:46 +09:30
Jon
6c1542f572 refactor(itim): Serializer Unit Test Suite re-written to Pytest for model Cluster
ref: #932 #928
2025-08-03 11:31:19 +09:30
Jon
10550495d8 refactor(itim): API Fields render Functional Test Suite re-written to Pytest for model Cluster
ref: #932 #928
2025-08-03 11:30:39 +09:30
Jon
d241a9a683 refactor(itim): Model Functional Test Suite re-written to Pytest for model Cluster
ref: #932 #928
2025-08-03 11:28:25 +09:30
Jon
1b8be14f12 refactor(itim): API Metadata Functional Test Suite re-written to Pytest for model Cluster
ref: #932 #928
2025-08-03 11:27:30 +09:30
Jon
4c49bb0bd2 Merge pull request #925 from nofusscomputing/refactor-itam-tests 2025-08-02 12:44:27 +09:30
Jon
6578d67250 refactor(itam): Remove old test suites no longer required model SoftwareVersion
ref: #925 closes #927
2025-08-02 12:15:54 +09:30
Jon
0f9cbfdc13 refactor(itam): ViewSet Unit Test Suite re-written to Pytest for model SoftwareVersion
ref: #925 #927
2025-08-02 12:15:45 +09:30
Jon
fc984c5034 refactor(itam): Serializer Unit Test Suite re-written to Pytest for model SoftwareVersion
ref: #925 #927
2025-08-02 12:15:34 +09:30
Jon
7d47a9ca49 refactor(itam): Model Functional Test Suite re-written to Pytest for model SoftwareVersion
ref: #925 #927
2025-08-02 12:15:03 +09:30
Jon
2890750d50 refactor(itam): API Fields render Functional Test Suite re-written to Pytest for model SoftwareVersion
ref: #925 #927
2025-08-02 12:14:52 +09:30
Jon
c1b44c03fe refactor(itam): API Metadata Functional Test Suite re-written to Pytest for model SoftwareVersion
ref: #925 #927
2025-08-02 12:14:35 +09:30
Jon
207ba2285a refactor(itam): Remove old test suites no longer required model SoftwareCategory
ref: #925 closes #926
2025-08-02 12:13:56 +09:30
Jon
dd337b68bc refactor(itam): ViewSet Unit Test Suite re-written to Pytest for model SoftwareCategory
ref: #925 #926
2025-08-02 12:13:44 +09:30
Jon
42e191ba76 refactor(itam): Serializer Unit Test Suite re-written to Pytest for model SoftwareCategory
ref: #925 #926
2025-08-02 12:13:26 +09:30
Jon
dfb1af1ff7 refactor(itam): Model Functional Test Suite re-written to Pytest for model SoftwareCategory
ref: #925 #926
2025-08-02 12:10:43 +09:30
Jon
df8265dd55 refactor(itam): API Fields render Functional Test Suite re-written to Pytest for model SoftwareCategory
ref: #925 #926
2025-08-02 12:10:30 +09:30
Jon
e14780eb22 refactor(itam): API Metadata Functional Test Suite re-written to Pytest for model SoftwareCategory
ref: #925 #926
2025-08-02 12:10:20 +09:30
Jon
9104cd021f refactor(itam): Remove old test suites no longer required model Software
ref: #925 closes #924
2025-08-02 11:33:04 +09:30
Jon
5db10a4b6d refactor(itam): ViewSet Unit Test Suite re-written to Pytest for model Software
ref: #925 #924
2025-08-02 11:32:55 +09:30
Jon
6faa185406 refactor(itam): Serializer Unit Test Suite re-written to Pytest for model Software
ref: #925 #924
2025-08-02 11:32:44 +09:30
Jon
7fb56d87d6 refactor(itam): Model Functional Test Suite re-written to Pytest for model Software
ref: #925 #924
2025-08-02 11:32:26 +09:30
Jon
cf09a15690 refactor(itam): API Fields render Functional Test Suite re-written to Pytest for model Software
ref: #925 #924
2025-08-02 11:32:16 +09:30
Jon
76dfcb8bce refactor(itam): API Metadata Functional Test Suite re-written to Pytest for model Software
ref: #925 #924
2025-08-02 11:31:59 +09:30
Jon
430cbe6385 refactor(itam): Remove old test suites no longer required model OperatingSystemVersion
ref: #925 closes #923
2025-08-02 11:04:22 +09:30
Jon
bcce98e884 refactor(itam): ViewSet Unit Test Suite re-written to Pytest for model OperatingSystemVersion
ref: #925 #923
2025-08-02 11:04:06 +09:30
Jon
66706df727 refactor(itam): Serializer Unit Test Suite re-written to Pytest for model OperatingSystemVersion
ref: #925 #923
2025-08-02 11:03:49 +09:30
Jon
838bc871c1 refactor(itam): Model Functional Test Suite re-written to Pytest for model OperatingSystemVersion
ref: #925 #923
2025-08-02 11:03:26 +09:30
Jon
69f1c1c3b6 refactor(itam): API Fields render Functional Test Suite re-written to Pytest for model OperatingSystemVersion
ref: #925 #923
2025-08-02 11:03:12 +09:30
Jon
8d0d9240a8 refactor(itam): API Metadata Functional Test Suite re-written to Pytest for model OperatingSystemVersion
ref: #925 #923
2025-08-02 11:02:42 +09:30
Jon
d92f967bb9 refactor(itam): Remove old test suites no longer required model OperatingSystem
ref: #925 closes #922
2025-08-02 10:29:59 +09:30
Jon
7413a5686d refactor(itam): ViewSet Unit Test Suite re-written to Pytest for model OperatingSystem
ref: #925 #922
2025-08-02 10:25:45 +09:30
Jon
3d4018e306 refactor(itam): Serializer Unit Test Suite re-written to Pytest for model OperatingSystem
ref: #925 #922
2025-08-02 10:25:31 +09:30
Jon
93dc76fc1a refactor(itam): Model Functional Test Suite re-written to Pytest for model OperatingSystem
ref: #925 #922
2025-08-02 10:25:11 +09:30
Jon
f461b7500f refactor(itam): API Fields render Functional Test Suite re-written to Pytest for model OperatingSystem
ref: #925 #922
2025-08-02 10:24:59 +09:30
Jon
4b1548afa8 refactor(itam): API Metadata Functional Test Suite re-written to Pytest for model OperatingSystem
ref: #925 #922
2025-08-02 10:24:13 +09:30
Jon
3fa8bdf468 Merge pull request #920 from nofusscomputing/itam-test-refactor 2025-07-31 13:55:59 +09:30
Jon
8363c50b91 chore(itam): correct field type for Model Unit test suite for model DeviceType
ref: #920 closes #919
2025-07-31 13:29:10 +09:30
Jon
3bd673b2ae refactor(itam): API Metadata Functional Test Suite re-written to Pytest for model DeviceType
ref: #920 #919
2025-07-31 13:28:26 +09:30
Jon
e9bc7e543a refactor(itam): Model Functional Test Suite re-written to Pytest for model DeviceType
ref: #920 #919
2025-07-31 13:28:01 +09:30
Jon
20694b950a refactor(itam): API Fields render Test Suite re-written to Pytest for model DeviceType
ref: #920 #919
2025-07-31 13:27:42 +09:30
Jon
095deacf65 test(itam): ViewSet Unit Test Suite added for model DeviceType
ref: #920 #919
2025-07-31 13:27:10 +09:30
Jon
5e1ebc949e refactor(itam): Serializer Unit Test Suite re-written to Pytest for model DeviceType
ref: #920 #919
2025-07-31 13:25:50 +09:30
Jon
9b3340f44c refactor(itam): ViewSet Unit Test Suite re-written to Pytest for model DeviceModel
ref: #920 closes #916
2025-07-31 12:54:48 +09:30
Jon
c93dbf48c9 test(itam): Serializer UnitTest Suite added for model DeviceModel
ref: #920 #916
2025-07-31 12:51:04 +09:30
Jon
6414f70468 refactor(itam): API Metadata Functional Test Suite re-written to Pytest for model DeviceModel
ref: #920 #916
2025-07-31 12:48:05 +09:30
Jon
9e24bf4eed test(itam): API Fields render Functional Test Suite added for model DeviceModel
ref: #920 #916
2025-07-31 12:47:17 +09:30
Jon
565996bc2a test(itam): Model Functional Test Suite added for model DeviceModel
ref: #920 #916
2025-07-31 12:46:55 +09:30
Jon
3bc35777ca test(itam): Refactor failing tests to cater for uniqueness so they pass
ref: #920 #915
2025-07-31 12:46:25 +09:30
Jon
0bc313c198 test(itam): Model Functional Test Suite aded for model Device
ref: #920 closes #915
2025-07-31 11:55:22 +09:30
Jon
ff1085df24 refactor(itam): API Field Render Functional Test Suite re-written to PyTest for model Device
ref: #920 #915
2025-07-31 11:54:50 +09:30
Jon
b6743ebe4c refactor(itam): Metadate Functional Test Suite re-enabled for model Device
ref: #920 #915
2025-07-31 11:34:18 +09:30
Jon
701193ea82 refactor(itam): Viewset Unit Test Suite re-written to pytest for model Device
ref: #920 #915
2025-07-31 11:27:41 +09:30
Jon
55408f1280 refactor(itam): Serializer Unit Test Suite re-enabled for model Device
ref: #920 #915
2025-07-31 11:27:10 +09:30
Jon
b84c3d1b14 chore(itam): clean old test suite no longer used
ref: #920 #915
2025-07-31 11:25:28 +09:30
Jon
b0597d354a Merge pull request #908 from nofusscomputing/config_management-refactor-tests 2025-07-30 10:27:34 +09:30
Jon
c32cc6c954 refactor(core): API Render Unit Test Suite re-enabled for model Manufacturer
ref: #908 #911 #914
2025-07-30 10:02:15 +09:30
Jon
b84571bd44 refactor(core): API Metadata Functional Test Suite re-enabled for model Manufacturer
ref: #908 #911 #914
2025-07-30 10:01:49 +09:30
Jon
3a5630995b refactor(core): Serializer Functional Test Suite re-enabled for model Manufacturer
ref: #908 #911 #914
2025-07-30 10:01:30 +09:30
Jon
ee5055950d refactor(core): ViewSet Test Suite re-written to pytest for model Manufacturer
ref: #908 #911 #914
2025-07-30 10:00:46 +09:30
Jon
9e6322b5f1 refactor(config_management): ViewSet Test Suite re-written to pytest for model ConfigGroupSoftware
ref: #908 #907
2025-07-30 09:15:01 +09:30
Jon
a805660f0f refactor(config_management): API fields Test Suite re-enalbed for model ConfigGroupSoftware
ref: #908 #907
2025-07-30 09:00:10 +09:30
Jon
7bce005a05 refactor(config_management): API Metadata Functional Test Suite for model ConfigGroupSoftware
ref: #908 #907
2025-07-30 08:59:07 +09:30
Jon
811c92ada6 refactor(config_management): Serializer Functional Test Suite Enabled for model ConfigGroupSoftware
ref: #908 #907
2025-07-30 08:58:34 +09:30
Jon
e3b9cba23c refactor(config_management): Model Unit Test Suite re-written to pytest for model ConfigGroup
ref: #908 closes #905
2025-07-30 08:27:50 +09:30
Jon
6f58f2985c test(config_management): ViewSet Unit Test Suite re-written to pytest for model ConfigGroup
ref: #908 #905
2025-07-30 08:27:02 +09:30
Jon
98891be181 test(config_management): Serializer Unit Test Suite re-written to pytest for model ConfigGroup
ref: #908 #905
2025-07-30 08:26:06 +09:30
Jon
bb93b4ebed test(config_management): Model Functional Test Suite re-written to pytest for model ConfigGroup
ref: #908 #905
2025-07-30 08:25:44 +09:30
Jon
a82ff5a41f refactor(config_management): API Metadata Functional Test Suite re-written to pytest for model ConfigGroup
ref: #908 #905
2025-07-30 08:25:15 +09:30
Jon
224a69319e test(config_management): API Field Render Functional Test Suite re-written to pytest for model ConfigGroup
ref: #908 #905
2025-07-30 08:24:09 +09:30
Jon
854b295807 Merge pull request #904 from nofusscomputing/assistance-refactor-tests 2025-07-29 16:26:33 +09:30
Jon
fc0b645d2d test(assistance): API Field Render Functional Test Suite re-written to pytest for model KnowledgeBaseCategory
ref: #904 closes #901
2025-07-29 16:01:17 +09:30
Jon
4b5caad7d5 refactor(assistance): Serializer Unit Test Suite re-written to pytest for model KnowledgeBase
ref: #904 closes #900
2025-07-29 15:47:51 +09:30
Jon
5f5d7923c6 chore(bae): Dont create model if abstract for functional model test suite
ref: #904
2025-07-29 15:31:09 +09:30
Jon
099c70d466 test(assistance): Model Functional Test Suite re-written to pytest for model KnowledgeBaseCategory
ref: #904 #901
2025-07-29 15:25:55 +09:30
Jon
2ff5c345e8 refactor(assistance): MetaData Unit Test Suite re-written to pytest for model KnowledgeBaseCategory
ref: #904 #901
2025-07-29 15:25:23 +09:30
Jon
9f20fe9614 refactor(assistance): Serializer Unit Test Suite re-written to pytest for model KnowledgeBaseCategory
ref: #904 #901
2025-07-29 15:25:10 +09:30
Jon
cf5b78b6b2 test(assistance): Model Functional Test Suite re-written to pytest for model KnowledgeBase
ref: #904 closes #900
2025-07-29 14:39:40 +09:30
Jon
cc481f94e9 chore(basae): Add capability to Functional Model Test Suite create fixture to cater for many to many field
ref: #904
2025-07-29 14:36:28 +09:30
Jon
3248d5201d chore(assistance): Cleanup Metadata Functional Test suite for model KnowledgeBase
ref: #904 #900
2025-07-29 14:35:05 +09:30
Jon
283051a4ad chore(test): Add capability to recurse array fixture to return the correct object in the expected format
ref: #904
2025-07-29 13:48:48 +09:30
Jon
03d320f6a0 test(assistance): API Fields Render Functional Test Suite re-written to pytest for model KnowledgeBase
ref: #904 #900
2025-07-29 13:47:57 +09:30
Jon
83ebf12978 chore(api): Add capability to API Fields model create fixture to cater for many to many field
ref: #904
2025-07-29 13:42:58 +09:30
Jon
09c1acbb1f refactor(assistance): ViewSet Unit Test Suite re-written to pytest for model KnowledgeBaseCategory
ref: #904 #901
2025-07-29 12:21:07 +09:30
Jon
4fc58c5ea1 refactor(assistance): Serializer Unit Test Suite re-written to pytest for model KnowledgeBaseCategory
ref: #904 #901
2025-07-29 12:20:51 +09:30
Jon
c476548aa3 refactor(assistance): Serializer Unit TestSuite re-written to pytest for model KnowledgeBase
ref: #904 #900
2025-07-29 12:20:08 +09:30
Jon
1812746a02 refactor(assistance): ViewSet TestSuite re-written to pytest for model KnowledgeBase
ref: #904 #900
2025-07-29 12:19:15 +09:30
Jon
78cf8522e3 Merge pull request #897 from nofusscomputing/access-test-refactor 2025-07-28 13:13:10 +09:30
Jon
9e7c4a8191 refactor(access): ViewSet TestSuite re-written to pytest for model Tenant
ref: #897 #899
2025-07-28 13:05:42 +09:30
Jon
fa1cee32cf chore(human_resources): Remove superflous functional tests for ViewSet for model Employee
ref: #897 #881
2025-07-28 11:53:34 +09:30
Jon
ca3af15847 chore(human_resources): Remove superflous functional tests for Serializer for model Employee
ref: #897 #881
2025-07-28 11:53:20 +09:30
Jon
c0c65903f4 chore(human_resources): Remove superflous functional tests for ViewSet for model Employee
ref: #897 #881
2025-07-28 11:53:01 +09:30
Jon
c19fe7f874 chore(access): Remove superflous functional tests for ViewSet for model Person
ref: #897 #878
2025-07-28 11:52:31 +09:30
Jon
05d87c93e6 chore(access): Remove superflous test permission for model Person
ref: #897 #878
2025-07-28 11:52:18 +09:30
Jon
ca661c9ebb chore(access): Remove superflous functional tests for ViewSet for model Entity
ref: #897 #877
2025-07-28 11:52:04 +09:30
Jon
2a7bf9c57b chore(access): Remove superflous test permission for model Entity
ref: #897 #877
2025-07-28 11:51:33 +09:30
Jon
5794d88ce4 chore(access): Remove superflous functional tests for Serializer for model Contact
ref: #897 #879
2025-07-28 11:51:10 +09:30
Jon
73e3781fe6 chore(access): Remove superflous functional tests for Serializer for model Contact
ref: #897 #879
2025-07-28 11:50:56 +09:30
Jon
f95639681d chore(access): Remove superflous test permission for model Contact
ref: #897 #879
2025-07-28 11:50:27 +09:30
Jon
c99166fffa chore(access): Remove superflous functional tests for ViewSet for model Company
ref: #897 #880
2025-07-28 11:50:00 +09:30
Jon
850e183f45 chore(access): Remove superflous functional tests for Serializer for model Company
ref: #897 #880
2025-07-28 11:49:51 +09:30
Jon
10569b6a46 chore(access): Remove superflous test permission for model Company
ref: #897 #880
2025-07-28 11:49:30 +09:30
Jon
464bf0da1d refactor(access): ViewSet TestSuite re-written to pytest for model Person
ref: #897 #878
2025-07-28 11:21:51 +09:30
Jon
123828d96d refactor(access): ViewSet TestSuite re-written to pytest for model Entity
ref: #897 #877
2025-07-28 11:21:00 +09:30
Jon
a72e153aa3 refactor(access): ViewSet TestSuite re-written to pytest for model Contact
ref: #897 #879
2025-07-28 11:20:35 +09:30
Jon
3ed7471c15 refactor(access): ViewSet TestSuite re-written to pytest for model Company
ref: #897 #880
2025-07-28 11:20:16 +09:30
Jon
c85b666a84 chore(api): Add kwargs for model detection for SubModel ViewSet checks
ref: #897 #895 #898
2025-07-28 11:16:03 +09:30
Jon
6baeb12be6 chore(api): SubModel ViewSet Test Suite temp disable _log attribute check until feature developed
ref: #897 #895 #898
2025-07-28 10:45:36 +09:30
Jon
2769859db0 test(api): SubModel ViewSet Test Suite to test re-written class
ref: #897 #895
2025-07-28 10:31:30 +09:30
Jon
209c01f5a3 test(api): Dont test a django object that has not been customised
ref: #897 #895 #877
2025-07-28 09:57:28 +09:30
Jon
fc5490afe0 Merge pull request #896 from nofusscomputing/refactor-test-viewser 2025-07-27 15:01:57 +09:30
Jon
83b1ca577b test(access): Initial ViewSet Unit Test Suite for Entity Model
ref: #896 #877
2025-07-27 15:00:37 +09:30
Jon
04409ed2c8 chore(api): remove suprflous test case in Common ViewSet TestSuite
ref: #896 #730 #895
2025-07-27 14:57:12 +09:30
Jon
7018c2d963 refactor(api): migrate Common ViewSet unittest.mock to mocker
ref: #896 #730 #895
2025-07-27 14:15:03 +09:30
Jon
6c83d0f0d7 chore(api): Skip Common ViewSet Meta/Options Test cases
ref: #896 #730 #895
2025-07-27 14:14:28 +09:30
Jon
b0cc4b8691 refactor(api): migrate Common ViewSet Unit Test Suite attribute to use test case unit_class
ref: #896 #730 #895
2025-07-27 12:35:41 +09:30
Jon
d7f231c831 chore(test): Mark test of class attribute existance as a regression test
ref: #896
2025-07-27 12:33:02 +09:30
Jon
96ec149017 refactor(api): Converted Common ViewSet Unit Test Suite to use Pytest
ref: #896 #876 #895
2025-07-27 09:56:11 +09:30
Jon
a623056325 Merge pull request #893 from nofusscomputing/access-test-unit-serializers 2025-07-26 09:34:37 +09:30
Jon
ee31b9348f refactor(api): partial conversion to pytest for Common ViewSet Unit Test Suite
ref: #893 #876 #895
2025-07-26 09:30:36 +09:30
Jon
c252717bb7 chore(api): mark ALL ViewSet Unit Test Suites to skip
Viewset tests being refactored

ref: #893 #876 #895
2025-07-26 08:22:39 +09:30
Jon
4b7549b87b refactor(api): Rename create Serializer unit test to is_valid
ref: #893 #730
2025-07-26 07:37:29 +09:30
Jon
2806f6bc8e test(access): Add Serializer unit test suit for model Role
ref: #893 #894
2025-07-26 07:37:21 +09:30
Jon
b0b7208eaa test(access): Add Serializer unit test suit for model Person
ref: #893 #878
2025-07-26 07:34:25 +09:30
Jon
c089b6fdf4 test(access): Add Serializer unit test suit for model Entity
ref: #893 #877
2025-07-26 07:33:58 +09:30
Jon
b9a9346b3f test(access): Add Serializer unit test suit for model Contact
ref: #893 #879
2025-07-26 07:33:31 +09:30
Jon
d49f71d3fe test(access): Add Serializer unit test suit for model Company
ref: #893 #880
2025-07-26 07:32:34 +09:30
Jon
b63fd35c5b Merge pull request #892 from nofusscomputing/2025-07-25 2025-07-25 08:38:15 +09:30
Jon
14a3df16c8 chore(access): remove superfluous API Permissions Test suite for Tenant model
test already covered under meta api permissions

ref: #892
2025-07-25 08:13:46 +09:30
Jon
4dbef179c9 chore(core): refactor viewset checks so they work for model TicketBase
ref: #892 #889
2025-07-25 07:46:34 +09:30
Jon
18c1c4029e chore(accounting): refactor viewset checks so they work for model AssetBase
ref: #892 #887
2025-07-25 07:40:18 +09:30
Jon
52001959d9 chore(human_resources): refactor api perm checks so they work for model employee
ref: #892 #881
2025-07-25 07:39:46 +09:30
Jon
b78c0e3045 chore(access): refactor api perm checks so they work for model contact
ref: #892 #879
2025-07-25 07:39:17 +09:30
Jon
2e0953d0ed chore(access): refactor api perm checks so they work for model person
ref: #892 #878
2025-07-25 07:38:28 +09:30
Jon
bca0f0a3e2 test(itim): Refactor TicketSLM model API Fields render test Suite to PyTest
ref: #892 #890
2025-07-25 06:59:23 +09:30
Jon
bd51c55a15 test(itim): Refactor TicketRequest model API Fields render test Suite to PyTest
ref: #892 #891
2025-07-25 06:59:19 +09:30
Jon
bc0180b246 test(core): Refactor TicketBase model API Fields render test Suite to PyTest
ref: #892 #889
2025-07-25 06:59:05 +09:30
Jon
c7b16874d3 chore: correct fixture
ref: #892 #888
2025-07-25 06:39:26 +09:30
Jon
47daac3a1b Merge pull request #883 from nofusscomputing/2025-07-24 2025-07-24 19:15:40 +09:30
Jon
590535516b test(api): Refactor Test Suite for API Fields render tests to PyTest
ref: #883 #730 #876
2025-07-24 18:50:27 +09:30
Jon
1fbbbfba88 test(itam): Refactor ITAMAssetBase model API Fields render test Suite to PyTest
ref: #883 #888
2025-07-24 18:47:14 +09:30
Jon
767957ad66 test(accounting): Refactor AssetBase model API Fields render test Suite to PyTest
ref: #883 #887
2025-07-24 18:46:40 +09:30
Jon
82bbf88c6f test(core): Refactor TicketCommentSolution model API Fields render test Suite to PyTest
ref: #883 #886 #728
2025-07-24 18:23:53 +09:30
Jon
daf68103ad test(core): Refactor TicketCommentAction model API Fields render test Suite to PyTest
ref: #883 #885 #736
2025-07-24 18:21:50 +09:30
Jon
8159799afc test(core): Refactor TicketCommentBase model API Fields render test Suite to PyTest
ref: #883 #884 #726
2025-07-24 18:20:40 +09:30
Jon
25b8993462 test(human_resources): Refactor Employee model API Fields render test Suite to PyTest
ref: #883 #881
2025-07-24 17:13:52 +09:30
Jon
3fc2b538a8 test(access): Refactor Person model API Fields render test Suite to PyTest
ref: #883 #878
2025-07-24 17:13:07 +09:30
Jon
ca938d2b61 test(access): Refactor Entity model API Fields render test Suite to PyTest
ref: #883 #877
2025-07-24 17:12:35 +09:30
Jon
6e65802932 test(access): Refactor Contact model API Fields render test Suite to PyTest
ref: #883 #879
2025-07-24 17:11:35 +09:30
Jon
cbaaefa87d test(access): Refactor Company model API Fields render test Suite to PyTest
ref: #883 #880
2025-07-24 17:10:18 +09:30
Jon
6b28dbf346 fix(base): on fixture cleanup, only clean if obj exists
ref: #883 #730
2025-07-24 16:53:04 +09:30
Jon
a84676c227 refactor(base): normalize empty/not used to be models.NOT_PROVIDED
ref: #883 #730
2025-07-24 15:46:48 +09:30
Jon
8191785134 test(devops): Adjust functional model test to use fixture kwargs
ref: #883 #882
2025-07-24 15:37:38 +09:30
Jon
6e1d0c747d refactor(base): adjust functional model test to use fixture kwargs
ref: #883 #735
2025-07-24 15:36:23 +09:30
Jon
482014004c Merge pull request #873 from nofusscomputing/2025-07-23 2025-07-23 12:28:24 +09:30
Jon
3d45e0ddfc feat(access): Filter history permissions
ref: #873 #875 closes #643
2025-07-23 12:03:05 +09:30
Jon
36303ec28f chore(api): clean up/remove api v1 from docs
ref: #873 closes #343
2025-07-23 10:12:12 +09:30
Jon
5eb0931495 chore(api): re-enable notes/history api field check
ref: #873 closes #768
2025-07-23 09:58:48 +09:30
Jon
7392c9700d fix(core): required field must be null for logical chek to function
ref: #873 #768
2025-07-23 09:50:00 +09:30
Jon
68084d8a05 test: Ensure when obj created via serializer calls full_clean
ref: #873 #874 closes #445
2025-07-23 08:33:54 +09:30
Jon
76bf78d3f5 test: Ensure Clean methods called
ref: #873 #445
2025-07-23 08:21:06 +09:30
Jon
a749862dbc chore(access): correct pytest mark for model role
ref: #873
2025-07-23 07:29:33 +09:30
Jon
25d3c5cb5a chore(base): remove ui templates
ref: #873 closes #757
2025-07-23 07:06:32 +09:30
Jon
7c7bfaf26a chore(base): remove ui scripts
ref: #873 #757
2025-07-23 07:06:18 +09:30
Jon
39c09f066d chore(base): remove ui icons
ref: #873 #757
2025-07-23 07:06:07 +09:30
Jon
bc7344c757 chore(base): remove ui Stylesheets
ref: #873 #757
2025-07-23 07:03:04 +09:30
Jon
971e1d61ea Merge pull request #872 from nofusscomputing/2025-07-21 2025-07-23 06:35:17 +09:30
Jon
f6c1b77c43 test: Test case for model field type
ref: #872
2025-07-21 16:05:40 +09:30
Jon
c8fade9e4d refactor(api): Update Test Suite for AuthToken model
ref: #872 #869
2025-07-21 13:43:08 +09:30
Jon
31a03b4226 Merge pull request #871 from nofusscomputing/test-refactor-for-new-inheritance 2025-07-20 12:57:47 +09:30
Jon
de87364b9c refactor(tests): Unskip tests that'll work now due to model inheritance change
ref: #871 #771 #395 #859
2025-07-20 12:34:15 +09:30
Jon
a382561245 refactor(api): Update Test Suite for AuthToken model
ref: #871 closes #869 #735 #771
2025-07-20 12:13:53 +09:30
Jon
0b9eeea12c refactor(api): Update URL route name for Role AuthToken
ref: #870 #869
2025-07-20 12:01:30 +09:30
Jon
7800b1abb0 refactor(api): Switch to inherit from Centurion model for model AuthToken
ref: #871 #869
2025-07-20 12:00:02 +09:30
Jon
049cf6577e fix(itam): field slug no longer avail, use str
ref: #871 #820
2025-07-20 11:41:56 +09:30
Jon
c154cef6d5 refactor(access): When adding model role via api, status is 201/created
ref: #871 #844
2025-07-20 11:24:52 +09:30
Jon
132765833e refactor(itim): Update Test Suite for TicketCommentSolution model
ref: #871 closes #866
2025-07-20 10:59:03 +09:30
Jon
842fc38a98 chore(core): addd rand int to username
ref: #871
2025-07-20 07:24:07 +09:30
Jon
35d2e869b0 chore(core): dont delete obj on fixture clean
ref: #871
2025-07-20 07:09:16 +09:30
Jon
f0fdf4ed15 refactor(itim): Update Test Suite for TicketSLM model
ref: #871 closes #868
2025-07-18 19:34:32 +09:30
Jon
41576f9862 refactor(itim): Update Test Suite for TicketRequest model
ref: #871 closes #867
2025-07-18 19:34:17 +09:30
Jon
4ffbf81b71 refactor(core): Update Test Suite for TicketBase model
ref: #871 closes #861
2025-07-18 19:33:53 +09:30
Jon
cf06783aec refactor(core): Update Test Suite for TicketCommentSolution model
ref: #871 #866
2025-07-18 17:35:47 +09:30
Jon
80ab996851 refactor(core): Update Test Suite for TicketCommentAction model
ref: #871 #864
2025-07-18 17:35:00 +09:30
Jon
13cf3f8152 refactor(core): Update Test Suite for TicketCommentBase model
ref: #871 #865
2025-07-18 17:32:40 +09:30
Jon
9d78d112ec refactor(core): Initial Update Test Suite for TicketCommentBase model
ref: #871 #865
2025-07-17 00:12:13 +09:30
Jon
27e842a57f refactor(core): Update Tests to cater for inheritence changes
ref: #871 #861
2025-07-16 21:56:12 +09:30
Jon
8cc8fdad8b refactor(itim): Update Test Suite for RequestTicket model
ref: #871 #868
2025-07-16 21:29:52 +09:30
Jon
35c5c7ca66 refactor(itim): Update Test Suite for SLMTicket model
ref: #871 #868
2025-07-16 21:29:02 +09:30
Jon
645baa24d9 refactor(itim): Update Test Suite for SLMTicket model
ref: #871 #868
2025-07-15 21:51:05 +09:30
Jon
739cefbf1c refactor(core): Update Test Suite for TicketBase model
ref: #871 #863
2025-07-15 21:11:40 +09:30
Jon
15cf7096f2 chore(core): TicketBase model fn cleanup
ref: #871 #863
2025-07-15 21:11:13 +09:30
Jon
fd5b223632 chore: Update DB test fixture
ref: #871 #863
2025-07-15 21:06:50 +09:30
Jon
42ea8121a8 Merge pull request #870 from nofusscomputing/refactor-ticket-inheritence 2025-07-15 02:50:19 +09:30
Jon
d3741e74e2 refactor(core): Update Test Suite for TicketBase model
ref: #870 #861
2025-07-15 02:15:28 +09:30
Jon
b4f61223d6 refactor(core): Switch to inherit from Centurion model for model TicketBase
ref: #870 #863
2025-07-15 02:14:34 +09:30
Jon
1efa932fb9 refactor(core): Switch to inherit from Centurion model for model SLMTicketBase
ref: #870 #868
2025-07-14 22:20:04 +09:30
Jon
a04c963431 chore: Update DB test fixture
ref: #870 #816 #865
2025-07-13 23:20:09 +09:30
Jon
815075174a refactor(core): Update URL route name for Role TicketCommentBase
ref: #870 #865
2025-07-13 23:07:05 +09:30
Jon
9df5a5898e refactor(core): Switch to inherit from Centurion model for model TicketCommentBase
ref: #870 #865
2025-07-13 23:06:35 +09:30
Jon
ceabd56e1b refactor(core): Update URL route name for Role TicketBase
ref: #870 #861
2025-07-13 23:05:54 +09:30
Jon
61a1792e4c refactor(core): Switch to inherit from Centurion model for model TicketBase
ref: #870 #861
2025-07-13 23:03:49 +09:30
Jon
3baed3f8f5 refactor(core): Add fn get_organization to centurion mixin
Fn is required for perms to work correctly

ref: #870
2025-07-13 22:30:15 +09:30
Jon
9a516fbebc Merge pull request #862 from nofusscomputing/refactor-switch-model-inheritence 2025-07-13 21:36:52 +09:30
Jon
be708b1244 test(fixture): if item already exists, when fetching remove modified field from query if not found with
field is an auto field and most likely wont match the existing item

ref: #862
2025-07-13 21:11:55 +09:30
Jon
2f7865bb83 feat(access): Add Audit and notes tables for model Role
ref: #862 #844
2025-07-12 18:27:03 +09:30
Jon
b643347c01 test(access): Model Role is not usable within global org, remove test
ref: #862 #844
2025-07-12 18:21:51 +09:30
Jon
957052da84 refactor(access): Adjust add permission test for model Role
ref: #862 #844
2025-07-12 17:30:58 +09:30
Jon
b2e0982b4c refactor(access): Migrations for Inheritance change for Role model
ref: #862 closes #844
2025-07-12 16:57:20 +09:30
Jon
ca63e4d6fc refactor(access): Update URL route name for Role model
ref: #862 #844
2025-07-12 16:56:41 +09:30
Jon
3b7e88969e refactor(access): Update Test Suite for Role model
ref: #862 #844
2025-07-12 16:56:07 +09:30
Jon
953dce2984 feat(access): Add AuditHistory Serializer for Role model
ref: #862 #844
2025-07-12 16:44:43 +09:30
Jon
e0c8ef46f5 feat(access): Add Notes Serializer for Role model
ref: #862 #844
2025-07-12 16:43:58 +09:30
Jon
548051df6d refactor(access): Switch to inherit from Centurion model for model Role
ref: #862 #844
2025-07-12 16:42:59 +09:30
Jon
d6eb33141a refactor: Asset and ITAM Asset must use url kwarg model_name not asset_model
ref: #862 closes #857 #858
2025-07-12 16:13:08 +09:30
Jon
4f36769fba refactor(accounting): Update existing tests to work due to model inheritance changes
ref: #862 #857
2025-07-10 20:35:32 +09:30
Jon
018004ccb9 refactor(itam): Update URL route name for ITAMAssetBase model
ref: #862 #858
2025-07-10 19:54:28 +09:30
Jon
b851388d37 refactor(itam): Update Test Suite for ITAMAssetBase model
ref: #862 #858
2025-07-10 19:53:38 +09:30
Jon
38b4542a58 feat(itam): Add AuditHistory Serializer for ITAMAssetBase model
ref: #862 #858
2025-07-10 19:51:13 +09:30
Jon
3b5673ae4b feat(itam): Add Notes Serializer for ITAMAssetBase model
ref: #862 #858
2025-07-10 19:50:53 +09:30
Jon
e4e7ad915b refactor(itam): Switch to inherit from Centurion model for model ITAMAssetBase
ref: #862 #858
2025-07-10 19:50:04 +09:30
Jon
de7c52d733 refactor(accounting): Switch to inherit from Centurion model for model AssetBase
ref: #862 #857
2025-07-10 19:48:21 +09:30
Jon
d741992b6d refactor(accounting): Update URL route name for AssetBase model
ref: #862 #857
2025-07-10 19:47:18 +09:30
Jon
9b3c8d2225 refactor(accounting): Update Test Suite for AssetBase model
ref: #862 #857
2025-07-10 19:43:54 +09:30
Jon
4ff457a58c feat(accounting): Add AuditHistory Serializer for AssetBase model
ref: #862 #857
2025-07-10 19:33:36 +09:30
Jon
46b4df5dc1 feat(accounting): Add Notes Serializer for AssetBase model
ref: #862 #857
2025-07-10 19:32:57 +09:30
Jon
2482148466 refactor(accounting): Switch to inherit from Centurion model for model AssetBase
ref: #862 #857
2025-07-10 19:28:41 +09:30
Jon
2c1c769988 Merge pull request #860 from nofusscomputing/fix-stuff 2025-07-09 11:18:54 +09:30
Jon
38f3a3bf05 fix(core): Include model so content type is created
ref: #860
2025-07-09 10:54:59 +09:30
Jon
965bde51bc Merge pull request #856 from nofusscomputing/test-functional-get-working 2025-07-07 21:24:30 +09:30
Jon
303cc31f6a test(devops): skip Model History entry test as it should be done as part of serializer and viewset
ref: #856 #781
2025-07-07 20:55:22 +09:30
Jon
97f99abe2c chore: ensure api post items for tests is the correct type
ref: #856
2025-07-07 18:51:59 +09:30
Jon
93642ee6a1 Merge pull request #855 from nofusscomputing/test-get-functional-working 2025-07-07 00:41:19 +09:30
Jon
eeaf3ab5fc test(devops): update no_org_serializer test so it works for model SoftwareEnableFeatureFlag
ref: #855 #812
2025-07-07 00:16:17 +09:30
Jon
5b6f9bec00 chore(tests): cater for manytomany for api fields
ref: #855
2025-07-07 00:16:11 +09:30
Jon
cf7fb57583 chore(itam): Ensure when creating Model ITAMAsset that the asset number field is populated
ref: #855 #737
2025-07-06 22:48:47 +09:30
Jon
45abdc2e00 feat: When attempting to create and objetc must be unique and alrready exists, dont return error return existing object
ref: #855
2025-07-06 22:20:54 +09:30
Jon
22ad79386e chore(settings): Remove old AppSettings model permission tests
ref: #855 #834
2025-07-06 20:59:03 +09:30
Jon
baabf84234 fix(settings): AppSettings requires super user perms
ref: #855 #834
2025-07-06 20:55:18 +09:30
Jon
c54de5c627 feat(access): History + Notes model migrations for Company Model
ref: #855 #801
2025-07-06 20:23:48 +09:30
Jon
803d7f3223 test(itam): Model DeviceOperatingSystem is not multi-org based skip those tests
ref: #855 #801
2025-07-06 19:14:13 +09:30
Jon
b5f55c1eea test(settings): Model UserSettings does not allowing adding rows, skip test
ref: #855 #836
2025-07-06 19:06:57 +09:30
Jon
888fc68180 test(settings): Model AppSettings does not allowing adding rows, skip test
ref: #855 #834
2025-07-06 19:06:20 +09:30
Jon
5d8062fcef Merge pull request #849 from nofusscomputing/test-model-inheritance-refactor 2025-07-04 19:51:58 +09:30
Jon
e99ab1b0c6 test(fixture): Ensure _meta attribute exists when cleaning up models prior to attempting to use
ref: #849
2025-07-04 19:30:33 +09:30
Jon
7c85d9653f revert(api): when testing create object, remove the actual created object prior to testing the add
object is class scoped and cant be deleted

ref: #849
2025-07-04 19:06:48 +09:30
Jon
9ebf9bf3de refactor(api): dont query db for instance, use existing from response
ref: #849
2025-07-04 18:42:51 +09:30
Jon
57936073db feat(api): map notfound and perm denied django -> drf exceptions
ref: #849
2025-07-04 17:57:08 +09:30
Jon
638e2ba986 chore: add notation to capture unknwon exception for capture
ref: #849
2025-07-04 13:28:55 +09:30
Jon
6af615f918 test(devops): SoftwareEnableFeatureFlagging model does not use global org, so dont test global org return
ref: #849
2025-07-04 13:26:13 +09:30
Jon
37a69888b6 test(api): when testing create object, remove the actual created object prior to testing the add
ref: #849
2025-07-04 13:26:07 +09:30
Jon
c2255a5834 test(fixture): when creating object and it exists, rtn that object
ref: #849
2025-07-04 13:25:35 +09:30
Jon
77cf598e4d fix(api): Convert Django Exceptions to DRF API Exception equivilent
ref: #849 #854
2025-07-04 13:23:31 +09:30
Jon
1f4ce92623 test(devops): If test publically accessable, dont test by user org only as test is NA
ref: #849 #782
2025-07-04 10:10:15 +09:30
Jon
882ae90d83 fix(api): Ensure if exception DRF, message returned is from that exception
ref: #849
2025-07-04 10:03:48 +09:30
Jon
ea88076d7f test(settings): UserSettings perms tests are for the user that is accessing them
ref: #849 #836
2025-07-04 09:45:50 +09:30
Jon
6e925e8456 test(settings): UserSettings perms tests are not org based, skip those tests
ref: #849 #836
2025-07-04 09:38:34 +09:30
Jon
ffaac107f4 refactor(api): additional perms tests if they exist must be inc first
ref: #849
2025-07-04 09:38:26 +09:30
Jon
b282162a86 test(settings): AppSettings perms tests are not org based, skip those tests
ref: #849 #834
2025-07-04 09:38:07 +09:30
Jon
05fd82459a chore: Add makemigrations debug launch to vscode
ref: #849
2025-07-04 08:41:40 +09:30
Jon
b2383a2236 refactor(devops): remove ViewSet get_queryset function
not required as the model is set to the actual model

ref: #849 #809
2025-07-04 08:41:40 +09:30
Jon
bf1bb23dd5 chore(test): Add required fields to service fixture
ref: #849 #828
2025-07-04 08:41:40 +09:30
Jon
73a704d5e3 fix(devops): git repository is sub-model ViewSet must inherit from SubModel
ref: #848 #809 #810 #811
2025-07-04 08:40:36 +09:30
Jon
7b22541002 chore(access): Update common viewset test suite mock request
ref: #847 #840 #841 #842 #843 #845
2025-07-04 08:40:36 +09:30
Jon
1ba7661f07 refactor(access): Update Entity model ViewSet attribute model_kwarg to model_name
ref: #847 #840 #841 #842 #843 #845
2025-07-04 08:40:36 +09:30
Jon
2eb0ba674e refactor(access): Update Entity model ViewSet to inherit from submodel-rewrite
ref: #847 #840 #841 #842 #843 #845
2025-07-04 08:40:36 +09:30
Jon
6ae3b193fa chore(access): remove get_url_kwargs function as it's not required
ref: #847 #840 #841 #842 #843 #845
2025-07-04 08:40:36 +09:30
Jon
2b7eaace4d fix(access): entity field entity_type is an auto field
ref: #847
2025-07-04 08:40:36 +09:30
Jon
4f8fca9aff chore: Ensure employee fixture creates integer within max of field
ref: #847
2025-07-04 08:40:36 +09:30
Jon
53a474fa2a chore: update apifield test suit to set model class var and for the removal of fields property from models
ref: #847
2025-07-04 08:40:36 +09:30
Jon
b549059d15 chore(test): update db fixture
ref: #839
2025-07-04 08:40:36 +09:30
Jon
e7eb1442b7 docs(issue_template): remove notes and history requirements from new model issue template
ref: #839
2025-07-04 08:40:36 +09:30
Jon
6d2406ae1c chore(access): Add pytest mark for Model Entity Tests
ref: #839 closes #840
2025-07-04 08:40:36 +09:30
Jon
aa86f04aa2 chore(access): Add pytest mark for Model Company Tests
ref: #839 closes #845
2025-07-04 08:40:36 +09:30
Jon
6d33653db0 feat(human_resources): Add model tag for Employee model
ref: #839 closes #843
2025-07-04 08:40:36 +09:30
Jon
bc3545d53e refactor(access): Update Test Suite for Employee model
ref: #839 #843
2025-07-04 08:40:36 +09:30
Jon
3ea44aaabe feat(human_resources): Add AuditHistory Serializer for Employee model
ref: #839 #843
2025-07-04 08:40:36 +09:30
Jon
d7442cfff4 feat(human_resources): Add Notes Serializer for Employee model
ref: #839 #843
2025-07-04 08:40:36 +09:30
Jon
23832fff6a feat(human_resources): Change model to inherit from CenturionModel for Employee model
ref: #839 #843
2025-07-04 08:40:36 +09:30
Jon
c5f8412d46 feat(access): Add model tag for Person model
ref: #839 closes #841
2025-07-04 08:40:36 +09:30
Jon
a582cbbe59 refactor(access): Update Test Suite for Person model
ref: #839 #841
2025-07-04 08:40:36 +09:30
Jon
8c48fb6c37 feat(access): Add AuditHistory Serializer for Person model
ref: #839 #841
2025-07-04 08:40:36 +09:30
Jon
3c6589f07c feat(access): Add Notes Serializer for Person model
ref: #839 #841
2025-07-04 08:40:36 +09:30
Jon
d1fbead077 feat(access): Change model to inherit from CenturionModel for Person model
ref: #839 #841
2025-07-04 08:40:36 +09:30
Jon
3025c397b5 feat(access): Add model tag for Contact model
ref: #839 closes #842
2025-07-04 08:40:36 +09:30
Jon
43490b7407 refactor(access): Update Test Suite for Contact model
ref: #839 #842
2025-07-04 08:40:36 +09:30
Jon
e15bb11a76 feat(access): Add AuditHistory Serializer for Contact model
ref: #839 #842
2025-07-04 08:40:36 +09:30
Jon
1823cb4ec1 feat(access): Add Notes Serializer for Contact model
ref: #839 #842
2025-07-04 08:40:36 +09:30
Jon
9de99e07f7 feat(access): Change model to inherit from CenturionModel for Contact model
ref: #839 #842
2025-07-04 08:40:36 +09:30
Jon
c9c8cf6700 refactor(access): Update Test Suite for Company model
ref: #839 #845 #760
2025-07-04 08:40:36 +09:30
Jon
af868fcf4f feat(access): Add AuditHistory Serializer for Company model
ref: #839 #845 #760
2025-07-04 08:40:36 +09:30
Jon
e9fe6a2bdc feat(access): Add Notes Serializer for Entity model
ref: #839 #845 #760
2025-07-04 08:40:36 +09:30
Jon
595b232db9 feat(access): Change model to inherit from CenturionModel for Company model
ref: #839 #845 #760
2025-07-04 08:40:36 +09:30
Jon
87d0a5174f feat(access): Change model to inherit from CenturionModel for Entity model
ref: #839 closes #840
2025-07-04 08:40:36 +09:30
Jon
f074abefa7 refactor(access): Update URL route name for Entity model
ref: #839 #840 #841 #842 #843 #844 #845
2025-07-04 08:40:36 +09:30
Jon
b6dae72a07 refactor(access): Update Test Suite for Entity model
ref: #839 #840
2025-07-04 08:40:36 +09:30
Jon
847e4f93ea feat(access): Add AuditHistory Serializer for Entity model
ref: #839 #840
2025-07-04 08:40:36 +09:30
Jon
3943171534 feat(access): Add Notes Serializer for Entity model
ref: #839 #840
2025-07-04 08:40:36 +09:30
Jon
ef5d132ab3 feat(access): Change model to inherit from CenturionModel for Entity model
ref: #839 #840
2025-07-04 08:40:36 +09:30
Jon
874ce0c4f4 chore: enable creating reandom email field in model_kwarg_data fixture
ref: #839
2025-07-04 08:40:36 +09:30
Jon
ae20451033 chore: make model_instance a function fixture
ref: #839
2025-07-04 08:40:36 +09:30
Jon
fefb7e67a0 test(settings): for api checks for model AppSettings, make user super_user
required so that tests can run

ref: #839
2025-07-04 08:40:36 +09:30
Jon
41da9fb6a0 test(settings): Exclude inter-org tests for model AppSettings
perms for appsettings are global

ref: #839 #834
2025-07-04 08:40:36 +09:30
Jon
5234051538 refactor(access): Update is_tenancy_object to check for CenturionModel
ref: #839 #767
2025-07-04 08:40:36 +09:30
Jon
ebea2da906 test(settings): Remove old API Permission tests no longer required
ref: #833 #836
2025-07-04 08:40:36 +09:30
Jon
e233bf4487 test(settings): Ensure ExternalLink model hasrequired field template added
ref: #833 #835
2025-07-04 08:40:36 +09:30
Jon
ea1d6f4a20 chore(api): Add support to API Permission to include additional tests
ref: #833
2025-07-04 08:40:36 +09:30
Jon
0a9a26a43b refactor(access): For request middleware, use filter and first object so that testing can occur when mre than one exists
ref: #833
2025-07-04 08:40:36 +09:30
Jon
8f984e6c21 test(api): if model lacks list endpoint, check if method alllowed for test cases for Functional API perms test suite
ref: #833
2025-07-04 08:40:36 +09:30
Jon
7e3ae4c0bc test(api): if model lacks organization field, xfail returned orgs test cases for Functional API perms test suite
ref: #833
2025-07-04 08:40:36 +09:30
Jon
ef6ebcdcf4 fix(access): Ensure that if method not allowed, exception is thrown first before perms check
ref: #833
2025-07-04 08:40:36 +09:30
Jon
0b8b0bc850 test: Ensure service fixture assosiates with device
ref: #833 #828
2025-07-04 08:40:35 +09:30
Jon
e3804b4f9b test(api): if model lacks organization field, xfail returned orgs test cases for Functional API perms test suite
ref: #833 #820
2025-07-04 08:40:35 +09:30
Jon
ded80d4a8c fix(itam): Model software must be related linked to organization model
ref: #833 #820
2025-07-04 08:40:35 +09:30
Jon
2027f3fe97 test: Add depreciated models to be excluded from coverage
ref: #833
2025-07-04 08:40:35 +09:30
Jon
239540c9ab chore: correct docs linting error
ref: #833
2025-07-04 08:40:35 +09:30
Jon
164aa21fad feat(settings): Add model tag for ExtrnalLink model
ref: #833 #835 closes #584
2025-07-04 08:40:35 +09:30
Jon
78539f2551 refactor(settings): Update URL route name for UserSettings model
ref: #833 closes #836
2025-07-04 08:40:35 +09:30
Jon
095239f199 refactor(settings): Update Test Suite for ExternalLink model
ref: #833 #836
2025-07-04 08:40:35 +09:30
Jon
ea8c81c64d feat(settings): Add AuditHistory Serializer for UserSettings model
ref: #833 #836
2025-07-04 08:40:35 +09:30
Jon
80770deafd feat(settings): Add Notes Serializer for UserSettings model
ref: #833 #836
2025-07-04 08:40:35 +09:30
Jon
05a32711b5 feat(settings): Change model to inherit from CenturionModel for UserSettings model
ref: #833 #836
2025-07-04 08:40:35 +09:30
Jon
1fe669e932 feat(settings): Add model ExternalLink to migrate for history and notes
ref: #833 closes #835
2025-07-04 08:40:35 +09:30
Jon
801bac9e6d refactor(settings): Update URL route name for ExternalLink model
ref: #833 #835
2025-07-04 08:40:35 +09:30
Jon
4a3f2ae6db refactor(settings): Update Test Suite for ExternalLink model
ref: #833 #835
2025-07-04 08:40:35 +09:30
Jon
fdbf9f81db feat(settings): Add AuditHistory Serializer for ExternalLink model
ref: #833 #835
2025-07-04 08:40:35 +09:30
Jon
b1fcc58741 feat(settings): Add Notes Serializer for ExternalLink model
ref: #833 #835
2025-07-04 08:40:35 +09:30
Jon
278b9e5c08 feat(settings): Change model to inherit from CenturionModel for ExternalSettings model
ref: #833 #835
2025-07-04 08:40:35 +09:30
Jon
cec4b39f5a feat(settings): Add model AppSettings to migrate for history and notes
ref: #833 closes #834
2025-07-04 08:40:35 +09:30
Jon
c264ab2cd4 refactor(settings): Update URL route name for AppSettings model
ref: #833 #834
2025-07-04 08:40:35 +09:30
Jon
44688c35df fix(access): if user has no orgs, dont filter by for query
ref: #833
2025-07-04 08:40:35 +09:30
Jon
f023901dc4 refactor(settings): Update Test Suite for AppSettings model
ref: #833 #834
2025-07-04 08:40:35 +09:30
Jon
c53a488a27 feat(settings): Add AuditHistory Serializer for AppSettings model
ref: #833 #834
2025-07-04 08:40:35 +09:30
Jon
51f7b94360 feat(settings): Add Notes Serializer for AppSettings model
ref: #833 #834
2025-07-04 08:40:35 +09:30
Jon
f7e71be426 feat(settings): Change model to inherit from CenturionModel for AppSettings model
ref: #833 #834
2025-07-04 08:40:35 +09:30
Jon
39bcd74c56 chore: Add support for testing tenant model to fixture model_instance
ref: #833
2025-07-04 08:40:35 +09:30
Jon
763836dd79 chore: skip depreciated linked ticket tests
ref: #833
2025-07-04 08:40:35 +09:30
Jon
3667ed76d3 feat(project_management): Add model ProjectType to migrate for history and notes
ref: #833 closes #832
2025-07-04 08:40:35 +09:30
Jon
f62fa6d166 refactor(project_management): Update URL route name for ProjectType model
ref: #833 #832
2025-07-04 08:40:35 +09:30
Jon
caf2fd0ad3 refactor(project_management): Update Test Suite for ProjectType model
ref: #833 #832
2025-07-04 08:40:35 +09:30
Jon
c7dda4110a feat(project_management): Add AuditHistory Serializer for ProjectTYpe model
ref: #833 #832
2025-07-04 08:40:35 +09:30
Jon
33bba65b44 feat(project_management): Add Notes Serializer for ProjectType model
ref: #833 #832
2025-07-04 08:40:35 +09:30
Jon
c7595f71ea feat(project_management): Change model to inherit from CenturionModel for ProjectType model
ref: #830 #832 closes #594
2025-07-04 08:40:35 +09:30
Jon
3e6570045c feat(project_management): Add model ProjectState to migrate for history and notes
ref: #833 closes #831
2025-07-04 08:40:35 +09:30
Jon
461b3f4933 refactor(project_management): Update URL route name for ProjectState model
ref: #833 #831
2025-07-04 08:40:35 +09:30
Jon
4c53c92a22 refactor(project_management): Update Test Suite for ProjectState model
ref: #833 #831
2025-07-04 08:40:35 +09:30
Jon
fbe5675bc9 feat(project_management): Add AuditHistory Serializer for ProjectState model
ref: #833 #831
2025-07-04 08:40:35 +09:30
Jon
f1f70e9a22 feat(project_management): Add Notes Serializer for ProjectState model
ref: #833 #831
2025-07-04 08:40:35 +09:30
Jon
e5946cecbc feat(project_management): Change model to inherit from CenturionModel for ProjectState model
ref: #830 #831
2025-07-04 08:40:35 +09:30
Jon
1af06bbaa6 feat(project_management): Add model ProjectMilestone to migrate for history and notes
ref: #833 closes #830
2025-07-04 08:40:35 +09:30
Jon
ff77aaac13 refactor(project_management): Update URL route name for ProjectMilestone model
ref: #833 #830
2025-07-04 08:40:35 +09:30
Jon
c07b208a63 refactor(project_management): Update Test Suite for ProjectMilestone model
ref: #833 #830
2025-07-04 08:40:35 +09:30
Jon
cc82c80639 feat(project_management): Add AuditHistory Serializer for ProjectMilestone model
ref: #833 #830
2025-07-04 08:40:35 +09:30
Jon
ba26a18682 feat(project_management): Add Notes Serializer for ProjectMilestone model
ref: #833 #830
2025-07-04 08:40:35 +09:30
Jon
c9a21bc3e9 feat(project_management): Change model to inherit from CenturionModel for ProjectManagement model
ref: #833 #830 closes #591
2025-07-04 08:40:35 +09:30
Jon
60b38cc61b chore: correct tests
ref: #824
2025-07-04 08:40:34 +09:30
Jon
936c6b4cd6 chore: fix accessing var that dont exist
ref: #824
2025-07-04 08:40:34 +09:30
Jon
6a7dd54c58 chore: remove depreciated docs
ref: #824 #343 #757
2025-07-04 08:40:34 +09:30
Jon
3cbe4201d0 chore: fix accessing var that dont exist
ref: #824
2025-07-04 08:40:34 +09:30
Jon
253ee3822a feat(project_management): Add model Project to migrate for history and notes
ref: #824 closes #829
2025-07-04 08:40:34 +09:30
Jon
bf7fa83e39 refactor(project_management): Update URL route name for Project model
ref: #824 #829
2025-07-04 08:40:34 +09:30
Jon
6c1eee1d98 refactor(project_management): Update Test Suite for Project model
ref: #824 #829
2025-07-04 08:40:34 +09:30
Jon
dc3d02eb66 feat(project_management): Add AuditHistory Serializer for Project model
ref: #824 #829
2025-07-04 08:40:34 +09:30
Jon
afb688a396 feat(project_management): Add Notes Serializer for Project model
ref: #824 #829
2025-07-04 08:40:34 +09:30
Jon
b378565ff6 feat(project_management): Change model to inherit from CenturionModel for Project model
ref: #824 #829 closes #590
2025-07-04 08:40:34 +09:30
Jon
a9cde74013 feat(itim): Add model Service to migrate for history and notes
ref: #824 closes #828
2025-07-04 08:40:34 +09:30
Jon
27f35e6fde refactor(itim): Update URL route name for Service model
ref: #824 #828
2025-07-04 08:40:34 +09:30
Jon
f377ad102e refactor(itim): Update Test Suite for Service model
ref: #824 #828
2025-07-04 08:40:34 +09:30
Jon
fa7c70f2ce feat(itim): Add AuditHistory Serializer for Service model
ref: #824 #828
2025-07-04 08:40:34 +09:30
Jon
1f6a36ec8e feat(itim): Add Notes Serializer for Service model
ref: #824 #828
2025-07-04 08:40:34 +09:30
Jon
33617bd608 feat(itim): Change model to inherit from CenturionModel for Service model
ref: #824 #828
2025-07-04 08:40:34 +09:30
Jon
b83a087081 feat(itim): Add model Port to migrate for history and notes
ref: #824 closes #827
2025-07-04 08:40:34 +09:30
Jon
8fd243e691 refactor(itim): Update URL route name for Port model
ref: #824 #827
2025-07-04 08:40:34 +09:30
Jon
b20cab4f8e refactor(itim): Update Test Suite for Port model
ref: #824 #827
2025-07-04 08:40:34 +09:30
Jon
f25c7274c6 feat(itim): Add AuditHistory Serializer for Port model
ref: #824 #827
2025-07-04 08:40:34 +09:30
Jon
1e339a1f0d feat(itim): Add Notes Serializer for Port model
ref: #824 #827
2025-07-04 08:40:34 +09:30
Jon
00c3eff30e feat(itim): Change model to inherit from CenturionModel for Port model
ref: #824 #827 closes #589
2025-07-04 08:40:34 +09:30
Jon
6163b4ad2d refactor(itim): Update URL route name for ClusterType model
ref: #824 closes #826 #580
2025-07-04 08:40:34 +09:30
Jon
8452e678da refactor(itim): Update Test Suite for ClusterType model
ref: #824 #826
2025-07-04 08:40:34 +09:30
Jon
30c19031eb feat(itim): Add AuditHistory Serializer for ClusterType model
ref: #824 #826
2025-07-04 08:40:34 +09:30
Jon
d0e8b58176 feat(itim): Add Notes Serializer for ClusterType model
ref: #824 #826
2025-07-04 08:40:34 +09:30
Jon
a192659c80 feat(itim): Change model to inherit from CenturionModel for ClusterType model
ref: #824 #826
2025-07-04 08:40:34 +09:30
Jon
44489b308b feat(itim): Add model Cluster to migrate for history and notes
ref: #824 closes #825
2025-07-04 08:40:34 +09:30
Jon
1b875233da refactor(itim): Update URL route name for Cluster model
ref: #824 #825
2025-07-04 08:40:34 +09:30
Jon
93eb65316e refactor(itim): Update Test Suite for Cluster model
ref: #824 #825
2025-07-04 08:40:34 +09:30
Jon
1611537d86 feat(itim): Add Notes Serializer for Cluster model
ref: #824 #825
2025-07-04 08:40:34 +09:30
Jon
5da4e2338a feat(itim): Add AuditHistory Serializer for Cluster model
ref: #824 #825
2025-07-04 08:40:34 +09:30
Jon
07ef410c31 feat(itim): Change model to inherit from CenturionModel for Cluster model
ref: #824 #825
2025-07-04 08:40:34 +09:30
Jon
067aa8714f revert(core): return settings_value template tag
ref: #824
2025-07-04 08:40:34 +09:30
Jon
8c61c4e8a6 feat(itam): Add model SoftwareVersion to migrate for history and notes
ref: #823 closes #822
2025-07-04 08:40:34 +09:30
Jon
234e85368a refactor(itam): Update Test Suite for SoftwareVersion model
ref: #823 #822
2025-07-04 08:40:34 +09:30
Jon
915101820e refactor(itam): Update URL route name for SoftwareVersion model
ref: #823 #822
2025-07-04 08:40:34 +09:30
Jon
93992dbef5 feat(itam): Add Notes Serializer for SoftwareVersiony model
ref: #823 #822
2025-07-04 08:40:34 +09:30
Jon
81e7d21d6f feat(itam): Add AuditHistory Serializer for SoftwareVersion model
ref: #823 #822
2025-07-04 08:40:34 +09:30
Jon
ae4b2a3c04 feat(itam): Change model to inherit from CenturionModel for SoftwareVersion model
ref: #823 #822
2025-07-04 08:40:34 +09:30
Jon
cb0d095eb7 feat(itam): Add model SoftwareCategory to migrate for history and notes
ref: #823 closes #821
2025-07-04 08:40:33 +09:30
Jon
b491ba45e5 refactor(itam): Update Test Suite for SoftwareCategory model
ref: #823 #821
2025-07-04 08:40:33 +09:30
Jon
610e4665a6 refactor(itam): Update URL route name for SoftwareCategory model
ref: #823 #820
2025-07-04 08:40:33 +09:30
Jon
c2ad9e3189 feat(itam): Add Notes Serializer for SoftwareCategory model
ref: #823 #821
2025-07-04 08:40:33 +09:30
Jon
0d2b2d2183 feat(itam): Add AuditHistory Serializer for SoftwareCategory model
ref: #823 #821
2025-07-04 08:40:33 +09:30
Jon
851bf553b0 feat(itam): Change model to inherit from CenturionModel for SoftwareCategory model
ref: #823 #821 closes #595
2025-07-04 08:40:33 +09:30
Jon
d6da2cf0fb feat(itam): Add model Software to migrate for history and notes
ref: #823 #820
2025-07-04 08:40:33 +09:30
Jon
ecc544ce19 refactor: cater for dev that does not exist in test cleanup
ref: #823
2025-07-04 08:40:33 +09:30
Jon
7542521866 refactor(itam): Update Test Suite for Software model
ref: #823 closes #820
2025-07-04 08:40:33 +09:30
Jon
df43ee9e7a refactor(itam): Update URL route name for Software model
ref: #823 #820
2025-07-04 08:40:33 +09:30
Jon
bdbcc46db5 feat(itam): Add Notes Serializer for Software model
ref: #823 #820
2025-07-04 08:40:33 +09:30
Jon
f8e659ddd5 feat(itam): Add AuditHistory Serializer for Software model
ref: #823 #820
2025-07-04 08:40:33 +09:30
Jon
e87e3992aa feat(itam): Change model to inherit from CenturionModel for Software model
ref: #823 #820
2025-07-04 08:40:33 +09:30
Jon
61672c04e3 chore: add pytest mark for os version unit tests
ref: #823 #819
2025-07-04 08:40:33 +09:30
Jon
8ca2513952 feat(itam): Add model OperatingSystemVersion to migrate for history and notes
ref: #823 closes #819
2025-07-04 08:40:33 +09:30
Jon
0b1d658db9 refactor(itam): Update Test Suite for OperatingSystemVersion model
ref: #823 #819
2025-07-04 08:40:33 +09:30
Jon
e60081fea6 feat(itam): Add Notes Serializer for OperatingSystemVersion model
ref: #823 #819
2025-07-04 08:40:33 +09:30
Jon
7ee6970615 feat(itam): Add AuditHistory Serializer for OperatingSystemVersion model
ref: #823 #819
2025-07-04 08:40:33 +09:30
Jon
580df01cc5 feat(itam): Change model to inherit from CenturionModel for OperatingSystemVersion model
ref: #823 #819 closes #588
2025-07-04 08:40:33 +09:30
Jon
4a38f73ddf chore(itam): add missing pytest mark serializer
ref:
2025-07-04 08:40:33 +09:30
Jon
c29e5890eb chore(itam): add missing import
ref:#817 #818
2025-07-04 08:40:33 +09:30
Jon
175ab02a7d feat(itam): Add model OperatingSystem to migrate for history and notes
ref:#817 closes #818
2025-07-04 08:40:33 +09:30
Jon
434992323f refactor(itam): Update Test Suite for OperatingSystem model
ref:#817 #818
2025-07-04 08:40:33 +09:30
Jon
7cbe13ffe4 refactor(itam): Update URL route name for DeviceSoftware model
ref:#817 #818
2025-07-04 08:40:33 +09:30
Jon
5fc4d7da91 feat(itam): Add Note Serializer for DeviceSoftware model
ref:#817 #818
2025-07-04 08:40:33 +09:30
Jon
1a598fc917 feat(itam): Add AuditHistory Serializer for DeviceSoftware model
ref:#817 #818
2025-07-04 08:40:33 +09:30
Jon
465c0d8679 feat(itam): Change model to inherit from CenturionModel for DeviceSoftware model
ref:#817 #818
2025-07-04 08:40:33 +09:30
Jon
d7e70c1e62 refactor(itam): Update Test Suite for DeviceSoftware model
ref:#817 closes #802
2025-07-04 08:40:33 +09:30
Jon
48cf7b56c4 feat(itam): Change model to inherit from Centurion for DeviceSoftware model
ref:#817 #802
2025-07-04 08:40:33 +09:30
Jon
fbc2bf081e refactor(itam): Update Test Suite for DeviceDeviceOperatingSystem model
ref:#817 closes #801
2025-07-04 08:40:33 +09:30
Jon
4aaf2f87ef refactor(itam): Update URL route for DeviceDeviceOperatingSystem model
ref:#817 #801
2025-07-04 08:40:33 +09:30
Jon
32ffe34cf3 refactor(itam): Migration for updating model inheritance for DeviceDeviceOperatingSystem model
ref:#817 #801
2025-07-04 08:40:33 +09:30
Jon
281e233a7a refactor(itam): Updated Unit model test suite for DeviceType model
ref:#817 closes #803
2025-07-04 08:40:33 +09:30
Jon
b5de17441b feat(itam): Add model_tag to DeviceType model
ref:#817 #803 closes #581 #582
2025-07-04 08:40:33 +09:30
Jon
731c069c0b refactor(devops): Updated Unit model test suite for DeviceModel model
ref:#817 closes #800
2025-07-04 08:40:33 +09:30
Jon
729bcf9a57 refactor(devops): Migration for updating model inheritance for DeviceModel model
ref:#817 #800
2025-07-04 08:40:33 +09:30
Jon
3332674cb6 refactor(itam): Updated Unit model test suite for Device model
ref:#817 closes #799
2025-07-04 08:40:33 +09:30
Jon
306d4b5b7a feat(itam): Add DeviceType for history and notes data migration
ref:#817 #803
2025-07-04 08:40:33 +09:30
Jon
69e6177700 feat(itam): Add DeviceModel for history and notes data migration
ref:#817 #800
2025-07-04 08:40:33 +09:30
Jon
5e12ea7a57 feat(itam): Add DEvice for history and notes data migration
ref:#817 #799
2025-07-04 08:40:33 +09:30
Jon
5d56837f1e refactor(devops): Updated Unit model test ssuite for SoftwareEnabledFeatureFlag model
ref:#817 closes #812
2025-07-04 08:40:33 +09:30
Jon
dabf663651 refactor(devops): Migration for updating model inheritance for SoftwareEnabledFeatureFlag model
ref:#817 #812
2025-07-04 08:40:33 +09:30
Jon
1841023896 refactor(devops): Update url route basename for SoftwareEnabledFeatureFlag model
ref:#817 #812
2025-07-04 08:40:32 +09:30
Jon
d48c19a8ed feat(devops): Switch SoftwareEnabledFeatureFlag model to inherit from CenturionModel
ref: #817 #812
2025-07-04 08:40:32 +09:30
Jon
4f5a4c4124 chore: dont set model id for an instance during testing
ref: #813
2025-07-04 08:40:32 +09:30
Jon
f44fb28b8d chore: correct pytest model marks
ref: #813
2025-07-04 08:40:32 +09:30
Jon
a241ba61b0 chore(core): correct test for get_url_kwargs for meta abstract model
ref: #813
2025-07-04 08:40:32 +09:30
Jon
dbf67f7737 fix(devops): Ensure mandatory fields are writeable for model GitRepository
ref: #813 #515
2025-07-04 08:40:32 +09:30
Jon
da865fd5a8 refactor(tests): make all parameterized_ vars properties
ref: #813
2025-07-04 08:40:32 +09:30
Jon
446ea7c910 chore(core): correct test for get_url_kwargs for meta abstract model
ref: #813 #793
2025-07-04 08:40:32 +09:30
Jon
d4de500593 chore(config_management): Mark get_url methods as xfail for abstract models
ref: #813 #793
2025-07-04 08:40:32 +09:30
Jon
f81133f96c chore(config_management): ConfigGroupHost has no endpoint
ref: #813 #793
2025-07-04 08:40:32 +09:30
Jon
40e240c15b test(api): Update Functional API Permission test suite to cater for public RO endpoints
ref: #813 #767 #729
2025-07-04 08:40:32 +09:30
Jon
c5823152ca feat(devops): Update checkin model fixture so it creates the feature flag
ref: #813 #808
2025-07-04 08:40:32 +09:30
Jon
b17fcf0eac feat(devops): Add methods get_url and get_url_kwargs to CheckIn model
ref: #813 #808
2025-07-04 08:40:32 +09:30
Jon
9a737ac1c4 chore: correct inheritance order
ref: #813
2025-07-04 08:40:32 +09:30
Jon
b764ebf6e1 test(core): Ensure model mehod get_url_kwargs returns a dict for all Centurion Models
ref: #813 closes #809 #810 #811
2025-07-04 08:40:32 +09:30
Jon
6193fe0418 feat(devops): Add migration to signal
ref: #813 #811
2025-07-04 08:40:32 +09:30
Jon
18a4158f3e feat(devops): Add migration to signal
ref: #813 #810
2025-07-04 08:40:32 +09:30
Jon
82d1e9995f test(devops): Add GitLabRepository Unit Model test suite
ref: #813 #811
2025-07-04 08:40:32 +09:30
Jon
e7942a79ed chore: update test db fixture
ref: #807
2025-07-04 08:40:32 +09:30
Jon
7378b103e1 test(devops): Add GitHubRepository Unit Model test suite
ref: #807 #515 #810
2025-07-04 08:40:32 +09:30
Jon
07b6a2f4e2 test(devops): Add GitRepository Unit Model test suite
ref: #807 #515 #809
2025-07-04 08:40:32 +09:30
Jon
8f0a5386af feat(devops): Add migration to signal
ref: #807 #515 #809
2025-07-04 08:40:32 +09:30
Jon
2cb334f25f feat(devops): Add migration to signal
ref: #807 #515 #810
2025-07-04 08:40:32 +09:30
Jon
b4daa61b36 feat(devops): Update URL route basename
ref: #807 #515 #809 #810 #811
2025-07-04 08:40:32 +09:30
Jon
0e5b5db7b9 feat(devops): Migrations for switching GitLabRepository model to inherit from CenturionModel
ref: #807 #515 #811
2025-07-04 08:40:32 +09:30
Jon
0daf4a5316 feat(devops): Migrations for switching GitRepository model to inherit from CenturionModel
ref: #807 #515 #810
2025-07-04 08:40:32 +09:30
Jon
74420f13cc feat(devops): Migrations for switching GitRepository model to inherit from CenturionModel
ref: #807 #515 #809
2025-07-04 08:40:32 +09:30
Jon
192c768f9a feat(devops): Serializers for GitRepository models notes and history
ref: #807 #515 #809
2025-07-04 08:40:32 +09:30
Jon
f6dc4ff512 feat(devops): Serializers for GitHubGitRepository models notes and history
ref: #807 #515 #810
2025-07-04 08:40:32 +09:30
Jon
ec1457f3f8 feat(devops): Serializers for GitLabGitRepository models notes and history
ref: #807 #515 #809
2025-07-04 08:40:32 +09:30
Jon
2ffb93a630 feat(devops): Switch GitLabGitRepository model to inherit from CenturionModel
ref: #807 #515 #809
2025-07-04 08:40:32 +09:30
Jon
4a484c31a2 feat(devops): Switch GitHubGitRepository model to inherit from CenturionModel
ref: #807 #515 #810
2025-07-04 08:40:32 +09:30
Jon
87c5768945 feat(devops): Switch GitRepository model to inherit from CenturionModel
ref: #807 #515 #809
2025-07-04 08:40:32 +09:30
Jon
bff14dc21a refactor(core): adjust CenturionSubModel to not be it's own inheritable class
it's not required as the inheritance does not match the actual class'.

ref: #807 #767
2025-07-04 08:40:32 +09:30
Jon
6b54eebbd2 feat(devops): Update Checkin model url route basename
ref: #807 closes #808
2025-07-04 08:40:32 +09:30
Jon
9a250c988d feat(devops): Add app_namespace Checkin model
ref: #807 #808
2025-07-04 08:40:32 +09:30
Jon
d2d46e7efd test(devops): Add Checkin Unit Model test suite
ref: #807 #676 #808
2025-07-04 08:40:32 +09:30
Jon
2da0fe4e3c feat(devops): Add Checkin to migrate model history/notes
ref: #807 #808
2025-07-04 08:40:32 +09:30
Jon
d43a1bc213 feat(devops): Migrations for switching Checkin model to inherit from CenturionModel
ref: #807 #676 #808
2025-07-04 08:40:32 +09:30
Jon
53726e3eba feat(devops): Switch Checkin model to inherit from CenturionModel
ref: #807 #676 #808
2025-07-04 08:40:32 +09:30
Jon
dff529ba5e test(devops): correct GitGroup Unit model test suite
ref: #807 closes #781
2025-07-04 08:40:31 +09:30
Jon
0d149edee5 test(devops): correct FeatureFlag Unit model test suite
ref: #807 closes #782
2025-07-04 08:40:31 +09:30
Jon
80c1915598 feat(core): add TicketCommentCategory to history/notes migration
ref: #807 closes #798
2025-07-04 08:40:31 +09:30
Jon
32d296885d test(core): Add TicketCommentCategory Unit model test suite
ref: #807 #798
2025-07-04 08:40:31 +09:30
Jon
7480b371aa feat(core): add model tag to ticket comment category
ref: #807 #798
2025-07-04 08:40:31 +09:30
Jon
2d3e496e32 feat(core): Migrations for TicketCategory
ref: #807 closes #797
2025-07-04 08:40:31 +09:30
Jon
5817ff723b feat(core): add TicketCategory to history/notes migration
ref: #807 closes #797
2025-07-04 08:40:31 +09:30
Jon
abdcea07a6 test(core): Add TicketCategory Unit model test suite
ref: #807 #797
2025-07-04 08:40:31 +09:30
Jon
f234b338ee feat(core): add model tag to ticket category
ref: #807 #797
2025-07-04 08:40:31 +09:30
Jon
f2de2dc4ab feat(core): add Manufacturer to history/notes migration
ref: #807 closes #796
2025-07-04 08:40:31 +09:30
Jon
5bc7daf202 test(core): Add Manufacturer Unit model test suite
ref: #807 #796
2025-07-04 08:40:31 +09:30
Jon
ebbb7e8e6e feat(core): add model tag to manufacturer
ref: #807 #796
2025-07-04 08:40:31 +09:30
Jon
14891990f8 chore: add pytest marks to model tests
ref: #807
2025-07-04 08:40:31 +09:30
Jon
48e20a366d feat(config_management): add ConfigGroups to history/notes migration
ref: #807 closes #795
2025-07-04 08:40:31 +09:30
Jon
0c147768ba feat(config_management): add ConfigGroupSoftware to history/notes migration
ref: #807 closes #794
2025-07-04 08:40:31 +09:30
Jon
6025750637 feat(config_management): add ConfigGroupHosts to history/notes migration
ref: #807 closes #793
2025-07-04 08:40:31 +09:30
Jon
b9701757e0 feat(access): add tenant to history/notes migration
ref: #807 closes #790 #785 #786
2025-07-04 08:40:31 +09:30
Jon
d71eee7178 test(access): Add Tenant Unit serializer test suite
ref: #807 #730 #790
2025-07-04 08:40:31 +09:30
Jon
f7c6be71ba test: Add initial unit serializer test suite
ref: #807 #730
2025-07-04 08:40:31 +09:30
Jon
5d09bf04ff chore: Add action to mockview init
ref: #807
2025-07-04 08:40:31 +09:30
Jon
05c9864d68 chore: remove unique field uuid from device kwargs
ref: #805
2025-07-04 08:40:31 +09:30
Jon
1e0539f2d6 fix(access): add property organization to Tenant model
required so that perms work

ref: #805 #790
2025-07-04 08:40:31 +09:30
Jon
f7c581333a chore: Add pytest marks to tests
ref: #805
2025-07-04 08:40:31 +09:30
Jon
ac7af08598 test(access): Update Tenant URL route basename again
ref: #805 #790
2025-07-04 08:40:31 +09:30
Jon
4930523af0 feat(access): Migration for switching model inheritence to CenturionModel
ref: #805 #799
2025-07-04 08:40:31 +09:30
Jon
277c96f3a3 test(itam): Updated Unit model test for Device Model
ref: #805 #799
2025-07-04 08:40:31 +09:30
Jon
aa525407c3 feat(itam): Update model methods
ref: #805 #799
2025-07-04 08:40:31 +09:30
Jon
cf3725f12c chore: update test db fixture
ref: #805
2025-07-04 08:40:31 +09:30
Jon
4740248e7f feat(access): Migration for switching model inheritence to CenturionMixin
ref: #805 #790
2025-07-04 08:40:31 +09:30
Jon
666511b7f4 test(access): Update Tenant URL route basename
ref: #805 #790
2025-07-04 08:40:31 +09:30
Jon
a7a1d85978 test(access): Tenant Model Tests
ref: #805 #790
2025-07-04 08:40:31 +09:30
Jon
35b3710562 chore(access): disable tests to be refactored
ref: #805 #790
2025-07-04 08:40:31 +09:30
Jon
708c2ae92c feat(access): Switch model inheritence to CenturionMixin
ref: #805 #790
2025-07-04 08:40:31 +09:30
Jon
a959e4cbb5 test(api): Update Functional API Permissions to support listview models with kwargs
ref: #805 #767
2025-07-04 08:40:31 +09:30
Jon
0a3f2257e5 chore: update test db fixture
ref: #805
2025-07-04 08:40:31 +09:30
Jon
dac8e41546 test(api): exclude model ConfigGroupHosts from api permission tests as it has no endpoint
ref: #805
2025-07-04 08:40:31 +09:30
Jon
dbdfe4e6c0 refactor(core): Move CenturionModel logic to Mixin
ref: #805 #767
2025-07-04 08:40:31 +09:30
Jon
7ad1851cc0 refactor(core): rename mixin -> mixins
ref: #805 #767
2025-07-04 08:40:31 +09:30
Jon
2bdffb947f chore(base): correct typo
ref: #804
2025-07-04 08:40:31 +09:30
Jon
77c47c12b4 chore(itam): disable pre CenturionModel inheritance tests
ref: #804 #799
2025-07-04 08:40:31 +09:30
Jon
162910d9ec chore(itam): disable pre CenturionModel inheritance tests
ref: #804 #802
2025-07-04 08:40:31 +09:30
Jon
2eed0bbf4f chore(itam): disable pre CenturionModel inheritance tests
ref: #804 #801
2025-07-04 08:40:31 +09:30
Jon
d97dfa4df1 chore(itam): disable pre CenturionModel inheritance tests
ref: #804 #801
2025-07-04 08:40:31 +09:30
Jon
0f575652f9 chore(itam): disable pre CenturionModel inheritance tests
ref: #804 #802
2025-07-04 08:40:30 +09:30
Jon
cebc6b668a chore(itam): disable pre CenturionModel inheritance tests
ref: #804 #802
2025-07-04 08:40:30 +09:30
Jon
2fe75ba369 chore(base): correct typo
ref: #804
2025-07-04 08:40:30 +09:30
Jon
2f59a34b69 chore(base): Add pytest marks to pyproject.toml
ref: #804
2025-07-04 08:40:30 +09:30
Jon
613ad7e4e4 refactor(base): model instancxe code de-duplicated
ref: #804
2025-07-04 08:40:30 +09:30
Jon
f5ef97ab4a feat(itam): Update url basename
ref: #804 #794
2025-07-04 08:40:30 +09:30
Jon
a9e0749ad3 feat(itam): Update url basename
ref: #804 #795
2025-07-04 08:40:30 +09:30
Jon
9ed6bcf55c feat(base): add support for manytomany for model unit tests
ref: #804 #799
2025-07-04 08:40:30 +09:30
Jon
aa9a6e09db feat(itam): Update url basename
ref: #804 #799
2025-07-04 08:40:30 +09:30
Jon
5bdabe0793 chore(devops): disable pre CenturionModel inheritance tests
ref: #804 #782
2025-07-04 08:40:30 +09:30
Jon
40a70020a5 revert(access): revert model inheriteance work (db)
ref: #804 #791 #792
2025-07-04 08:40:30 +09:30
Jon
d129256c4e revert(access): revert model inheriteance work
ref: #804 #791
2025-07-04 08:40:30 +09:30
Jon
7753c98f43 revert(access): revert model inheriteance work
ref: #804 #792
2025-07-04 08:40:30 +09:30
Jon
496c5d57ac feat(core): Update url basename
ref: #804 #802
2025-07-04 08:40:30 +09:30
Jon
90fc516722 feat(core): Update url basename
ref: #804 #803
2025-07-04 08:40:30 +09:30
Jon
d1f003820a feat(core): Update url basename
ref: #804 #798
2025-07-04 08:40:30 +09:30
Jon
7a614c80f7 feat(core): Update url basename
ref: #804 #796
2025-07-04 08:40:30 +09:30
Jon
5e0604a44b feat(core): Update url basename
ref: #804 #800
2025-07-04 08:40:30 +09:30
Jon
b5cac23f9d feat(core): Update url basename
ref: #804 #797
2025-07-04 08:40:30 +09:30
Jon
96b83309d1 chore(device): disable pre CenturionModel inheritance tests
ref: #804 #803
2025-07-04 08:40:30 +09:30
Jon
c4c4f8eca5 chore(device): disable pre CenturionModel inheritance tests
ref: #804 #802
2025-07-04 08:40:30 +09:30
Jon
a836e0de47 chore(device): disable pre CenturionModel inheritance tests
ref: #804 #801
2025-07-04 08:40:30 +09:30
Jon
7444b9bacf chore(device): disable pre CenturionModel inheritance tests
ref: #804 #800
2025-07-04 08:40:30 +09:30
Jon
4a9de878ed chore(device): disable pre CenturionModel inheritance tests
ref: #804 #799
2025-07-04 08:40:30 +09:30
Jon
48ea6c4491 chore(core): disable ticket tests for ticket models that are being depreciated
ref: #804 #564
2025-07-04 08:40:30 +09:30
Jon
b3c9f00a08 chore: update fixtures
ref: #804
2025-07-04 08:40:30 +09:30
Jon
8200b47025 fix(itam): Add missing import now
ref: #804 #799
2025-07-04 08:40:30 +09:30
Jon
c70dd867c9 test(api): API Permissions Functional test to supprt name as unique field
ref: #804
2025-07-04 08:40:30 +09:30
Jon
725782af6e feat(access): TeamUsers do not require notes
ref: #804 #792
2025-07-04 08:40:30 +09:30
Jon
2e41922d9c chore: add test fixtures for models
ref: #804 #771
2025-07-04 08:40:30 +09:30
Jon
d3b4958a01 chore: update test db fixture
ref: #804
2025-07-04 08:40:30 +09:30
Jon
7326598f6c fix(core): notes meta model must add model_kwargs fixture
ref: #804 #768
2025-07-04 08:40:30 +09:30
Jon
35b72a048e fix(core): clean_fields for created_by field belongs in model that contains field
ref: #804 #768
2025-07-04 08:40:30 +09:30
Jon
ab68b56056 feat(config_management): ConfigGroupHosts and ConfigGroupSoftware do not require notes
ref: #804 #793 #794
2025-07-04 08:40:30 +09:30
Jon
7b55d37117 fix(core): audit meta model must add model_kwargs fixture
ref: #804
2025-07-04 08:40:30 +09:30
Jon
39d3d0786b fix: model fixture names must match model_name
ref: #804
2025-07-04 08:40:30 +09:30
Jon
41fde61184 chore(core): mock further attributes
ref: #804
2025-07-04 08:40:30 +09:30
Jon
18036ee8d0 chore(config_managment): disable pre CenturionModel inheritance tests
ref: #804 #794
2025-07-04 08:40:30 +09:30
Jon
ec95f4b45d chore(config_managment): disable pre CenturionModel inheritance tests
ref: #804 #795
2025-07-04 08:40:30 +09:30
Jon
520008acff fix: clean up mock model from django apps
ref: #804
2025-07-04 08:40:30 +09:30
Jon
a3b9815891 chore(core): disable pre CenturionModel inheritance tests
ref: #804 #796 #797 #798
2025-07-04 08:40:29 +09:30
Jon
dc56ced765 test(config_management): Completed ConfigGroupSoftware Model Tests
ref: #804 #794
2025-07-04 08:40:29 +09:30
Jon
8c4e5d5c1d test(config_management): Completed ConfigGroup Model Tests
ref: #804 #795
2025-07-04 08:40:29 +09:30
Jon
0e604228aa test(config_management): Completed ConfigGroupHost Model Tests
ref: #804 #793
2025-07-04 08:40:29 +09:30
Jon
4fda640832 chore: for mode instance, actually create it
ref: #804
2025-07-04 08:40:29 +09:30
Jon
9fec7f69f5 chore: add spt to class test cases for fields to be set as non-existant
ref: #804
2025-07-04 08:40:29 +09:30
Jon
71108f6089 refactor(config_management): Add ConfigGroupHost Model Tests
ref: #804 #793
2025-07-04 08:40:29 +09:30
Jon
39208edf93 refactor(config_management): Add ConfigGroupSoftware Model Tests
ref: #804 #794
2025-07-04 08:40:29 +09:30
Jon
2118e56808 refactor(config_management): Add ConfigGroup Model Tests
ref: #804 #795
2025-07-04 08:40:29 +09:30
Jon
d86a719f24 chore(config_management): disable old ConfigGroupSoftware tests
ref: #804 #794
2025-07-04 08:40:29 +09:30
Jon
5c27115991 chore(assistance): disable old ConfigGroup tests
ref: #804 #795
2025-07-04 08:40:29 +09:30
Jon
52235e2e82 chore(assistance): correct fixuture kwargs for kb
ref: #804 #795
2025-07-04 08:40:29 +09:30
Jon
d714476c97 chore(access): remove tests for models that will be depreciated
ref: #804 #791 #792
2025-07-04 08:40:29 +09:30
Jon
274347ebc1 fix(core): When obtaining model fields ensure it exists first
ref: #789 #767
2025-07-04 08:40:29 +09:30
Jon
276e322eef chore(access): TeamUser model does not require audithistory
model will be depreciated soon

ref: #789 #792
2025-07-04 08:40:29 +09:30
Jon
f56ee55347 chore: Update test db fixtures
ref: #789
2025-07-04 08:40:29 +09:30
Jon
ad1f92cdb4 chore(access): Team model Unit Tests for skip
ref: #789 #791
2025-07-04 08:40:29 +09:30
Jon
7cc8192ec2 feat(config_management): Add url_kwargs to ConfigGroupSoftware model
ref: #789 #794
2025-07-04 08:40:29 +09:30
Jon
9509765ba5 feat(access): Add url_kwargs to Team model
ref: #789 #791
2025-07-04 08:40:29 +09:30
Jon
8b694aabf5 feat(access): Add url_kwargs to TeamUser model
ref: #789 #792
2025-07-04 08:40:29 +09:30
Jon
8f0d0fbe16 chore: Remove all references to field is_global
field no longer used

ref: #789 #767
2025-07-04 08:40:29 +09:30
Jon
8c406e1d59 feat(access): Update TeamUser API basename
ref: #789 #792
2025-07-04 08:40:29 +09:30
Jon
9ab4e4ec7e feat(access): Update Team API basename
ref: #789 #791
2025-07-04 08:40:29 +09:30
Jon
2e5d6d4894 fix(access): use getattr instead as attribute may exist as None
ref: #789
2025-07-04 08:40:29 +09:30
Jon
bcd66fd657 feat(itam): switch model Device to inheirt from CenturionModel
ref: #789 #799
2025-07-04 08:40:29 +09:30
Jon
8b8ee525f7 feat(itam): switch model DeviceType to inheirt from CenturionModel
ref: #789 #803
2025-07-04 08:40:29 +09:30
Jon
3e63f896a5 feat(itam): switch model DeviceModel to inheirt from CenturionModel
ref: #789 #800
2025-07-04 08:40:29 +09:30
Jon
7173d9f554 feat(core): switch model TicketCategory to inheirt from CenturionModel
ref: #789 #797
2025-07-04 08:40:29 +09:30
Jon
20b173bf1c feat(core): switch model TicktetCommentCategory to inheirt from CenturionModel
ref: #789 #798
2025-07-04 08:40:29 +09:30
Jon
ac6f580153 feat(core): switch model Manufacturer to inheirt from CenturionModel
ref: #789 #796
2025-07-04 08:40:29 +09:30
Jon
d06bf78d0a fix(assistance): make kb article field longer for model name
ref: #789
2025-07-04 08:40:29 +09:30
Jon
e75bc124c9 feat(config_management): switch model ConfigGroupHosts to inheirt from CenturionModel
ref: #789 #795
2025-07-04 08:40:29 +09:30
Jon
fc60d7f3be feat(config_management): switch model ConfigGroupSoftware to inheirt from CenturionModel
ref: #789 #795
2025-07-04 08:40:29 +09:30
Jon
cff3bc5b2c feat(config_management): switch model ConfigGroups to inheirt from CenturionModel
ref: #789 #795
2025-07-04 08:40:29 +09:30
Jon
8202a37576 feat(access): switch model TeamUsers to inheirt from CenturionModel
ref: #789 #792
2025-07-04 08:40:29 +09:30
Jon
5186b2f173 feat(access): switch model Team to inheirt from CenturionModel
ref: #789 #791
2025-07-04 08:40:29 +09:30
Jon
e9a8ad1c48 test(core): mock the user object within the model context
ref: #789 #759
2025-07-04 08:40:28 +09:30
Jon
143dd2af35 chore(access): remove old ui mixin
ref: #789 #757
2025-07-04 08:40:28 +09:30
Jon
09beeb46af test(core): creating a model is a functional not unit test
ref: #789 #759
2025-07-04 08:40:28 +09:30
Jon
883c0961f6 chore: as part of api func tests, dont delete api perms user as part of fixture cleanup
ref: #789
2025-07-04 08:40:28 +09:30
Jon
3d9cde3b25 chore: Add support for confftest for parameterized tests to have no values
ref: #789
2025-07-04 08:40:28 +09:30
Jon
1d80cdd5c3 docs: update release notes
ref: #789
2025-07-04 08:40:28 +09:30
Jon
86da111b85 chore(project_management): Remove API v1 code
ref: #789 #343
2025-07-04 08:40:28 +09:30
Jon
38b1746f26 chore(itam): Remove API v1 code
ref: #789 #343
2025-07-04 08:40:28 +09:30
Jon
f6e3390d26 chore(core): Remove API v1 code
ref: #789 #343
2025-07-04 08:40:28 +09:30
Jon
cf8feb2637 chore(config_management): Remove API v1 code
ref: #789 #343
2025-07-04 08:40:28 +09:30
Jon
f2a2352a3c chore(base): Remove API v1 code
ref: #789 #343
2025-07-04 08:40:28 +09:30
Jon
78334da031 chore(api): Remove API v1 code
ref: #789 #343
2025-07-04 08:40:28 +09:30
Jon
398b78855d chore(access): Remove API v1 code
ref: #789 #343
2025-07-04 08:40:28 +09:30
Jon
7691ad5b0b feat(core): If user context not supplied, dont create audithistory for model
this allows tests and direct creation via code if required.

ref: #789 #759
2025-07-04 08:40:28 +09:30
Jon
a8e2536bd2 chore(base): remove tests no longer used
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
dd9a906073 chore(base): remove methods no longer used in context processor
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
82bfacbab3 chore: disable api field notess and history tests
tests being re-written

ref: #788 #759 #768
2025-07-04 08:40:28 +09:30
Jon
728db3f740 chore: Add premeta notes and history models to init so they can be migrated
ref: #788 #759 #768
2025-07-04 08:40:28 +09:30
Jon
8a390b9caf chore(core): remove old old history model
ref: #788 #759
2025-07-04 08:40:28 +09:30
Jon
3155794931 chore(core): Remove Template tags
not using django ui anymore

ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
f79a9d628b chore(api): Remove pre-meta history code from common serializer
ref: #788 #759
2025-07-04 08:40:28 +09:30
Jon
bf39631db8 chore(settings): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
3c114abb11 chore(project_management): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
a30ba02def chore(itim): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
aa7de88f8d chore(itam): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
24c960dc86 chore(devops): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
0ded2bcebd chore(core): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
82f0f87878 chore(config_management): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
0792dd1604 chore(api): Remove pre-meta notes code from common serializer
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
baa9a6206d chore(accounting): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
bf7179b4f9 chore(access): Remove pre-meta notes code
ref: #788 #768
2025-07-04 08:40:28 +09:30
Jon
b8db09d9b8 chore: temp disable api field notes and history checks
ref: #788
2025-07-04 08:40:28 +09:30
Jon
9ff93976f2 chore(base): pass instance of model for class tests
ref: #788
2025-07-04 08:40:28 +09:30
Jon
b535aa4703 chore(project_management): disable project test that contain kb untill rewrite
ref: #788 #735
2025-07-04 08:40:28 +09:30
Jon
074aa4832a feat(access): Add init to tenancy model to clear state
ref: #788 #767
2025-07-04 08:40:28 +09:30
Jon
cc483e2cb5 chore(core): disable ticket linked item kb article functional test
ref: #788 #735
2025-07-04 08:40:28 +09:30
Jon
f8faa7f040 chore(settings): Remove no longer used Django UI
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
764e631be6 chore(project_management): Remove no longer used Django UI
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
882c2afc9f chore(itim): Remove no longer used Django UI
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
6aa7953c2a chore(itam): Remove no longer used Django UI
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
25d510f086 chore(core): Remove no longer used Django UI
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
97b07e1663 chore(config_management): Remove no longer used Django UI
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
3d961ecc9e chore(base): disable tests that require rewrite
ref: #788 #735
2025-07-04 08:40:28 +09:30
Jon
05921057fd chore(assistance): Remove no longer used Django UI
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
90f68d7fe5 chore(api): Remove old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:28 +09:30
Jon
642ecc4e6c chore(access): Remove no longer used Django UI
ref: #788 #757
2025-07-04 08:40:28 +09:30
Jon
b1530b3c19 chore(base): Dont reload model, reset the parts that change in tests
creates issues with mocking

ref: #788
2025-07-04 08:40:28 +09:30
Jon
c64add9ce7 chore(core): disable old delete so it's no longer used by models yet to inherit from CenturionModel
ref: #788 #759
2025-07-04 08:40:28 +09:30
Jon
3915678675 feat(core): Ensure that model has user context
ref: #788 #759
2025-07-04 08:40:27 +09:30
Jon
f42e255f37 chore(core): disable old delete so it's no longer used by models yet to inherit from CenturionModel
ref: #788 #759
2025-07-04 08:40:27 +09:30
Jon
c0455af2fa chore(itam): mock base delete so abstract classes can be called
ref: #788
2025-07-04 08:40:27 +09:30
Jon
4d211a2cb7 chore(assistance): disable tests that require rewrite
ref: #788 #735
2025-07-04 08:40:27 +09:30
Jon
3205f9e946 chore(base): add fixture try block
ref: #788
2025-07-04 08:40:27 +09:30
Jon
0c62172f03 chore(base): fixture sanitization
ref: #783
2025-07-04 08:40:27 +09:30
Jon
c8a5bbcfb6 chore(itam): Remove more old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
cf5f43f33c chore(settings): Remove old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
3f05100cde chore(project_management): Remove old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
b6bc39e784 chore(itim): Remove old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
d4350dc444 chore(itam): Remove old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
c3905360f4 chore(core): Remove old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
71e2d2f112 chore(config_management): Remove old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
d0f3923226 chore(access): Remove old Notes Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
a53f4caa81 chore(settings): fixture sanitization
ref: #783
2025-07-04 08:40:27 +09:30
Jon
d18c9006d2 chore(settings): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
388f9a6039 chore(project_management): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
0a1166f1df chore(itim): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
74e54343b9 chore(itam): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
2cec1be952 chore(human_resources): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
b21b0f0b5b chore(core): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
731df89b40 chore(config_management): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
072cda66bf chore(accounting): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
d3f367f4b9 chore(access): Remove old History Tests
ref: #783 #735 #759
2025-07-04 08:40:27 +09:30
Jon
391a2f7767 feat(core): Add supprt to model_instance fixture for manytomany field
ref: #783
2025-07-04 08:40:27 +09:30
Jon
40ffdd86ba fix(assistance): Add missing field model_notes to KB serializer
ref: #783 #785
2025-07-04 08:40:27 +09:30
Jon
223aae2eb4 chore(assistance): Remove old KB notes
ref: #783 #785
2025-07-04 08:40:27 +09:30
Jon
22e35fbf1c chore(assistance): Remove old KB Category notes
ref: #783 #786
2025-07-04 08:40:27 +09:30
Jon
ba6f09c9b5 chore(base): Update test db creation fixtures
ref: #783
2025-07-04 08:40:27 +09:30
Jon
2509743597 refactor(assistance): Refactor KnowledgeBaseCategory Unit model tests
ref: #783 #786 #735
2025-07-04 08:40:27 +09:30
Jon
b76bc5a416 refactor(assistance): Update KnowledgeBase Unit viewset url basename
ref: #783 #785 #735
2025-07-04 08:40:27 +09:30
Jon
a6d781be47 refactor(assistance): Refactor KnowledgeBase Unit model tests
ref: #783 #785 #735
2025-07-04 08:40:27 +09:30
Jon
69bbe94b06 feat(core): Add supprt to model create test for manytomany field
ref: #783
2025-07-04 08:40:27 +09:30
Jon
be3ce40471 chore(assistance): Remove KnowledgeBase Note ViewSet
ref: #783 #785
2025-07-04 08:40:27 +09:30
Jon
98fd342343 chore(assistance): Remove KnowledgeBaseCategory Note ViewSet
ref: #783 #786
2025-07-04 08:40:27 +09:30
Jon
e0a4526d0c chore(assistance): TMP disable KB category tests that require refactor
ref: #783 #786
2025-07-04 08:40:27 +09:30
Jon
2b6d421b91 chore(assistance): TMP disable KB tests that require refactor
ref: #783 #785
2025-07-04 08:40:27 +09:30
Jon
a3fda45055 feat(assistance): migrations for new history and notes models for KnowledgeBaseCategory model
ref: #783 #786
2025-07-04 08:40:27 +09:30
Jon
0a0577aa24 feat(assistance): migrations for new history and notes models for KnowledgeBase model
ref: #783 #785
2025-07-04 08:40:27 +09:30
Jon
78ed699463 feat(assistance): Model inheritance migrations
ref: #783 #785 #786
2025-07-04 08:40:27 +09:30
Jon
6d0f655c97 chore(assistance): remove old history and notes tests for KnowledgeBaseCategory model
ref: #783 #786
2025-07-04 08:40:27 +09:30
Jon
2220dcf851 chore(assistance): remove old history and notes tests for KnowledgeBase model
ref: #783 #785
2025-07-04 08:40:27 +09:30
Jon
a5a391fba6 refactor(assistance): Add new history and notes Serializer for KnowledgeBase model
ref: #783 #785
2025-07-04 08:40:27 +09:30
Jon
de9358c943 refactor(assistance): Add new history and notes Serializer for KnowledgeBaseCategory model
ref: #783 #786
2025-07-04 08:40:27 +09:30
Jon
f5b1738fd2 refactor(assistance): Change KnowledgeBaseCategory model inheritance TenancyObject -> CenturionModel
ref: #783 #786
2025-07-04 08:40:27 +09:30
Jon
b80cc3e839 refactor(assistance): Change KnowledgeBase model inheritance TenancyObject -> CenturionModel
ref: #783 #785
2025-07-04 08:40:27 +09:30
Jon
734c29f41b refactor(assistance): MV kb category model to its own file
ref: #783
2025-07-04 08:40:27 +09:30
Jon
507182983b chore(devops): Remove GitGroup old notes URL route
ref: #783 #781
2025-07-04 08:40:26 +09:30
Jon
0a413a6581 chore(devops): Remove GitGroup old notes serializer
ref: #783 #781
2025-07-04 08:40:26 +09:30
Jon
c476f2a12c chore(devops): Remove GitGroup old notes viewset
ref: #783 #781
2025-07-04 08:40:26 +09:30
Jon
0f3da21aa4 chore(devops): Add FeatureFlag old history and notes models to init so they exist
ref: #783 #782
2025-07-04 08:40:26 +09:30
Jon
d5b465ea0e chore(devops): Add GitGroup old history and notes models to init so they exist
ref: #783 #781
2025-07-04 08:40:26 +09:30
Jon
caeabe0793 feat(core): Migrate Centurion Model history and notes within a post_migrate signal
ref: #783 #758 #759 #778 #768
2025-07-04 08:40:26 +09:30
Jon
9dc2114258 fix(core): Before attempting to get model audit data confirm fields dont already exist
ref: #783
2025-07-04 08:40:26 +09:30
Jon
91b33be834 fix(api): check if model has notes enabled before adding url to body
ref:
2025-07-04 08:40:26 +09:30
Jon
6f66b4cf95 test(devops): re-implement temp removed test suites.
ref: #780 #515 #782
2025-07-04 08:40:26 +09:30
Jon
0abb416620 test(api): API Permissions Auto-Creator test suite
ref: #780 #730 #767
2025-07-04 08:40:26 +09:30
Jon
3a010e166e test(devops): Add GitGroup API Permissions tests
ref: #780 #515
2025-07-04 08:40:26 +09:30
Jon
616f37fca2 test(core): Add fixtures for api permission tests
ref: #780 #730
2025-07-04 08:40:26 +09:30
Jon
c042725dc7 test(core): rewrite api permissions test suite to use pytest and fixtures
ref: #780 #730
2025-07-04 08:40:26 +09:30
Jon
026c408754 feat(core): Add ability to CenturionModel get_url to be either detail/list
ref: #780 #767
2025-07-04 08:40:26 +09:30
Jon
ae42147f69 fix(api): Only return View Serialized data if status code is HTTP/2xx
ref: #780
2025-07-04 08:40:26 +09:30
Jon
764ae1133d chore: update db test fixture
ref: #780
2025-07-04 08:40:26 +09:30
Jon
1d31a259df refactor(tests): Create global model fixtures
ref: #780 #729
2025-07-04 08:40:26 +09:30
Jon
66d14ea5bb chore(tests): Depreciate old FeateFlag Tests
ref: #780 #729
2025-07-04 08:40:26 +09:30
Jon
2f22d0f135 docs(development): Update test suit locations
ref: #780 #729
2025-07-04 08:40:26 +09:30
Jon
56bb1863f2 chore: move api render to functional dir
ref: #780 #729
2025-07-04 08:40:26 +09:30
Jon
9790ee51f3 chore(devops): Remove FeatureFlag Notes Tests
ref: #780 #782
2025-07-04 08:40:26 +09:30
Jon
8892ba7e3f chore(devops): Remove FeatureFlag History Tests
ref: #780 #782
2025-07-04 08:40:26 +09:30
Jon
9e93c12860 chore(devops): Remove FeatureFlag notes URLRoute
ref: #780 #782
2025-07-04 08:40:26 +09:30
Jon
cf3c177715 chore(devops): Remove FeatureFlag notes ViewSet
ref: #780 #782
2025-07-04 08:40:26 +09:30
Jon
db93903119 chore(devops): Remove FeatureFlag notes Serializer
ref: #780 #782
2025-07-04 08:40:26 +09:30
Jon
4414f585a6 feat(core): New Management command to list models
ref: #780 #771
2025-07-04 08:40:26 +09:30
Jon
f6634bab78 refactor(devops): Switch FeatureFlag model unit tests to CenturionModel
ref: #780 #782
2025-07-04 08:40:26 +09:30
Jon
ef294cc081 feat(devops): Switch model FeatureFlag inheritance to CenturionModel
ref: #780 #782
2025-07-04 08:40:26 +09:30
Jon
2d1ec6a84a docs: Update model notes docs for new meta model
ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
b37a284a0a test(core): Ensure Method clean_fields functions for CenturionNotesModel
ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
1fa3278b73 test(core): Function Model test suite for CenturionModelNote Meta Models
ref: #779 #778 #768
2025-07-04 08:40:26 +09:30
Jon
5bf9c30c58 chore: Update test fixtures
ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
637a76f1fe test(core): Interim Unit Model test suite for CenturionModelNote Meta Models
ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
9afca66ad6 test(core): Interim Unit Model test suite for CenturionModelNote
ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
031fd79f13 feat(core): Disable Notes for model CenturionModelNote
A notes model does not require notes

ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
5429c17f98 feat(devops): Enable Model notes for GitGroup
ref: #779 #778 #515
2025-07-04 08:40:26 +09:30
Jon
473ffb0ec0 feat(core): add Swagger docs for CenturionModelNotes ViewSet
ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
62e7eb9c47 feat(core): Meta Model for CenturionModelNotes
ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
695bfa7f51 feat(core): Finalize Serializer for CenturionModelNotes
ref: #779 #778
2025-07-04 08:40:26 +09:30
Jon
a5227f0608 feat(api): Add to common serializer meta notes model for notes url
ref: #779 #767
2025-07-04 08:40:26 +09:30
Jon
1d77247e40 feat(core): Interim Meta model CenturionNotes
ref: #776 #778
2025-07-04 08:40:26 +09:30
Jon
bb774bc2c9 feat(core): Interim ViewSet for model CenturionNotes
ref: #776 #778
2025-07-04 08:40:26 +09:30
Jon
ce96d71083 feat(core): URL Route for model CenturionNotes
ref: #776 #778
2025-07-04 08:40:26 +09:30
Jon
c905f8c010 feat(core): Serializer for model CenturionNotes
ref: #776 #778
2025-07-04 08:40:26 +09:30
Jon
084bdf61bd feat(core): Migration for model CenturionNotes
ref: #776 #778
2025-07-04 08:40:26 +09:30
Jon
21b3aa3b4a feat(core): Add model CenturionNotes
ref: #776 #778
2025-07-04 08:40:26 +09:30
Jon
8c6e863403 chore: correct liniting errors
ref: #776
2025-07-04 08:40:26 +09:30
Jon
f890fb6d52 feat(devops): dont allow deleting a git group if it has children
ref: #776
2025-07-04 08:40:25 +09:30
Jon
0babe48208 chore: correct liniting errors
ref: #776
2025-07-04 08:40:25 +09:30
Jon
4290136b69 chore: update pylint to v3.3.7
ref: #776
2025-07-04 08:40:25 +09:30
Jon
121a0c3f2c refactor(settings): move url routes from core.urls to own module urls_api.py
ref: #776 closes #777
2025-07-04 08:40:25 +09:30
Jon
e04869cc65 refactor(project_management): move url routes from core.urls to own module urls_api.py
ref: #776 #777
2025-07-04 08:40:25 +09:30
Jon
dc6d34de71 refactor(itim): move url routes from core.urls to own module urls_api.py
ref: #776 #777
2025-07-04 08:40:25 +09:30
Jon
0b7fcbbc26 refactor(itam): move url routes from core.urls to own module urls_api.py
ref: #776 #777
2025-07-04 08:40:25 +09:30
Jon
1cc378c69a refactor(core): move url routes from core.urls to own module urls_api.py
ref: #776 #777
2025-07-04 08:40:25 +09:30
Jon
959b8ac51a refactor(config_management): move url routes from core.urls to own module urls_api.py
ref: #776 #777
2025-07-04 08:40:25 +09:30
Jon
f4f9729c7d refactor(assistance): move url routes from core.urls to own module urls_api.py
ref: #776 #777
2025-07-04 08:40:25 +09:30
Jon
54195c271a refactor(access): move url routes from core.urls to own module urls_api.py
ref: #776 #777
2025-07-04 08:40:25 +09:30
Jon
79b8cdd26b chore: add fixture to setup user perms for api tests
ref: #776 #730 #735
2025-07-04 08:40:25 +09:30
Jon
f53531fbbd docs(development): Audit History API Docs added
ref: #776 #759
2025-07-04 08:40:25 +09:30
Jon
6141ad1d5a docs(development): Audit History updates
ref: #776 #759
2025-07-04 08:40:25 +09:30
Jon
428770a8eb chore: rm pylint error
this file is due for refactor so urls are in own modules

ref: #776
2025-07-04 08:40:25 +09:30
Jon
11e12ec70f chore: code review fixes
ref: #775
2025-07-04 08:40:25 +09:30
Jon
ba64fdd36e chore: add further pylint rules
ref: #775
2025-07-04 08:40:25 +09:30
Jon
416b6f5a75 test(core): Dynamic Unit Test Suites for Meta Models AuditHistory
ref: #775 #759 #767
2025-07-04 08:40:25 +09:30
Jon
adc1c8fba7 test(core): Unit Test Centurion Model method __str__
ref: #767
2025-07-04 08:40:25 +09:30
Jon
ade35d0e2d test(core): Unit Test Centurion Model method get_url_kwargs
ref: #775 #759 #767
2025-07-04 08:40:25 +09:30
Jon
212af84d28 test(core): Unite Tesxt Centurion Model method get_url attr _is_submodel set
ref: #775 #759 #767
2025-07-04 08:40:25 +09:30
Jon
7ed75fc3e9 test(core): Unite Tesxt Centurion Model method get_url attr model_name set
ref: #775 #767
2025-07-04 08:40:25 +09:30
Jon
e554923c0b feat(devops): Add model tag attribute to model
ref: #773 #515 #576
2025-07-04 08:40:25 +09:30
Jon
17f4295763 feat(core): Add to Centurion Model an attribute to set the models tag
ref: #773 #767 #576
2025-07-04 08:40:25 +09:30
Jon
8e81bc06db docs(user): Add AuditHsitory Docs
ref: #773 #759
2025-07-04 08:40:25 +09:30
Jon
0b30f3b70f feat(core): Add Context to model when ViewSet loads
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
827894ef23 feat(devops): Add AuditHistory Serializer for GitGroup
ref: #773 #759
2025-07-04 08:40:25 +09:30
Jon
7a2e77cba6 feat(core): Add AuditHistory Serializer
ref: #773 #759
2025-07-04 08:40:25 +09:30
Jon
187ad724a2 feat(core): Add AuditHistory ViewSet
ref: #773 #759
2025-07-04 08:40:25 +09:30
Jon
9e2587d6c3 feat(core): Add URL route for AuditHistory
ref: #773 #759
2025-07-04 08:40:25 +09:30
Jon
21e7d7b444 feat(core): Add audithistory URL to serializer for models with _audit_enabled=True
ref: #773 #767 #759
2025-07-04 08:40:25 +09:30
Jon
26b5aa7f45 docs(development): Initial Serializer docs
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
37ff9d38cb fix(core): Conduct kwargs check fr ticket comment serializer during init
ref: #773
2025-07-04 08:40:25 +09:30
Jon
f440788dae refactor(api): Update Common ViewSet methds for re-write
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
279ea1991d feat(core): Models url kwarg helper
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
6b899e477d feat(core): Support setting custom model name for url basename
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
9a3e17a6d3 feat(api): Add sub-model filter to get_queryset method
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
851d6e8b2f chore: correct test so it works
ref: #773 #759
2025-07-04 08:40:25 +09:30
Jon
114b2e1ae3 test(core): Ensure model that has audit enableed has audit model
ref: #773 #515
2025-07-04 08:40:25 +09:30
Jon
2b6a15cf8f test(core): Add Functional model Test Suite for CenturionAuditModel
ref: #773 #515
2025-07-04 08:40:25 +09:30
Jon
a46187f36e test(devops): Ensure that a Github group cant have a parent/"be nested"
ref: #773 #515 #249
2025-07-04 08:40:25 +09:30
Jon
fc256445db test(devops): Ensure that when create a child git group that the tenancy matches the parent git group
ref: #773 #515
2025-07-04 08:40:25 +09:30
Jon
60f6269a71 test(devops): Add Functional model Test Suite
ref: #773 #515
2025-07-04 08:40:25 +09:30
Jon
660da485cd test(core): Add Base Centurion model Functional Test Suite
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
d86b07b4fa test(access): Add Base Tenancy model Functional Test Suite
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
ea7cea2aa9 test(base): Add Base model Functional Test Suite
ref: #773 #767
2025-07-04 08:40:25 +09:30
Jon
06e8e277c1 feat(core): Disable models audit history on model delete
can't create an audit entry without a model, why? it was deleted

ref: #773 #759
2025-07-04 08:40:25 +09:30
Jon
df4ffa5e93 fix(core): Enable CenturionAudit model to get model history for item being deleted
ref: #773 #759
2025-07-04 08:40:24 +09:30
Jon
15ab6a7f70 chore: update test fixtures
ref: #773
2025-07-04 08:40:24 +09:30
Jon
8e0906eb73 test(core): Model Unit Tests for AuditHistory get_model_history method
ref: #773 #759
2025-07-04 08:40:24 +09:30
Jon
685de22ad2 chore: add pytest marks to tests
ref: #772
2025-07-04 08:40:24 +09:30
Jon
62ec58d9d8 test(core): reset vals so as not to fuck other tests over
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
ee79dafd6b test(core): Correct test for method get_audit_values for CenturionAbstractModel
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
d31b70a2a0 chore(core): update Current ModelHistory query to exclude new AuditHistory model
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
766b4272be chore(devops): remove tests that were left there when file was copied from another test suite
ref: #772 #515
2025-07-04 08:40:24 +09:30
Jon
76daab8e1f chore: adjust test so params are under a property
ref: #772
2025-07-04 08:40:24 +09:30
Jon
82e617afbe fix(core): When creating the AuditHistory entry for a model, use the user from context
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
197cf4eb73 fix(core): When collecting AuditHistory cater for models being created
ref: #772 #767
2025-07-04 08:40:24 +09:30
Jon
5a80e48b21 feat(core): Use Previous TenancyManager until UserModel rewrite done
ref: #772 #766 #767
2025-07-04 08:40:24 +09:30
Jon
bd66b8ec94 chore: remove Adding of history tasks from issue_template for new models
ref: #772
2025-07-04 08:40:24 +09:30
Jon
d8b69e3ff2 fix(api): remove surerflous feature for fetching app_namespace for models metadata
if the model required the parent models `app_namespace` it already exists when the class is inerited,

ref: #772
2025-07-04 08:40:24 +09:30
Jon
cff519d199 test(devops): Initial Model Unit tests for GitGroup
ref: #772 #515
2025-07-04 08:40:24 +09:30
Jon
2e88dfc5c1 refactor(devops): Switch GitGroup Model to CenturionModel
ref: #772 #515 #759 #767
2025-07-04 08:40:24 +09:30
Jon
f5a2168958 feat(core): Process a models history within AuditHistory
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
35a46c90d3 feat(core): Enable AuditHistory signal to start when apps are ready
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
bc1f12c47f feat(core): Add model instance to history object during history creation
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
7a1e9e10a3 feat(core): Update Meta AuditModel db_name to be suffixed _audithistory
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
9425793190 fix(core): Correct attribute names for referencing a Centurion Model from an AuditModel
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
d3347082d1 test(core): Add field model_notes as an excluded field for AuditModels
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
12ec0f34f9 feat(core): remove unnessecary method clean_fields from audit model
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
5e169eb7f8 chore(core): Add temp objects to CenturionAbstractModel to support depreciated features
these will be removed when #767 is complete

ref: #772 #767
2025-07-04 08:40:24 +09:30
Jon
105d89ee61 fix(core): Correct before lookup for current models audit history
ref: #772 #759 #767
2025-07-04 08:40:24 +09:30
Jon
64e53f6980 feat(core): remove un-needed field model_notes from audit models
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
0c6a15d22d docs(development): Add new abstract models to API docs
ref: #772
2025-07-04 08:40:24 +09:30
Jon
db41c73300 test(core): Remaining Unit Model Test Cases for CenturionAuditMeta Model
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
da3a471d04 docs(development): Partial update to models
ref: #772 #767
2025-07-04 08:40:24 +09:30
Jon
b5147e2448 refactor(core): Loading of meta models should not be hidden behind program start ags
Meta Models must always exist

ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
0a35a32136 test(core): Initial Unit Model Test Cases for CenturionAuditMeta Model
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
8b62014d88 test(core): Unit Model Test Cases for CenturionSubAbstract model
ref: #772 #767
2025-07-04 08:40:24 +09:30
Jon
16bbb3328b test(core): Initial Unit Model Test Cases for CenturionAudit Model
ref: #772 #759
2025-07-04 08:40:24 +09:30
Jon
d0ce759635 test(core): Unit test cases for Centurion get_url relative + non-relative
ref: #772 #767
2025-07-04 08:40:24 +09:30
Jon
6f0ef8ab31 test(access): Unit Model Tests for TenancyAbstractModel
ref: #770 #767 #445
2025-07-04 08:40:24 +09:30
Jon
28117bb2bb chore(core): remove methods not required
ref: #770 #767
2025-07-04 08:40:24 +09:30
Jon
4d93ba7339 refactor(core): To obtain audit_values loop through model fields
ref: #770 #767
2025-07-04 08:40:24 +09:30
Jon
d098a09e83 fix(core): When deleting a model check if sub-model within delete method
ref: #770 #767
2025-07-04 08:40:24 +09:30
Jon
678bc18cb6 test(base): Unit Common Model test cases suite
ref: #770 #758 #767
2025-07-04 08:40:24 +09:30
Jon
8fd418787e test(base): Unit Common Class test cases suite
ref: #770 #758 #767
2025-07-04 08:40:24 +09:30
Jon
85d8d74cbf test(access): Unit Model Tests for TenancyAbstractModel
ref: #770 #758 #767
2025-07-04 08:40:24 +09:30
Jon
3e6d9233ca chore(pytest): rename pytest_configure -> pytest_report_header
ref: #770
2025-07-04 08:40:24 +09:30
Jon
06ad1fec5e chore(pytest): Create and use fixture of Fresh DB instead of migrations for testing
ref: #770
2025-07-04 08:40:24 +09:30
Jon
95281d35eb chore(pytest): give parameterized tests the option to use functions as a value
ref: #770
2025-07-04 08:40:24 +09:30
Jon
5aae562caf feat(core): Run meta models create on Core module ready
ref: #770 #759
2025-07-04 08:40:24 +09:30
Jon
49e66df006 feat(core): New model core.CenturionAudit
ref: #770 #759
2025-07-04 08:40:24 +09:30
Jon
504ded9047 feat(core): cause sub-audit models to chuck a wobbler if clean_fields not re-implementated
ref: #770 #759
2025-07-04 08:40:24 +09:30
Jon
a7f84924db chore: remove unused imports
ref: #770
2025-07-04 08:40:24 +09:30
Jon
6647ddbc99 chore: comment out test setup for skeleton test suites not in use yet
ref: #770
2025-07-04 08:40:24 +09:30
Jon
73fdaee33f refactor: rejig whats in each inherited centurion model
ref: #770
2025-07-04 08:40:24 +09:30
Jon
0884bc314a chore: add linting rule for unused imports
ref: #770
2025-07-04 08:40:23 +09:30
Jon
15b4446775 fix(access): Tenancy Manager should not attempt to get org as related field if it does not exist
ref: #770
2025-07-04 08:40:23 +09:30
Jon
af2bc77920 feat(access): remove mill-seconds from datetime auto fields
ref: #770 #759
2025-07-04 08:40:23 +09:30
Jon
9cb507286f chore: correct code from revert
ref: #765
2025-07-04 08:40:23 +09:30
Jon
db97b574da feat(core): Centurion model Base
ref: #765 #767
2025-07-04 08:40:23 +09:30
Jon
31e200bb01 feat(core): Centurion Audit model
ref: #765 #759
2025-07-04 08:40:23 +09:30
Jon
0192f2f3a8 fix(api): ensure val returns at least none
ref: #765
2025-07-04 08:40:23 +09:30
Jon
8f097fb44e chore(access): planning work for centurion Tenancy model
ref: #765 #766
2025-07-04 08:40:23 +09:30
Jon
daf2811be7 chore(access): planning work for centurion user model
ref: #765 #766
2025-07-04 08:40:23 +09:30
Jon
2c33fa6f62 revert(core): Relocate history model class
reverted commit was 5cc08e3e94

ref: #765 #766
2025-07-04 08:40:23 +09:30
Jon
9d7a3e2e79 refactor(access): prefetch org with tenancy object
ref: #765
2025-07-04 08:40:23 +09:30
Jon
23dfdfe0b3 chore(core): remove old manual migration no longer required
ref: #765
2025-07-04 08:40:23 +09:30
Jon
473763af36 feat(core): permissions getter for role model
ref: #765 #551
2025-07-04 08:40:23 +09:30
Jon
47c12f5d55 chore(core): skeleton test cases
ref: #765 #759
2025-07-04 08:40:23 +09:30
Jon
64ea376962 feat(core): Audit History Signal for Delete/Save
ref: #765 #759
2025-07-04 08:40:23 +09:30
Jon
bd7ff92ab3 chore: Add pylint conf
ref: #765
2025-07-04 08:40:23 +09:30
Jon
bff1049414 chore: correct pylint errors
ref: #765
2025-07-04 08:40:23 +09:30
Jon
a1b9ecb0fc feat(core): Dynamic History model creation
ref: #765 #758 #759
2025-07-04 08:38:55 +09:30
Jon
262e883a26 refactor(core): Relocate history model class
ref: #765 #759
2025-07-04 08:38:55 +09:30
Jon
17c7980e03 refactor(base): rename app to centurion
ref: #764
2025-07-04 08:38:55 +09:30
3d2d759d6b build: bump version 1.17.1 -> 1.18.0 2025-07-03 22:55:51 +00:00
Jon
b73de03d27 Merge pull request #851 from nofusscomputing/850-fix-itim-validation-failure 2025-07-04 08:08:00 +09:30
Jon
a9e953812c feat(python): upgrade django 5.1.9 -> 5.1.10
ref: #851
2025-07-04 07:47:21 +09:30
Jon
4344265ed5 fix(itim): Correct config that is in the incorrect format
Users can input config that contains bytecode chars which inturn, makes the config entered a str. convert any config that is a str to a dict, the correct format.

ref: #851 fixes #850
2025-07-04 07:42:05 +09:30
1751 changed files with 48726 additions and 78213 deletions

View File

@ -17,5 +17,5 @@ commitizen:
prerelease_offset: 1
tag_format: $version
update_changelog_on_bump: false
version: 1.17.1
version: 1.18.0
version_scheme: semver

View File

@ -39,35 +39,16 @@ Describe in detail the following:
- [ ] 🔗 URL Route Added
- [ ] 🏷️ Model tag added to `app/core/lib/slash_commands/linked_model.CommandLinkedModel.get_model()` function
- [ ] 🏷️ [Model tag]().
- [ ] 📘 Tag updated in the [docs](https://nofusscomputing.com/projects/centurion_erp/user/core/markdown/#model-reference)
- [ ] tag added to `app/core/lib/slash_commands/linked_model.CommandLinkedModel.get_model()`
- [ ] ⚒️ Migration _Ticket Linked Item item_type choices update_
>[!note]
> Ensure that when creating the tag the following is adhered to:
> - Two words are not to contain a space char, `\s`. It is to be replaced with an underscore `_`
> - As much as practical, keep the tag as close to the model name as possible
- [ ] 📝 New [History model](https://nofusscomputing.com/projects/centurion_erp/development/core/model_history/) created
- Sub-Models **_ONLY_**
- [ ] Model class variable [`history_app_label`](https://nofusscomputing.com/projects/centurion_erp/development/models/#history) set to correct application label
- [ ] Model class variable [`history_model_name`](https://nofusscomputing.com/projects/centurion_erp/development/models/#history) set to correct model label
- [ ] 📓 New [Notes model](https://nofusscomputing.com/projects/centurion_erp/development/core/model_notes/) created
- [ ] 🆕 Model Created
- [ ] 🛠️ Migrations added
- [ ] Add `app_label` to KB Models `app/assistance/models/model_knowledge_base_article.all_models().model_apps`
- [ ] _(Notes not used/required) -_ Add `model_name` to KB Models `app/assistance/models/model_knowledge_base_article.all_models().excluded_models`
- [ ] 🧪 [Unit tested](https://nofusscomputing.com/projects/centurion_erp/development/core/model_notes/#testing)
- [ ] 🧪 [Functional tested](https://nofusscomputing.com/projects/centurion_erp/development/core/model_notes/#testing)
- [ ] tag added to class
- [ ] Admin Documentation added/updated _if applicable_
- [ ] Developer Documentation added/updated _if applicable_
- [ ] User Documentation added/updated
---
@ -79,14 +60,13 @@ Describe in detail the following:
### 🧪 Tests
- Unit Tests
- [ ] API Render (fields)
- [ ] [Model](https://nofusscomputing.com/projects/centurion_erp/development/models/#tests)
- [ ] ViewSet
- [ ] Serializer
- Function Test
- [ ] History API Render (fields)
- [ ] History Entries
- [ ] API Metadata
- [ ] API Permissions
- [ ] API Render (fields)
- [ ] Model
- [ ] Serializer
- [ ] ViewSet

View File

@ -8,5 +8,6 @@
"qwtel.sqlite-viewer",
"jebbs.markdown-extended",
"william-voyek.vscode-nginx",
"detachhead.basedpyright",
]
}

25
.vscode/launch.json vendored
View File

@ -29,7 +29,7 @@
"3",
"--bind",
"0.0.0.0:8002",
"app.wsgi:application",
"centurion.wsgi:application",
],
"django": true,
"autoStartBrowser": false,
@ -50,6 +50,29 @@
"autoStartBrowser": false,
"program": "${workspaceFolder}/app/manage.py"
},
{
"name": "Centurion Model (Management Command)",
"type": "debugpy",
"request": "launch",
"args": [
"models",
// "0.0.0.0:8002"
],
"django": true,
"autoStartBrowser": false,
"program": "${workspaceFolder}/app/manage.py"
},
{
"name": "Make Migrations",
"type": "debugpy",
"request": "launch",
"args": [
"makemigrations"
],
"django": true,
"autoStartBrowser": false,
"program": "${workspaceFolder}/app/manage.py"
},
{
"name": "Migrate",
"type": "debugpy",

11
.vscode/settings.json vendored
View File

@ -6,6 +6,7 @@
],
"python.testing.pytestArgs": [
"--override-ini", "addopts=",
"--no-migrations",
"app",
],
"python.testing.unittestEnabled": false,
@ -24,4 +25,14 @@
"green": 90
},
"telemetry.feedback.enabled": false,
"python.languageServer": "None",
"debug.javascript.enableNetworkView": false,
"typescript.experimental.expandableHover": false,
"ipynb.experimental.serialization": false,
"notebook.experimental.generate": false,
"extensions.experimental.issueQuickAccess": false,
"workbench.commandPalette.experimental.enableNaturalLanguageSearch": false,
"multiDiffEditor.experimental.enabled": false,
"diffEditor.experimental.showEmptyDecorations": false,
"editor.experimental.asyncTokenization": false,
}

View File

@ -1,3 +1,13 @@
## 1.18.0 (2025-07-03)
### feat
- **python**: upgrade django 5.1.9 -> 5.1.10
### Fixes
- **itim**: Correct config that is in the incorrect format
## 1.17.1 (2025-06-02)
### Fixes

View File

@ -1,3 +1,28 @@
## Version 1.18.0
- Added new model for History
!!! info
Migration of the old history tables to the new history tables occurs as part of post migration. As such the time it will take to migrate the history is dependent upon how many history entries per model. This should be planned for when upgrading to this version. if for some reason the migration is interrupted, you can safely restart it again by running the migrate command.
!!! note
Permission migration from the old history models to the new Audit History models are not migrated. As such users whom used to be able to access history models will need to be granted the required permission to view the new Audit History models
- Added new model for notes
!!! info
Migration of the old notes tables to the new note tables occurs as part of post migration. As such the time it will take to migrate the history is dependent upon how many history entries per model. This should be planned for when upgrading to this version. if for some reason the migration is interrupted, you can safely restart it again by running the migrate command.
!!! note
Permission migration from the old history models to the new Centurion Notes models are not migrated. As such users whom used to be able to access notes models will need to be granted the required permission to view the new Centurion Notes models
- Removed Django UI
[UI](https://github.com/nofusscomputing/centurion_erp) must be deployed seperatly.
- Removed API v1
## Version 1.17.0
- Added setting for log files.

View File

@ -1,6 +1,7 @@
from django.db import models
from django.utils.timezone import now
from django.template.defaultfilters import slugify
class AutoCreatedField(models.DateTimeField):
"""
@ -50,7 +51,7 @@ class AutoLastModifiedField(AutoCreatedField):
def pre_save(self, model_instance, add):
value = now()
value = now().replace(microsecond=0)
setattr(model_instance, self.attname, value)

View File

@ -1,38 +0,0 @@
from django import forms
from django.db.models import Q
from app import settings
from access.models.tenant import Tenant as Organization
from core.forms.common import CommonModelForm
class OrganizationForm(CommonModelForm):
class Meta:
model = Organization
fields = [
'name',
'manager',
'model_notes',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['created'] = forms.DateTimeField(
label="Created",
input_formats=settings.DATETIME_FORMAT,
initial=kwargs['instance'].created,
disabled=True,
required=False,
)
self.fields['modified'] = forms.DateTimeField(
label="Modified",
input_formats=settings.DATETIME_FORMAT,
initial=kwargs['instance'].modified,
disabled=True,
required=False,
)

View File

@ -1,69 +0,0 @@
from django import forms
from django.db.models import Q
from django.forms import inlineformset_factory
from .team_users import TeamUsersForm, TeamUsers
from access.models.team import Team
from access.functions import permissions
from app import settings
from core.forms.common import CommonModelForm
TeamUserFormSet = inlineformset_factory(
model=TeamUsers,
parent_model= Team,
extra = 1,
fields=[
'user',
'manager'
]
)
class TeamFormAdd(CommonModelForm):
class Meta:
model = Team
fields = [
'team_name',
'model_notes',
]
class TeamForm(CommonModelForm):
class Meta:
model = Team
fields = [
'team_name',
'permissions',
'model_notes',
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['created'] = forms.DateTimeField(
label="Created",
input_formats=settings.DATETIME_FORMAT,
initial=kwargs['instance'].created,
disabled=True,
required=False,
)
self.fields['modified'] = forms.DateTimeField(
label="Modified",
input_formats=settings.DATETIME_FORMAT,
initial=kwargs['instance'].modified,
disabled=True,
required=False,
)
self.fields['permissions'].widget.attrs = {'style': "height: 200px;"}
self.fields['permissions'].queryset = permissions.permission_queryset()

View File

@ -1,16 +0,0 @@
from django.db.models import Q
from app import settings
from access.models.team_user import TeamUsers
from core.forms.common import CommonModelForm
class TeamUsersForm(CommonModelForm):
class Meta:
model = TeamUsers
fields = [
'user',
'manager',
]

View File

@ -1,4 +1,10 @@
from django.contrib.auth.models import Permission
from django.apps import apps
from django.contrib.auth.models import (
ContentType,
Permission
)
from django.conf import settings
def permission_queryset():
"""Filter Permissions to those used within the application
@ -7,7 +13,7 @@ def permission_queryset():
list: Filtered queryset that only contains the used permissions
"""
apps = [
centurion_apps = [
'access',
'accounting',
'assistance',
@ -52,8 +58,48 @@ def permission_queryset():
'view_history',
]
if not settings.RUNNING_TESTS:
models = apps.get_models()
for model in models:
if(
not str(model._meta.object_name).endswith('AuditHistory')
and not str(model._meta.model_name).lower().endswith('history')
):
# check `endswith('history')` can be removed when the old history models are removed
continue
content_type = ContentType.objects.get(
app_label = model._meta.app_label,
model = model._meta.model_name
)
permissions = Permission.objects.filter(
content_type = content_type,
)
for permission in permissions:
if(
not permission.codename == 'view_' + str(model._meta.model_name)
and str(model._meta.object_name).endswith('AuditHistory')
):
exclude_permissions += [ permission.codename ]
elif(
not str(model._meta.object_name).endswith('AuditHistory')
and str(model._meta.model_name).lower().endswith('history')
):
# This `elif` can be removed when the old history models are removed
exclude_permissions += [ permission.codename ]
return Permission.objects.select_related('content_type').filter(
content_type__app_label__in=apps,
content_type__app_label__in = centurion_apps,
).exclude(
content_type__model__in = exclude_models
).exclude(

View File

@ -1,15 +1,10 @@
import django
from django.contrib.auth.middleware import (
AuthenticationMiddleware,
SimpleLazyObject,
partial,
)
from django.contrib.auth.models import Group
from django.utils.deprecation import MiddlewareMixin
from access.models.tenant import Tenant as Organization
from access.models.tenant import Tenant
from access.models.team import Team
@ -28,9 +23,9 @@ class RequestTenancy(MiddlewareMixin):
def process_request(self, request):
request.app_settings = AppSettings.objects.select_related('global_organization').get(
request.app_settings = AppSettings.objects.select_related('global_organization').filter(
owner_organization = None
)
)[0]
request.tenancy = Tenancy(user = request.user, app_settings = request.app_settings)
@ -45,8 +40,8 @@ class Tenancy:
_app_settings: AppSettings = None
_user_organizations: list([Organization]) = None
"""Cached User Organizations"""
_user_organizations: list([Tenant]) = None
"""Cached User Tenants"""
_user_teams: list([Team]) = None
"""Cached User Teams"""
@ -95,7 +90,7 @@ class Tenancy:
def is_member(self, organization: Organization) -> bool:
def is_member(self, organization: Tenant) -> bool:
"""Returns true if the current user is a member of the organization
iterates over the user_organizations list and returns true if the user is a member
@ -118,11 +113,11 @@ class Tenancy:
def has_organization_permission(self, organization: Organization, permissions_required: str) -> bool:
def has_organization_permission(self, organization: Tenant, permissions_required: str) -> bool:
""" Check if user has permission within organization.
Args:
organization (int): Organization to check.
organization (int): Tenant to check.
permissions_required (list): if doing object level permissions, pass in required permission.
Returns:
@ -131,9 +126,9 @@ class Tenancy:
has_permission: bool = False
if type(organization) is not Organization:
if type(organization) is not Tenant:
raise TypeError('Organization must be of type Organization')
raise TypeError('Tenant must be of type Tenant')
if type(permissions_required) is not str:

View File

@ -0,0 +1,110 @@
# Generated by Django 5.1.9 on 2025-06-06 01:41
import access.models.tenancy_abstract
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("access", "0010_company_alter_entity_entity_type_alter_person_dob_and_more"),
("core", "0028_delete_history"),
]
operations = [
migrations.RemoveField(
model_name="team",
name="is_global",
),
migrations.AlterField(
model_name="team",
name="model_notes",
field=models.TextField(
blank=True,
help_text="Tid bits of information",
null=True,
verbose_name="Notes",
),
),
migrations.AlterField(
model_name="team",
name="organization",
field=models.ForeignKey(
help_text="Tenant this belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.tenant",
validators=[
access.models.tenancy_abstract.TenancyAbstractModel.validatate_organization_exists
],
verbose_name="Tenant",
),
),
migrations.CreateModel(
name="TeamAuditHistory",
fields=[
(
"centurionaudit_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionaudit",
),
),
(
"model",
models.ForeignKey(
help_text="Model this history belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="audit_history",
to="access.team",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Team History",
"verbose_name_plural": "Team Histories",
"db_table": "access_team_audithistory",
"managed": True,
},
bases=("core.centurionaudit", models.Model),
),
migrations.CreateModel(
name="TeamCenturionModelNote",
fields=[
(
"centurionmodelnote_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionmodelnote",
),
),
(
"model",
models.ForeignKey(
help_text="Model this note belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.team",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Team Note",
"verbose_name_plural": "Team Notes",
"db_table": "access_team_centurionmodelnote",
"managed": True,
},
bases=("core.centurionmodelnote", models.Model),
)
]

View File

@ -0,0 +1,102 @@
# Generated by Django 5.1.9 on 2025-06-06 01:43
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("access", "0011_remove_team_is_global_model_notes_and_more"),
("core", "0028_delete_history"),
]
operations = [
migrations.AddField(
model_name="teamusers",
name="model_notes",
field=models.TextField(
blank=True,
help_text="Tid bits of information",
null=True,
verbose_name="Notes",
),
),
migrations.AlterField(
model_name="teamusers",
name="id",
field=models.AutoField(
help_text="ID of the item",
primary_key=True,
serialize=False,
unique=True,
verbose_name="ID",
),
),
migrations.CreateModel(
name="TeamUsersAuditHistory",
fields=[
(
"centurionaudit_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionaudit",
),
),
(
"model",
models.ForeignKey(
help_text="Model this history belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="audit_history",
to="access.teamusers",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Team User History",
"verbose_name_plural": "Team User Histories",
"db_table": "access_teamusers_audithistory",
"managed": True,
},
bases=("core.centurionaudit", models.Model),
),
migrations.CreateModel(
name="TeamUsersCenturionModelNote",
fields=[
(
"centurionmodelnote_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionmodelnote",
),
),
(
"model",
models.ForeignKey(
help_text="Model this note belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.teamusers",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Team User Note",
"verbose_name_plural": "Team User Notes",
"db_table": "access_teamusers_centurionmodelnote",
"managed": True,
},
bases=("core.centurionmodelnote", models.Model),
),
]

View File

@ -0,0 +1,16 @@
# Generated by Django 5.1.9 on 2025-06-06 05:22
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("access", "0012_teamusers_model_notes_alter_teamusers_id_and_more"),
]
operations = [
migrations.DeleteModel(
name="TeamUsersAuditHistory",
),
]

View File

@ -0,0 +1,16 @@
# Generated by Django 5.1.9 on 2025-06-07 09:05
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("access", "0013_delete_teamusersaudithistory"),
]
operations = [
migrations.DeleteModel(
name="TeamUsersCenturionModelNote",
),
]

View File

@ -0,0 +1,75 @@
# Generated by Django 5.1.9 on 2025-06-07 10:10
import access.models.team
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("access", "0014_delete_teamuserscenturionmodelnote"),
]
operations = [
migrations.RemoveField(
model_name="teamcenturionmodelnote",
name="centurionmodelnote_ptr",
),
migrations.RemoveField(
model_name="teamcenturionmodelnote",
name="model",
),
migrations.RemoveField(
model_name="teamusers",
name="model_notes",
),
migrations.AddField(
model_name="team",
name="is_global",
field=models.BooleanField(
default=False,
help_text="Is this a global object?",
verbose_name="Global Object",
),
),
migrations.AlterField(
model_name="team",
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="team",
name="organization",
field=models.ForeignKey(
help_text="Tenant this belongs to",
on_delete=django.db.models.deletion.CASCADE,
to="access.tenant",
validators=[access.models.team.Team.validatate_organization_exists],
verbose_name="Tenant",
),
),
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.DeleteModel(
name="TeamAuditHistory",
),
migrations.DeleteModel(
name="TeamCenturionModelNote",
),
]

View File

@ -0,0 +1,112 @@
# Generated by Django 5.1.9 on 2025-06-08 04:18
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"access",
"0015_remove_teamcenturionmodelnote_centurionmodelnote_ptr_and_more",
),
("core", "0031_remove_ticketcategory_is_global_and_more"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RemoveField(
model_name="tenant",
name="slug",
),
migrations.AlterField(
model_name="tenant",
name="manager",
field=models.ForeignKey(
blank=True,
help_text="Manager for this Tenancy",
null=True,
on_delete=django.db.models.deletion.PROTECT,
to=settings.AUTH_USER_MODEL,
verbose_name="Manager",
),
),
migrations.AlterField(
model_name="tenant",
name="model_notes",
field=models.TextField(
blank=True,
help_text="Tid bits of information",
null=True,
verbose_name="Notes",
),
),
migrations.CreateModel(
name="TenantAuditHistory",
fields=[
(
"centurionaudit_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionaudit",
),
),
(
"model",
models.ForeignKey(
help_text="Model this history belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="audit_history",
to="access.tenant",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Tenant History",
"verbose_name_plural": "Tenant Histories",
"db_table": "access_tenant_audithistory",
"managed": True,
},
bases=("core.centurionaudit", models.Model),
),
migrations.CreateModel(
name="TenantCenturionModelNote",
fields=[
(
"centurionmodelnote_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionmodelnote",
),
),
(
"model",
models.ForeignKey(
help_text="Model this note belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.tenant",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Tenant Note",
"verbose_name_plural": "Tenant Notes",
"db_table": "access_tenant_centurionmodelnote",
"managed": True,
},
bases=("core.centurionmodelnote", models.Model),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 5.1.9 on 2025-06-17 07:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("access", "0016_remove_tenant_slug_alter_tenant_manager_and_more"),
("core", "0033_alter_ticketcommentcategory_parent_and_more"),
]
operations = [
migrations.DeleteModel(
name="EntityHistory",
),
migrations.DeleteModel(
name="EntityNotes",
),
]

View File

@ -0,0 +1,253 @@
# Generated by Django 5.1.9 on 2025-06-17 07:32
import access.models.tenancy_abstract
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("access", "0017_remove_entitynotes_model_and_more"),
("core", "0033_alter_ticketcommentcategory_parent_and_more"),
]
operations = [
migrations.RemoveField(
model_name="entity",
name="is_global",
),
migrations.AlterField(
model_name="entity",
name="id",
field=models.AutoField(
help_text="ID of the item",
primary_key=True,
serialize=False,
unique=True,
verbose_name="ID",
),
),
migrations.AlterField(
model_name="entity",
name="model_notes",
field=models.TextField(
blank=True,
help_text="Tid bits of information",
null=True,
verbose_name="Notes",
),
),
migrations.AlterField(
model_name="entity",
name="organization",
field=models.ForeignKey(
help_text="Tenant this belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.tenant",
validators=[
access.models.tenancy_abstract.TenancyAbstractModel.validatate_organization_exists
],
verbose_name="Tenant",
),
),
migrations.CreateModel(
name="ContactAuditHistory",
fields=[
(
"centurionaudit_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionaudit",
),
),
(
"model",
models.ForeignKey(
help_text="Model this history belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.contact",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Contact History",
"verbose_name_plural": "Contact Histories",
"db_table": "access_contact_audithistory",
"managed": True,
},
bases=("core.centurionaudit",),
),
migrations.CreateModel(
name="ContactCenturionModelNote",
fields=[
(
"centurionmodelnote_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionmodelnote",
),
),
(
"model",
models.ForeignKey(
help_text="Model this note belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.contact",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Contact Note",
"verbose_name_plural": "Contact Notes",
"db_table": "access_contact_centurionmodelnote",
"managed": True,
},
bases=("core.centurionmodelnote",),
),
migrations.CreateModel(
name="EntityAuditHistory",
fields=[
(
"centurionaudit_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionaudit",
),
),
(
"model",
models.ForeignKey(
help_text="Model this history belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="audit_history",
to="access.entity",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Entity History",
"verbose_name_plural": "Entity Histories",
"db_table": "access_entity_audithistory",
"managed": True,
},
bases=("core.centurionaudit",),
),
migrations.CreateModel(
name="EntityCenturionModelNote",
fields=[
(
"centurionmodelnote_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionmodelnote",
),
),
(
"model",
models.ForeignKey(
help_text="Model this note belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.entity",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Entity Note",
"verbose_name_plural": "Entity Notes",
"db_table": "access_entity_centurionmodelnote",
"managed": True,
},
bases=("core.centurionmodelnote",),
),
migrations.CreateModel(
name="PersonAuditHistory",
fields=[
(
"centurionaudit_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionaudit",
),
),
(
"model",
models.ForeignKey(
help_text="Model this history belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.person",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Person History",
"verbose_name_plural": "Person Histories",
"db_table": "access_person_audithistory",
"managed": True,
},
bases=("core.centurionaudit",),
),
migrations.CreateModel(
name="PersonCenturionModelNote",
fields=[
(
"centurionmodelnote_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionmodelnote",
),
),
(
"model",
models.ForeignKey(
help_text="Model this note belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.person",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Person Note",
"verbose_name_plural": "Person Notes",
"db_table": "access_person_centurionmodelnote",
"managed": True,
},
bases=("core.centurionmodelnote",),
),
]

View File

@ -0,0 +1,81 @@
# Generated by Django 5.1.10 on 2025-07-06 10:38
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("access", "0018_remove_entity_is_global_alter_entity_id_and_more"),
("core", "0033_alter_ticketcommentcategory_parent_and_more"),
]
operations = [
migrations.CreateModel(
name="CompanyAuditHistory",
fields=[
(
"centurionaudit_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionaudit",
),
),
(
"model",
models.ForeignKey(
help_text="Model this history belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.company",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Company History",
"verbose_name_plural": "Company Histories",
"db_table": "access_company_audithistory",
"managed": True,
},
bases=("core.centurionaudit",),
),
migrations.CreateModel(
name="CompanyCenturionModelNote",
fields=[
(
"centurionmodelnote_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionmodelnote",
),
),
(
"model",
models.ForeignKey(
help_text="Model this note belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.company",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Company Note",
"verbose_name_plural": "Company Notes",
"db_table": "access_company_centurionmodelnote",
"managed": True,
},
bases=("core.centurionmodelnote",),
),
]

View File

@ -0,0 +1,56 @@
# Generated by Django 5.1.10 on 2025-07-12 07:20
import access.models.tenancy_abstract
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("access", "0019_companyaudithistory_companycenturionmodelnote"),
]
operations = [
migrations.AlterField(
model_name="role",
name="id",
field=models.AutoField(
help_text="ID of the item",
primary_key=True,
serialize=False,
unique=True,
verbose_name="ID",
),
),
migrations.AlterField(
model_name="role",
name="model_notes",
field=models.TextField(
blank=True,
help_text="Tid bits of information",
null=True,
verbose_name="Notes",
),
),
migrations.AlterField(
model_name="role",
name="organization",
field=models.ForeignKey(
help_text="Tenant this belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.tenant",
validators=[
access.models.tenancy_abstract.TenancyAbstractModel.validatate_organization_exists
],
verbose_name="Tenant",
),
),
migrations.DeleteModel(
name="RoleHistory",
),
migrations.DeleteModel(
name="RoleNotes",
),
]

View File

@ -0,0 +1,81 @@
# Generated by Django 5.1.10 on 2025-07-12 08:50
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("access", "0020_remove_rolenotes_model_and_more"),
("core", "0033_alter_ticketcommentcategory_parent_and_more"),
]
operations = [
migrations.CreateModel(
name="RoleAuditHistory",
fields=[
(
"centurionaudit_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionaudit",
),
),
(
"model",
models.ForeignKey(
help_text="Model this history belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="audit_history",
to="access.role",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Role History",
"verbose_name_plural": "Role Histories",
"db_table": "access_role_audithistory",
"managed": True,
},
bases=("core.centurionaudit",),
),
migrations.CreateModel(
name="RoleCenturionModelNote",
fields=[
(
"centurionmodelnote_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="core.centurionmodelnote",
),
),
(
"model",
models.ForeignKey(
help_text="Model this note belongs to",
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="access.role",
verbose_name="Model",
),
),
],
options={
"verbose_name": "Role Note",
"verbose_name_plural": "Role Notes",
"db_table": "access_role_centurionmodelnote",
"managed": True,
},
bases=("core.centurionmodelnote",),
),
]

View File

@ -1,438 +0,0 @@
from django.contrib.auth.mixins import AccessMixin, PermissionRequiredMixin
from django.contrib.auth.models import Group
from django.core.exceptions import PermissionDenied
from django.utils.functional import cached_property
from access.models.tenant import Tenant as Organization
from access.models.team import Team
class OrganizationMixin():
"""Base Organization class"""
parent_model: str = None
""" Parent Model
This attribute defines the parent model for the model in question. The parent model when defined
will be used as the object to obtain the permissions from.
"""
parent_model_pk_kwarg: str = 'pk'
"""Parent Model kwarg
This value is used to define the kwarg that is used as the parent objects primary key (pk).
"""
request = None
user_groups = []
def get_parent_obj(self):
""" Get the Parent Model Object
Use in views where the the model has no organization and the organization should be fetched from the parent model.
Requires attribute `parent_model` within the view with the value of the parent's model class
Returns:
parent_model (Model): with PK from kwargs['pk']
"""
return self.parent_model.objects.get(pk=self.kwargs[self.parent_model_pk_kwarg])
def object_organization(self) -> int:
id = None
if hasattr(self, '_object_organization'):
return int(self._object_organization)
try:
if hasattr(self, 'get_queryset'):
self.get_queryset()
if self.parent_model:
obj = self.get_parent_obj()
id = obj.get_organization().id
if obj.is_global:
id = 0
if hasattr(self, 'get_object') and id is None:
obj = self.get_object()
id = obj.get_organization().id
if hasattr(obj, 'is_global'):
if obj.is_global:
id = 0
if hasattr(self, 'instance') and id is None: # Form Instance
id = self.instance.get_organization()
except AttributeError:
if self.request.method == 'POST':
if self.request.POST.get("organization", ""):
id = int(self.request.POST.get("organization", ""))
for field in self.request.POST.dict(): # cater for fields prefixed '<prefix>-<field name>'
a_field = str(field).split('-')
if len(a_field) == 2:
if a_field[1] == 'organization':
id = int(self.request.POST.get(field))
except:
pass
if id is not None:
self._object_organization = id
return id
def is_member(self, organization: int) -> bool:
"""Returns true if the current user is a member of the organization
iterates over the user_organizations list and returns true if the user is a member
Returns:
bool: _description_
"""
is_member = False
if organization is None:
return False
if int(organization) in self.user_organizations():
is_member = True
return is_member
def get_permission_required(self):
"""
Override of 'PermissionRequiredMixin' method so that this mixin can obtain the required permission.
"""
if not hasattr(self, 'permission_required'):
return []
if self.permission_required is None:
raise ImproperlyConfigured(
f"{self.__class__.__name__} is missing the "
f"permission_required attribute. Define "
f"{self.__class__.__name__}.permission_required, or override "
f"{self.__class__.__name__}.get_permission_required()."
)
if isinstance(self.permission_required, str):
perms = (self.permission_required,)
else:
perms = self.permission_required
return perms
@cached_property
def is_manager(self) -> bool:
""" Returns true if the current user is a member of the organization"""
is_manager = False
return is_manager
def user_organizations(self) -> list():
"""Current Users organizations
Fetches the Organizations the user is apart of.
Get All groups the user is part of, fetch the associated team,
iterate over the results adding the organization ID to a list to be returned.
Returns:
_type_: User Organizations.
"""
user_organizations = []
if hasattr(self, '_user_organizations'):
return self._user_organizations
teams = Team.objects
for group in self.request.user.groups.all():
team = teams.get(pk=group.id)
self.user_groups = self.user_groups + [group.id]
user_organizations = user_organizations + [team.organization.id]
if len(user_organizations) > 0:
self._user_organizations = user_organizations
return user_organizations
# ToDo: Ensure that the group has access to item
def has_organization_permission(self, organization: int = None, permissions_required: list = None) -> bool:
""" Check if user has permission within organization.
Args:
organization (int, optional): Organization to check. Defaults to None.
permissions_required (list, optional): if doing object level permissions, pass in required permission. Defaults to None.
Returns:
bool: True for yes.
"""
has_permission = False
if permissions_required is None:
permissions_required = self.get_permission_required()
if not organization:
organization = self.object_organization()
else:
organization = int(organization)
if self.is_member(organization) or organization == 0:
groups = Group.objects.filter(pk__in=self.user_groups)
for group in groups:
team = Team.objects.filter(pk=group.id)
team = team.values('organization_id').get()
for permission in group.permissions.values('content_type__app_label', 'codename').all():
assembled_permission = str(permission["content_type__app_label"]) + '.' + str(permission["codename"])
if assembled_permission in permissions_required and (team['organization_id'] == organization or organization == 0):
return True
return has_permission
def permission_check(self, request, permissions_required: list = None) -> bool:
self.request = request
if permissions_required:
self.permission_required = permissions_required
organization_manager_models = [
'access.tenant',
'access.team',
'access.teamusers',
]
is_organization_manager = False
queryset = None
if hasattr(self, 'get_queryset'):
queryset = self.get_queryset()
obj = None
if hasattr(self, 'get_object'):
try:
obj = self.get_object()
except:
pass
if hasattr(self, 'model'):
if self.model._meta.label_lower in organization_manager_models:
organization = Organization.objects.get(pk=self.object_organization())
if organization.manager == request.user:
is_organization_manager = True
return True
if request.user.is_superuser:
return True
if permissions_required:
perms = permissions_required
else:
perms = self.get_permission_required()
if self.has_organization_permission(permissions_required = perms):
return True
if self.request.user.has_perms(perms) and str(self.request.method).lower() == 'get':
if len(self.kwargs) == 0 or (len(self.kwargs) == 1 and 'ticket_type' in self.kwargs):
return True
for required_permission in self.permission_required:
if required_permission.replace(
'view_', ''
) == 'access.tenant' and len(self.kwargs) == 0:
return True
return False
class OrganizationPermission(AccessMixin, OrganizationMixin):
"""## Permission Checking
The base django permissions have not been modified with this app providing Multi-Tenancy. This is done by a mixin, that checks if the item is apart of an organization, if it is; confirmation is made that the user is part of the same organization and as long as they have the correct permission within the organization, access is granted.
### How it works
The overall permissions system of django has not been modified with it remaining fully functional. The multi-tenancy has been setup based off of an organization with teams. A team to the underlying django system is an extension of the django auth group and for every team created a django auth group is created. THe group name is set using the following format: `<organization>_<team name>` and contains underscores `_` instead of spaces.
A User who is added to an team as a "Manager" can modify the team members or if they have permission `access.change_team` which also allows the changing of team permissions. Modification of an organization can be done by the django administrator (super user) or any user with permission `access._change_organization`.
Items can be set as `Global`, meaning that all users who have the correct permission regardless of organization will be able to take action against the object.
Permissions that can be modified for a team have been limited to application permissions only unless adjust the permissions from the django admin site.
### Multi-Tenancy workflow
The workflow is conducted as part of the view and has the following flow:
1. Checks if user is member of organization the object the action is being performed on. Will also return true if the object has field `is_global` set to `true`.
1. Fetches all teams the user is part of.
1. obtains all permissions that are linked to the team.
1. checks if user has the required permission for the action.
1. confirms that the team the permission came from is part of the same organization as the object the action is being conducted on.
1. ONLY on success of the above items, grants access.
"""
permission_required: list = []
""" Permission required for the view
Not specifying this property adjusts the permission check logic so that you can
use the `permission_check()` function directly.
An example of a get request....
``` py
def get(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if not self.permission_check(request, [ 'access.view_organization' ]):
raise PermissionDenied('You are not part of this organization')
return super().get(request, *args, **kwargs)
```
this example details manual usage of the `permission_check()` function for a get request.
"""
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
if len(self.permission_required) == 0:
if hasattr(self, 'get_dynamic_permissions'):
self.permission_required = self.get_dynamic_permissions()
if len(self.permission_required) > 0:
non_organization_models = [
'TaskResult'
]
if hasattr(self, 'model'):
if hasattr(self.model, '__name__'):
if self.model.__name__ in non_organization_models:
if hasattr(self, 'get_object'):
self.get_object()
perms = self.get_permission_required()
if not self.request.user.has_perms(perms):
return self.handle_no_permission()
return super().dispatch(self.request, *args, **kwargs)
if not self.permission_check(request):
raise PermissionDenied('You are not part of this organization')
return super().dispatch(self.request, *args, **kwargs)

View File

@ -1,10 +1,8 @@
import django
from django.contrib.auth.models import Group
from django.db import models
from access.models.tenant import Tenant as Organization
from access.models.team import Team
User = django.contrib.auth.get_user_model()

View File

@ -1,13 +1,11 @@
import traceback
from django.core.exceptions import ObjectDoesNotExist
from rest_framework import exceptions
from rest_framework.permissions import DjangoObjectPermissions
from access.models.tenancy import Tenant, TenancyObject
from access.models.tenancy import Tenant
from core import exceptions as centurion_exceptions
from core.mixins.centurion import Centurion
@ -60,11 +58,11 @@ class OrganizationPermissionMixin(
if hasattr(view, 'model'):
self._is_tenancy_model = issubclass(view.model, TenancyObject)
self._is_tenancy_model = issubclass(view.model, Centurion)
if view.get_parent_model():
self._is_tenancy_model = issubclass(view.get_parent_model(), TenancyObject)
self._is_tenancy_model = issubclass(view.get_parent_model(), Centurion)
return self._is_tenancy_model
@ -113,6 +111,12 @@ class OrganizationPermissionMixin(
raise centurion_exceptions.NotAuthenticated()
if request.method not in view.allowed_methods:
raise centurion_exceptions.MethodNotAllowed(method = request.method)
try:
if (
@ -156,12 +160,7 @@ class OrganizationPermissionMixin(
has_permission_required: bool = permission_required in user_permissions
if request.method not in view.allowed_methods:
raise centurion_exceptions.MethodNotAllowed(method = request.method)
elif not has_permission_required and not request.user.is_superuser:
if not has_permission_required and not request.user.is_superuser:
raise centurion_exceptions.PermissionDenied()
@ -291,6 +290,11 @@ class OrganizationPermissionMixin(
view.model.__name__ == 'AuthToken'
and request._user.id == int(view.kwargs.get('model_id', 0))
)
or ( # org=None is the application wide settings.
view.model.__name__ == 'AppSettings'
and request.user.is_superuser
and obj.organization is None
)
):
return True

View File

@ -1,4 +1,3 @@
from . import contact
from . import company_base
from . import person
from . import role
from .organization_history import OrganizationHistory # pylint: disable=W0611:unused-import
from .organization_notes import OrganizationNotes # pylint: disable=W0611:unused-import

View File

@ -12,6 +12,10 @@ class Company(
# references in code to `organization` witch clashes with the intended name of
# this model.
_is_submodel = True
documentation = ''
class Meta:
@ -40,10 +44,6 @@ class Company(
return self.name
documentation = ''
history_model_name = 'company'
page_layout: dict = [
{
"name": "Details",
@ -95,8 +95,3 @@ class Company(
'organization',
'created',
]
def clean(self):
super().clean()

View File

@ -8,6 +8,10 @@ class Contact(
Person
):
documentation = ''
_is_submodel = True
class Meta:
@ -42,10 +46,6 @@ class Contact(
return self.f_name + ' ' + self.l_name
documentation = ''
history_model_name = 'contact'
page_layout: list = [
{
"name": "Details",

View File

@ -1,18 +1,23 @@
from django.db import models
from rest_framework.reverse import reverse
from access.fields import AutoLastModifiedField
from access.fields import AutoCreatedField, AutoLastModifiedField
from access.models.tenancy import TenancyObject
from core.lib.feature_not_used import FeatureNotUsed
from core.models.centurion import CenturionModel
class Entity(
TenancyObject
CenturionModel
):
model_tag = 'entity'
documentation = ''
kb_model_name = 'entity'
url_model_name = 'entity'
class Meta:
@ -29,15 +34,6 @@ class Entity(
verbose_name_plural = 'Entities'
id = models.AutoField(
blank=False,
help_text = 'Primary key of the entry',
primary_key=True,
unique=True,
verbose_name = 'ID'
)
entity_type = models.CharField(
blank = False,
help_text = 'Type this entity is',
@ -46,8 +42,6 @@ class Entity(
verbose_name = 'Entity Type'
)
created = AutoCreatedField()
modified = AutoLastModifiedField()
@ -64,22 +58,8 @@ class Entity(
return str( related_model )
# app_namespace = 'access'
history_app_label = 'access'
history_model_name = 'entity'
kb_model_name = 'entity'
note_basename = '_api_v2_entity_note'
documentation = ''
page_layout: dict = []
table_fields: list = [
'organization',
'entity_type',
@ -89,6 +69,23 @@ class Entity(
]
def clean_fields(self, exclude = None ):
related_model = self.get_related_model()
if related_model is None:
related_model = self
if self.entity_type != str(related_model._meta.verbose_name).lower().replace(' ', '_'):
self.entity_type = str(related_model._meta.verbose_name).lower().replace(' ', '_')
super().clean_fields( exclude = exclude )
def get_related_field_name(self) -> str:
meta = getattr(self, '_meta')
@ -107,7 +104,6 @@ class Entity(
):
return related_object.name
break
return ''
@ -145,105 +141,3 @@ class Entity(
return related_model
def get_url_kwargs(self) -> dict:
model = self.get_related_model()
if len(self._meta.parents) == 0 and model is None:
return {
'pk': self.id
}
if model is None:
model = self
kwargs = {
'entity_model': str(model._meta.verbose_name).lower().replace(' ', '_'),
}
if model.pk:
kwargs.update({
'pk': model.id
})
return kwargs
def get_url( self, request = None ) -> str:
"""Fetch the models URL
If URL kwargs are required to generate the URL, define a `get_url_kwargs` that returns them.
Args:
request (object, optional): The request object that was made by the end user. Defaults to None.
Returns:
str: Canonical URL of the model if the `request` object was provided. Otherwise the relative URL.
"""
model = None
if getattr(self, 'get_related_model', None):
model = self.get_related_model()
if model is None:
model = self
sub_entity = ''
if model._meta.model_name != 'entity':
sub_entity = '_sub'
kwargs = self.get_url_kwargs()
view = 'list'
if 'pk' in kwargs:
view = 'detail'
if request:
return reverse(f"v2:" + model.get_app_namespace() + f"_api_v2_entity" + sub_entity + "-" + view, request=request, kwargs = kwargs )
return reverse(f"v2:" + model.get_app_namespace() + f"_api_v2_entity" + sub_entity + "-" + view, kwargs = kwargs )
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
related_model = self.get_related_model()
if related_model is None:
related_model = self
if self.entity_type != str(related_model._meta.verbose_name).lower().replace(' ', '_'):
self.entity_type = str(related_model._meta.verbose_name).lower().replace(' ', '_')
super().save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
def save_history(self, before: dict, after: dict) -> bool:
from access.models.entity_history import EntityHistory
history = super().save_history(
before = before,
after = after,
history_model = EntityHistory
)
return history

View File

@ -1,55 +0,0 @@
from django.db import models
from access.models.entity import Entity
from core.models.model_history import ModelHistory
from devops.models.feature_flag import FeatureFlag
class EntityHistory(
ModelHistory
):
class Meta:
db_table = 'access_entity_history'
ordering = ModelHistory._meta.ordering
verbose_name = 'Entity History'
verbose_name_plural = 'Entity History'
model = models.ForeignKey(
Entity,
blank = False,
help_text = 'Model this note belongs to',
null = False,
on_delete = models.CASCADE,
related_name = 'history',
verbose_name = 'Model',
)
table_fields: list = []
page_layout: dict = []
def get_object(self):
return self
def get_serialized_model(self, serializer_context):
model = None
from access.serializers.entity import BaseSerializer
model = BaseSerializer(self.model, context = serializer_context)
return model

View File

@ -1,45 +0,0 @@
from django.db import models
from access.models.entity import Entity
from core.models.model_notes import ModelNotes
class EntityNotes(
ModelNotes
):
class Meta:
db_table = 'access_entity_notes'
ordering = ModelNotes._meta.ordering
verbose_name = 'Entity Note'
verbose_name_plural = 'Entity Notes'
model = models.ForeignKey(
Entity,
blank = False,
help_text = 'Model this note belongs to',
null = False,
on_delete = models.CASCADE,
related_name = 'notes',
verbose_name = 'Model',
)
table_fields: list = []
page_layout: dict = []
def get_url_kwargs(self) -> dict:
return {
'model_id': self.model.pk,
'pk': self.pk
}

View File

@ -1 +1 @@
from .tenant import Tenant as Organization
from .tenant import Tenant as Organization # pylint: disable=W0611:unused-import

View File

@ -10,6 +10,10 @@ class Person(
Entity
):
_is_submodel = True
documentation = ''
class Meta:
@ -63,10 +67,6 @@ class Person(
return self.f_name + ' ' + self.l_name + f' (DOB: {self.dob})'
documentation = ''
history_model_name = 'person'
page_layout: dict = []
table_fields: list = [
@ -112,8 +112,8 @@ class Person(
raise ValidationError(
detail = {
'dob': f'Person {self.f_name} {self.l_name} already exists with this birthday {entry.dob}'
'dob': f'Person {self.f_name} {self.l_name}' \
f'already exists with this birthday {entry.dob}'
},
code = 'duplicate_person_on_dob'
)

View File

@ -1,15 +1,20 @@
from django.contrib.auth.models import Permission
from django.db import models
from access.fields import AutoCreatedField, AutoLastModifiedField
from access.models.tenancy import TenancyObject
from access.fields import AutoLastModifiedField
from core.models.centurion import CenturionModel
class Role(
TenancyObject
CenturionModel
):
documentation = ''
model_tag = 'role'
class Meta:
@ -28,14 +33,6 @@ class Role(
verbose_name_plural = 'Roles'
id = models.AutoField(
blank=False,
help_text = 'Primary key of the entry',
primary_key=True,
unique=True,
verbose_name = 'ID'
)
name = models.CharField(
blank = False,
help_text = 'Name of this role',
@ -53,12 +50,8 @@ class Role(
verbose_name = 'Permissions'
)
created = AutoCreatedField()
modified = AutoLastModifiedField()
is_global = None
def __str__(self) -> str:
@ -66,8 +59,6 @@ class Role(
return str( self.organization ) + ' / ' + self.name
documentation = ''
page_layout: dict = [
{
"name": "Details",
@ -130,14 +121,29 @@ class Role(
]
def save_history(self, before: dict, after: dict) -> bool:
_permissions: list[ Permission ] = None
from access.models.role_history import RoleHistory
_permissions_int: list[ int ] = None
history = super().save_history(
before = before,
after = after,
history_model = RoleHistory
)
def get_permissions(self, as_int_list = False ):
return history
if self._permissions is None:
permissions = []
permissions_int = []
for permission in self.permissions: # pylint: disable=E1133:not-an-iterable
if permission in _permissions:
continue
permissions += [ permission ]
permissions_int += [ permission.id ]
self._permissions = permissions
self._permissions_int = permissions_int
if as_int_list:
return self._permissions_int
return self._permissions_int

View File

@ -1,53 +0,0 @@
from django.db import models
from core.models.model_history import ModelHistory
from access.models.role import Role
class RoleHistory(
ModelHistory
):
class Meta:
db_table = 'access_role_history'
ordering = ModelHistory._meta.ordering
verbose_name = 'Role History'
verbose_name_plural = 'Role History'
model = models.ForeignKey(
Role,
blank = False,
help_text = 'Model this note belongs to',
null = False,
on_delete = models.CASCADE,
related_name = 'history',
verbose_name = 'Model',
)
table_fields: list = []
page_layout: dict = []
def get_object(self):
return self
def get_serialized_model(self, serializer_context):
model = None
from access.serializers.role import BaseSerializer
model = BaseSerializer(self.model, context = serializer_context)
return model

View File

@ -1,45 +0,0 @@
from django.db import models
from access.models.role import Role
from core.models.model_notes import ModelNotes
class RoleNotes(
ModelNotes
):
class Meta:
db_table = 'access_role_notes'
ordering = ModelNotes._meta.ordering
verbose_name = 'Role Note'
verbose_name_plural = 'Role Notes'
model = models.ForeignKey(
Role,
blank = False,
help_text = 'Model this note belongs to',
null = False,
on_delete = models.CASCADE,
related_name = 'notes',
verbose_name = 'Model',
)
table_fields: list = []
page_layout: dict = []
def get_url_kwargs(self) -> dict:
return {
'model_id': self.model.pk,
'pk': self.pk
}

View File

@ -179,12 +179,12 @@ class Team(Group, TenancyObject):
def save_history(self, before: dict, after: dict) -> bool:
from access.models.team_history import TeamHistory
from access.models.team_history import TeamAuditHistory
history = super().save_history(
before = before,
after = after,
history_model = TeamHistory
history_model = TeamAuditHistory
)

View File

@ -15,7 +15,7 @@ from access.models.tenant import Tenant
from access.models.team import Team
from core.lib.feature_not_used import FeatureNotUsed
from core.mixin.history_save import SaveHistory
from core.mixins.history_save import SaveHistory
User = django.contrib.auth.get_user_model()

View File

@ -1,4 +1,3 @@
import django
import logging
from django.db import models
@ -9,7 +8,7 @@ from access.models.tenant import Tenant
from core import exceptions as centurion_exceptions
from core.middleware.get_request import get_request
from core.mixin.history_save import SaveHistory
from core.mixins.history_save import SaveHistory
@ -52,6 +51,10 @@ class TenancyManager(models.Manager):
user_organizations: list(str()) = []
has_tenant_field = False
if getattr(self.model, 'organization', None) is not None:
has_tenant_field = True
if request:
@ -70,29 +73,33 @@ class TenancyManager(models.Manager):
if team.organization.id not in user_organizations:
if not user_organizations:
# if not user_organizations:
self.user_organizations = []
# self.user_organizations = []
user_organizations += [ team.organization.id ]
# if len(user_organizations) > 0 and not user.is_superuser and self.model.is_global is not None:
if len(user_organizations) > 0 and not user.is_superuser:
if getattr(self.model, 'is_global', False) is True:
if has_tenant_field:
return super().get_queryset().filter(
return super().get_queryset().select_related('organization').filter(
models.Q(organization__in=user_organizations)
|
models.Q(is_global = True)
)
else:
return super().get_queryset().filter(
models.Q(organization__in=user_organizations)
)
# return super().get_queryset().filter(
# models.Q(organization__in=user_organizations)
# )
return super().get_queryset().filter()
if has_tenant_field:
return super().get_queryset().select_related('organization')
return super().get_queryset()
@ -229,7 +236,7 @@ class TenancyObject(SaveHistory):
if self.app_namespace:
app_namespace = self.app_namespace + ':'
app_namespace = self.app_namespace
return str(app_namespace)
@ -248,12 +255,17 @@ class TenancyObject(SaveHistory):
model_name = str(self._meta.verbose_name.lower()).replace(' ', '_')
namespace = f'v2'
if self.get_app_namespace():
namespace = namespace + ':' + self.get_app_namespace()
if request:
return reverse(f"v2:" + self.get_app_namespace() + f"_api_v2_{model_name}-detail", request=request, kwargs = self.get_url_kwargs() )
return reverse(f"{namespace}:_api_v2_{model_name}-detail", request=request, kwargs = self.get_url_kwargs() )
return reverse(f"v2:" + self.get_app_namespace() + f"_api_v2_{model_name}-detail", kwargs = self.get_url_kwargs() )
return reverse(f"{namespace}:_api_v2_{model_name}-detail", kwargs = self.get_url_kwargs() )
def get_url_kwargs(self) -> dict:

View File

@ -0,0 +1,126 @@
from django.core.exceptions import (
ValidationError,
)
from django.db import models
from access.models.tenancy import (
TenancyManager as TenancyManagerDepreciated
)
from access.models.tenant import Tenant
class TenancyManager(
models.Manager
):
"""Multi-Tennant Object Manager
This manager specifically caters for the multi-tenancy features of Centurion ERP.
"""
def get_queryset(self):
""" Fetch the data
When the model contains the user data, the query is filtered to their
and the globally defined Tenancy only.
Returns:
(queryset): **super user**: return unfiltered data.
(queryset): **not super user**: return data from the stored unique organizations.
"""
user = None # When CenturionUser in use
if hasattr(self.model, 'context'):
user = self.model.context['user']
has_tenant_field = False
if getattr(self.model, 'organization', None) is not None:
has_tenant_field = True
if user:
tenancies = user.get_tenancies(int_list = True)
if len(tenancies) > 0 and not request.user.is_superuser:
if has_tenant_field:
return super().get_queryset().select_related('organization').filter(
models.Q(organization__in = tenancies)
)
return super().get_queryset().filter()
if has_tenant_field:
return super().get_queryset().select_related('organization')
return super().get_queryset()
class TenancyAbstractModel(
models.Model,
):
""" Tenancy Model Abstract class.
This class is for inclusion within **every** model within Centurion ERP.
Provides the required fields, functions and methods for multi tennant objects.
Unless otherwise stated, **no** object within this class may be overridden.
Raises:
ValidationError: User failed to supply organization
"""
objects = TenancyManagerDepreciated()
""" ~~Multi-Tenant Manager~~
**Note:** ~~This manager relies upon the model class having `context['user']`
set. without a user the manager can not perform multi-tenant queries.~~
"""
class Meta:
abstract = True
def validatate_organization_exists(self):
"""Ensure that the user did provide an organization
Raises:
ValidationError: User failed to supply organization.
"""
if not self:
raise ValidationError(
code = 'required',
message = 'You must provide an organization'
)
organization = models.ForeignKey(
Tenant,
blank = False,
help_text = 'Tenant this belongs to',
null = False,
on_delete = models.CASCADE,
related_name = '+',
validators = [
validatate_organization_exists
],
verbose_name = 'Tenant'
)
def get_tenant(self) -> Tenant:
""" Return the models Tenancy
This model can be safely over-ridden as long as it returns the models
tenancy
"""
return self.organization

View File

@ -3,31 +3,35 @@ import django
from django.conf import settings
from django.db import models
from rest_framework.reverse import reverse
from access.fields import (
AutoCreatedField,
AutoLastModifiedField,
AutoSlugField
)
from core.mixin.history_save import SaveHistory
from core.mixins.centurion import Centurion
User = django.contrib.auth.get_user_model()
class Tenant(SaveHistory):
class Tenant(
Centurion,
):
@property
def organization(self):
return self
model_tag = 'tenant'
class Meta:
verbose_name = "Tenant"
verbose_name_plural = "Tenants"
ordering = ['name']
def save(self, *args, **kwargs):
ordering = [
'name'
]
if self.slug == '_':
self.slug = self.name.lower().replace(' ', '_')
super().save(*args, **kwargs)
id = models.AutoField(
blank = False,
@ -47,38 +51,39 @@ class Tenant(SaveHistory):
manager = models.ForeignKey(
settings.AUTH_USER_MODEL,
blank = False,
blank = True,
help_text = 'Manager for this Tenancy',
null = True,
on_delete=models.SET_NULL,
on_delete = models.PROTECT,
verbose_name = 'Manager'
)
model_notes = models.TextField(
blank = True,
default = None,
help_text = 'Tid bits of information',
null = True,
verbose_name = 'Notes',
)
slug = AutoSlugField()
created = AutoCreatedField()
modified = AutoLastModifiedField()
def get_organization(self):
return self
def __int__(self):
return self.id
def __str__(self):
return self.name
def get_organization(self):
return self
table_fields: list = [
'nbsp',
'name',
@ -134,28 +139,5 @@ class Tenant(SaveHistory):
]
def get_url( self, request = None ) -> str:
if request:
return reverse("v2:_api_v2_organization-detail", request=request, kwargs={'pk': self.id})
return reverse("v2:_api_v2_organization-detail", kwargs={'pk': self.id})
def save_history(self, before: dict, after: dict) -> bool:
from access.models.organization_history import OrganizationHistory
history = super().save_history(
before = before,
after = after,
history_model = OrganizationHistory
)
return history
Organization = Tenant

View File

@ -0,0 +1,197 @@
from django.contrib.auth.models import Permission, User
from django.core.exceptions import PermissionDenied
from access.models.tenant import Tenant
class CenturionUser(
User,
):
"""Centurion User
A Multi-Tenant User wirh permission Checking.
ToDo:
- Add to Roles user field `related_name = roles`
- Add to Roles group field `related_name = roles`
# - have group lookup prefetch related roles__permissions
- have user lookup prefetch related roles__permissions and groups__roles__permissions
Args:
User (Model): Django Base User
"""
_tenancies: list[Tenant] = None
_tenancies_int: list[int] = None
_permissions: list[Permission] = None
_permissions_by_tenancy: dict[ str, list[ Permission ] ] = None
"""Permissions by Tenancy
`{ 'tenancy_{id}': [ Permission ] }`
"""
# EMAIL_FIELD = 'email' # Update contact email field name so it's different to the user model.
# REQUIRED_FIELDS = [
# EMAIL_FIELD,
# 'f_name',
# 'l_name',
# ]
class Meta:
abstract = False
proxy = True # User will be linked to Employee/Customer entity via related_name from the entity.
# ToDo: refactory Employee/Customer to inherit from a new model. entity_user
verbose_name = 'Centurion User'
verbose_name_plural = 'Centurion Users'
def get_full_name(self) -> str:
return f'{self.entity_user.f_name} {self.entity_user.l_name}'
def get_group_permissions(self, tenancy: bool = True) -> dict[ str, list[ Permission ] ] | list[ Permission ]:
""" Get the Users Permissions
Args:
tenancy (bool, optional): Return permission in list. Defaults to True.
Returns:
dict[ str, list[ Permission ] ]: Permissions listed by tenancy
list[ Permission ]: All Permissions
"""
for group in self.groups: # pylint: disable=E1133:not-an-iterable
for role in group.roles:
pass
# role.get_permissions()
def get_permissions(self, tenancy: bool = True) -> dict[ str, list[ Permission ] ] | list[ Permission ]:
""" Get the Users Permissions
Args:
tenancy (bool, optional): Return permission in list. Defaults to True.
Returns:
dict[ str, list[ Permission ] ]: Permissions listed by tenancy
list[ Permission ]: All Permissions
"""
# also get group permissions. self.get_group_permissions()
for role in self.roles:
pass
# role.get_permissions()
# also populate `self._tenancies` and `self._tenancies_int`
return []
def get_short_name() -> str:
return self.entity_user.f_name
def get_tenancies(self, int_list = False) -> list[ Tenant ] | list[ int ]:
"""Get the Tenancies the user is in.
Args:
int_list (bool, optional): Return Tenancy list as int values. Defaults to False.
Returns:
list[ Tenant ] | list[ int ]: All Tenancies the user is in.
"""
if self._tenancies is None:
if self._permissions is None:
self.get_permissions
tenancies: list = []
tenancies_int: list = []
for role in self.roles:
if role.organization in tenancies:
continue
tenancies += [ role.organization ]
tenancies_int += [ role.organization.id ]
self._tenancies = tenancies
self._tenancies_int = tenancies_int
if as_int_list:
return self._tenancies_int
return self._tenancies
def has_module_perms(self, app_label): # is this needed?
# if has app_label in perms
raise PermissionDenied
def has_perm(self, permission: Permission, obj = None, tenancy: Tenant = None) -> bool:
if(
obj is None
and tenancy is None
):
raise ValueError('Both obj and tenancy cant be None')
if tenancy is None:
tenancy = obj.organization
# if self.has_tenancy_permission(perm, tenancy):
# for tenancy, permissions in self.get_permissions().items()
if tenancy is None:
raise ValueError('tenancy cant be None')
permissions = self.get_permissions()
if f'tenancy_{tenancy.id}' not in permissions:
raise PermissionDenied
for tenancy, permissions in self.get_permissions().items():
if(
tenancy == f'tenancy_{tenancy.id}'
and perm in permissions
):
return True
raise PermissionDenied
def has_perms(self, permission_list: list[ Permission ], obj = None, tenancy: Tenant = None):
for perm in perm_list:
self.has_perm( perm, obj )
return True

View File

@ -0,0 +1,56 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from api.serializers import common
from centurion.models.meta import CompanyAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionaudit import (
BaseSerializer,
ViewSerializer as AuditHistoryViewSerializer
)
@extend_schema_serializer(component_name = 'CompanyAuditHistoryModelSerializer')
class ModelSerializer(
common.CommonModelSerializer,
BaseSerializer
):
"""Git Group Audit History Base Model"""
_urls = serializers.SerializerMethodField('get_url')
class Meta:
model = CompanyAuditHistory
fields = [
'id',
'organization',
'display_name',
'content_type',
'model',
'before',
'after',
'action',
'user',
'created',
'_urls',
]
read_only_fields = fields
@extend_schema_serializer(component_name = 'CompanyAuditHistoryViewSerializer')
class ViewSerializer(
ModelSerializer,
AuditHistoryViewSerializer,
):
"""Git Group Audit History Base View Model"""
pass

View File

@ -0,0 +1,56 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from api.serializers import common
from centurion.models.meta import ContactAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionaudit import (
BaseSerializer,
ViewSerializer as AuditHistoryViewSerializer
)
@extend_schema_serializer(component_name = 'ContactAuditHistoryModelSerializer')
class ModelSerializer(
common.CommonModelSerializer,
BaseSerializer
):
"""Git Group Audit History Base Model"""
_urls = serializers.SerializerMethodField('get_url')
class Meta:
model = ContactAuditHistory
fields = [
'id',
'organization',
'display_name',
'content_type',
'model',
'before',
'after',
'action',
'user',
'created',
'_urls',
]
read_only_fields = fields
@extend_schema_serializer(component_name = 'ContactAuditHistoryViewSerializer')
class ViewSerializer(
ModelSerializer,
AuditHistoryViewSerializer,
):
"""Git Group Audit History Base View Model"""
pass

View File

@ -0,0 +1,56 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from api.serializers import common
from centurion.models.meta import EntityAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionaudit import (
BaseSerializer,
ViewSerializer as AuditHistoryViewSerializer
)
@extend_schema_serializer(component_name = 'EntityAuditHistoryModelSerializer')
class ModelSerializer(
common.CommonModelSerializer,
BaseSerializer
):
"""Git Group Audit History Base Model"""
_urls = serializers.SerializerMethodField('get_url')
class Meta:
model = EntityAuditHistory
fields = [
'id',
'organization',
'display_name',
'content_type',
'model',
'before',
'after',
'action',
'user',
'created',
'_urls',
]
read_only_fields = fields
@extend_schema_serializer(component_name = 'EntityAuditHistoryViewSerializer')
class ViewSerializer(
ModelSerializer,
AuditHistoryViewSerializer,
):
"""Git Group Audit History Base View Model"""
pass

View File

@ -0,0 +1,56 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from api.serializers import common
from centurion.models.meta import PersonAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionaudit import (
BaseSerializer,
ViewSerializer as AuditHistoryViewSerializer
)
@extend_schema_serializer(component_name = 'PersonAuditHistoryModelSerializer')
class ModelSerializer(
common.CommonModelSerializer,
BaseSerializer
):
"""Git Group Audit History Base Model"""
_urls = serializers.SerializerMethodField('get_url')
class Meta:
model = PersonAuditHistory
fields = [
'id',
'organization',
'display_name',
'content_type',
'model',
'before',
'after',
'action',
'user',
'created',
'_urls',
]
read_only_fields = fields
@extend_schema_serializer(component_name = 'PersonAuditHistoryViewSerializer')
class ViewSerializer(
ModelSerializer,
AuditHistoryViewSerializer,
):
"""Git Group Audit History Base View Model"""
pass

View File

@ -0,0 +1,56 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from api.serializers import common
from centurion.models.meta import RoleAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionaudit import (
BaseSerializer,
ViewSerializer as AuditHistoryViewSerializer
)
@extend_schema_serializer(component_name = 'RoleAuditHistoryModelSerializer')
class ModelSerializer(
common.CommonModelSerializer,
BaseSerializer
):
"""Git Group Audit History Base Model"""
_urls = serializers.SerializerMethodField('get_url')
class Meta:
model = RoleAuditHistory
fields = [
'id',
'organization',
'display_name',
'content_type',
'model',
'before',
'after',
'action',
'user',
'created',
'_urls',
]
read_only_fields = fields
@extend_schema_serializer(component_name = 'RoleAuditHistoryViewSerializer')
class ViewSerializer(
ModelSerializer,
AuditHistoryViewSerializer,
):
"""Git Group Audit History Base View Model"""
pass

View File

@ -0,0 +1,56 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from api.serializers import common
from centurion.models.meta import TenantAuditHistory # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionaudit import (
BaseSerializer,
ViewSerializer as AuditHistoryViewSerializer
)
@extend_schema_serializer(component_name = 'TenantAuditHistoryModelSerializer')
class ModelSerializer(
common.CommonModelSerializer,
BaseSerializer
):
"""Git Group Audit History Base Model"""
_urls = serializers.SerializerMethodField('get_url')
class Meta:
model = TenantAuditHistory
fields = [
'id',
'organization',
'display_name',
'content_type',
'model',
'before',
'after',
'action',
'user',
'created',
'_urls',
]
read_only_fields = fields
@extend_schema_serializer(component_name = 'TenantAuditHistoryViewSerializer')
class ViewSerializer(
ModelSerializer,
AuditHistoryViewSerializer,
):
"""Git Group Audit History Base View Model"""
pass

View File

@ -0,0 +1,87 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from access.serializers.organization import (TenantBaseSerializer)
from centurion.models.meta import CompanyCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
BaseSerializer,
ModelSerializer as BaseModelModelSerializer,
ViewSerializer as BaseModelViewSerializer
)
@extend_schema_serializer(component_name = 'CompanyModelNoteModelSerializer')
class ModelSerializer(
BaseModelModelSerializer,
):
_urls = serializers.SerializerMethodField('get_url')
def get_url(self, item) -> dict:
return {
'_self': item.get_url( request = self._context['view'].request ),
}
class Meta:
model = CompanyCenturionModelNote
fields = [
'id',
'organization',
'display_name',
'body',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
read_only_fields = [
'id',
'display_name',
'organization',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
def validate(self, attrs):
is_valid = False
note_model = self.Meta.model.model.field.related_model
attrs['model'] = note_model.objects.get(
id = int( self.context['view'].kwargs['model_id'] )
)
is_valid = super().validate(attrs)
return is_valid
@extend_schema_serializer(component_name = 'CompanyModelNoteViewSerializer')
class ViewSerializer(
ModelSerializer,
BaseModelViewSerializer,
):
organization = TenantBaseSerializer( many = False, read_only = True )

View File

@ -0,0 +1,87 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from access.serializers.organization import (TenantBaseSerializer)
from centurion.models.meta import ContactCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
BaseSerializer,
ModelSerializer as BaseModelModelSerializer,
ViewSerializer as BaseModelViewSerializer
)
@extend_schema_serializer(component_name = 'ContactModelNoteModelSerializer')
class ModelSerializer(
BaseModelModelSerializer,
):
_urls = serializers.SerializerMethodField('get_url')
def get_url(self, item) -> dict:
return {
'_self': item.get_url( request = self._context['view'].request ),
}
class Meta:
model = ContactCenturionModelNote
fields = [
'id',
'organization',
'display_name',
'body',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
read_only_fields = [
'id',
'display_name',
'organization',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
def validate(self, attrs):
is_valid = False
note_model = self.Meta.model.model.field.related_model
attrs['model'] = note_model.objects.get(
id = int( self.context['view'].kwargs['model_id'] )
)
is_valid = super().validate(attrs)
return is_valid
@extend_schema_serializer(component_name = 'ContactModelNoteViewSerializer')
class ViewSerializer(
ModelSerializer,
BaseModelViewSerializer,
):
organization = TenantBaseSerializer( many = False, read_only = True )

View File

@ -0,0 +1,87 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from access.serializers.organization import (TenantBaseSerializer)
from centurion.models.meta import EntityCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
BaseSerializer,
ModelSerializer as BaseModelModelSerializer,
ViewSerializer as BaseModelViewSerializer
)
@extend_schema_serializer(component_name = 'EntityModelNoteModelSerializer')
class ModelSerializer(
BaseModelModelSerializer,
):
_urls = serializers.SerializerMethodField('get_url')
def get_url(self, item) -> dict:
return {
'_self': item.get_url( request = self._context['view'].request ),
}
class Meta:
model = EntityCenturionModelNote
fields = [
'id',
'organization',
'display_name',
'body',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
read_only_fields = [
'id',
'display_name',
'organization',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
def validate(self, attrs):
is_valid = False
note_model = self.Meta.model.model.field.related_model
attrs['model'] = note_model.objects.get(
id = int( self.context['view'].kwargs['model_id'] )
)
is_valid = super().validate(attrs)
return is_valid
@extend_schema_serializer(component_name = 'EntityModelNoteViewSerializer')
class ViewSerializer(
ModelSerializer,
BaseModelViewSerializer,
):
organization = TenantBaseSerializer( many = False, read_only = True )

View File

@ -0,0 +1,87 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from access.serializers.organization import (TenantBaseSerializer)
from centurion.models.meta import PersonCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
BaseSerializer,
ModelSerializer as BaseModelModelSerializer,
ViewSerializer as BaseModelViewSerializer
)
@extend_schema_serializer(component_name = 'PersonModelNoteModelSerializer')
class ModelSerializer(
BaseModelModelSerializer,
):
_urls = serializers.SerializerMethodField('get_url')
def get_url(self, item) -> dict:
return {
'_self': item.get_url( request = self._context['view'].request ),
}
class Meta:
model = PersonCenturionModelNote
fields = [
'id',
'organization',
'display_name',
'body',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
read_only_fields = [
'id',
'display_name',
'organization',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
def validate(self, attrs):
is_valid = False
note_model = self.Meta.model.model.field.related_model
attrs['model'] = note_model.objects.get(
id = int( self.context['view'].kwargs['model_id'] )
)
is_valid = super().validate(attrs)
return is_valid
@extend_schema_serializer(component_name = 'PersonModelNoteViewSerializer')
class ViewSerializer(
ModelSerializer,
BaseModelViewSerializer,
):
organization = TenantBaseSerializer( many = False, read_only = True )

View File

@ -0,0 +1,87 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from access.serializers.organization import (TenantBaseSerializer)
from centurion.models.meta import RoleCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
BaseSerializer,
ModelSerializer as BaseModelModelSerializer,
ViewSerializer as BaseModelViewSerializer
)
@extend_schema_serializer(component_name = 'RoleModelNoteModelSerializer')
class ModelSerializer(
BaseModelModelSerializer,
):
_urls = serializers.SerializerMethodField('get_url')
def get_url(self, item) -> dict:
return {
'_self': item.get_url( request = self._context['view'].request ),
}
class Meta:
model = RoleCenturionModelNote
fields = [
'id',
'organization',
'display_name',
'body',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
read_only_fields = [
'id',
'display_name',
'organization',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
def validate(self, attrs):
is_valid = False
note_model = self.Meta.model.model.field.related_model
attrs['model'] = note_model.objects.get(
id = int( self.context['view'].kwargs['model_id'] )
)
is_valid = super().validate(attrs)
return is_valid
@extend_schema_serializer(component_name = 'RoleModelNoteViewSerializer')
class ViewSerializer(
ModelSerializer,
BaseModelViewSerializer,
):
organization = TenantBaseSerializer( many = False, read_only = True )

View File

@ -0,0 +1,87 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_serializer
from access.serializers.organization import (TenantBaseSerializer)
from centurion.models.meta import TenantCenturionModelNote # pylint: disable=E0401:import-error disable=E0611:no-name-in-module
from core.serializers.centurionmodelnote import ( # pylint: disable=W0611:unused-import
BaseSerializer,
ModelSerializer as BaseModelModelSerializer,
ViewSerializer as BaseModelViewSerializer
)
@extend_schema_serializer(component_name = 'TeamModelNoteModelSerializer')
class ModelSerializer(
BaseModelModelSerializer,
):
_urls = serializers.SerializerMethodField('get_url')
def get_url(self, item) -> dict:
return {
'_self': item.get_url( request = self._context['view'].request ),
}
class Meta:
model = TenantCenturionModelNote
fields = [
'id',
'organization',
'display_name',
'body',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
read_only_fields = [
'id',
'display_name',
'organization',
'created_by',
'modified_by',
'content_type',
'model',
'created',
'modified',
'_urls',
]
def validate(self, attrs):
is_valid = False
note_model = self.Meta.model.model.field.related_model
attrs['model'] = note_model.objects.get(
id = int( self.context['view'].kwargs['model_id'] )
)
is_valid = super().validate(attrs)
return is_valid
@extend_schema_serializer(component_name = 'TeamModelNoteViewSerializer')
class ViewSerializer(
ModelSerializer,
BaseModelViewSerializer,
):
organization = TenantBaseSerializer( many = False, read_only = True )

View File

@ -66,7 +66,6 @@ class ModelSerializer(
'entity_type',
'display_name',
'model_notes',
'is_global',
'created',
'modified',
'_urls',

View File

@ -41,7 +41,6 @@ class ModelSerializer(
'display_name',
'name',
'model_notes',
'is_global',
'created',
'modified',
'_urls',

View File

@ -46,7 +46,6 @@ class ModelSerializer(
'email',
'directory',
'model_notes',
'is_global',
'created',
'modified',
'_urls',

View File

@ -1,41 +0,0 @@
from core.serializers.model_notes import (
ModelNoteBaseSerializer,
ModelNoteModelSerializer,
ModelNoteViewSerializer
)
from access.models.entity_notes import EntityNotes
class EntityNoteBaseSerializer(ModelNoteBaseSerializer):
pass
class EntityNoteModelSerializer(
ModelNoteModelSerializer
):
class Meta:
model = EntityNotes
fields = ModelNoteModelSerializer.Meta.fields + [
'model',
]
read_only_fields = ModelNoteModelSerializer.Meta.read_only_fields + [
'model',
'content_type',
]
class EntityNoteViewSerializer(
ModelNoteViewSerializer,
EntityNoteModelSerializer,
):
pass

View File

@ -44,7 +44,6 @@ class ModelSerializer(
'l_name',
'dob',
'model_notes',
'is_global',
'created',
'modified',
'_urls',

View File

@ -4,7 +4,7 @@ from rest_framework import serializers
from access.models.tenant import Tenant
from app.serializers.user import UserBaseSerializer
from centurion.serializers.user import UserBaseSerializer
from core import fields as centurion_field
@ -20,7 +20,7 @@ class TenantBaseSerializer(serializers.ModelSerializer):
return str( item )
url = serializers.HyperlinkedIdentityField(
view_name="v2:_api_v2_organization-detail", format="html"
view_name="v2:_api_tenant-detail", format="html"
)
class Meta:
@ -61,13 +61,13 @@ class TenantModelSerializer(
'model_pk': item.pk
}
),
'notes': reverse(
"v2:_api_v2_organization_note-list",
request=self._context['view'].request,
kwargs={
'model_id': item.pk
}
),
# 'notes': reverse(
# "v2:_api_v2_organization_note-list",
# request=self._context['view'].request,
# kwargs={
# 'model_id': item.pk
# }
# ),
'teams': reverse("v2:_api_v2_organization_team-list", request=self._context['view'].request, kwargs={'organization_id': item.pk}),
}

View File

@ -1,48 +0,0 @@
from rest_framework import serializers
from access.models.organization_notes import OrganizationNotes
from api.serializers import common
from app.serializers.user import UserBaseSerializer
from core.serializers.model_notes import (
ModelNotes,
ModelNoteBaseSerializer,
ModelNoteModelSerializer,
ModelNoteViewSerializer
)
class OrganizationNoteBaseSerializer(ModelNoteBaseSerializer):
pass
class OrganizationNoteModelSerializer(
ModelNoteModelSerializer
):
class Meta:
model = OrganizationNotes
fields = ModelNoteModelSerializer.Meta.fields + [
'model',
]
read_only_fields = ModelNoteModelSerializer.Meta.read_only_fields + [
'model',
'content_type',
]
class OrganizationNoteViewSerializer(
ModelNoteViewSerializer,
OrganizationNoteModelSerializer,
):
pass

View File

@ -9,7 +9,7 @@ from access.serializers.organization import TenantBaseSerializer
from api.serializers import common
from app.serializers.permission import PermissionBaseSerializer
from centurion.serializers.permission import PermissionBaseSerializer

View File

@ -1,48 +0,0 @@
from rest_framework import serializers
from access.models.role_notes import RoleNotes
from api.serializers import common
from app.serializers.user import UserBaseSerializer
from core.serializers.model_notes import (
ModelNotes,
ModelNoteBaseSerializer,
ModelNoteModelSerializer,
ModelNoteViewSerializer
)
class RoleNoteBaseSerializer(ModelNoteBaseSerializer):
pass
class RoleNoteModelSerializer(
ModelNoteModelSerializer
):
class Meta:
model = RoleNotes
fields = ModelNoteModelSerializer.Meta.fields + [
'model',
]
read_only_fields = ModelNoteModelSerializer.Meta.read_only_fields + [
'model',
'content_type',
]
class RoleNoteViewSerializer(
ModelNoteViewSerializer,
RoleNoteModelSerializer,
):
pass

View File

@ -1,48 +0,0 @@
from rest_framework import serializers
from access.models.team_notes import TeamNotes
from api.serializers import common
from app.serializers.user import UserBaseSerializer
from core.serializers.model_notes import (
ModelNotes,
ModelNoteBaseSerializer,
ModelNoteModelSerializer,
ModelNoteViewSerializer
)
class TeamNoteBaseSerializer(ModelNoteBaseSerializer):
pass
class TeamNoteModelSerializer(
ModelNoteModelSerializer
):
class Meta:
model = TeamNotes
fields = ModelNoteModelSerializer.Meta.fields + [
'model',
]
read_only_fields = ModelNoteModelSerializer.Meta.read_only_fields + [
'model',
'content_type',
]
class TeamNoteViewSerializer(
ModelNoteViewSerializer,
TeamNoteModelSerializer,
):
pass

View File

@ -1,12 +1,10 @@
from rest_framework.reverse import reverse
from rest_framework import serializers
from access.models.team_user import TeamUsers
from api.serializers import common
from app.serializers.user import UserBaseSerializer
from centurion.serializers.user import UserBaseSerializer
@ -55,7 +53,7 @@ class TeamUserModelSerializer(
get_url = super().get_url( item = item )
del get_url['history']
# del get_url['history']
del get_url['knowledge_base']

View File

@ -9,7 +9,7 @@ from api.serializers import common
from access.functions.permissions import permission_queryset
from access.serializers.organization import TenantBaseSerializer
from app.serializers.permission import Permission, PermissionBaseSerializer
from centurion.serializers.permission import PermissionBaseSerializer
from core import fields as centurion_field
@ -94,7 +94,6 @@ class TeamModelSerializer(
'model_notes',
'permissions',
'organization',
'is_global',
'created',
'modified',
'_urls',

View File

@ -1,22 +0,0 @@
{% extends 'base.html.j2' %}
{% block content_header_icon %}{% endblock %}
{% block content %}
<table class="data">
<tr>
<th>Name</th>
<th>Created</th>
<th>Modified</th>
</tr>
{% for org in organization_list %}
<tr>
<td><a href="/organization/{{ org.id }}/">{{ org.name }}</a></td>
<td>{{ org.created }}</td>
<td>{{ org.modified }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,106 +0,0 @@
{% extends 'base.html.j2' %}
{% load markdown %}
{% block title %}Organization - {{ organization.name }}{% endblock %}
{% block content %}
<style>
form div .helptext {
background-color: rgb(0, 140, 255);
display: block;
}
.detail-view-field {
display:unset;
height: 30px;
line-height: 30px;
padding: 0px 20px 40px 20px;
}
.detail-view-field label {
display: inline-block;
font-weight: bold;
width: 200px;
margin: 10px;
/*padding: 10px;*/
height: 30px;
line-height: 30px;
}
.detail-view-field span {
display: inline-block;
width: 340px;
margin: 10px;
/*padding: 10px;*/
border-bottom: 1px solid #ccc;
height: 30px;
line-height: 30px;
}
</style>
<div style="align-items:flex-start; align-content: center; display: flexbox; width: 100%">
<div style="display: inline; width: 40%; margin: 30px;">
<div class="detail-view-field">
<label>{{ form.name.label }}</label>
<span>{{ form.name.value }}</span>
</div>
<div class="detail-view-field">
<label>{{ form.manager.label }}</label>
<span>{{ organization.manager }}</span>
</div>
<div class="detail-view-field">
<label>{{ form.created.label }}</label>
<span>{{ form.created.value }}</span>
</div>
<div class="detail-view-field">
<label>{{ form.modified.label }}</label>
<span>{{ form.modified.value }}</span>
</div>
</div>
<div style="display: inline; width: 40%; margin: 30px; text-align: left;">
<div>
<label style="font-weight: bold; width: 100%; border-bottom: 1px solid #ccc; display: block; text-align: inherit;">{{ form.model_notes.label }}</label>
<div style="display: inline-block; text-align: left;">{{ form.model_notes.value | markdown | safe }}</div>
</div>
</div>
<div style="display: block;">
<input type="button" value="<< Back" onclick="window.location='{% url 'Access:Organizations' %}';">
<input type="button" value="New Team" onclick="window.location='{% url 'Access:_team_add' organization.id %}';">
</div>
<hr />
<table>
<thead>
<tr>
<th>Team Name</th>
<th>Created</th>
<th>Modified</th>
</tr>
</thead>
{% for field in teams %}
<tr>
<td><a href="{% url 'Access:_team_view' organization_id=organization.id pk=field.id %}">{{ field.team_name }}</a></td>
<td>{{ field.created }}</td>
<td>{{ field.modified }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,48 +0,0 @@
{% extends 'base.html.j2' %}
{% block title %}Team - {{ team.team_name }}{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_div }}
<input style="display:unset;" type="submit" value="Submit">
</form>
<hr />
<input type="button" value="<< Back" onclick="window.location='{% url 'Access:_organization_view' pk=organization.id %}';">
<input type="button" value="Delete Team"
onclick="window.location='{% url 'Access:_team_delete' organization_id=organization.id pk=team.id %}';">
<input type="button" value="Assign User"
onclick="window.location='{% url 'Access:_team_user_add' organization_id=organization.id pk=team.id %}';">
{{ formset.management_form }}
<table id="formset" class="form">
<thead>
<tr>
<th>User</th>
<th>Manager</th>
<th>Created</th>
<th>Modified</th>
<th>&nbsp;</th>
</tr>
</thead>
{% for field in teamusers %}
<tr>
<td>{{ field.user }}</td>
<td><input type="checkbox" {% if field.manager %}checked{% endif %} disabled></td>
<td>{{ field.created }}</td>
<td>{{ field.modified }}</td>
<td><a
href="{% url 'Access:_team_user_delete' organization_id=organization.id team_id=field.team_id pk=field.id %}">Delete</a></a>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,32 +0,0 @@
class TenancyObject:
""" Tests for checking TenancyObject """
model = None
""" Model to be tested """
should_model_history_be_saved: bool = True
""" Should model history be saved.
By default this should always be 'True', however in special
circumstances, this may not be desired.
"""
# def test_history_save(self):
# """Confirm the desired intent for saving model history."""
# assert self.model.save_model_history == self.should_model_history_be_saved
# @pytest.mark.skip(reason="to be written")
# def test_edit_no_organization_fails(self):
# """ Devices must be assigned an organization
# Must not be able to edit an item without an organization
# """
# pass

View File

@ -0,0 +1,204 @@
import pytest
import random
from django.test import Client
class AdditionalTestCases:
def test_permission_add(self, model_instance, api_request_permissions,
model_kwargs, kwargs_api_create
):
""" Check correct permission for add
Attempt to add as user with permission
"""
client = Client()
client.force_login( api_request_permissions['user']['add'] )
the_model = model_instance( kwargs_create = self.kwargs_create_item )
url = the_model.get_url( many = True )
the_model.delete()
kwargs = kwargs_api_create.copy()
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
response = client.post(
path = url,
data = kwargs,
content_type = 'application/json'
)
assert response.status_code == 201, response.content
def test_returned_results_only_user_orgs(self, model_instance, model_kwargs, api_request_permissions):
"""Returned results check
Ensure that a query to the viewset endpoint does not return
items that are not part of the users organizations.
"""
if model_kwargs.get('organization', None) is None:
pytest.xfail( reason = 'Model lacks organization field. test is n/a' )
client = Client()
viewable_organizations = [
api_request_permissions['tenancy']['user'].id,
]
if getattr(self, 'global_organization', None):
# Cater for above test that also has global org
viewable_organizations += [ api_request_permissions['tenancy']['global'] ]
client.force_login( api_request_permissions['user']['view'] )
kwargs = self.kwargs_create_item.copy()
kwargs.update({
'organization': api_request_permissions['tenancy']['different']
})
model_instance(
kwargs_create = kwargs
)
kwargs = self.kwargs_create_item.copy()
kwargs.update({
'organization': api_request_permissions['tenancy']['global']
})
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
model_instance(
kwargs_create = kwargs
)
kwargs = self.kwargs_create_item.copy()
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
the_model = model_instance( kwargs_create = kwargs )
response = client.get(
path = the_model.get_url( many = True )
)
# if response.status_code == 405:
# pytest.xfail( reason = 'ViewSet does not have this request method.' )
# elif IsAuthenticatedOrReadOnly in response.renderer_context['view'].permission_classes:
# pytest.xfail( reason = 'ViewSet is public viewable, test is N/A' )
assert response.status_code == 200
contains_different_org: bool = False
for item in response.data['results']:
if 'organization' not in item:
pytest.xfail( reason = 'Model lacks organization field. test is n/a' )
if(
int(item['organization']['id']) not in viewable_organizations
and
int(item['organization']['id']) != api_request_permissions['tenancy']['global'].id
):
contains_different_org = True
print(f'Failed returned row was: {item}')
assert not contains_different_org
def test_returned_data_from_user_and_global_organizations_only(
self, model_instance, model_kwargs, api_request_permissions
):
"""Check items returned
Items returned from the query Must be from the users organization and
global ONLY!
"""
if model_kwargs.get('organization', None) is None:
pytest.xfail( reason = 'Model lacks organization field. test is n/a' )
client = Client()
only_from_user_org: bool = True
viewable_organizations = [
api_request_permissions['tenancy']['user'].id,
api_request_permissions['tenancy']['global'].id
]
kwargs = self.kwargs_create_item.copy()
kwargs.update({
'organization': api_request_permissions['tenancy']['different']
})
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
the_model = model_instance(
kwargs_create = kwargs
)
kwargs = self.kwargs_create_item.copy()
kwargs.update({
'organization': api_request_permissions['tenancy']['global']
})
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
model_instance(
kwargs_create = kwargs
)
client.force_login( api_request_permissions['user']['view'] )
kwargs = self.kwargs_create_item.copy()
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
the_model = model_instance( kwargs_create = kwargs )
response = client.get(
path = the_model.get_url( many = True )
)
assert len(response.data['results']) >= 2 # fail if only one item extist.
for row in response.data['results']:
if 'organization' not in row:
pytest.xfail( reason = 'Model lacks organization field. test is n/a' )
if row['organization']['id'] not in viewable_organizations:
only_from_user_org = False
print(f"Users org: {api_request_permissions['tenancy']['user'].id}")
print(f"global org: {api_request_permissions['tenancy']['global'].id}")
print(f'Failed returned row was: {row}')
assert only_from_user_org

View File

@ -0,0 +1,204 @@
import pytest
import random
from django.test import Client
class AdditionalTestCases:
def test_permission_add(self, model_instance, api_request_permissions,
model_kwargs, kwargs_api_create
):
""" Check correct permission for add
Attempt to add as user with permission
"""
client = Client()
client.force_login( api_request_permissions['user']['add'] )
the_model = model_instance( kwargs_create = self.kwargs_create_item )
url = the_model.get_url( many = True )
the_model.delete()
kwargs = kwargs_api_create.copy()
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
response = client.post(
path = url,
data = kwargs,
content_type = 'application/json'
)
assert response.status_code == 201, response.content
def test_returned_results_only_user_orgs(self, model_instance, model_kwargs, api_request_permissions):
"""Returned results check
Ensure that a query to the viewset endpoint does not return
items that are not part of the users organizations.
"""
if model_kwargs.get('organization', None) is None:
pytest.xfail( reason = 'Model lacks organization field. test is n/a' )
client = Client()
viewable_organizations = [
api_request_permissions['tenancy']['user'].id,
]
if getattr(self, 'global_organization', None):
# Cater for above test that also has global org
viewable_organizations += [ api_request_permissions['tenancy']['global'] ]
client.force_login( api_request_permissions['user']['view'] )
kwargs = self.kwargs_create_item.copy()
kwargs.update({
'organization': api_request_permissions['tenancy']['different']
})
model_instance(
kwargs_create = kwargs
)
kwargs = self.kwargs_create_item.copy()
kwargs.update({
'organization': api_request_permissions['tenancy']['global']
})
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
model_instance(
kwargs_create = kwargs
)
kwargs = self.kwargs_create_item.copy()
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
the_model = model_instance( kwargs_create = kwargs )
response = client.get(
path = the_model.get_url( many = True )
)
# if response.status_code == 405:
# pytest.xfail( reason = 'ViewSet does not have this request method.' )
# elif IsAuthenticatedOrReadOnly in response.renderer_context['view'].permission_classes:
# pytest.xfail( reason = 'ViewSet is public viewable, test is N/A' )
assert response.status_code == 200
contains_different_org: bool = False
for item in response.data['results']:
if 'organization' not in item:
pytest.xfail( reason = 'Model lacks organization field. test is n/a' )
if(
int(item['organization']['id']) not in viewable_organizations
and
int(item['organization']['id']) != api_request_permissions['tenancy']['global'].id
):
contains_different_org = True
print(f'Failed returned row was: {item}')
assert not contains_different_org
def test_returned_data_from_user_and_global_organizations_only(
self, model_instance, model_kwargs, api_request_permissions
):
"""Check items returned
Items returned from the query Must be from the users organization and
global ONLY!
"""
if model_kwargs.get('organization', None) is None:
pytest.xfail( reason = 'Model lacks organization field. test is n/a' )
client = Client()
only_from_user_org: bool = True
viewable_organizations = [
api_request_permissions['tenancy']['user'].id,
api_request_permissions['tenancy']['global'].id
]
kwargs = self.kwargs_create_item.copy()
kwargs.update({
'organization': api_request_permissions['tenancy']['different']
})
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
the_model = model_instance(
kwargs_create = kwargs
)
kwargs = self.kwargs_create_item.copy()
kwargs.update({
'organization': api_request_permissions['tenancy']['global']
})
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
model_instance(
kwargs_create = kwargs
)
client.force_login( api_request_permissions['user']['view'] )
kwargs = self.kwargs_create_item.copy()
kwargs['dob'] = str(random.randint(1972, 2037)) + '-' + str(
random.randint(1, 12)) + '-' + str(random.randint(1, 28))
the_model = model_instance( kwargs_create = kwargs )
response = client.get(
path = the_model.get_url( many = True )
)
assert len(response.data['results']) >= 2 # fail if only one item extist.
for row in response.data['results']:
if 'organization' not in row:
pytest.xfail( reason = 'Model lacks organization field. test is n/a' )
if row['organization']['id'] not in viewable_organizations:
only_from_user_org = False
print(f"Users org: {api_request_permissions['tenancy']['user'].id}")
print(f"global org: {api_request_permissions['tenancy']['global'].id}")
print(f'Failed returned row was: {row}')
assert only_from_user_org

View File

@ -0,0 +1,44 @@
import pytest
from django.test import Client
class AdditionalTestCases:
def test_permission_add(self, model_instance, api_request_permissions,
model_kwargs, kwargs_api_create
):
""" Check correct permission for add
Attempt to add as user with permission
"""
client = Client()
client.force_login( api_request_permissions['user']['add'] )
the_model = model_instance( kwargs_create = model_kwargs )
url = the_model.get_url( many = True )
response = client.post(
path = url,
data = kwargs_api_create,
content_type = 'application/json'
)
assert response.status_code == 201, response.content
def test_returned_data_from_user_and_global_organizations_only(
self
):
"""Check items returned
Items returned from the query Must be from the users organization and
global ONLY!
"""
pytest.mark.xfail( reason = 'model is not for global use' )

View File

@ -22,3 +22,14 @@ def create_serializer():
yield ModelSerializer
@pytest.fixture( scope = 'class')
def model_kwargs(request, kwargs_company):
request.cls.kwargs_create_item = kwargs_company.copy()
yield kwargs_company.copy()
if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item

View File

@ -0,0 +1,36 @@
import pytest
from access.tests.functional.entity.test_functional_entity_api_fields import (
EntityAPIInheritedCases
)
@pytest.mark.model_company
class CompanyAPITestCases(
EntityAPIInheritedCases,
):
@property
def parameterized_api_fields(self):
return {
'name': {
'expected': str
}
}
class CompanyAPIInheritedCases(
CompanyAPITestCases,
):
pass
@pytest.mark.module_access
class CompanyAPIPyTest(
CompanyAPITestCases,
):
pass

View File

@ -53,11 +53,11 @@ class CompanyMetadataInheritedCases(
}
# self.url_kwargs = {
# 'entity_model': self.model._meta.sub_model_type
# 'model_name': self.model._meta.sub_model_type
# }
# self.url_view_kwargs = {
# 'entity_model': self.model._meta.sub_model_type
# 'model_name': self.model._meta.sub_model_type
# }
super().setUpTestData()

View File

@ -1,43 +0,0 @@
import pytest
from access.tests.functional.entity.test_functional_entity_permission import (
EntityPermissionsAPIInheritedCases
)
class CompanyPermissionsAPITestCases(
EntityPermissionsAPIInheritedCases,
):
add_data: dict = {
'name': 'Ian1',
}
kwargs_create_item: dict = {
'name': 'Ian2',
}
kwargs_create_item_diff_org: dict = {
'name': 'Ian3',
}
class CompanyPermissionsAPIInheritedCases(
CompanyPermissionsAPITestCases,
):
add_data: dict = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
class CompanyPermissionsAPIPyTest(
CompanyPermissionsAPITestCases,
):
pass

View File

@ -1,46 +0,0 @@
import pytest
from rest_framework.exceptions import ValidationError
from access.tests.functional.entity.test_functional_entity_serializer import (
MockView,
EntitySerializerInheritedCases
)
class CompanySerializerTestCases(
EntitySerializerInheritedCases
):
parameterized_test_data: dict = {
"name": {
'will_create': False,
'exception_key': 'required'
},
}
valid_data: dict = {
'name': 'Ian',
}
"""Valid data used by serializer to create object"""
class CompanySerializerInheritedCases(
CompanySerializerTestCases,
):
parameterized_test_data: dict = None
valid_data: dict = None
"""Valid data used by serializer to create object"""
class CompanySerializerPyTest(
CompanySerializerTestCases,
):
parameterized_test_data: dict = None

View File

@ -1,58 +0,0 @@
from django.test import TestCase
from access.models.company_base import Company
from access.tests.functional.entity.test_functional_entity_viewset import (
EntityViewSetInheritedCases
)
class ViewSetTestCases(
EntityViewSetInheritedCases,
):
add_data: dict = {
'name': 'Ian',
}
kwargs_create_item: dict = {
'name': 'Ian2',
}
kwargs_create_item_diff_org: dict = {
'name': 'Ian3',
}
model = Company
class CompanyViewSetInheritedCases(
ViewSetTestCases,
):
model = None
@classmethod
def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
super().setUpTestData()
class CompanyViewSetTest(
ViewSetTestCases,
TestCase,
):
pass

View File

@ -22,3 +22,13 @@ def create_serializer():
yield ModelSerializer
@pytest.fixture( scope = 'class')
def model_kwargs(request, kwargs_contact):
request.cls.kwargs_create_item = kwargs_contact.copy()
yield kwargs_contact.copy()
if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item

View File

@ -0,0 +1,41 @@
import pytest
from access.tests.functional.person.test_functional_person_api_fields import (
PersonAPIInheritedCases
)
@pytest.mark.model_contact
class ContactAPITestCases(
PersonAPIInheritedCases,
):
property
def parameterized_api_fields(self):
return {
'email': {
'expected': str
},
'directory': {
'expected': bool
}
}
class ContactAPIInheritedCases(
ContactAPITestCases,
):
pass
@pytest.mark.module_access
class ContactAPIPyTest(
ContactAPITestCases,
):
pass

View File

@ -1,60 +0,0 @@
from django.test import TestCase
from access.models.contact import Contact
from access.tests.functional.person.test_functional_person_history import (
PersonHistoryInheritedCases
)
class ContactTestCases(
PersonHistoryInheritedCases,
):
field_name = 'model_notes'
kwargs_create_obj: dict = {
'email': 'ipfunny@unit.test',
}
kwargs_delete_obj: dict = {
'email': 'ipweird@unit.test',
}
model = Contact
class ContactHistoryInheritedCases(
ContactTestCases,
):
model = None
"""Entity model to test"""
kwargs_create_obj: dict = None
kwargs_delete_obj: dict = None
@classmethod
def setUpTestData(self):
self.kwargs_create_obj.update(
super().kwargs_create_obj
)
self.kwargs_delete_obj.update(
super().kwargs_delete_obj
)
super().setUpTestData()
class ContactHistoryTest(
ContactTestCases,
TestCase,
):
pass

View File

@ -1,70 +0,0 @@
import pytest
from access.tests.functional.person.test_functional_person_permission import (
PersonPermissionsAPIInheritedCases
)
class ContactPermissionsAPITestCases(
PersonPermissionsAPIInheritedCases,
):
add_data: dict = {
'email': 'ipfunny@unit.test',
}
kwargs_create_item: dict = {
'email': 'ipweird@unit.test',
}
kwargs_create_item_diff_org: dict = {
'email': 'ipstrange@unit.test',
}
class ContactPermissionsAPIInheritedCases(
ContactPermissionsAPITestCases,
):
add_data: dict = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
# url_name = '_api_v2_entity_sub'
# @pytest.fixture(scope='class')
# def inherited_var_setup(self, request):
# request.cls.url_kwargs.update({
# 'entity_model': self.model._meta.sub_model_type
# })
# request.cls.url_view_kwargs.update({
# 'entity_model': self.model._meta.sub_model_type
# })
# @pytest.fixture(scope='class', autouse = True)
# def class_setup(self, request, django_db_blocker,
# model,
# var_setup,
# prepare,
# inherited_var_setup,
# diff_org_model,
# create_model,
# ):
# pass
class ContactPermissionsAPIPyTest(
ContactPermissionsAPITestCases,
):
pass

View File

@ -1,46 +0,0 @@
import pytest
from rest_framework.exceptions import ValidationError
from access.tests.functional.person.test_functional_person_serializer import (
MockView,
PersonSerializerInheritedCases
)
class ContactSerializerTestCases(
PersonSerializerInheritedCases
):
parameterized_test_data: dict = {
"email": {
'will_create': False,
'exception_key': 'required'
}
}
valid_data: dict = {
'email': 'contactentityduplicatetwo@unit.test',
}
"""Valid data used by serializer to create object"""
class ContactSerializerInheritedCases(
ContactSerializerTestCases,
):
parameterized_test_data: dict = None
valid_data: dict = None
"""Valid data used by serializer to create object"""
class ContactSerializerPyTest(
ContactSerializerTestCases,
):
parameterized_test_data: dict = None

View File

@ -1,58 +0,0 @@
from django.test import TestCase
from access.models.contact import Contact
from access.tests.functional.person.test_functional_person_viewset import (
PersonViewSetInheritedCases
)
class ViewSetTestCases(
PersonViewSetInheritedCases,
):
add_data: dict = {
'email': 'ipfunny@unit.test',
}
kwargs_create_item: dict = {
'email': 'ipweird@unit.test',
}
kwargs_create_item_diff_org: dict = {
'email': 'ipstrange@unit.test',
}
model = Contact
class ContactViewSetInheritedCases(
ViewSetTestCases,
):
model = None
@classmethod
def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
super().setUpTestData()
class ContactViewSetTest(
ViewSetTestCases,
TestCase,
):
pass

View File

@ -22,3 +22,13 @@ def create_serializer():
yield ModelSerializer
@pytest.fixture( scope = 'class')
def model_kwargs(request, kwargs_entity):
request.cls.kwargs_create_item = kwargs_entity.copy()
yield kwargs_entity.copy()
if hasattr(request.cls, 'kwargs_create_item'):
del request.cls.kwargs_create_item

View File

@ -0,0 +1,48 @@
import pytest
from access.models.entity import Entity
from api.tests.functional.test_functional_api_fields import (
APIFieldsInheritedCases,
)
@pytest.mark.model_entity
class EntityAPITestCases(
APIFieldsInheritedCases,
):
base_model = Entity
@property
def parameterized_api_fields(self):
return {
'entity_type': {
'expected': str
},
'_urls.history': {
'expected': str
},
'_urls.knowledge_base': {
'expected': str
}
}
class EntityAPIInheritedCases(
EntityAPITestCases,
):
pass
@pytest.mark.module_access
class EntityAPIPyTest(
EntityAPITestCases,
):
pass

View File

@ -1,78 +0,0 @@
from django.test import TestCase
from access.models.entity_history import Entity, EntityHistory
from core.tests.abstract.test_functional_history import HistoryEntriesCommon
class HistoryTestCases(
HistoryEntriesCommon,
):
field_name = 'model_notes'
history_model = EntityHistory
kwargs_create_obj: dict = {}
kwargs_delete_obj: dict = {}
model = Entity
@classmethod
def setUpTestData(self):
super().setUpTestData()
self.obj = self.model.objects.create(
organization = self.organization,
model_notes = self.field_value_original,
**self.kwargs_create_obj,
)
self.obj_delete = self.model.objects.create(
organization = self.organization,
model_notes = 'another note',
**self.kwargs_delete_obj,
)
self.call_the_banners()
class EntityHistoryInheritedCases(
HistoryTestCases,
):
model = None
"""Entity model to test"""
kwargs_create_obj: dict = None
kwargs_delete_obj: dict = None
@classmethod
def setUpTestData(self):
self.kwargs_create_obj.update(
super().kwargs_create_obj
)
self.kwargs_delete_obj.update(
super().kwargs_delete_obj
)
super().setUpTestData()
class EntityHistoryTest(
HistoryTestCases,
TestCase,
):
pass

View File

@ -223,7 +223,7 @@ class EntityMetadataInheritedCases(
kwargs_create_item_diff_org: dict = {}
url_name = '_api_v2_entity_sub'
url_name = '_api_entity_sub'
@classmethod
@ -240,11 +240,11 @@ class EntityMetadataInheritedCases(
}
self.url_kwargs = {
'entity_model': self.model._meta.sub_model_type
'model_name': self.model._meta.sub_model_type
}
self.url_view_kwargs = {
'entity_model': self.model._meta.sub_model_type
'model_name': self.model._meta.sub_model_type
}
super().setUpTestData()
@ -257,4 +257,4 @@ class EntityMetadataTest(
):
url_name = '_api_v2_entity'
url_name = '_api_entity'

View File

@ -1,89 +0,0 @@
import pytest
from api.tests.functional.test_functional_api_permissions import (
APIPermissionsInheritedCases,
)
class EntityPermissionsAPITestCases(
APIPermissionsInheritedCases,
):
add_data: dict = {}
app_namespace = 'v2'
change_data = {}
delete_data = {}
kwargs_create_item: dict = {}
kwargs_create_item_diff_org: dict = {}
url_kwargs: dict = {}
url_name = '_api_v2_entity'
url_view_kwargs: dict = {}
def test_returned_data_from_user_and_global_organizations_only(self):
"""Check items returned
This test case is a over-ride of a test case with the same name.
This model is not a tenancy model making this test not-applicable.
Items returned from the query Must be from the users organization and
global ONLY!
"""
pass
class EntityPermissionsAPIInheritedCases(
EntityPermissionsAPITestCases,
):
add_data: dict = None
kwargs_create_item: dict = None
kwargs_create_item_diff_org: dict = None
url_name = '_api_v2_entity_sub'
@pytest.fixture(scope='class')
def inherited_var_setup(self, request):
request.cls.url_kwargs.update({
'entity_model': self.model._meta.sub_model_type
})
request.cls.url_view_kwargs.update({
'entity_model': self.model._meta.sub_model_type
})
@pytest.fixture(scope='class', autouse = True)
def class_setup(self, request, django_db_blocker,
model,
var_setup,
prepare,
inherited_var_setup,
diff_org_model,
create_model,
):
pass
class EntityPermissionsAPIPyTest(
EntityPermissionsAPITestCases,
):
pass

View File

@ -28,7 +28,7 @@ class MockView:
"""
@pytest.mark.skip(reason = 'see #874, tests being refactored')
class EntitySerializerTestCases:

View File

@ -1,266 +0,0 @@
import django
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from access.models.entity import Entity
from access.models.tenant import Tenant as Organization
from access.models.team import Team
from access.models.team_user import TeamUsers
from api.tests.abstract.api_serializer_viewset import SerializersTestCases
User = django.contrib.auth.get_user_model()
class ViewSetBase:
add_data: dict = {
'model_notes': 'added model note'
}
app_namespace = 'v2'
base_model = Entity
"""Base model for this sub model
don't change or override this value
"""
change_data = None
delete_data = {}
kwargs_create_item: dict = {
'model_notes': 'added model note'
}
kwargs_create_item_diff_org: dict = {
'model_notes': 'added model note'
}
model = None
url_kwargs: dict = {}
url_view_kwargs: dict = {}
url_name = None
@classmethod
def setUpTestData(self):
"""Setup Test
1. Create an organization for user and item
. create an organization that is different to item
2. Create a team
3. create teams with each permission: view, add, change, delete
4. create a user per team
"""
organization = Organization.objects.create(name='test_org')
self.organization = organization
self.different_organization = Organization.objects.create(name='test_different_organization')
self.view_user = User.objects.create_user(username="test_user_view", password="password")
self.item = self.model.objects.create(
organization = organization,
**self.kwargs_create_item
)
self.other_org_item = self.model.objects.create(
organization = self.different_organization,
**self.kwargs_create_item_diff_org
)
self.url_view_kwargs.update({ 'pk': self.item.id })
if self.add_data is not None:
self.add_data.update({
'organization': self.organization.id,
})
view_permissions = Permission.objects.get(
codename = 'view_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
view_team = Team.objects.create(
team_name = 'view_team',
organization = organization,
)
view_team.permissions.set([view_permissions])
add_permissions = Permission.objects.get(
codename = 'add_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
add_team = Team.objects.create(
team_name = 'add_team',
organization = organization,
)
add_team.permissions.set([add_permissions])
change_permissions = Permission.objects.get(
codename = 'change_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
change_team = Team.objects.create(
team_name = 'change_team',
organization = organization,
)
change_team.permissions.set([change_permissions])
delete_permissions = Permission.objects.get(
codename = 'delete_' + self.model._meta.model_name,
content_type = ContentType.objects.get(
app_label = self.model._meta.app_label,
model = self.model._meta.model_name,
)
)
delete_team = Team.objects.create(
team_name = 'delete_team',
organization = organization,
)
delete_team.permissions.set([delete_permissions])
self.no_permissions_user = User.objects.create_user(username="test_no_permissions", password="password")
TeamUsers.objects.create(
team = view_team,
user = self.view_user
)
self.add_user = User.objects.create_user(username="test_user_add", password="password")
TeamUsers.objects.create(
team = add_team,
user = self.add_user
)
self.change_user = User.objects.create_user(username="test_user_change", password="password")
TeamUsers.objects.create(
team = change_team,
user = self.change_user
)
self.delete_user = User.objects.create_user(username="test_user_delete", password="password")
TeamUsers.objects.create(
team = delete_team,
user = self.delete_user
)
self.different_organization_user = User.objects.create_user(username="test_different_organization_user", password="password")
different_organization_team = Team.objects.create(
team_name = 'different_organization_team',
organization = self.different_organization,
)
different_organization_team.permissions.set([
view_permissions,
add_permissions,
change_permissions,
delete_permissions,
])
TeamUsers.objects.create(
team = different_organization_team,
user = self.different_organization_user
)
def test_sanity_is_asset_sub_model(self):
"""Sanity Test
This test ensures that the model being tested `self.model` is a
sub-model of `self.base_model`.
This test is required as the same viewset is used for all sub-models
of `Entity`
"""
assert issubclass(self.model, self.base_model)
class ViewSetTestCases(
ViewSetBase,
SerializersTestCases,
):
model = Entity
class EntityViewSetInheritedCases(
ViewSetTestCases,
):
model = None
url_name = '_api_v2_entity_sub'
@classmethod
def setUpTestData(self):
self.kwargs_create_item = {
**super().kwargs_create_item,
**self.kwargs_create_item
}
self.kwargs_create_item_diff_org = {
**super().kwargs_create_item_diff_org,
**self.kwargs_create_item_diff_org
}
self.url_kwargs = {
'entity_model': self.model._meta.sub_model_type
}
self.url_view_kwargs = {
'entity_model': self.model._meta.sub_model_type
}
super().setUpTestData()
class EntityViewSetTest(
ViewSetTestCases,
TestCase,
):
url_name = '_api_v2_entity'

View File

@ -1,81 +0,0 @@
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from access.models.entity_notes import Entity, EntityNotes
from core.tests.abstract.model_notes_api_fields import ModelNotesNotesAPIFields
class NotesAPITestCases(
ModelNotesNotesAPIFields,
):
entity_model = None
model = EntityNotes
kwargs_model_create: dict = None
# url_view_kwargs: dict = None
view_name: str = '_api_v2_entity_note'
@classmethod
def setUpTestData(self):
"""Setup Test
1. Call parent setup
2. Create a model note
3. add url kwargs
4. make the API request
"""
super().setUpTestData()
self.item = self.model.objects.create(
organization = self.organization,
content = 'a random comment',
content_type = ContentType.objects.get(
app_label = str(self.model._meta.app_label).lower(),
model = str(self.model.model.field.related_model.__name__).replace(' ', '').lower(),
),
model = self.entity_model.objects.create(
organization = self.organization,
model_notes = 'text',
**self.kwargs_model_create
),
created_by = self.view_user,
modified_by = self.view_user,
)
self.url_view_kwargs = {
'model_id': self.item.model.pk,
'pk': self.item.pk
}
self.make_request()
class EntityNotesAPIInheritedCases(
NotesAPITestCases,
):
entity_model = None
kwargs_model_create = None
class EntityNotesAPITest(
NotesAPITestCases,
TestCase,
):
entity_model = Entity
kwargs_model_create = {}

View File

@ -1,162 +0,0 @@
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from access.viewsets.entity_notes import ViewSet
from core.tests.abstract.test_functional_notes_viewset import (
ModelNotesViewSetBase,
ModelNotesMetadata,
ModelNotesPermissionsAPI,
ModelNotesSerializer
)
class ViewSetBase(
ModelNotesViewSetBase
):
viewset = ViewSet
kwargs_create_model_item: dict = {}
kwargs_create_model_item_other_org: dict = {}
url_name = '_api_v2_entity_note'
@classmethod
def setUpTestData(self):
super().setUpTestData()
self.item = self.viewset.model.objects.create(
organization = self.organization,
content = 'a random comment',
content_type = ContentType.objects.get(
app_label = str(self.model._meta.app_label).lower(),
model = str(self.model.model.field.related_model.__name__).replace(' ', '').lower(),
),
model = self.viewset.model.model.field.related_model.objects.create(
organization = self.organization,
model_notes = 'text',
**self.kwargs_create_model_item
),
created_by = self.view_user,
modified_by = self.view_user,
)
self.other_org_item = self.viewset.model.objects.create(
organization = self.different_organization,
content = 'a random comment',
content_type = ContentType.objects.get(
app_label = str(self.model._meta.app_label).lower(),
model = str(self.model.model.field.related_model.__name__).replace(' ', '').lower(),
),
model = self.viewset.model.model.field.related_model.objects.create(
organization = self.organization,
model_notes = 'text',
**self.kwargs_create_model_item_other_org
),
created_by = self.view_user,
modified_by = self.view_user,
)
self.url_kwargs = {
'model_id': self.item.model.pk,
}
self.url_view_kwargs = {
'model_id': self.item.model.pk,
'pk': self.item.id
}
class NotesPermissionsAPITestCases(
ViewSetBase,
ModelNotesPermissionsAPI,
):
viewset = None
def test_returned_data_from_user_and_global_organizations_only(self):
"""Check items returned
This test case is a over-ride of a test case with the same name.
This model is not a global model making this test not-applicable.
Items returned from the query Must be from the users organization and
global ONLY!
"""
pass
class EntityNotesPermissionsAPIInheritedCases(
NotesPermissionsAPITestCases,
):
viewset = None
class EntityNotesPermissionsAPITest(
NotesPermissionsAPITestCases,
TestCase,
):
viewset = ViewSet
class NotesSerializerTestCases(
ViewSetBase,
ModelNotesSerializer,
):
viewset = None
class EntityNotesSerializerInheritedCases(
NotesSerializerTestCases,
):
viewset = None
class EntityNotesSerializerTest(
NotesSerializerTestCases,
TestCase,
):
viewset = ViewSet
class NotesMetadataTestCases(
ViewSetBase,
ModelNotesMetadata,
):
viewset = None
class EntityNotesMetadataInheritedCases(
NotesMetadataTestCases,
):
viewset = None
class EntityNotesMetadataTest(
NotesMetadataTestCases,
TestCase,
):
viewset = ViewSet

View File

@ -1,32 +0,0 @@
from django.test import TestCase
from access.models.organization_history import Tenant as Organization, OrganizationHistory
from core.tests.abstract.test_functional_history import HistoryEntriesCommon
class History(
HistoryEntriesCommon,
TestCase,
):
model = Organization
history_model = OrganizationHistory
@classmethod
def setUpTestData(self):
super().setUpTestData()
self.obj = self.model.objects.create(
name = self.field_value_original,
)
self.obj_delete = self.model.objects.create(
name = self.field_value_delete,
)
self.call_the_banners()

View File

@ -1,20 +1,14 @@
import django
import pytest
import unittest
import requests
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser, Permission
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import reverse
from django.test import Client, TestCase
from django.test import TestCase
from access.models.tenant import Tenant as Organization
from access.models.team import Team
from access.models.team_user import TeamUsers
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
@ -28,7 +22,7 @@ class ViewSetBase:
app_namespace = 'v2'
url_name = '_api_v2_organization'
url_name = '_api_tenant'
change_data = {'name': 'device'}
@ -197,108 +191,6 @@ class ViewSetBase:
class OrganizationPermissionsAPI(
ViewSetBase,
APIPermissions,
TestCase
):
def test_returned_data_from_user_and_global_organizations_only(self):
"""Check items returned
This test case is a over-ride of a test case with the same name.
This model is not a tenancy model making this test not-applicable.
Items returned from the query Must be from the users organization and
global ONLY!
"""
pass
def test_add_has_permission(self):
""" Check correct permission for add
Attempt to add as user with permission
"""
client = Client()
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' )
client.force_login( self.add_user )
response = client.post( url, data = self.add_data )
assert response.status_code == 201
def test_returned_results_only_user_orgs(self):
"""Returned results check
This test case is an override of a test of the same name.
organizations are not tenancy objects and therefor are supposed to
return all items when a user queries them.
Ensure that a query to the viewset endpoint does not return
items that are not part of the users organizations.
"""
# Ensure the other org item exists, without test not able to function
print('Check that the different organization item has been defined')
assert hasattr(self, 'other_org_item')
# ensure that the variables for the two orgs are different orgs
print('checking that the different and user oganizations are different')
assert self.different_organization.id != self.organization.id
client = Client()
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')
client.force_login(self.view_user)
response = client.get(url)
contains_different_org: bool = False
# for item in response.data['results']:
# if int(item['id']) != self.organization.id:
# contains_different_org = True
assert len(response.data['results']) == 2
def test_add_different_organization_denied(self):
""" Check correct permission for add
This test is a duplicate of a test case with the same name.
Organizations are not tenancy models so this test does nothing of value
attempt to add as user from different organization
"""
pass
class OrganizationViewSet(
ViewSetBase,
SerializersTestCases,

View File

@ -1,116 +0,0 @@
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from access.viewsets.organization_notes import ViewSet
from core.tests.abstract.test_functional_notes_viewset import (
ModelNotesViewSetBase,
ModelNotesMetadata,
ModelNotesPermissionsAPI,
ModelNotesSerializer
)
class ViewSetBase(
ModelNotesViewSetBase
):
viewset = ViewSet
url_name = '_api_v2_organization_note'
@classmethod
def setUpTestData(self):
super().setUpTestData()
self.item = self.viewset.model.objects.create(
organization = self.organization,
content = 'a random comment',
content_type = ContentType.objects.get(
app_label = str(self.model._meta.app_label).lower(),
model = str(self.model.model.field.related_model.__name__).replace(' ', '').lower(),
),
model = self.organization,
created_by = self.view_user,
modified_by = self.view_user,
)
self.other_org_item = self.viewset.model.objects.create(
organization = self.different_organization,
content = 'a random comment',
content_type = ContentType.objects.get(
app_label = str(self.model._meta.app_label).lower(),
model = str(self.model.model.field.related_model.__name__).replace(' ', '').lower(),
),
model = self.different_organization,
created_by = self.view_user,
modified_by = self.view_user,
)
self.global_org_item = self.viewset.model.objects.create(
organization = self.global_organization,
content = 'a random comment global_organization',
content_type = ContentType.objects.get(
app_label = str(self.model._meta.app_label).lower(),
model = str(self.model.model.field.related_model.__name__).replace(' ', '').lower(),
),
model = self.global_organization,
created_by = self.view_user,
modified_by = self.view_user,
)
self.url_kwargs = {
'model_id': self.item.model.pk,
}
self.url_view_kwargs = {
'model_id': self.item.model.pk,
'pk': self.item.id
}
class OrganizationModelNotesPermissionsAPI(
ViewSetBase,
ModelNotesPermissionsAPI,
TestCase,
):
def test_returned_data_from_user_and_global_organizations_only(self):
"""Check items returned
This test case is a over-ride of a test case with the same name.
This model is not a global model making this test not-applicable.
Items returned from the query Must be from the users organization and
global ONLY!
"""
pass
class OrganizationModelNotesSerializer(
ViewSetBase,
ModelNotesSerializer,
TestCase,
):
pass
class OrganizationModelNotesMetadata(
ViewSetBase,
ModelNotesMetadata,
TestCase,
):
pass

Some files were not shown because too many files have changed in this diff Show More