OAuth.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <div>
  3. <setting-tabs :activeTab="'settings.oauth.tokens'"></setting-tabs>
  4. <div class="options-tabs">
  5. <form-wrapper>
  6. <div v-if="isRemoteUser" class="notification is-warning has-text-centered" v-html="$t('auth.auth_handled_by_proxy')" />
  7. <h4 class="title is-4 has-text-grey-light">{{ $t('settings.personal_access_tokens') }}</h4>
  8. <div class="is-size-7-mobile">
  9. {{ $t('settings.token_legend')}}
  10. </div>
  11. <div class="mt-3">
  12. <a tabindex="0" class="is-link" @click="createToken" @keyup.enter="createToken">
  13. <font-awesome-icon :icon="['fas', 'plus-circle']" /> {{ $t('settings.generate_new_token')}}
  14. </a>
  15. </div>
  16. <div v-if="tokens.length > 0">
  17. <div v-for="token in tokens" :key="token.id" class="group-item is-size-5 is-size-6-mobile">
  18. <font-awesome-icon v-if="token.value" class="has-text-success" :icon="['fas', 'check']" /> {{ token.name }}
  19. <!-- revoke link -->
  20. <div class="tags is-pulled-right">
  21. <button v-if="token.value" class="button tag" :class="{'is-link': !$root.showDarkMode}" v-clipboard="() => token.value" v-clipboard:success="clipboardSuccessHandler">{{ $t('commons.copy') }}</button>
  22. <button class="button tag" :class="$root.showDarkMode ? 'is-dark':'is-white'" @click="revokeToken(token.id)" :title="$t('settings.revoke')">{{ $t('settings.revoke') }}</button>
  23. </div>
  24. <!-- edit link -->
  25. <!-- <router-link :to="{ name: 'settings.oauth.editPAT' }" class="has-text-grey pl-1" :title="$t('commons.edit')">
  26. <font-awesome-icon :icon="['fas', 'pen-square']" />
  27. </router-link> -->
  28. <!-- warning msg -->
  29. <span v-if="token.value" class="is-size-7-mobile is-size-6 my-3">
  30. {{ $t('settings.make_sure_copy_token') }}
  31. </span>
  32. <!-- token value -->
  33. <span v-if="token.value" class="pat is-family-monospace is-size-6 is-size-7-mobile has-text-success">
  34. {{ token.value }}
  35. </span>
  36. </div>
  37. <div class="mt-2 is-size-7 is-pulled-right">
  38. {{ $t('settings.revoking_a_token_is_permanent')}}
  39. </div>
  40. </div>
  41. <div v-if="isFetching && tokens.length === 0" class="has-text-centered mt-6">
  42. <span class="is-size-4">
  43. <font-awesome-icon :icon="['fas', 'spinner']" spin />
  44. </span>
  45. </div>
  46. <!-- footer -->
  47. <vue-footer :showButtons="true">
  48. <!-- close button -->
  49. <p class="control">
  50. <router-link :to="{ name: 'accounts', params: { toRefresh: false } }" class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" tabindex="0">{{ $t('commons.close') }}</router-link>
  51. </p>
  52. </vue-footer>
  53. </form-wrapper>
  54. </div>
  55. </div>
  56. </template>
  57. <script>
  58. import Form from './../../components/Form'
  59. export default {
  60. data(){
  61. return {
  62. tokens : [],
  63. isFetching: false,
  64. form: new Form({
  65. token : '',
  66. }),
  67. isRemoteUser: false,
  68. }
  69. },
  70. mounted() {
  71. this.fetchTokens()
  72. },
  73. methods : {
  74. /**
  75. * Get all groups from backend
  76. */
  77. async fetchTokens() {
  78. this.isFetching = true
  79. await this.axios.get('/oauth/personal-access-tokens', {returnError: true})
  80. .then(response => {
  81. const tokens = []
  82. response.data.forEach((data) => {
  83. if (data.id === this.$route.params.token_id) {
  84. data.value = this.$route.params.accessToken
  85. tokens.unshift(data)
  86. }
  87. else {
  88. tokens.push(data)
  89. }
  90. })
  91. this.tokens = tokens
  92. })
  93. .catch(error => {
  94. if( error.response.status === 400 ) {
  95. this.isRemoteUser = true
  96. }
  97. else {
  98. this.$router.push({ name: 'genericError', params: { err: error.response } });
  99. }
  100. })
  101. this.isFetching = false
  102. },
  103. clipboardSuccessHandler ({ value, event }) {
  104. this.$notify({ type: 'is-success', text: this.$t('commons.copied_to_clipboard') })
  105. },
  106. clipboardErrorHandler ({ value, event }) {
  107. console.log('error', value)
  108. },
  109. /**
  110. * revoke a token (after confirmation)
  111. */
  112. async revokeToken(tokenId) {
  113. if(confirm(this.$t('settings.confirm.revoke'))) {
  114. await this.axios.delete('/oauth/personal-access-tokens/' + tokenId).then(response => {
  115. // Remove the revoked token from the collection
  116. this.tokens = this.tokens.filter(a => a.id !== tokenId)
  117. this.$notify({ type: 'is-success', text: this.$t('settings.token_revoked') })
  118. });
  119. }
  120. },
  121. /**
  122. * Open the PAT creation view
  123. */
  124. createToken() {
  125. if (this.isRemoteUser) {
  126. this.$notify({ type: 'is-warning', text: this.$t('errors.unsupported_with_reverseproxy') })
  127. }
  128. else this.$router.push({ name: 'settings.oauth.generatePAT' })
  129. },
  130. },
  131. }
  132. </script>