admin.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <!--
  2. Copyright (C) 2024 Nicola Murino
  3. This WebUI uses the KeenThemes Mega Bundle, a proprietary theme:
  4. https://keenthemes.com/products/templates-mega-bundle
  5. KeenThemes HTML/CSS/JS components are allowed for use only within the
  6. SFTPGo product and restricted to be used in a resealable HTML template
  7. that can compete with KeenThemes products anyhow.
  8. This WebUI is allowed for use only within the SFTPGo product and
  9. therefore cannot be used in derivative works/products without an
  10. explicit grant from the SFTPGo Team ([email protected]).
  11. -->
  12. {{template "base" .}}
  13. {{- define "page_body"}}
  14. <div class="card shadow-sm">
  15. <div class="card-header bg-light">
  16. <h3 data-i18n="{{.Title}}" class="card-title section-title"></h3>
  17. </div>
  18. <div class="card-body">
  19. {{- template "errmsg" .Error}}
  20. <form id="admin_form" action="{{.CurrentURL}}" method="POST" autocomplete="off">
  21. <div class="form-group row">
  22. <label for="idUsername" data-i18n="login.username" class="col-md-3 col-form-label">Username</label>
  23. <div class="col-md-9">
  24. <input id="idUsername" type="text" placeholder="" name="username" value="{{.Admin.Username}}" maxlength="255" autocomplete="off"
  25. spellcheck="false" required {{if .IsAdd}}class="form-control"{{else}}class="form-control-plaintext readonly-input" readonly{{end}} />
  26. </div>
  27. </div>
  28. <div class="form-group row mt-10">
  29. <label for="idPassword" data-i18n="login.password" class="col-md-3 col-form-label">Password</label>
  30. <div class="col-md-9">
  31. <input id="idPassword" type="password" class="form-control" name="password" autocomplete="new-password"
  32. spellcheck="false" value="" {{if not .IsAdd}}aria-describedby="idPasswordHelp"{{end}} />
  33. {{- if not .IsAdd}}
  34. <div id="idPasswordHelp" class="form-text" data-i18n="admin.password_help"></div>
  35. {{- end}}
  36. </div>
  37. </div>
  38. <div class="form-group row mt-10">
  39. <label for="idStatus" data-i18n="general.status" class="col-md-3 col-form-label">Status</label>
  40. <div class="col-md-9">
  41. <select id="idStatus" name="status" class="form-select" data-control="i18n-select2" data-hide-search="true">
  42. <option data-i18n="general.active" value="1" {{- if eq .Admin.Status 1 }} selected{{- end}}>Active</option>
  43. <option data-i18n="general.inactive" value="0" {{- if eq .Admin.Status 0 }} selected{{- end}}>Inactive</option>
  44. </select>
  45. </div>
  46. </div>
  47. <div class="form-group row mt-10">
  48. <label for="idPermissions" data-i18n="general.permissions" class="col-md-3 col-form-label">Permissions</label>
  49. <div class="col-md-9">
  50. <select id="idPermissions" name="permissions" class="form-select" data-control="i18n-select2" data-hide-search="true" data-close-on-select="false" multiple>
  51. {{- range $validPerm := .Admin.GetValidPerms}}
  52. <option value="{{$validPerm}}" {{- range $perm :=$.Admin.Permissions }}{{- if eq $perm $validPerm}} selected{{- end}}{{- end}}>{{$validPerm}}</option>
  53. {{- end}}
  54. </select>
  55. </div>
  56. </div>
  57. {{- if .Roles}}
  58. <div class="card mt-10">
  59. <div class="card-header bg-light">
  60. <h3 data-i18n="general.role" class="card-title section-title-inner">Role</h3>
  61. </div>
  62. <div class="card-body">
  63. {{template "infomsg" "admin.role_help"}}
  64. <div class="form-group row mt-10">
  65. <label for="idRole" data-i18n="general.role" class="col-md-3 col-form-label">Role</label>
  66. <div class="col-md-9">
  67. <select id="idRole" name="role" data-i18n="[data-placeholder]general.role_placeholder" class="form-select" data-control="i18n-select2" data-placeholder="Select a role" data-allow-clear="true">
  68. <option value=""></option>
  69. {{- range .Roles}}
  70. <option value="{{.Name}}" {{if eq $.Admin.Role .Name}}selected{{end}}>{{.Name}}</option>
  71. {{- end}}
  72. </select>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. {{- end}}
  78. {{- if .Groups}}
  79. <div class="card mt-10">
  80. <div class="card-header bg-light">
  81. <h3 data-i18n="admin.users_groups" class="card-title section-title-inner">Groups for users</h3>
  82. </div>
  83. <div class="card-body">
  84. <div id="groups">
  85. {{template "infomsg" "admin.users_groups_help"}}
  86. <div class="form-group">
  87. <div data-repeater-list="groups">
  88. {{range $idx, $val := .Admin.Groups}}
  89. <div data-repeater-item>
  90. <div data-repeater-item>
  91. <div class="form-group row">
  92. <div class="col-md-6 mt-3 mt-md-8">
  93. <select name="group" data-i18n="[data-placeholder]general.group_placeholder" class="form-select select-repetear" data-allow-clear="true">
  94. <option value=""></option>
  95. {{- range $.Groups}}
  96. <option value="{{.Name}}" {{- if eq $val.Name .Name}} selected{{- end}}>{{.Name}}</option>
  97. {{- end}}
  98. </select>
  99. </div>
  100. <div class="col-md-5 mt-3 mt-md-8">
  101. <select name="group_type" class="form-select select-repetear">
  102. <option value="0" data-i18n="admin.group_membership" {{if eq $val.Options.AddToUsersAs 0}}selected{{end}}>Add as membership</option>
  103. <option value="1" data-i18n="admin.group_primary" {{if eq $val.Options.AddToUsersAs 1}}selected{{end}}>Add as primary</option>
  104. <option value="2" data-i18n="admin.group_secondary" {{if eq $val.Options.AddToUsersAs 2}}selected{{end}}>Add as secondary</option>
  105. </select>
  106. </div>
  107. <div class="col-md-1 mt-3 mt-md-8">
  108. <a href="#" data-repeater-delete
  109. class="btn btn-light-danger ps-5 pe-4">
  110. <i class="ki-duotone ki-trash fs-2">
  111. <span class="path1"></span>
  112. <span class="path2"></span>
  113. <span class="path3"></span>
  114. <span class="path4"></span>
  115. <span class="path5"></span>
  116. </i>
  117. </a>
  118. </div>
  119. </div>
  120. </div>
  121. </div>
  122. {{- else}}
  123. <div data-repeater-item>
  124. <div class="form-group row">
  125. <div class="col-md-6 mt-3 mt-md-8">
  126. <select name="group" data-i18n="[data-placeholder]general.group_placeholder" class="form-select select-repetear" data-allow-clear="true">
  127. <option value=""></option>
  128. {{- range $.Groups}}
  129. <option value="{{.Name}}">{{.Name}}</option>
  130. {{- end}}
  131. </select>
  132. </div>
  133. <div class="col-md-5 mt-3 mt-md-8">
  134. <select name="group_type" class="form-select select-repetear select-first">
  135. <option value="0" data-i18n="admin.group_membership">Add as membership</option>
  136. <option value="1" data-i18n="admin.group_primary">Add as primary</option>
  137. <option value="2" data-i18n="admin.group_secondary">Add as secondary</option>
  138. </select>
  139. </div>
  140. <div class="col-md-1 mt-3 mt-md-8">
  141. <a href="#" data-repeater-delete
  142. class="btn btn-light-danger ps-5 pe-4">
  143. <i class="ki-duotone ki-trash fs-2">
  144. <span class="path1"></span>
  145. <span class="path2"></span>
  146. <span class="path3"></span>
  147. <span class="path4"></span>
  148. <span class="path5"></span>
  149. </i>
  150. </a>
  151. </div>
  152. </div>
  153. </div>
  154. {{- end}}
  155. </div>
  156. </div>
  157. <div class="form-group mt-5">
  158. <a href="#" data-repeater-create class="btn btn-light-primary">
  159. <i class="ki-duotone ki-plus fs-3"></i>
  160. <span data-i18n="general.add">Add</span>
  161. </a>
  162. </div>
  163. </div>
  164. </div>
  165. </div>
  166. {{- end}}
  167. <div class="card mt-10">
  168. <div class="card-header bg-light">
  169. <h3 data-i18n="admin.user_page_pref" class="card-title section-title-inner">User page preferences</h3>
  170. </div>
  171. <div class="card-body">
  172. {{template "infomsg" "admin.user_page_pref_help"}}
  173. <div class="form-group row mt-10">
  174. <label for="idUserPageHiddenSections" data-i18n="admin.hide_sections" class="col-md-3 col-form-label">Hide sections</label>
  175. <div class="col-md-9">
  176. <select id="idUserPageHiddenSections" name="user_page_hidden_sections" class="form-select" data-control="i18n-select2" data-hide-search="true" data-close-on-select="false" multiple>
  177. <option value="1" data-i18n="title.groups" {{if .Admin.Filters.Preferences.HideGroups}}selected{{end}}>Groups</option>
  178. <option value="2" data-i18n="storage.title" {{if .Admin.Filters.Preferences.HideFilesystem}}selected{{end}}>Filesystem</option>
  179. <option value="3" data-i18n="title.folders" {{if .Admin.Filters.Preferences.HideVirtualFolders}}selected{{end}}>Virtual Folders</option>
  180. <option value="4" data-i18n="title.profile" {{if .Admin.Filters.Preferences.HideProfile}}selected{{end}}>Profile</option>
  181. <option value="5" data-i18n="general.acls" {{if .Admin.Filters.Preferences.HideACLs}}selected{{end}}>ACLs</option>
  182. <option value="6" data-i18n="general.quota_limits" {{if .Admin.Filters.Preferences.HideDiskQuotaAndBandwidthLimits}}selected{{end}}>Disk quota and bandwidth limits</option>
  183. <option value="7" data-i18n="general.advanced_settings" {{if .Admin.Filters.Preferences.HideAdvancedSettings}}selected{{end}}>Advanced settings</option>
  184. </select>
  185. </div>
  186. </div>
  187. <div class="form-group row mt-10">
  188. <label for="idDefaultUsersExpiration" data-i18n="admin.default_users_expiration" class="col-md-3 col-form-label">Default users expiration</label>
  189. <div class="col-md-9">
  190. <input id="idDefaultUsersExpiration" type="number" min="0" class="form-control" name="default_users_expiration" value="{{.Admin.Filters.Preferences.DefaultUsersExpiration}}" aria-describedby="idDefaultUsersExpirationHelp"/>
  191. <div id="idDefaultUsersExpirationHelp" class="form-text" data-i18n="admin.default_users_expiration_help"></div>
  192. </div>
  193. </div>
  194. </div>
  195. </div>
  196. <div class="form-group row mt-10">
  197. <label for="idEmail" data-i18n="general.email" class="col-md-3 col-form-label">Email</label>
  198. <div class="col-md-9">
  199. <input id="idEmail" type="email" class="form-control" placeholder="" name="email" value="{{.Admin.Email}}"
  200. maxlength="255" autocomplete="off" spellcheck="false" />
  201. </div>
  202. </div>
  203. <div class="form-group row mt-10">
  204. <label for="idDescription" data-i18n="general.description" class="col-md-3 col-form-label">Description</label>
  205. <div class="col-md-9">
  206. <input id="idDescription" type="text" class="form-control" name="description" value="{{.Admin.Description}}" maxlength="255">
  207. </div>
  208. </div>
  209. <div class="form-group row mt-10">
  210. <label for="idAllowedIP" data-i18n="general.allowed_ip_mask" class="col-md-3 col-form-label">Allowed IP/Mask</label>
  211. <div class="col-md-9">
  212. <textarea class="form-control" id="idAllowedIP" name="allowed_ip" aria-describedby="idAllowedIPHelp"
  213. rows="3">{{.Admin.GetAllowedIPAsString}}</textarea>
  214. <div id="idAllowedIPHelp" class="form-text" data-i18n="general.ip_mask_help"></div>
  215. </div>
  216. </div>
  217. <div class="form-group row align-items-center mt-10">
  218. <label data-i18n="general.api_key_auth" class="col-md-3 col-form-label" for="idAllowAPIKeyAuth">API key authentication</label>
  219. <div class="col-md-9">
  220. <div class="form-check form-switch form-check-custom form-check-solid">
  221. <input class="form-check-input" type="checkbox" id="idAllowAPIKeyAuth" name="allow_api_key_auth" {{if .Admin.Filters.AllowAPIKeyAuth}}checked{{end}}/>
  222. <label data-i18n="filters.api_key_auth_help" class="form-check-label fw-semibold text-gray-800" for="idAllowAPIKeyAuth">
  223. Allow to impersonate yourself, in REST API, with an API key
  224. </label>
  225. </div>
  226. </div>
  227. </div>
  228. <div class="form-group row mt-10">
  229. <label for="idAdditionalInfo" data-i18n="general.additional_info" class="col-md-3 col-form-label">Additional info</label>
  230. <div class="col-md-9">
  231. <textarea id="idAdditionalInfo" class="form-control" name="additional_info" rows="3">{{.Admin.AdditionalInfo}}</textarea>
  232. </div>
  233. </div>
  234. <div class="d-flex justify-content-end mt-12">
  235. <input type="hidden" name="_form_token" value="{{.CSRFToken}}">
  236. <button type="submit" id="form_submit" class="btn btn-primary px-10" name="form_action" value="submit">
  237. <span data-i18n="general.submit" class="indicator-label">
  238. Submit
  239. </span>
  240. <span data-i18n="general.wait" class="indicator-progress">
  241. Please wait...
  242. <span class="spinner-border spinner-border-sm align-middle ms-2"></span>
  243. </span>
  244. </button>
  245. </div>
  246. </form>
  247. </div>
  248. </div>
  249. {{- end}}
  250. {{- define "extra_js"}}
  251. <script {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}} src="{{.StaticURL}}/assets/plugins/custom/formrepeater/formrepeater.bundle.js"></script>
  252. <script type="text/javascript" {{- if .CSPNonce}} nonce="{{.CSPNonce}}"{{- end}}>
  253. $(document).on("i18nload", function(){
  254. initRepeater('#groups');
  255. initRepeaterItems();
  256. });
  257. $(document).on("i18nshow", function(){
  258. $('#admin_form').submit(function (event) {
  259. let submitButton = document.querySelector('#form_submit');
  260. submitButton.setAttribute('data-kt-indicator', 'on');
  261. submitButton.disabled = true;
  262. });
  263. });
  264. </script>
  265. {{- end}}