base.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. <!--
  2. Copyright (C) 2019-2023 Nicola Murino
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as published
  5. by the Free Software Foundation, version 3.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU Affero General Public License for more details.
  10. You should have received a copy of the GNU Affero General Public License
  11. along with this program. If not, see <https://www.gnu.org/licenses/>.
  12. -->
  13. {{define "base"}}
  14. <!DOCTYPE html>
  15. <html lang="en">
  16. <head>
  17. <meta charset="utf-8">
  18. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  19. <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  20. <meta name="description" content="">
  21. <meta name="author" content="">
  22. <title>{{.Branding.Name}} - {{template "title" .}}</title>
  23. <link rel="shortcut icon" href="{{.StaticURL}}{{.Branding.FaviconPath}}" />
  24. <!-- Custom fonts for this template-->
  25. <link href="{{.StaticURL}}/vendor/fontawesome-free/css/fontawesome.min.css" rel="stylesheet" type="text/css">
  26. <link href="{{.StaticURL}}/vendor/fontawesome-free/css/solid.min.css" rel="stylesheet" type="text/css">
  27. <link href="{{.StaticURL}}/vendor/fontawesome-free/css/regular.min.css" rel="stylesheet" type="text/css">
  28. <!-- Custom styles for this template-->
  29. {{- range .Branding.DefaultCSS}}
  30. <link href="{{$.StaticURL}}{{.}}" rel="stylesheet" type="text/css">
  31. {{- end}}
  32. <style>
  33. {{template "commoncss" .}}
  34. </style>
  35. {{block "extra_css" .}}{{end}}
  36. {{range .Branding.ExtraCSS}}
  37. <link href="{{$.StaticURL}}{{.}}" rel="stylesheet" type="text/css">
  38. {{end}}
  39. </head>
  40. <body id="page-top">
  41. <!-- Page Wrapper -->
  42. <div id="wrapper">
  43. {{if .LoggedAdmin.Username}}
  44. <!-- Sidebar -->
  45. <ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
  46. <!-- Sidebar - Brand -->
  47. <div class="sidebar-brand d-flex align-items-center justify-content-center">
  48. <div class="sidebar-brand-icon">
  49. <img src="{{.StaticURL}}{{.Branding.LogoPath}}" alt="logo" style="width: 2rem; height: auto;">
  50. </div>
  51. <div class="sidebar-brand-text mx-3" style="text-transform: none;">{{.Branding.ShortName}}</div>
  52. </div>
  53. <!-- Divider -->
  54. <hr class="sidebar-divider my-0">
  55. {{ if .LoggedAdmin.HasPermission "view_users"}}
  56. <li class="nav-item {{if eq .CurrentURL .UsersURL}}active{{end}}">
  57. <a class="nav-link" href="{{.UsersURL}}">
  58. <i class="fas fa-users"></i>
  59. <span>{{.UsersTitle}}</span></a>
  60. </li>
  61. {{ end }}
  62. {{ if .LoggedAdmin.HasPermission "manage_groups"}}
  63. <li class="nav-item {{if eq .CurrentURL .GroupsURL}}active{{end}}">
  64. <a class="nav-link" href="{{.GroupsURL}}">
  65. <i class="fas fa-user-friends"></i>
  66. <span>{{.GroupsTitle}}</span></a>
  67. </li>
  68. {{end}}
  69. {{ if .LoggedAdmin.HasPermission "manage_folders"}}
  70. <li class="nav-item {{if eq .CurrentURL .FoldersURL}}active{{end}}">
  71. <a class="nav-link" href="{{.FoldersURL}}">
  72. <i class="fas fa-folder"></i>
  73. <span>{{.FoldersTitle}}</span></a>
  74. </li>
  75. {{end}}
  76. {{ if .LoggedAdmin.HasPermission "view_conns"}}
  77. <li class="nav-item {{if eq .CurrentURL .ConnectionsURL}}active{{end}}">
  78. <a class="nav-link" href="{{.ConnectionsURL}}">
  79. <i class="fas fa-exchange-alt"></i>
  80. <span>{{.ConnectionsTitle}}</span></a>
  81. </li>
  82. {{end}}
  83. {{ if .LoggedAdmin.HasPermission "manage_event_rules"}}
  84. <li class="nav-item {{if .IsEventManagerPage}}active{{end}}">
  85. <a class="nav-link {{if not .IsEventManagerPage}}collapsed{{end}}" href="#" data-toggle="collapse" data-target="#collapseEventManager"
  86. aria-expanded="true" aria-controls="collapseEventManager">
  87. <i class="fas fa-calendar-alt"></i>
  88. <span>Event Manager</span>
  89. </a>
  90. <div id="collapseEventManager" class="collapse {{if .IsEventManagerPage}}show{{end}}" aria-labelledby="headingEventManager" data-parent="#accordionSidebar">
  91. <div class="bg-white py-2 collapse-inner rounded">
  92. <a class="collapse-item {{if eq .CurrentURL .EventRulesURL}}active{{end}}" href="{{.EventRulesURL}}">{{.EventRulesTitle}}</a>
  93. <a class="collapse-item {{if eq .CurrentURL .EventActionsURL}}active{{end}}" href="{{.EventActionsURL}}">{{.EventActionsTitle}}</a>
  94. </div>
  95. </div>
  96. </li>
  97. {{end}}
  98. {{ if or (.LoggedAdmin.HasPermission "manage_ip_lists") (and .HasDefender (.LoggedAdmin.HasPermission "view_defender"))}}
  99. <li class="nav-item {{if .IsIPManagerPage}}active{{end}}">
  100. <a class="nav-link {{if not .IsIPManagerPage}}collapsed{{end}}" href="#" data-toggle="collapse" data-target="#collapseIPManager"
  101. aria-expanded="true" aria-controls="collapseIPManager">
  102. <i class="fas fa-shield-alt"></i>
  103. <span>IP Manager</span>
  104. </a>
  105. <div id="collapseIPManager" class="collapse {{if .IsIPManagerPage}}show{{end}}" aria-labelledby="headingIPManager" data-parent="#accordionSidebar">
  106. <div class="bg-white py-2 collapse-inner rounded">
  107. {{ if .LoggedAdmin.HasPermission "manage_ip_lists"}}
  108. <a class="collapse-item {{if eq .CurrentURL .IPListsURL}}active{{end}}" href="{{.IPListsURL}}">{{.IPListsTitle}}</a>
  109. {{end}}
  110. {{ if and .HasDefender (.LoggedAdmin.HasPermission "view_defender")}}
  111. <a class="collapse-item {{if eq .CurrentURL .DefenderURL}}active{{end}}" href="{{.DefenderURL}}">{{.DefenderTitle}}</a>
  112. {{end}}
  113. </div>
  114. </div>
  115. </li>
  116. {{end}}
  117. {{ if .LoggedAdmin.HasPermission "manage_admins"}}
  118. <li class="nav-item {{if eq .CurrentURL .AdminsURL}}active{{end}}">
  119. <a class="nav-link" href="{{.AdminsURL}}">
  120. <i class="fas fa-user-cog"></i>
  121. <span>{{.AdminsTitle}}</span></a>
  122. </li>
  123. {{end}}
  124. {{ if .LoggedAdmin.HasPermission "manage_roles"}}
  125. <li class="nav-item {{if eq .CurrentURL .RolesURL}}active{{end}}">
  126. <a class="nav-link" href="{{.RolesURL}}">
  127. <i class="fas fa-user-lock"></i>
  128. <span>{{.RolesTitle}}</span></a>
  129. </li>
  130. {{end}}
  131. {{ if or (.LoggedAdmin.HasPermission "manage_system") (.LoggedAdmin.HasPermission "view_status") (and .HasSearcher (.LoggedAdmin.HasPermission "view_events"))}}
  132. <li class="nav-item {{if .IsServerManagerPage}}active{{end}}">
  133. <a class="nav-link {{if not .IsServerManagerPage}}collapsed{{end}}" href="#" data-toggle="collapse" data-target="#collapseServerManager"
  134. aria-expanded="true" aria-controls="collapseServerManager">
  135. <i class="fas fa-tools"></i>
  136. <span>Server Manager</span>
  137. </a>
  138. <div id="collapseServerManager" class="collapse {{if .IsServerManagerPage}}show{{end}}" aria-labelledby="headingServerManager" data-parent="#accordionSidebar">
  139. <div class="bg-white py-2 collapse-inner rounded">
  140. {{ if .LoggedAdmin.HasPermission "manage_system"}}
  141. <a class="collapse-item {{if eq .CurrentURL .ConfigsURL}}active{{end}}" href="{{.ConfigsURL}}">{{.ConfigsTitle}}</a>
  142. {{end}}
  143. {{ if and .HasSearcher (.LoggedAdmin.HasPermission "view_events")}}
  144. <a class="collapse-item {{if eq .CurrentURL .EventsURL}}active{{end}}" href="{{.EventsURL}}">{{.EventsTitle}}</a>
  145. {{end}}
  146. {{ if .LoggedAdmin.HasPermission "manage_system"}}
  147. <a class="collapse-item {{if eq .CurrentURL .MaintenanceURL}}active{{end}}" href="{{.MaintenanceURL}}">{{.MaintenanceTitle}}</a>
  148. {{end}}
  149. {{ if .LoggedAdmin.HasPermission "view_status"}}
  150. <a class="collapse-item {{if eq .CurrentURL .StatusURL}}active{{end}}" href="{{.StatusURL}}">{{.StatusTitle}}</a>
  151. {{end}}
  152. </div>
  153. </div>
  154. </li>
  155. {{end}}
  156. <!-- Divider -->
  157. <hr class="sidebar-divider d-none d-md-block">
  158. <!-- Sidebar Toggler (Sidebar) -->
  159. <div class="text-center d-none d-md-inline">
  160. <button class="rounded-circle border-0" id="sidebarToggle"></button>
  161. </div>
  162. </ul>
  163. <!-- End of Sidebar -->
  164. {{end}}
  165. <!-- Content Wrapper -->
  166. <div id="content-wrapper" class="d-flex flex-column">
  167. <!-- Main Content -->
  168. <div id="content">
  169. {{if .LoggedAdmin.Username}}
  170. <!-- Topbar -->
  171. <nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
  172. <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
  173. <i class="fa fa-bars"></i>
  174. </button>
  175. <!-- Topbar Navbar -->
  176. <ul class="navbar-nav ml-auto">
  177. {{block "additionalnavitems" .}}{{end}}
  178. <!-- Nav Item - User Information -->
  179. <li class="nav-item dropdown no-arrow">
  180. <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-toggle="dropdown"
  181. aria-haspopup="true" aria-expanded="false">
  182. <span class="mr-2 d-none d-lg-inline text-gray-600 small">{{.LoggedAdmin.Username}}</span>
  183. <i class="fas fa-user fa-fw"></i>
  184. </a>
  185. <!-- Dropdown - User Information -->
  186. <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in" aria-labelledby="userDropdown">
  187. {{if not .HasExternalLogin}}
  188. <a class="dropdown-item" href="{{.ProfileURL}}">
  189. <i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
  190. Profile
  191. </a>
  192. <a class="dropdown-item" href="{{.ChangePwdURL}}">
  193. <i class="fas fa-key fa-sm fa-fw mr-2 text-gray-400"></i>
  194. Change password
  195. </a>
  196. {{if .LoggedAdmin.CanManageMFA}}
  197. <a class="dropdown-item" href="{{.MFAURL}}">
  198. <i class="fas fa-user-lock fa-sm fa-fw mr-2 text-gray-400"></i>
  199. Two-Factor Auth
  200. </a>
  201. {{end}}
  202. <div class="dropdown-divider"></div>
  203. {{end}}
  204. <a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
  205. <i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
  206. Logout
  207. </a>
  208. </div>
  209. </li>
  210. </ul>
  211. </nav>
  212. <!-- End of Topbar -->
  213. {{end}}
  214. <!-- Begin Page Content -->
  215. <div class="container-fluid">
  216. {{template "page_body" .}}
  217. </div>
  218. <!-- /.container-fluid -->
  219. </div>
  220. <!-- End of Main Content -->
  221. {{if .LoggedAdmin.Username}}
  222. <!-- Footer -->
  223. <footer class="sticky-footer bg-white">
  224. <div class="container my-auto">
  225. <div class="copyright text-center my-auto">
  226. <span>SFTPGo {{.Version}}</span>
  227. </div>
  228. </div>
  229. </footer>
  230. <!-- End of Footer -->
  231. {{end}}
  232. </div>
  233. <!-- End of Content Wrapper -->
  234. </div>
  235. <!-- End of Page Wrapper -->
  236. <!-- Scroll to Top Button-->
  237. <a class="scroll-to-top rounded" href="#page-top">
  238. <i class="fas fa-angle-up"></i>
  239. </a>
  240. {{if .LoggedAdmin.Username}}
  241. <!-- Logout Modal-->
  242. <div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel"
  243. aria-hidden="true">
  244. <div class="modal-dialog" role="document">
  245. <div class="modal-content">
  246. <div class="modal-header">
  247. <h5 class="modal-title" id="modalLabel">Ready to Leave?</h5>
  248. <button class="close" type="button" data-dismiss="modal" aria-label="Close">
  249. <span aria-hidden="true">&times;</span>
  250. </button>
  251. </div>
  252. <div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
  253. <div class="modal-footer">
  254. <button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
  255. <a class="btn btn-primary" href="{{.LogoutURL}}">Logout</a>
  256. </div>
  257. </div>
  258. </div>
  259. </div>
  260. {{end}}
  261. {{block "dialog" .}}{{end}}
  262. <!-- Bootstrap core JavaScript-->
  263. <script src="{{.StaticURL}}/vendor/jquery/jquery.min.js"></script>
  264. <script src="{{.StaticURL}}/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
  265. <!-- Core plugin JavaScript-->
  266. <script src="{{.StaticURL}}/vendor/jquery-easing/jquery.easing.min.js"></script>
  267. <!-- Custom scripts for all pages-->
  268. <script src="{{.StaticURL}}/js/sb-admin-2.min.js"></script>
  269. <script type="text/javascript">
  270. function escapeHTML(str) {
  271. var div = document.createElement('div');
  272. div.appendChild(document.createTextNode(str));
  273. return div.innerHTML;
  274. }
  275. function unescapeHTML(escapedStr) {
  276. var div = document.createElement('div');
  277. div.innerHTML = escapedStr;
  278. var child = div.childNodes[0];
  279. return child ? child.nodeValue : '';
  280. }
  281. function fixedEncodeURIComponent(str) {
  282. return encodeURIComponent(unescapeHTML(str)).replace(/[!'()*]/g, function (c) {
  283. return '%' + c.charCodeAt(0).toString(16);
  284. });
  285. }
  286. </script>
  287. <!-- Page level plugins -->
  288. {{block "extra_js" .}}{{end}}
  289. </body>
  290. </html>
  291. {{end}}