You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

571 lines
22 KiB

  1. {% extends "base.html" %}
  2. {% load compress static hc_extras %}
  3. {% block title %}Project Settings - {{ project }}{% endblock %}
  4. {% block content %}
  5. {% with project.transfer_request as transfer_request %}
  6. <div class="row">
  7. <div class="col-sm-9 col-md-6">
  8. {% for message in messages %}
  9. <p class="alert alert-{{ message.tags }}">{{ message }}</p>
  10. {% endfor %}
  11. {% if transfer_request and transfer_request.user == request.user %}
  12. {% with can_accept=transfer_request.can_accept %}
  13. <div id="transfer-request" class="panel">
  14. <div class="panel-body settings-block">
  15. <h2>Ownership Transfer Request</h2>
  16. <p>
  17. <strong>{{ project.owner.email }}</strong> would like to transfer
  18. the ownership of this project to you.
  19. </p>
  20. {% if not can_accept %}
  21. {% with num_checks=project.num_checks num_available=request.profile.num_checks_available %}
  22. <p>
  23. This project has
  24. <strong>{{ num_checks }} check{{ num_checks|pluralize}}</strong>,
  25. but your account only has space for
  26. <strong>{{ num_available }} additional check{{ num_available|pluralize }}</strong>.
  27. To accept the transfer, please
  28. <a href="{% url 'hc-billing' %}">upgrade your account first!</a>
  29. </p>
  30. {% endwith%}
  31. {% endif %}
  32. <div class="pull-right">
  33. <form method="post">
  34. {% csrf_token %}
  35. <button
  36. type="submit"
  37. name="reject_transfer"
  38. class="btn btn-default">Reject</button>
  39. <button
  40. type="submit"
  41. name="accept_transfer"
  42. {% if not can_accept %}disabled{% endif %}
  43. class="btn btn-primary">Accept</button>
  44. </form>
  45. </div>
  46. </div>
  47. </div>
  48. {% endwith %}
  49. {% endif %}
  50. <div class="panel panel-{{ project_name_status|default:'default' }}">
  51. <div class="panel-body settings-block">
  52. <h2>Project Name</h2>
  53. {{ project }}
  54. {% if rw %}
  55. <a
  56. href="#"
  57. class="btn btn-default pull-right"
  58. data-toggle="modal"
  59. data-target="#set-project-name-modal">Change Project Name</a>
  60. {% endif %}
  61. </div>
  62. {% if project_name_updated %}
  63. <div class="panel-footer">
  64. Project name updated
  65. </div>
  66. {% endif %}
  67. </div>
  68. <div class="panel panel-{{ api_status|default:'default' }}">
  69. <div class="panel-body settings-block">
  70. <h2>API Access</h2>
  71. {% if project.api_key %}
  72. {% if show_api_keys %}
  73. <p>
  74. API key: <br />
  75. <pre>{{ project.api_key }}</pre>
  76. </p>
  77. {% if project.api_key_readonly %}
  78. <p>
  79. API key (read-only): <br />
  80. <pre>{{ project.api_key_readonly }}</pre>
  81. </p>
  82. <p>Related links:</p>
  83. <ul>
  84. <li><a href="{% url 'hc-serve-doc' 'api' %}">API documentation</a></li>
  85. {% if enable_prometheus %}
  86. <li>
  87. <a href="{% url 'hc-metrics' project.code project.api_key_readonly %}">Prometheus metrics endpoint</a>
  88. </li>
  89. {% endif %}
  90. <li>
  91. <a href="{{ project.dashboard_url }}">Read-only dashboard</a>
  92. (<a href="https://github.com/healthchecks/dashboard/#security">security considerations</a>)
  93. </li>
  94. </ul>
  95. {% endif %}
  96. <button
  97. data-toggle="modal"
  98. data-target="#revoke-api-key-modal"
  99. class="btn btn-danger pull-right">Revoke</button>
  100. {% else %}
  101. <form method="post">
  102. <span class="ic-ok"></span>
  103. API access is enabled.
  104. {% csrf_token %}
  105. {% if rw %}
  106. <button
  107. type="submit"
  108. name="show_api_keys"
  109. class="btn btn-default pull-right">Show API Keys</button>
  110. {% endif %}
  111. </form>
  112. {% endif %}
  113. {% else %}
  114. <span class="ic-cancel"></span>
  115. API access is disabled.
  116. <form method="post">
  117. {% csrf_token %}
  118. <button
  119. type="submit"
  120. name="create_api_keys"
  121. class="btn btn-default pull-right">Create API Keys</button>
  122. </form>
  123. {% endif %}
  124. </div>
  125. {% if api_keys_created %}
  126. <div class="panel-footer">
  127. API keys created
  128. </div>
  129. {% endif %}
  130. {% if api_keys_revoked %}
  131. <div class="panel-footer">
  132. API keys revoked
  133. </div>
  134. {% endif %}
  135. </div>
  136. {% with invite_suggestions=project.invite_suggestions %}
  137. <div class="panel panel-{{ team_status|default:'default' }}">
  138. <div class="panel-body settings-block">
  139. <h2>Team Access</h2>
  140. {% if project.team.exists or invite_suggestions %}
  141. <table id="team-table" class="table">
  142. <tr>
  143. <th>Email</th>
  144. <th>Role</th>
  145. <th></th>
  146. </tr>
  147. <tr>
  148. <td class="email">{{ project.owner.email }}</td>
  149. <td>Owner</td>
  150. <td></td>
  151. </tr>
  152. {% for m in project.member_set.all %}
  153. <tr>
  154. <td class="email">{{ m.user.email }}</td>
  155. <td>
  156. {% if m.rw %}
  157. Member
  158. {% else %}
  159. Read-only
  160. {% endif %}
  161. </td>
  162. <td>
  163. {% if is_owner %}
  164. <a
  165. href="#"
  166. data-email="{{ m.user.email }}"
  167. class="pull-right member-remove">Remove</a>
  168. {% endif %}
  169. </td>
  170. </tr>
  171. {% endfor %}
  172. {% if is_owner and invite_suggestions %}
  173. <tr id="suggestions-row">
  174. <td colspan="3">
  175. Add Users from Other Teams
  176. </td>
  177. </tr>
  178. {% for user in invite_suggestions %}
  179. <tr class="invite-suggestion">
  180. <td>{{ user.email }} </td>
  181. <td></td>
  182. <td>
  183. <a
  184. href="#"
  185. data-email="{{ user.email }}"
  186. class="pull-right add-to-team">Add to Team</a>
  187. </td>
  188. </tr>
  189. {% endfor %}
  190. {% endif %}
  191. </table>
  192. {% else %}
  193. <p>
  194. <strong>Invite team members to your project.</strong>
  195. Share access to your checks and configured integrations
  196. without having to share login details.
  197. </p>
  198. {% endif %}
  199. <br />
  200. {% if is_owner %}
  201. {% if project.can_invite_new_users %}
  202. <a
  203. href="#"
  204. class="btn btn-primary pull-right"
  205. data-toggle="modal"
  206. data-target="#invite-team-member-modal">Invite a Team Member</a>
  207. {% else %}
  208. <div class="alert alert-info">
  209. <strong>Team size limit reached.</strong>
  210. To invite new members by email, please
  211. <a href="{% url 'hc-pricing' %}">upgrade your account!</a>
  212. </div>
  213. {% endif %}
  214. {% endif %}
  215. </div>
  216. {% endwith %}
  217. {% if team_member_invited %}
  218. <div class="panel-footer">
  219. {{ team_member_invited }} invited to team
  220. </div>
  221. {% endif %}
  222. {% if team_member_duplicate %}
  223. <div class="panel-footer">
  224. {{ team_member_duplicate }} is already a member
  225. </div>
  226. {% endif %}
  227. {% if team_member_removed %}
  228. <div class="panel-footer">
  229. {{ team_member_removed }} removed from team
  230. </div>
  231. {% endif %}
  232. </div>
  233. {% if is_owner %}
  234. <div class="panel panel-{{ transfer_status|default:'default' }}"">
  235. <div class="panel-body settings-block">
  236. <h2>Transfer Ownership</h2>
  237. {% if transfer_request %}
  238. <form method="post">
  239. {% csrf_token %}
  240. <button
  241. type="submit"
  242. name="cancel_transfer"
  243. class="btn btn-default pull-right">Cancel Transfer</button>
  244. </form>
  245. Transfer initiated, awaiting confirmation from
  246. <strong>{{ transfer_request.user.email }}</strong>.
  247. {% else %}
  248. <a href="#"
  249. class="btn btn-default pull-right"
  250. data-toggle="modal"
  251. data-target="#transfer-modal">Transfer Project&hellip;</a>
  252. Transfer this project to a team member.
  253. {% endif %}
  254. </div>
  255. {% if transfer_initiated %}
  256. <div class="panel-footer">
  257. Transfer initiated!
  258. </div>
  259. {% endif %}
  260. {% if transfer_cancelled %}
  261. <div class="panel-footer">
  262. Transfer cancelled!
  263. </div>
  264. {% endif %}
  265. </div>
  266. {% endif %}
  267. {% if is_owner %}
  268. <div class="panel panel-default">
  269. <div class="panel-body settings-block">
  270. {% csrf_token %}
  271. <h2>Remove Project</h2>
  272. <a href="#"
  273. id="remove-project"
  274. class="btn btn-default pull-right"
  275. data-toggle="modal"
  276. data-target="#remove-project-modal">Remove Project</a>
  277. This will permanently remove project {{ project }}.
  278. <form action="{% url 'hc-remove-project' project.code %}" method="post">
  279. </form>
  280. </div>
  281. </div>
  282. {% endif %}
  283. </div>
  284. </div>
  285. <div id="revoke-api-key-modal" class="modal">
  286. <div class="modal-dialog">
  287. <form id="revoke-api-key-form" method="post">
  288. {% csrf_token %}
  289. <div class="modal-content">
  290. <div class="modal-header">
  291. <button type="button" class="close" data-dismiss="modal">&times;</button>
  292. <h4>Revoke API Keys?</h4>
  293. </div>
  294. <div class="modal-body">
  295. <p>You are about to revoke your current API keys.</p>
  296. <p>Afterwards, you can create new API keys, but there will
  297. be <strong>no way of getting the current API
  298. keys back</strong>.
  299. </p>
  300. <p>Are you sure?</p>
  301. </div>
  302. <div class="modal-footer">
  303. <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  304. <button
  305. type="submit"
  306. name="revoke_api_keys"
  307. class="btn btn-danger">Revoke API Keys</button>
  308. </div>
  309. </div>
  310. </form>
  311. </div>
  312. </div>
  313. <div id="remove-team-member-modal" class="modal">
  314. <div class="modal-dialog">
  315. <form id="remove-team-member-form" method="post">
  316. {% csrf_token %}
  317. <div class="modal-content">
  318. <div class="modal-header">
  319. <button type="button" class="close" data-dismiss="modal">&times;</button>
  320. <h4>Remove Team Member</h4>
  321. </div>
  322. <div class="modal-body">
  323. <p>You are about to remove <strong id="rtm-email"></strong> from the project.</p>
  324. <p>Are you sure?</p>
  325. <input
  326. type="hidden"
  327. name="email"
  328. id="remove-team-member-email" />
  329. </div>
  330. <div class="modal-footer">
  331. <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  332. <button
  333. type="submit"
  334. name="remove_team_member"
  335. class="btn btn-danger">Remove Member from Project</button>
  336. </div>
  337. </div>
  338. </form>
  339. </div>
  340. </div>
  341. <div id="invite-team-member-modal" class="modal">
  342. <div class="modal-dialog">
  343. <form method="post" class="form-horizontal">
  344. {% csrf_token %}
  345. <input type="hidden" name="invite_team_member" value="1" />
  346. <div class="modal-content">
  347. <div class="modal-header">
  348. <button type="button" class="close" data-dismiss="modal">&times;</button>
  349. <h4>Invite a Team Member</h4>
  350. </div>
  351. <div class="modal-body">
  352. <ul>
  353. <li>Team Members can create and manage Checks and Integrations</li>
  354. <li>Only the project owner (you) can view and edit billing settings</li>
  355. </ul>
  356. <br />
  357. <div class="form-group">
  358. <label for="itm-email" class="col-sm-3 control-label">Email</label>
  359. <div class="col-sm-8">
  360. <input
  361. type="email"
  362. class="form-control"
  363. id="itm-email"
  364. name="email"
  365. maxlength="254"
  366. placeholder="[email protected]">
  367. </div>
  368. </div>
  369. <div class="form-group">
  370. <label class="col-sm-3 control-label">Access Level</label>
  371. <div class="col-sm-8">
  372. <label class="radio-container">
  373. <input
  374. type="radio"
  375. name="rw"
  376. value="1"
  377. checked>
  378. <span class="radiomark"></span>
  379. Team Member
  380. </label>
  381. <label class="radio-container">
  382. <input
  383. type="radio"
  384. name="rw"
  385. value="">
  386. <span class="radiomark"></span>
  387. Read-only
  388. <span class="help-block">
  389. Cannot modify checks or integrations.
  390. Cannot access project's API keys.
  391. </span>
  392. </label>
  393. </div>
  394. </div>
  395. </div>
  396. <div class="modal-footer">
  397. <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  398. <button
  399. type="submit"
  400. name="invite_team_member"
  401. class="btn btn-primary">Send Invite</button>
  402. </div>
  403. </div>
  404. </form>
  405. </div>
  406. </div>
  407. <div id="set-project-name-modal" class="modal">
  408. <div class="modal-dialog">
  409. <form method="post" class="form-horizontal">
  410. {% csrf_token %}
  411. <div class="modal-content">
  412. <div class="modal-header">
  413. <button type="button" class="close" data-dismiss="modal">&times;</button>
  414. <h4>Change Project Name</h4>
  415. </div>
  416. <div class="modal-body">
  417. <div class="form-group">
  418. <label for="project-name" class="col-sm-4 control-label">Project Name</label>
  419. <div class="col-sm-7">
  420. <input
  421. type="text"
  422. class="form-control"
  423. id="project-name"
  424. name="name"
  425. maxlength="60"
  426. value="{{ project }}">
  427. </div>
  428. </div>
  429. </div>
  430. <div class="modal-footer">
  431. <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  432. <button
  433. type="submit"
  434. name="set_project_name"
  435. class="btn btn-primary">Set Project Name</button>
  436. </div>
  437. </div>
  438. </form>
  439. </div>
  440. </div>
  441. <div id="remove-project-modal" class="modal">
  442. <div class="modal-dialog">
  443. <form method="post" action="{% url 'hc-remove-project' project.code %}">
  444. {% csrf_token %}
  445. <div class="modal-content">
  446. <div class="modal-header">
  447. <button type="button" class="close" data-dismiss="modal">&times;</button>
  448. <h4>Remove "{{ project }}"?</h4>
  449. </div>
  450. <div class="modal-body">
  451. <p>Danger zone! You are about to permanently remove
  452. project <strong>{{ project }}</strong> and all
  453. of its associated checks and integrations. Are you sure?
  454. </p>
  455. </div>
  456. <div class="modal-footer">
  457. <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  458. <button
  459. type="submit"
  460. class="btn btn-danger">Remove Project</button>
  461. </div>
  462. </div>
  463. </form>
  464. </div>
  465. </div>
  466. {% if not transfer_request %}
  467. <div id="transfer-modal" class="modal">
  468. <div class="modal-dialog">
  469. <form
  470. class="form-horizontal"
  471. method="post">
  472. {% csrf_token %}
  473. <input type="hidden" name="transfer_project" value="1" />
  474. <div class="modal-content">
  475. <div class="modal-header">
  476. <button type="button" class="close" data-dismiss="modal">&times;</button>
  477. <h4>Transfer Ownership</h4>
  478. </div>
  479. <div class="modal-body">
  480. {% if project.team %}
  481. <div class="form-group">
  482. <label for="update-name-input" class="col-sm-4 control-label">
  483. Choose owner
  484. </label>
  485. <div class="col-sm-7">
  486. <select
  487. id="new-owner"
  488. name="email"
  489. title="Select..."
  490. class="form-control selectpicker">
  491. {% for user in project.team %}
  492. <option>{{ user.email }}</option>
  493. {% endfor %}
  494. </select>
  495. </div>
  496. </div>
  497. {% else %}
  498. <p>
  499. This project currently has no team members.
  500. To transfer the ownership of this project, please start by
  501. inviting the new owner as a team member.
  502. </p>
  503. {% endif %}
  504. </div>
  505. <div class="modal-footer">
  506. <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
  507. <button
  508. id="transfer-confirm"
  509. disabled
  510. type="submit"
  511. class="btn btn-primary">Initiate Transfer</button>
  512. </div>
  513. </div>
  514. </form>
  515. </div>
  516. </div>
  517. {% endif %}
  518. {% endwith %}
  519. {% endblock %}
  520. {% block scripts %}
  521. {% compress js %}
  522. <script src="{% static 'js/jquery-2.1.4.min.js' %}"></script>
  523. <script src="{% static 'js/bootstrap.min.js' %}"></script>
  524. <script src="{% static 'js/bootstrap-select.min.js' %}"></script>
  525. <script src="{% static 'js/project.js' %}"></script>
  526. {% endcompress %}
  527. {% endblock %}