ldap.html 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. <form action="/_api/admin/security/passport-ldap" method="post" class="form-horizontal" id="ldapSetting" role="form">
  2. <fieldset>
  3. <legend>LDAP {{ t("security_setting.configuration") }}</legend>
  4. {% set nameForIsLdapEnabled = "settingForm[security:passport-ldap:isEnabled]" %}
  5. {% set isLdapEnabled = getConfig('crowi', 'security:passport-ldap:isEnabled') %}
  6. <div class="form-group">
  7. <label for="{{nameForIsLdapEnabled}}" class="col-xs-3 control-label">Use LDAP</label>
  8. <div class="col-xs-6">
  9. <div class="btn-group btn-toggle" data-toggle="buttons">
  10. <label class="btn btn-default btn-rounded btn-outline {% if isLdapEnabled %}active{% endif %}" data-active-class="primary">
  11. <input name="{{nameForIsLdapEnabled}}" value="true" type="radio"
  12. {% if true === isLdapEnabled %}checked{% endif %}> ON
  13. </label>
  14. <label class="btn btn-default btn-rounded btn-outline {% if !isLdapEnabled %}active{% endif %}" data-active-class="default">
  15. <input name="{{nameForIsLdapEnabled}}" value="false" type="radio"
  16. {% if !isLdapEnabled %}checked{% endif %}> OFF
  17. </label>
  18. </div>
  19. </div>
  20. </div>
  21. <div class="passport-ldap-hide-when-disabled" {%if !isLdapEnabled %}style="display: none;"{% endif %}>
  22. <div class="form-group">
  23. <label for="settingForm[security:passport-ldap:serverUrl]" class="col-xs-3 control-label">Server URL</label>
  24. <div class="col-xs-6">
  25. <input class="form-control" type="text"
  26. name="settingForm[security:passport-ldap:serverUrl]" value="{{ getConfig('crowi', 'security:passport-ldap:serverUrl') | default('') }}">
  27. <p class="help-block">
  28. <small>
  29. {{ t("security_setting.ldap.server_url_detail") }}<br>
  30. {{ t("security_setting.example") }}: <code>ldaps://ldap.company.com/ou=people,dc=company,dc=com</code>
  31. </small>
  32. </p>
  33. </div>
  34. </div>
  35. {% set nameForIsUserBind = "settingForm[security:passport-ldap:isUserBind]" %}
  36. {% set isUserBind = getConfig('crowi', 'security:passport-ldap:isUserBind') %}
  37. <div class="form-group">
  38. <label for="{{nameForIsUserBind}}" class="col-xs-3 control-label">{{ t("security_setting.ldap.bind_mode") }}</label>
  39. <div class="col-xs-6">
  40. <div class="btn-group btn-toggle" data-toggle="buttons">
  41. <label class="btn btn-default btn-rounded btn-outline {% if !isUserBind %}active{% endif %}" data-active-class="primary">
  42. <input name="{{nameForIsUserBind}}" value="false" type="radio"
  43. {% if !isUserBind %}checked{% endif %}> {{ t("security_setting.ldap.bind_manager") }}
  44. </label>
  45. <label class="btn btn-default btn-rounded btn-outline {% if isUserBind %}active{% endif %}" data-active-class="primary">
  46. <input name="{{nameForIsUserBind}}" value="true" type="radio"
  47. {% if isUserBind %}checked{% endif %}> {{ t("security_setting.ldap.bind_user") }}
  48. </label>
  49. </div>
  50. </div>
  51. </div>
  52. <div class="form-group">
  53. <label for="settingForm[security:passport-ldap:bindDN]" class="col-xs-3 control-label">Bind DN</label>
  54. <div class="col-xs-6">
  55. <input class="form-control" type="text"
  56. name="settingForm[security:passport-ldap:bindDN]" value="{{ getConfig('crowi', 'security:passport-ldap:bindDN') | default('') }}">
  57. <p class="help-block passport-ldap-managerbind" {% if isUserBind %}style="display: none;"{% endif %}>
  58. <small>
  59. {{ t("security_setting.ldap.bind_DN_manager_detail") }}<br>
  60. {{ t("security_setting.example") }}1: <code>uid=admin,dc=domain,dc=com</code><br>
  61. {{ t("security_setting.example") }}2: <code>admin@domain.com</code>
  62. </small>
  63. </p>
  64. <p class="help-block passport-ldap-userbind" {% if !isUserBind %}style="display: none;"{% endif %}>
  65. <small>
  66. {{ t("security_setting.ldap.bind_DN_user_detail1") }}<br>
  67. {{ t("security_setting.ldap.bind_DN_user_detail2") }}<br>
  68. {{ t("security_setting.example") }}1: <code>uid={% raw %}{{username}}{% endraw %},dc=domain,dc=com</code><br>
  69. {{ t("security_setting.example") }}2: <code>{% raw %}{{username}}{% endraw %}@domain.com</code>
  70. </small>
  71. </p>
  72. </div>
  73. </div>
  74. <div class="form-group">
  75. <label for="settingForm[security:passport-ldap:bindDNPassword]" class="col-xs-3 control-label">{{ t("security_setting.ldap.bind_DN_password") }}</label>
  76. <div class="col-xs-6">
  77. <input class="form-control passport-ldap-managerbind" type="password" {% if isUserBind %}style="display: none;"{% endif %}
  78. name="settingForm[security:passport-ldap:bindDNPassword]" value="{{ getConfig('crowi', 'security:passport-ldap:bindDNPassword') | default('') }}">
  79. <p class="help-block passport-ldap-managerbind">
  80. <small>
  81. {{ t("security_setting.ldap.bind_DN_password_manager_detail") }}
  82. </small>
  83. </p>
  84. <p class="help-block passport-ldap-userbind" {% if !isUserBind %}style="display: none;"{% endif %}>
  85. <small>
  86. {{ t("security_setting.ldap.bind_DN_password_user_detail") }}
  87. </small>
  88. </p>
  89. </div>
  90. </div>
  91. <div class="form-group">
  92. <label for="settingForm[security:passport-ldap:searchFilter]" class="col-xs-3 control-label">{{ t("security_setting.ldap.search_filter") }}</label>
  93. <div class="col-xs-6">
  94. <input class="form-control" type="text" placeholder="Default: (uid={% raw %}{{username}}{% endraw %})"
  95. name="settingForm[security:passport-ldap:searchFilter]" value="{{ getConfig('crowi', 'security:passport-ldap:searchFilter') | default('') }}">
  96. <p class="help-block">
  97. <small>
  98. {{ t("security_setting.ldap.search_filter_detail1") }}<br>
  99. {{ t("security_setting.ldap.search_filter_detail2") }}<br>
  100. {{ t("security_setting.ldap.search_filter_detail3") }}
  101. </small>
  102. </p>
  103. <p class="help-block">
  104. <small>
  105. {{ t("security_setting.example") }}1 - {{ t("security_setting.ldap.search_filter_example1") }}: <code>(|(uid={% raw %}{{username}}{% endraw %})(mail={% raw %}{{username}}{% endraw %}))</code><br>
  106. {{ t("security_setting.example") }}2 - {{ t("security_setting.ldap.search_filter_example2") }}: <code>(sAMAccountName={% raw %}{{username}}{% endraw %})</code>
  107. </small>
  108. </p>
  109. </div>
  110. </div>
  111. <h4>Attribute Mapping ({{ t("security_setting.optional") }})</h4>
  112. <div class="form-group">
  113. <label for="settingForm[security:passport-ldap:attrMapUsername]" class="col-xs-3 control-label">username</label>
  114. <div class="col-xs-6">
  115. <input class="form-control" type="text" placeholder="Default: uid"
  116. name="settingForm[security:passport-ldap:attrMapUsername]" value="{{ getConfig('crowi', 'security:passport-ldap:attrMapUsername') | default('') }}">
  117. <p class="help-block">
  118. <small>
  119. {{ t("security_setting.ldap.username_detail") }}
  120. </small>
  121. </p>
  122. </div>
  123. </div>
  124. <div class="form-group">
  125. <div class="col-xs-6 col-xs-offset-3">
  126. <div class="checkbox checkbox-info">
  127. <input type="checkbox" id="cbSameUsernameTreatedAsIdenticalUser" name="settingForm[security:passport-ldap:isSameUsernameTreatedAsIdenticalUser]" value="1"
  128. {% if getConfig('crowi', 'security:passport-ldap:isSameUsernameTreatedAsIdenticalUser') %}checked{% endif %} />
  129. <label for="cbSameUsernameTreatedAsIdenticalUser">
  130. {{ t("security_setting.Treat username matching as identical", "username") }}
  131. </label>
  132. <p class="help-block">
  133. <small>
  134. {{ t("security_setting.Treat username matching as identical_warn", "username") }}
  135. </small>
  136. </p>
  137. </div>
  138. </div>
  139. </div>
  140. <div class="form-group">
  141. <label for="settingForm[security:passport-ldap:attrMapMail]" class="col-xs-3 control-label">Mail</label>
  142. <div class="col-xs-6">
  143. <input class="form-control" type="text" placeholder="Default: mail"
  144. name="settingForm[security:passport-ldap:attrMapMail]" value="{{ getConfig('crowi', 'security:passport-ldap:attrMapMail') | default('') }}">
  145. <p class="help-block">
  146. <small>
  147. {{ t("security_setting.ldap.mail_detail") }}
  148. </small>
  149. </p>
  150. </div>
  151. </div>
  152. <div class="form-group">
  153. <label for="settingForm[security:passport-ldap:attrMapName]" class="col-xs-3 control-label">Name</label>
  154. <div class="col-xs-6">
  155. <input class="form-control" type="text"
  156. name="settingForm[security:passport-ldap:attrMapName]" value="{{ getConfig('crowi', 'security:passport-ldap:attrMapName') | default('') }}">
  157. <p class="help-block">
  158. <small>
  159. {{ t("security_setting.ldap.name_detail") }}
  160. </small>
  161. </p>
  162. </div>
  163. </div>
  164. <h4>{{ t("security_setting.ldap.group_search_filter") }} ({{ t("security_setting.optional") }})</h4>
  165. <div class="form-group">
  166. <label for="settingForm[security:passport-ldap:groupSearchBase]" class="col-xs-3 control-label">{{ t("security_setting.ldap.group_search_base_DN") }}</label>
  167. <div class="col-xs-6">
  168. <input class="form-control" type="text"
  169. name="settingForm[security:passport-ldap:groupSearchBase]" value="{{ getConfig('crowi', 'security:passport-ldap:groupSearchBase') | default('') }}">
  170. <p class="help-block">
  171. <small>
  172. {{ t("security_setting.ldap.group_search_base_DN_detail") }}<br>
  173. {{ t("security_setting.example") }}: <code>ou=groups,dc=domain,dc=com</code>
  174. </small>
  175. </p>
  176. </div>
  177. </div>
  178. <div class="form-group">
  179. <label for="settingForm[security:passport-ldap:groupSearchFilter]" class="col-xs-3 control-label">{{ t("security_setting.ldap.group_search_filter") }}</label>
  180. <div class="col-xs-6">
  181. <input class="form-control" type="text"
  182. name="settingForm[security:passport-ldap:groupSearchFilter]" value="{{ getConfig('crowi', 'security:passport-ldap:groupSearchFilter') | default('') }}">
  183. <p class="help-block">
  184. <small>
  185. {{ t("security_setting.ldap.group_search_filter_detail1") }}<br>
  186. {{ t("security_setting.ldap.group_search_filter_detail2") }}<br>
  187. {{ t("security_setting.ldap.group_search_filter_detail3") }}
  188. </small>
  189. </p>
  190. <p class="help-block">
  191. <small>
  192. {{ t("security_setting.example") }}: {{ t("security_setting.ldap.group_search_filter_detail4") }}
  193. </small>
  194. </p>
  195. </div>
  196. </div>
  197. <div class="form-group">
  198. <label for="settingForm[security:passport-ldap:groupSearchFilter]" class="col-xs-3 control-label">{{ t("security_setting.ldap.group_search_user_DN_property") }}</label>
  199. <div class="col-xs-6">
  200. <input class="form-control" type="text" placeholder="Default: uid"
  201. name="settingForm[security:passport-ldap:groupDnProperty]" value="{{ getConfig('crowi', 'security:passport-ldap:groupDnProperty') | default('') }}">
  202. <p class="help-block">
  203. <small>
  204. {{ t("security_setting.ldap.group_search_user_DN_property_detail") }}
  205. </small>
  206. </p>
  207. </div>
  208. </div>
  209. </div><!-- /.passport-ldap-configurations -->
  210. <div class="form-group">
  211. <div class="col-xs-offset-3 col-xs-6">
  212. <button type="submit" class="btn btn-primary">{# the first element is the default button to submit #}
  213. {{ t('Update') }}
  214. </button>
  215. <button type="button"
  216. class="btn btn-default passport-ldap-hide-when-disabled"
  217. data-target="#test-ldap-account" data-toggle="modal"
  218. {%if !isLdapEnabled %}style="display: none;"{% endif %}>
  219. {{ t("security_setting.ldap.test_config") }}
  220. </button>
  221. </div>
  222. </div>
  223. </fieldset>
  224. <input type="hidden" name="_csrf" value="{{ csrf() }}">
  225. <script>
  226. // switch display according to on / off of radio buttons
  227. $('input[name="{{nameForIsLdapEnabled}}"]:radio').change(function() {
  228. const isEnabled = ($(this).val() === "true");
  229. if (isEnabled) {
  230. $('.passport-ldap-hide-when-disabled').show(400);
  231. }
  232. else {
  233. $('.passport-ldap-hide-when-disabled').hide(400);
  234. }
  235. });
  236. // switch display according to on / off of radio buttons
  237. $('input[name="{{nameForIsUserBind}}"]:radio').change(function() {
  238. const isUserBind = ($(this).val() === "true");
  239. if (isUserBind) {
  240. $('input.passport-ldap-managerbind').hide();
  241. $('.help-block.passport-ldap-managerbind').hide();
  242. $('.help-block.passport-ldap-userbind').show();
  243. }
  244. else {
  245. $('input.passport-ldap-managerbind').show();
  246. $('.help-block.passport-ldap-managerbind').show();
  247. $('.help-block.passport-ldap-userbind').hide();
  248. }
  249. });
  250. // store which button is clicked when submit
  251. var submittedButton;
  252. $('button[type="submit"]').click(function() {
  253. submittedButton = $(this);
  254. });
  255. $('#ldapSetting, #ldapTest').each(function() {
  256. $(this).submit(function()
  257. {
  258. function showMessage(formId, msg, status) {
  259. $('#' + formId + ' .alert').remove();
  260. if (!status) {
  261. status = 'success';
  262. }
  263. var $message = $('<p class="alert"></p>');
  264. $message.addClass('alert-' + status);
  265. $message.html(msg.replace(/\n/g, '<br>'));
  266. $message.insertAfter('#' + formId + ' legend');
  267. if (status == 'success') {
  268. setTimeout(function()
  269. {
  270. $message.fadeOut({
  271. complete: function() {
  272. $message.remove();
  273. }
  274. });
  275. }, 5000);
  276. }
  277. }
  278. var $form = $(this);
  279. var $id = $form.attr('id');
  280. var $button = submittedButton;
  281. var $action = $button.attr('formaction') || $form.attr('action');
  282. $button.attr('disabled', 'disabled');
  283. var jqxhr = $.post($action, $form.serialize(), function(data)
  284. {
  285. if (data.status) {
  286. const message = data.message || '更新しました';
  287. showMessage($id, message);
  288. } else {
  289. showMessage($id, data.message, 'danger');
  290. }
  291. })
  292. .fail(function() {
  293. showMessage($id, 'エラーが発生しました', 'danger');
  294. })
  295. .always(function() {
  296. $button.prop('disabled', false);
  297. });
  298. return false;
  299. });
  300. });
  301. </script>
  302. </form>
  303. <div class="modal test-ldap-account" id="test-ldap-account">
  304. <div class="modal-dialog">
  305. <div class="modal-content">
  306. <div class="modal-header">
  307. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
  308. <div class="modal-title">{{ t('Test LDAP Account') }}</div>
  309. </div>
  310. <div class="modal-body">
  311. {% include '../../../widget/passport/ldap-association-tester.html' with { showLog: true } %}
  312. </div><!-- /.modal-body -->
  313. </div><!-- /.modal-content -->
  314. </div><!-- /.modal-dialog -->
  315. <script>
  316. /**
  317. * associate (submit the form)
  318. */
  319. function associateLdap() {
  320. var $form = $('#formLdapAssociationContainer > form');
  321. var $action = '/me/external-accounts/associateLdap';
  322. $form.attr('action', $action);
  323. $form.submit();
  324. }
  325. </script>
  326. </div><!-- /.modal -->