diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
commit | aee0a117a889461ce8ced6fcf73207fe017f1d99 (patch) | |
tree | 891d9ef189227a8445d83f35c1b0fc99573f4380 /app/assets/javascripts/access_tokens | |
parent | 8d46af3258650d305f53b819eabf7ab18d22f59e (diff) |
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'app/assets/javascripts/access_tokens')
4 files changed, 200 insertions, 0 deletions
diff --git a/app/assets/javascripts/access_tokens/components/token.vue b/app/assets/javascripts/access_tokens/components/token.vue new file mode 100644 index 00000000000..3954e541fe0 --- /dev/null +++ b/app/assets/javascripts/access_tokens/components/token.vue @@ -0,0 +1,55 @@ +<script> +import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue'; + +export default { + components: { InputCopyToggleVisibility }, + props: { + token: { + type: String, + required: true, + }, + inputId: { + type: String, + required: true, + }, + inputLabel: { + type: String, + required: true, + }, + copyButtonTitle: { + type: String, + required: true, + }, + }, + computed: { + formInputGroupProps() { + return { id: this.inputId }; + }, + }, +}; +</script> + +<template> + <div class="row"> + <div class="col-lg-12"> + <hr /> + </div> + <div class="col-lg-4"> + <h4 class="gl-mt-0"><slot name="title"></slot></h4> + <slot name="description"></slot> + </div> + <div class="col-lg-8"> + <input-copy-toggle-visibility + :label="inputLabel" + :label-for="inputId" + :form-input-group-props="formInputGroupProps" + :value="token" + :copy-button-title="copyButtonTitle" + > + <template #description> + <slot name="input-description"></slot> + </template> + </input-copy-toggle-visibility> + </div> + </div> +</template> diff --git a/app/assets/javascripts/access_tokens/components/tokens_app.vue b/app/assets/javascripts/access_tokens/components/tokens_app.vue new file mode 100644 index 00000000000..755991f64e0 --- /dev/null +++ b/app/assets/javascripts/access_tokens/components/tokens_app.vue @@ -0,0 +1,111 @@ +<script> +import { GlSprintf, GlLink } from '@gitlab/ui'; +import { pickBy } from 'lodash'; + +import { s__ } from '~/locale'; + +import { FEED_TOKEN, INCOMING_EMAIL_TOKEN, STATIC_OBJECT_TOKEN } from '../constants'; +import Token from './token.vue'; + +export default { + i18n: { + canNotAccessOtherData: s__('AccessTokens|It cannot be used to access any other data.'), + [FEED_TOKEN]: { + label: s__('AccessTokens|Feed token'), + copyButtonTitle: s__('AccessTokens|Copy feed token'), + description: s__( + 'AccessTokens|Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs.', + ), + inputDescription: s__( + 'AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}.', + ), + resetConfirmMessage: s__( + 'AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working.', + ), + }, + [INCOMING_EMAIL_TOKEN]: { + label: s__('AccessTokens|Incoming email token'), + copyButtonTitle: s__('AccessTokens|Copy incoming email token'), + description: s__( + 'AccessTokens|Your incoming email token authenticates you when you create a new issue by email, and is included in your personal project-specific email addresses.', + ), + inputDescription: s__( + 'AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}.', + ), + resetConfirmMessage: s__( + 'AccessTokens|Are you sure? Any issue email addresses currently in use will stop working.', + ), + }, + [STATIC_OBJECT_TOKEN]: { + label: s__('AccessTokens|Static object token'), + copyButtonTitle: s__('AccessTokens|Copy static object token'), + description: s__( + 'AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage.', + ), + inputDescription: s__( + 'AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}.', + ), + resetConfirmMessage: s__('AccessTokens|Are you sure?'), + }, + }, + htmlAttributes: { + [FEED_TOKEN]: { + inputId: 'feed_token', + containerTestId: 'feed-token-container', + }, + [INCOMING_EMAIL_TOKEN]: { + inputId: 'incoming_email_token', + containerTestId: 'incoming-email-token-container', + }, + [STATIC_OBJECT_TOKEN]: { + inputId: 'static_object_token', + containerTestId: 'static-object-token-container', + }, + }, + components: { Token, GlSprintf, GlLink }, + inject: ['tokenTypes'], + computed: { + enabledTokenTypes() { + return pickBy(this.tokenTypes, (tokenData, tokenType) => { + return ( + tokenData?.enabled && + this.$options.i18n[tokenType] && + this.$options.htmlAttributes[tokenType] + ); + }); + }, + }, +}; +</script> + +<template> + <div> + <token + v-for="(tokenData, tokenType) in enabledTokenTypes" + :key="tokenType" + :token="tokenData.token" + :input-id="$options.htmlAttributes[tokenType].inputId" + :input-label="$options.i18n[tokenType].label" + :copy-button-title="$options.i18n[tokenType].copyButtonTitle" + :data-testid="$options.htmlAttributes[tokenType].containerTestId" + > + <template #title>{{ $options.i18n[tokenType].label }}</template> + <template #description> + <p>{{ $options.i18n[tokenType].description }}</p> + <p>{{ $options.i18n.canNotAccessOtherData }}</p> + </template> + <template #input-description> + <gl-sprintf :message="$options.i18n[tokenType].inputDescription"> + <template #link="{ content }"> + <gl-link + :href="tokenData.resetPath" + :data-confirm="$options.i18n[tokenType].resetConfirmMessage" + data-method="put" + >{{ content }}</gl-link + > + </template> + </gl-sprintf> + </template> + </token> + </div> +</template> diff --git a/app/assets/javascripts/access_tokens/constants.js b/app/assets/javascripts/access_tokens/constants.js new file mode 100644 index 00000000000..6188c6d1bb5 --- /dev/null +++ b/app/assets/javascripts/access_tokens/constants.js @@ -0,0 +1,4 @@ +// Token types +export const FEED_TOKEN = 'feedToken'; +export const INCOMING_EMAIL_TOKEN = 'incomingEmailToken'; +export const STATIC_OBJECT_TOKEN = 'staticObjectToken'; diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js index 7f5f0403de6..9a1e7d877f8 100644 --- a/app/assets/javascripts/access_tokens/index.js +++ b/app/assets/javascripts/access_tokens/index.js @@ -1,9 +1,13 @@ import Vue from 'vue'; + import createFlash from '~/flash'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { parseRailsFormFields } from '~/lib/utils/forms'; import { __ } from '~/locale'; import ExpiresAtField from './components/expires_at_field.vue'; +import TokensApp from './components/tokens_app.vue'; +import { FEED_TOKEN, INCOMING_EMAIL_TOKEN, STATIC_OBJECT_TOKEN } from './constants'; export const initExpiresAtField = () => { const el = document.querySelector('.js-access-tokens-expires-at'); @@ -81,3 +85,29 @@ export const initProjectsField = () => { return null; }; + +export const initTokensApp = () => { + const el = document.getElementById('js-tokens-app'); + + if (!el) return false; + + const tokensData = convertObjectPropsToCamelCase(JSON.parse(el.dataset.tokensData), { + deep: true, + }); + + const tokenTypes = { + [FEED_TOKEN]: tokensData[FEED_TOKEN], + [INCOMING_EMAIL_TOKEN]: tokensData[INCOMING_EMAIL_TOKEN], + [STATIC_OBJECT_TOKEN]: tokensData[STATIC_OBJECT_TOKEN], + }; + + return new Vue({ + el, + provide: { + tokenTypes, + }, + render(createElement) { + return createElement(TokensApp); + }, + }); +}; |