Compare commits

...
Author SHA1 Message Date
Sojan Jose 6af34335a8 test: add spec for profile access token reset 2025-05-23 02:22:16 -07:00
11 changed files with 84 additions and 6 deletions
@@ -38,6 +38,11 @@ class Api::V1::ProfilesController < Api::BaseController
head :ok
end
def reset_access_token
@user.access_token.regenerate_token
@user.reload
end
private
def set_user
+4
View File
@@ -102,4 +102,8 @@ export default {
const urlData = endPoints('resendConfirmation');
return axios.post(urlData.url);
},
resetAccessToken() {
const urlData = endPoints('resetAccessToken');
return axios.post(urlData.url);
},
};
@@ -51,6 +51,9 @@ const endPoints = {
resendConfirmation: {
url: '/api/v1/profile/resend_confirmation',
},
resetAccessToken: {
url: '/api/v1/profile/reset_access_token',
},
};
export default page => {
@@ -76,7 +76,10 @@
"ACCESS_TOKEN": {
"TITLE": "Access Token",
"NOTE": "This token can be used if you are building an API based integration",
"COPY": "Copy"
"COPY": "Copy",
"RESET": "Reset",
"RESET_SUCCESS": "Access token regenerated",
"RESET_ERROR": "Could not reset token"
},
"AUDIO_NOTIFICATIONS_SECTION": {
"TITLE": "Audio Alerts",
@@ -7,7 +7,7 @@ const props = defineProps({
default: '',
},
});
const emit = defineEmits(['onCopy']);
const emit = defineEmits(['onCopy', 'onReset']);
const inputType = ref('password');
const toggleMasked = () => {
inputType.value = inputType.value === 'password' ? 'text' : 'password';
@@ -20,6 +20,10 @@ const maskIcon = computed(() => {
const onClick = () => {
emit('onCopy', props.value);
};
const onReset = () => {
emit('onReset');
};
</script>
<template>
@@ -56,5 +60,15 @@ const onClick = () => {
>
{{ $t('PROFILE_SETTINGS.FORM.ACCESS_TOKEN.COPY') }}
</FormButton>
<FormButton
type="button"
size="large"
icon="key"
variant="outline"
color-scheme="primary"
@click="onReset"
>
{{ $t('PROFILE_SETTINGS.FORM.ACCESS_TOKEN.RESET') }}
</FormButton>
</div>
</template>
@@ -181,6 +181,14 @@ export default {
await copyTextToClipboard(value);
useAlert(this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL'));
},
async resetAccessToken() {
const success = await this.$store.dispatch('resetAccessToken');
if (success) {
useAlert(this.$t('PROFILE_SETTINGS.FORM.ACCESS_TOKEN.RESET_SUCCESS'));
} else {
useAlert(this.$t('PROFILE_SETTINGS.FORM.ACCESS_TOKEN.RESET_ERROR'));
}
},
},
};
</script>
@@ -281,7 +289,11 @@ export default {
)
"
>
<AccessToken :value="currentUser.access_token" @on-copy="onCopyToken" />
<AccessToken
:value="currentUser.access_token"
@on-copy="onCopyToken"
@on-reset="resetAccessToken"
/>
</FormSection>
</div>
</template>
@@ -213,6 +213,16 @@ export const actions = {
}
},
resetAccessToken: async ({ commit }) => {
try {
const response = await authAPI.resetAccessToken();
commit(types.SET_CURRENT_USER, response.data);
return true;
} catch (error) {
return false;
}
},
resendConfirmation: async () => {
try {
await authAPI.resendConfirmation();
@@ -0,0 +1 @@
json.partial! 'api/v1/models/user', formats: [:json], resource: @user
-3
View File
@@ -16,16 +16,13 @@ development:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_dev') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', '') %>"
test:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_test') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', '') %>"
production:
<<: *default
database: "<%= ENV.fetch('POSTGRES_DATABASE', 'chatwoot_production') %>"
username: "<%= ENV.fetch('POSTGRES_USERNAME', 'chatwoot_prod') %>"
password: "<%= ENV.fetch('POSTGRES_PASSWORD', 'chatwoot_prod') %>"
+1
View File
@@ -295,6 +295,7 @@ Rails.application.routes.draw do
post :auto_offline
put :set_active_account
post :resend_confirmation
post :reset_access_token
end
end
@@ -296,4 +296,32 @@ RSpec.describe 'Profile API', type: :request do
end
end
end
describe 'POST /api/v1/profile/reset_access_token' do
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
post '/api/v1/profile/reset_access_token'
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
let(:agent) { create(:user, account: account, role: :agent) }
it 'regenerates the access token' do
old_token = agent.access_token.token
post '/api/v1/profile/reset_access_token',
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
agent.reload
json_response = response.parsed_body
expect(json_response['access_token']).to eq(agent.access_token.token)
expect(agent.access_token.token).not_to eq(old_token)
end
end
end
end