Skip to content
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
d238b5b
wrap admin panel in iframe
WillNilges Jan 4, 2025
3a867d2
slightly better
WillNilges Jan 4, 2025
8577796
Extract object info and query it with the meshdb API
WillNilges Jan 4, 2025
dc55709
Move script to its own file
WillNilges Jan 4, 2025
7db0687
Now if only I could get my admin map to behave
WillNilges Jan 4, 2025
3fb5d51
Aha, I have to listen for messages
WillNilges Jan 4, 2025
4eb5e15
Victory
WillNilges Jan 4, 2025
d545a8b
Allow map to change location of admin panel
WillNilges Jan 4, 2025
1099bf4
Refactor style sheets
WillNilges Jan 4, 2025
c0c8983
Restore map.js
WillNilges Jan 4, 2025
f20e2a6
make it not crash
WillNilges Jan 5, 2025
98baeba
Update environment variables
WillNilges Jan 5, 2025
d016323
Checkpoint: Subway refactor. This works!?
WillNilges Jan 10, 2025
35a1c3e
another checkpoint
WillNilges Jan 10, 2025
e64d4c7
another checkpoint: going to refactor iframe_panel to admin_panel_iframe
WillNilges Jan 10, 2025
b007f38
Capture back button requests
WillNilges Jan 10, 2025
3be7d48
Delete dead code
WillNilges Jan 10, 2025
357fa37
getting the map to be resizable through css
WillNilges Jan 11, 2025
35d1a44
computers are fucking dumb;
WillNilges Jan 11, 2025
b6cd4b4
some cleanup
WillNilges Jan 11, 2025
9fd0a2c
debugging weird flow control stuff
WillNilges Jan 11, 2025
93bf978
OK I think we have feature pairity
WillNilges Jan 11, 2025
eedd693
Pick up where we left off (protect against refreshes)
WillNilges Jan 11, 2025
8b21202
Pass URL through to the Admin Panel iFrame
WillNilges Jan 12, 2025
3e21134
Ope my code sucks
WillNilges Jan 12, 2025
3c6cc25
I have no idea what is going on
WillNilges Jan 12, 2025
e79ad04
Fix admin panel using relative URLs
WillNilges Jan 12, 2025
2fde80d
refactoring checkpoint
WillNilges Jan 12, 2025
d2f516e
Refactoring checkpoint 2
WillNilges Jan 12, 2025
52db0e0
Strip 'panel' out of get_admin_url
WillNilges Jan 12, 2025
27b0919
Skip iframe in search tests
WillNilges Jan 12, 2025
75c25a3
same for list
WillNilges Jan 12, 2025
5409788
same for change
WillNilges Jan 12, 2025
4358d7c
Lint
WillNilges Jan 12, 2025
149637e
Delete a bunch of stuff
WillNilges Jan 12, 2025
3564bf2
checkpoint: delete more things
WillNilges Jan 12, 2025
6d37aa9
fix layout issues
WillNilges Jan 12, 2025
69ace4c
Swap /admin and /admin/panel
WillNilges Jan 13, 2025
63dded2
Revert "same for change"
WillNilges Jan 13, 2025
f52d1cb
Revert "same for list"
WillNilges Jan 13, 2025
8d37570
Revert "Skip iframe in search tests"
WillNilges Jan 13, 2025
dee6453
Add simple test
WillNilges Jan 14, 2025
eb9e896
Add a slightly more complex test
WillNilges Jan 14, 2025
2a65892
Acutally, just add one test. See comment as to why
WillNilges Jan 14, 2025
da6abd4
whoops
WillNilges Jan 14, 2025
33c38bb
Add a way to get to /admin/panel and update map button logic
WillNilges Jan 14, 2025
c46f4dd
Swap /admin out from under users
WillNilges Jan 15, 2025
307222d
Fix URL if user goes to /admin/panel, I should probs make the URL a v…
WillNilges Jan 15, 2025
820893a
Refactor
WillNilges Jan 16, 2025
7ec13d0
andrew comments 1: Restore password reset, remove state override, fix…
WillNilges Jan 17, 2025
f42e5d7
andrew comments 2: Path
WillNilges Jan 17, 2025
2058a85
lint
WillNilges Jan 18, 2025
09cba15
Redirect top to login on logout
WillNilges Jan 18, 2025
57e5908
Move iframe escape logic to onAdminPanelLoad
WillNilges Jan 21, 2025
f3b67a6
Make clicking an los work
WillNilges Jan 21, 2025
764eec1
Fixes, disable map if on mobile
WillNilges Jan 21, 2025
78a2221
Remove override that was breaking mobile
WillNilges Jan 24, 2025
c4825dc
Update src/meshweb/static/admin/iframe_check.js
WillNilges Jan 27, 2025
c0dcf94
Update src/meshweb/static/admin/map.js
WillNilges Jan 27, 2025
6051f88
Fix variable and delete log lines
WillNilges Jan 27, 2025
d5eb255
Merge branch 'main' into wdn/map-iframe-2
WillNilges Feb 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/meshapi/admin/urls.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
from django.contrib import admin
from django.urls import path
from django.urls import path, re_path

from meshapi.admin.password_reset import (
AdminPasswordResetCompleteView,
AdminPasswordResetConfirmView,
AdminPasswordResetDoneView,
AdminPasswordResetView,
)
from meshdb.views import admin_iframe_view

urlpatterns = [
path("password_reset/", AdminPasswordResetView.as_view(), name="admin_password_reset"),
path("password_reset/done/", AdminPasswordResetDoneView.as_view(), name="password_reset_done"),
path("password_reset/<uidb64>/<token>/", AdminPasswordResetConfirmView.as_view(), name="password_reset_confirm"),
path("password_reset/done/", AdminPasswordResetCompleteView.as_view(), name="password_reset_complete"),
path("", admin.site.urls),
path("panel/", admin.site.urls),
re_path(r"^.*$", admin_iframe_view), # Match any other /admin/* URL
]
5 changes: 4 additions & 1 deletion src/meshapi/admin/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ def get_admin_url(model: Model, site_base_url: str) -> str:
reverse(
f"admin:{content_type.app_label}_{content_type.model}_change",
args=(model.pk,),
),
).replace(
"panel/", ""
), # Strip "panel" out of admin URL. "Panel" views are meant to be shown
# inside the admin panel iframe, and likely the user does not want that
)


Expand Down
76 changes: 38 additions & 38 deletions src/meshapi/tests/test_admin_change_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,25 +192,25 @@ def _submit_form(
return response

def test_change_building(self):
change_url = f"/admin/meshapi/building/{self.building_1.id}/change/"
change_url = f"/admin/panel/meshapi/building/{self.building_1.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="building_form"), 302)

def test_change_member(self):
change_url = f"/admin/meshapi/member/{self.member.id}/change/"
change_url = f"/admin/panel/meshapi/member/{self.member.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="member_form"), 302)

def test_change_member_no_email(self):
change_url = f"/admin/meshapi/member/{self.member2.id}/change/"
change_url = f"/admin/panel/meshapi/member/{self.member2.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="member_form"), 302)

self.member2.refresh_from_db()
self.assertIsNone(self.member2.primary_email_address)

def test_add_new_member(self):
change_url = "/admin/meshapi/member/add/"
change_url = "/admin/panel/meshapi/member/add/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="member_form")
fill_in_admin_form(
Expand Down Expand Up @@ -241,7 +241,7 @@ def test_add_new_member(self):
self.assertEqual(member.notes, "Test notes")

def test_add_new_member_name_only(self):
change_url = "/admin/meshapi/member/add/"
change_url = "/admin/panel/meshapi/member/add/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="member_form")
fill_in_admin_form(
Expand All @@ -265,57 +265,57 @@ def test_add_new_member_name_only(self):
self.assertEqual(member.notes, "")

def test_change_install(self):
change_url = f"/admin/meshapi/install/{self.install.id}/change/"
change_url = f"/admin/panel/meshapi/install/{self.install.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="install_form"), 302)

def test_change_link(self):
change_url = f"/admin/meshapi/link/{self.link.id}/change/"
change_url = f"/admin/panel/meshapi/link/{self.link.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="link_form"), 302)

def test_change_los(self):
change_url = f"/admin/meshapi/los/{self.los.id}/change/"
change_url = f"/admin/panel/meshapi/los/{self.los.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="los_form"), 302)

def test_change_device(self):
change_url = f"/admin/meshapi/device/{self.device1.id}/change/"
change_url = f"/admin/panel/meshapi/device/{self.device1.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="device_form"), 302)

def test_change_sector_accessed_via_device_redirect(self):
change_url = f"/admin/meshapi/device/{self.sector.id}/change/"
change_url = f"/admin/panel/meshapi/device/{self.sector.id}/change/"
response = self._call(change_url, 302)
self.assertEqual(response.url, f"http://testserver/admin/meshapi/sector/{self.sector.id}/change/")

def test_change_ap_accessed_via_device_redirect(self):
change_url = f"/admin/meshapi/device/{self.access_point.id}/change/"
change_url = f"/admin/panel/meshapi/device/{self.access_point.id}/change/"
response = self._call(change_url, 302)
self.assertEqual(response.url, f"http://testserver/admin/meshapi/accesspoint/{self.access_point.id}/change/")

def test_change_device_bad_id(self):
change_url = "/admin/meshapi/device/00000000-0000-0000-0000-000000000000/change/"
change_url = "/admin/panel/meshapi/device/00000000-0000-0000-0000-000000000000/change/"
response = self._call(change_url, 302)
self.assertEqual(response.url, "/admin/")
self.assertEqual(response.url, "/admin/panel/")

def test_change_sector(self):
change_url = f"/admin/meshapi/sector/{self.sector.id}/change/"
change_url = f"/admin/panel/meshapi/sector/{self.sector.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="sector_form"), 302)

def test_change_accesspoint(self):
change_url = f"/admin/meshapi/accesspoint/{self.access_point.id}/change/"
change_url = f"/admin/panel/meshapi/accesspoint/{self.access_point.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="accesspoint_form"), 302)

def test_change_node(self):
change_url = f"/admin/meshapi/node/{self.node1.id}/change/"
change_url = f"/admin/panel/meshapi/node/{self.node1.id}/change/"
response = self._call(change_url, 200)
self._submit_form(change_url, bs4.BeautifulSoup(response.content.decode()).find(id="node_form"), 302)

def test_change_node_remove_building(self):
change_url = f"/admin/meshapi/node/{self.node1.id}/change/"
change_url = f"/admin/panel/meshapi/node/{self.node1.id}/change/"
response = self._call(change_url, 200)
soup = bs4.BeautifulSoup(response.content.decode()).find(id="node_form")
fill_in_admin_form(
Expand All @@ -329,7 +329,7 @@ def test_change_node_remove_building(self):
self._submit_form(change_url, soup, 200, expect_failure=True)

def test_add_new_node(self):
change_url = "/admin/meshapi/node/add/"
change_url = "/admin/panel/meshapi/node/add/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="node_form")
fill_in_admin_form(
Expand Down Expand Up @@ -372,7 +372,7 @@ def test_add_new_node(self):
self.assertEqual(node.notes, "Test notes")

def test_add_new_node_no_building(self):
change_url = "/admin/meshapi/node/add/"
change_url = "/admin/panel/meshapi/node/add/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="node_form")
fill_in_admin_form(
Expand All @@ -395,7 +395,7 @@ def test_add_new_node_no_building(self):
self._submit_form(change_url, form_soup, 200, expect_failure=True)

def test_add_new_node_no_nn(self):
change_url = "/admin/meshapi/node/add/"
change_url = "/admin/panel/meshapi/node/add/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="node_form")
fill_in_admin_form(
Expand Down Expand Up @@ -437,7 +437,7 @@ def test_add_new_node_no_nn(self):
self.assertEqual(node.notes, "Test notes")

def test_add_new_planned_node_no_nn(self):
change_url = "/admin/meshapi/node/add/"
change_url = "/admin/panel/meshapi/node/add/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="node_form")
fill_in_admin_form(
Expand Down Expand Up @@ -480,7 +480,7 @@ def test_add_new_planned_node_no_nn(self):

def test_add_building(self):
enable_flag("EDIT_PANORAMAS")
change_url = "/admin/meshapi/building/add/"
change_url = "/admin/panel/meshapi/building/add/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="building_form")

Expand Down Expand Up @@ -521,7 +521,7 @@ def test_add_building(self):

def test_add_building_no_pano(self):
disable_flag("EDIT_PANORAMAS")
change_url = "/admin/meshapi/building/add/"
change_url = "/admin/panel/meshapi/building/add/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="building_form")

Expand Down Expand Up @@ -561,7 +561,7 @@ def test_add_building_no_pano(self):

def test_change_building_but_not_address(self):
enable_flag("EDIT_PANORAMAS")
change_url = f"/admin/meshapi/building/{self.building_1.id}/change/"
change_url = f"/admin/panel/meshapi/building/{self.building_1.id}/change/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="building_form")
fill_in_admin_form(
Expand Down Expand Up @@ -601,7 +601,7 @@ def test_change_building_but_not_address(self):

def test_change_building_address(self):
enable_flag("EDIT_PANORAMAS")
change_url = f"/admin/meshapi/building/{self.building_1.id}/change/"
change_url = f"/admin/panel/meshapi/building/{self.building_1.id}/change/"
response = self._call(change_url, 200)
form_soup = bs4.BeautifulSoup(response.content.decode()).find(id="building_form")
fill_in_admin_form(
Expand Down Expand Up @@ -656,16 +656,16 @@ def _call(self, route, code):
return response

def test_add_views_http_200(self):
self._call("/admin/auth/group/add/", 200)
self._call("/admin/auth/user/add/", 200)
self._call("/admin/authtoken/tokenproxy/add/", 200)
self._call("/admin/meshapi_hooks/celeryserializerhook/add/", 200)
self._call("/admin/meshapi/building/add/", 200)
self._call("/admin/meshapi/member/add/", 200)
self._call("/admin/meshapi/install/add/", 200)
self._call("/admin/meshapi/link/add/", 200)
self._call("/admin/meshapi/los/add/", 200)
self._call("/admin/meshapi/sector/add/", 200)
self._call("/admin/meshapi/device/add/", 200)
self._call("/admin/meshapi/accesspoint/add/", 200)
self._call("/admin/meshapi/node/add/", 200)
self._call("/admin/panel/auth/group/add/", 200)
self._call("/admin/panel/auth/user/add/", 200)
self._call("/admin/panel/authtoken/tokenproxy/add/", 200)
self._call("/admin/panel/meshapi_hooks/celeryserializerhook/add/", 200)
self._call("/admin/panel/meshapi/building/add/", 200)
self._call("/admin/panel/meshapi/member/add/", 200)
self._call("/admin/panel/meshapi/install/add/", 200)
self._call("/admin/panel/meshapi/link/add/", 200)
self._call("/admin/panel/meshapi/los/add/", 200)
self._call("/admin/panel/meshapi/sector/add/", 200)
self._call("/admin/panel/meshapi/device/add/", 200)
self._call("/admin/panel/meshapi/accesspoint/add/", 200)
self._call("/admin/panel/meshapi/node/add/", 200)
26 changes: 13 additions & 13 deletions src/meshapi/tests/test_admin_list_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,53 +96,53 @@ def _call(self, route, code):
return response

def test_list_group(self):
response = self._call("/admin/auth/group/", 200)
response = self._call("/admin/panel/auth/group/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_user(self):
response = self._call("/admin/auth/user/", 200)
response = self._call("/admin/panel/auth/user/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_authtoken(self):
response = self._call("/admin/authtoken/tokenproxy/", 200)
response = self._call("/admin/panel/authtoken/tokenproxy/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_hook(self):
response = self._call("/admin/meshapi_hooks/celeryserializerhook/", 200)
response = self._call("/admin/panel/meshapi_hooks/celeryserializerhook/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_building(self):
response = self._call("/admin/meshapi/building/", 200)
response = self._call("/admin/panel/meshapi/building/", 200)
self.assertEqual(2, get_admin_results_count(response.content.decode()))

def test_list_member(self):
response = self._call("/admin/meshapi/member/", 200)
response = self._call("/admin/panel/meshapi/member/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_install(self):
response = self._call("/admin/meshapi/install/", 200)
response = self._call("/admin/panel/meshapi/install/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_link(self):
response = self._call("/admin/meshapi/link/", 200)
response = self._call("/admin/panel/meshapi/link/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_los(self):
response = self._call("/admin/meshapi/los/", 200)
response = self._call("/admin/panel/meshapi/los/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_sector(self):
response = self._call("/admin/meshapi/sector/", 200)
response = self._call("/admin/panel/meshapi/sector/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_accesspoint(self):
response = self._call("/admin/meshapi/accesspoint/", 200)
response = self._call("/admin/panel/meshapi/accesspoint/", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_list_device(self):
response = self._call("/admin/meshapi/device/", 200)
response = self._call("/admin/panel/meshapi/device/", 200)
self.assertEqual(2, get_admin_results_count(response.content.decode()))

def test_list_node(self):
response = self._call("/admin/meshapi/node/", 200)
response = self._call("/admin/panel/meshapi/node/", 200)
self.assertEqual(2, get_admin_results_count(response.content.decode()))
28 changes: 14 additions & 14 deletions src/meshapi/tests/test_admin_search_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,43 +103,43 @@ def _call(self, route, code):
return response

def test_search_building(self):
response = self._call("/admin/meshapi/building/?q=8888", 200)
response = self._call("/admin/panel/meshapi/building/?q=8888", 200)
self.assertEqual(2, get_admin_results_count(response.content.decode()))

def test_search_member(self):
response = self._call("/admin/meshapi/member/?q=1", 200)
response = self._call("/admin/panel/meshapi/member/?q=1", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_install(self):
response = self._call(f"/admin/meshapi/install/?q={self.install.install_number}", 200)
response = self._call(f"/admin/panel/meshapi/install/?q={self.install.install_number}", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_link(self):
response = self._call("/admin/meshapi/link/?q=101", 200)
response = self._call("/admin/panel/meshapi/link/?q=101", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_los(self):
response = self._call("/admin/meshapi/los/?q=101", 200)
response = self._call("/admin/panel/meshapi/los/?q=101", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_sector(self):
response = self._call("/admin/meshapi/sector/?q=1", 200)
response = self._call("/admin/panel/meshapi/sector/?q=1", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_access_point(self):
response = self._call("/admin/meshapi/accesspoint/?q=1", 200)
response = self._call("/admin/panel/meshapi/accesspoint/?q=1", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_device(self):
response = self._call("/admin/meshapi/device/?q=1", 200)
response = self._call("/admin/panel/meshapi/device/?q=1", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_node(self):
response = self._call("/admin/meshapi/node/?q=101", 200)
response = self._call("/admin/panel/meshapi/node/?q=101", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_install_by_nn(self):
response = self._call("/admin/meshapi/install/?q=101", 200)
response = self._call("/admin/panel/meshapi/install/?q=101", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_install_by_nn_exact(self):
Expand All @@ -152,17 +152,17 @@ def test_search_install_by_nn_exact(self):
install2.notes = "NN101"
install2.save()

response = self._call("/admin/meshapi/install/?q=NN101", 200)
response = self._call("/admin/panel/meshapi/install/?q=NN101", 200)
self.assertEqual(2, get_admin_results_count(response.content.decode()))

def test_search_install_just_nn(self):
response = self._call("/admin/meshapi/install/?q=nN", 200)
response = self._call("/admin/panel/meshapi/install/?q=nN", 200)
self.assertEqual(0, get_admin_results_count(response.content.decode()))

def test_search_install_empty(self):
response = self._call("/admin/meshapi/install/?q=", 200)
response = self._call("/admin/panel/meshapi/install/?q=", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))

def test_search_install_referral(self):
response = self._call("/admin/meshapi/install/?q=reddit", 200)
response = self._call("/admin/panel/meshapi/install/?q=reddit", 200)
self.assertEqual(1, get_admin_results_count(response.content.decode()))
Loading