SubsonicTokenForm.vue 5.53 KB
Newer Older
1 2
<template>
  <form class="ui form" @submit.prevent="requestNewToken()">
3
    <h2><translate :translate-context="'Content/Settings/Title'">Subsonic API password</translate></h2>
4
    <p class="ui message" v-if="!subsonicEnabled">
5
      <translate :translate-context="'Content/Settings/Paragraph'">The Subsonic API is not available on this Funkwhale instance.</translate>
6 7
    </p>
    <p>
8
      <translate :translate-context="'Content/Settings/Paragraph'">Funkwhale is compatible with other music players that support the Subsonic API.</translate>&nbsp;<translate :translate-context="'Content/Settings/Paragraph'">You can use those to enjoy your playlist and music in offline mode, on your smartphone or tablet, for instance.</translate>
9 10
    </p>
    <p>
11
      <translate :translate-context="'Content/Settings/Paragraph'">However, accessing Funkwhale from those clients require a separate password you can set below.</translate>
12
    </p>
Agate's avatar
Agate committed
13
    <p><a href="https://docs.funkwhale.audio/users/apps.html#subsonic-compatible-clients" target="_blank">
14
      <translate :translate-context="'Content/Settings/Link'">Discover how to use Funkwhale from other apps</translate>
15 16 17 18 19
    </a></p>
    <div v-if="success" class="ui positive message">
      <div class="header">{{ successMessage }}</div>
    </div>
    <div v-if="subsonicEnabled && errors.length > 0" class="ui negative message">
20
      <div class="header"><translate :translate-context="'Content/Settings/Error message.Title'">Error</translate></div>
21 22 23 24 25 26 27 28 29 30 31 32 33
      <ul class="list">
        <li v-for="error in errors">{{ error }}</li>
      </ul>
    </div>
    <template v-if="subsonicEnabled">
      <div v-if="token" class="field">
        <password-input v-model="token" />
      </div>
      <dangerous-button
        v-if="token"
        color="grey"
        :class="['ui', {'loading': isLoading}, 'button']"
        :action="requestNewToken">
34 35 36
        <translate :translate-context="'Content/Settings/Button.Label/Verb'">Request a new password</translate>
        <p slot="modal-header"><translate :translate-context="'Popup/Settings/Title'">Request a new Subsonic API password?</translate></p>
        <p slot="modal-content"><translate :translate-context="'Popup/Settings/Paragraph'">This will log you out from existing devices that use the current password.</translate></p>
37
        <div slot="modal-confirm"><translate :translate-context="'Popup/Settings/Button.Label/Verb'">Request a new password</translate></div>
38 39 40 41 42
      </dangerous-button>
      <button
        v-else
        color="grey"
        :class="['ui', {'loading': isLoading}, 'button']"
43
        @click="requestNewToken"><translate :translate-context="'Content/Settings/Button.Label/Verb'">Request a password</translate></button>
44 45 46 47 48
        <dangerous-button
          v-if="token"
          color="yellow"
          :class="['ui', {'loading': isLoading}, 'button']"
          :action="disable">
49 50 51
          <translate :translate-context="'Content/Settings/Button.Label/Verb'">Disable Subsonic access</translate>
          <p slot="modal-header"><translate :translate-context="'Popup/Settings/Title'">Disable Subsonic API access?</translate></p>
          <p slot="modal-content"><translate :translate-context="'Popup/Settings/Paragraph'">This will completely disable access to the Subsonic API using from account.</translate></p>
52
          <div slot="modal-confirm"><translate :translate-context="'Popup/Settings/Button.Label'">Disable access</translate></div>
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
        </dangerous-button>
    </template>
  </form>
</template>

<script>
import axios from 'axios'
import PasswordInput from '@/components/forms/PasswordInput'

export default {
  components: {
    PasswordInput
  },
  data () {
    return {
      token: null,
      errors: [],
      success: false,
      isLoading: false,
      successMessage: ''
    }
  },
  created () {
    this.fetchToken()
  },
  methods: {
    fetchToken () {
      this.success = false
      this.errors = []
      this.isLoading = true
      let self = this
      let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
      return axios.get(url).then(response => {
        self.token = response.data['subsonic_api_token']
        self.isLoading = false
      }, error => {
        self.isLoading = false
        self.errors = error.backendErrors
      })
    },
    requestNewToken () {
94
      this.successMessage = this.$pgettext('Content/Settings/Message', 'Password updated')
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
      this.success = false
      this.errors = []
      this.isLoading = true
      let self = this
      let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
      return axios.post(url, {}).then(response => {
        self.token = response.data['subsonic_api_token']
        self.isLoading = false
        self.success = true
      }, error => {
        self.isLoading = false
        self.errors = error.backendErrors
      })
    },
    disable () {
110
      this.successMessage = this.$pgettext('Content/Settings/Message', 'Access disabled')
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
      this.success = false
      this.errors = []
      this.isLoading = true
      let self = this
      let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
      return axios.delete(url).then(response => {
        self.isLoading = false
        self.token = null
        self.success = true
      }, error => {
        self.isLoading = false
        self.errors = error.backendErrors
      })
    }
  },
  computed: {
    subsonicEnabled () {
      return this.$store.state.instance.settings.subsonic.enabled.value
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>