security.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. {% extends '../layout/admin.html' %}
  2. {% block html_title %}{{ customizeService.generateCustomTitle(t('security_settings')) }} · {% endblock %}
  3. {% block content_header %}
  4. <div class="header-wrap">
  5. <header id="page-header">
  6. <h1 id="admin-title" class="title">{{ t('security_settings') }}</h1>
  7. </header>
  8. </div>
  9. {% endblock %}
  10. {% block content_main %}
  11. <div class="content-main admin-security">
  12. <div class="row">
  13. <div class="col-md-3">
  14. {% include './widget/menu.html' with {current: 'security'} %}
  15. </div>
  16. <div class="col-md-9">
  17. {% set smessage = req.flash('successMessage') %}
  18. {% if smessage.length %}
  19. <div class="alert alert-success">
  20. {% for e in smessage %}
  21. {{ e }}<br>
  22. {% endfor %}
  23. </div>
  24. {% endif %}
  25. {% set emessage = req.flash('errorMessage') %}
  26. {% if emessage.length %}
  27. <div class="alert alert-danger">
  28. {% for e in emessage %}
  29. {{ e }}<br>
  30. {% endfor %}
  31. </div>
  32. {% endif %}
  33. <form action="/_api/admin/security/general" method="post" class="form-horizontal" id="generalSetting" role="form">
  34. <fieldset>
  35. <legend class="alert-anchor">{{ t('security_settings') }}</legend>
  36. <div class="form-group">
  37. <label for="settingForm[security:restrictGuestMode]" class="col-xs-3 control-label">{{ t('security_setting.Guest Users Access') }}</label>
  38. <div class="col-xs-6">
  39. {% set selectedValue = guestModeValue %}
  40. <select class="form-control selectpicker" {% if isWikiModeForced %}disabled{% endif %}
  41. name="settingForm[security:restrictGuestMode]" value="{{ getConfig('crowi', 'security:restrictGuestMode') }}">
  42. {% for modeValue, modeLabel in consts.restrictGuestMode %}
  43. <option value="{{ t(modeValue) }}" {% if modeValue == selectedValue %}selected{% endif %}>{{ t(modeLabel) }}</option>
  44. {% endfor %}
  45. </select>
  46. {% if isWikiModeForced %}
  47. <p class="alert alert-warning mt-2">
  48. <i class="icon-exclamation icon-fw"></i><b>FIXED</b><br>
  49. {{ t('security_setting.Fixed by env var', 'FORCE_WIKI_MODE', getConfig('crowi', 'security:wikiMode')) }}
  50. </p>
  51. {% endif %}
  52. </div>
  53. </div>
  54. <div class="form-group">
  55. <label for="settingForm[security:registrationMode]" class="col-xs-3 control-label">{{ t('Register limitation') }}</label>
  56. <div class="col-xs-6">
  57. <select class="form-control selectpicker" name="settingForm[security:registrationMode]" value="{{ getConfig('crowi', 'security:registrationMode') }}">
  58. {% for modeValue, modeLabel in consts.registrationMode %}
  59. <option value="{{ t(modeValue) }}" {% if modeValue == getConfig('crowi', 'security:registrationMode') %}selected{% endif %} >{{ t(modeLabel) }}</option>
  60. {% endfor %}
  61. </select>
  62. <p class="help-block small">{{ t('security_setting.Register limitation desc') }}</p>
  63. </div>
  64. </div>
  65. <div class="form-group">
  66. <label for="settingForm[security:registrationWhiteList]" class="col-xs-3 control-label">{{ t('The whitelist of registration permission E-mail address') }}</label>
  67. <div class="col-xs-8">
  68. <textarea class="form-control" type="textarea" name="settingForm[security:registrationWhiteList]" placeholder="{{ t('security_setting.example') }}: @growi.org">{{ getConfig('crowi', 'security:registrationWhiteList') | join('&#13') | raw }}</textarea>
  69. <p class="help-block small">{{ t("security_setting.restrict_emails") }}{{ t("security_setting.for_instance") }}<code>@growi.org</code>{{ t("security_setting.only_those") }}<br>
  70. {{ t("security_setting.insert_single") }}</p>
  71. </div>
  72. </div>
  73. <div class="form-group">
  74. {% set configName = 'settingForm[security:list-policy:hideRestrictedByOwner]' %}
  75. {% set configValue = getConfig('crowi', 'security:list-policy:hideRestrictedByOwner') %}
  76. {% set isEnabled = !configValue %}
  77. <label for="{{configName}}" class="col-xs-3 control-label">{{ t("security_setting.page_listing_1") }}</label>
  78. <div class="col-xs-9">
  79. <div class="btn-group btn-toggle" data-toggle="buttons">
  80. <label class="btn btn-default btn-rounded btn-outline {% if isEnabled %}active{% endif %}" data-active-class="primary">
  81. <input name="{{configName}}" value="false" type="radio" {% if isEnabled %}checked{% endif %}> ON
  82. </label>
  83. <label class="btn btn-default btn-rounded btn-outline {% if !isEnabled %}active{% endif %}" data-active-class="default">
  84. <input name="{{configName}}" value="true" type="radio" {% if !isEnabled %}checked{% endif %}> OFF
  85. </label>
  86. </div>
  87. <p class="help-block small">
  88. {{ t("security_setting.page_listing_1_desc") }}
  89. </p>
  90. </div>
  91. </div>
  92. <div class="form-group">
  93. {% set configName = 'settingForm[security:list-policy:hideRestrictedByGroup]' %}
  94. {% set configValue = getConfig('crowi', 'security:list-policy:hideRestrictedByGroup') %}
  95. {% set isEnabled = !configValue %}
  96. <label for="{{configName}}" class="col-xs-3 control-label">{{ t("security_setting.page_listing_2") }}</label>
  97. <div class="col-xs-9">
  98. <div class="btn-group btn-toggle" data-toggle="buttons">
  99. <label class="btn btn-default btn-rounded btn-outline {% if isEnabled %}active{% endif %}" data-active-class="primary">
  100. <input name="{{configName}}" value="false" type="radio" {% if isEnabled %}checked{% endif %}> ON
  101. </label>
  102. <label class="btn btn-default btn-rounded btn-outline {% if !isEnabled %}active{% endif %}" data-active-class="default">
  103. <input name="{{configName}}" value="true" type="radio" {% if !isEnabled %}checked{% endif %}> OFF
  104. </label>
  105. </div>
  106. <p class="help-block small">
  107. {{ t("security_setting.page_listing_2_desc") }}
  108. </p>
  109. </div>
  110. </div>
  111. <div class="form-group">
  112. {% set configName = 'settingForm[security:pageCompleteDeletionAuthority]' %}
  113. {% set configValue = getConfig('crowi','security:pageCompleteDeletionAuthority') %}
  114. <label for="{{configName}}" class="col-xs-3 control-label">{{ t('security_setting.complete_deletion') }}</label>
  115. <div class="col-xs-6">
  116. <select class="form-control selectpicker" name="settingForm[security:pageCompleteDeletionAuthority]" value="{{ configValue }}">
  117. <option value="anyOne" {% if configValue == "anyOne" %}selected{% endif %}>{{ t('security_setting.anyone') }}</option>
  118. <option value="adminOnly" {% if configValue =="adiminOnly" %}selected{% endif %}>{{ t('security_setting.admin_only') }}</option>
  119. <option value="adminAndAuthor" {% if configValue == "adminAndAuthor" %}selected{% endif %}>{{ t('security_setting.admin_and_author') }}</option>
  120. </select>
  121. <p class="help-block small">
  122. {{ t('security_setting.complete_deletion_explain') }}
  123. </p>
  124. </div>
  125. </div>
  126. <div class="form-group">
  127. <div class="col-xs-offset-3 col-xs-6">
  128. <input type="hidden" name="_csrf" value="{{ csrf() }}">
  129. <button type="submit" class="btn btn-primary">{{ t('Update') }}</button>
  130. </div>
  131. </div>
  132. </fieldset>
  133. </form>
  134. <!-- prevent XSS link -->
  135. <div class="mt-5">
  136. <legend>{{ t('security_setting.xss_prevent_setting') }}</legend>
  137. <div class="text-center">
  138. <a class="flexbox" style="font-size: large;" href="/admin/markdown/#preventXSS">
  139. <i class="fa-fw icon-login"></i> {{ t('security_setting.xss_prevent_setting_link') }}
  140. </a>
  141. </div>
  142. </div>
  143. <div class="auth-mechanism-configurations m-t-10">
  144. <legend>{{ t('security_setting.Authentication mechanism settings') }}</legend>
  145. {#
  146. # passport settings nav
  147. #}
  148. <div class="passport-settings">
  149. <ul class="nav nav-tabs" role="tablist">
  150. <li class="active">
  151. <a href="#passport-ldap" data-toggle="tab" role="tab"><i class="fa fa-sitemap"></i> LDAP</a>
  152. </li>
  153. <li>
  154. <a href="#passport-saml" data-toggle="tab" role="tab"><i class="fa fa-key"></i> SAML</a>
  155. </li>
  156. <li>
  157. <a href="#passport-google-oauth" data-toggle="tab" role="tab"><i class="fa fa-google"></i> Google</a>
  158. </li>
  159. <li>
  160. <a href="#passport-github" data-toggle="tab" role="tab"><i class="fa fa-github"></i> GitHub</a>
  161. </li>
  162. <li>
  163. <a href="#passport-twitter" data-toggle="tab" role="tab"><i class="fa fa-twitter"></i> Twitter</a>
  164. </li>
  165. <li>
  166. <a href="#passport-oidc" data-toggle="tab" role="tab"><i class="fa fa-openid"></i> OIDC</a>
  167. </li>
  168. <li>
  169. <a href="#passport-basic" data-toggle="tab" role="tab"><i class="fa fa-sign-in"></i> Basic</a>
  170. </li>
  171. <li class="tbd">
  172. <a href="#passport-facebook" data-toggle="tab" role="tab"><i class="fa fa-facebook"></i> (TBD) Facebook</a>
  173. </li>
  174. </ul>
  175. <div class="tab-content p-t-10">
  176. <div id="passport-ldap" class="tab-pane active" role="tabpanel" >
  177. {% include './widget/passport/ldap.html' with { settingForm: settingForm } %}
  178. </div>
  179. <div id="passport-saml" class="tab-pane" role="tabpanel" >
  180. {% include './widget/passport/saml.html' %}
  181. </div>
  182. <div id="passport-google-oauth" class="tab-pane" role="tabpanel">
  183. {% include './widget/passport/google-oauth.html' %}
  184. </div>
  185. <div id="passport-facebook" class="tab-pane" role="tabpanel">
  186. {% include './widget/passport/facebook.html' %}
  187. </div>
  188. <div id="passport-twitter" class="tab-pane" role="tabpanel">
  189. {% include './widget/passport/twitter.html' %}
  190. </div>
  191. <div id="passport-oidc" class="tab-pane" role="tabpanel">
  192. {% include './widget/passport/oidc.html' %}
  193. </div>
  194. <div id="passport-github" class="tab-pane" role="tabpanel">
  195. {% include './widget/passport/github.html' %}
  196. </div>
  197. <div id="passport-basic" class="tab-pane" role="tabpanel">
  198. {% include './widget/passport/basic.html' %}
  199. </div>
  200. </div><!-- /.tab-content -->
  201. </div>
  202. </div><!-- /.auth-mechanism-configurations -->
  203. </div>
  204. </div>
  205. <script>
  206. $('#generalSetting, #samlSetting, #googleSetting, #mechanismSetting, #githubSetting, #twitterSetting, #oidcSetting').each(function() {
  207. $(this).submit(function()
  208. {
  209. function showMessage(formId, msg, status) {
  210. $('#' + formId + ' > .alert').remove();
  211. $('#' + formId ).find('.alert').remove();
  212. if (!status) {
  213. status = 'success';
  214. }
  215. var $message = $('<p class="alert"></p>');
  216. $message.addClass('alert-' + status);
  217. $message.html(msg.replace(/\n/g, '<br>'));
  218. $message.insertAfter('#' + formId + ' .alert-anchor');
  219. if (status == 'success') {
  220. setTimeout(function()
  221. {
  222. $message.fadeOut({
  223. complete: function() {
  224. $message.remove();
  225. }
  226. });
  227. }, 5000);
  228. }
  229. }
  230. var $form = $(this);
  231. var $id = $form.attr('id');
  232. var $button = $('button', this);
  233. $button.attr('disabled', 'disabled');
  234. var jqxhr = $.post($form.attr('action'), $form.serialize(), function(data)
  235. {
  236. if (data.status) {
  237. showMessage($id, '更新しました Updated');
  238. } else {
  239. showMessage($id, data.message, 'danger');
  240. }
  241. })
  242. .fail(function() {
  243. showMessage($id, 'エラーが発生しました Error', 'danger');
  244. })
  245. .always(function() {
  246. $button.prop('disabled', false);
  247. });
  248. return false;
  249. });
  250. });
  251. </script>
  252. </div>
  253. {% endblock content_main %}
  254. {% block content_footer %}
  255. {% endblock content_footer %}