API & Client - complete users administration
This commit is contained in:
parent
c92787a0d5
commit
135281fe1d
@ -1156,6 +1156,24 @@ class TestUpdateUser(ApiTestCaseMixin):
|
|||||||
|
|
||||||
self.assert_400(response, 'valid email must be provided')
|
self.assert_400(response, 'valid email must be provided')
|
||||||
|
|
||||||
|
def test_it_returns_error_when_new_email_is_same_as_current_email(
|
||||||
|
self, app: Flask, user_1_admin: User, user_2: User
|
||||||
|
) -> None:
|
||||||
|
client, auth_token = self.get_test_client_and_auth_token(
|
||||||
|
app, user_1_admin.email
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.patch(
|
||||||
|
f'/api/users/{user_2.username}',
|
||||||
|
content_type='application/json',
|
||||||
|
data=json.dumps(dict(new_email=user_2.email)),
|
||||||
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assert_400(
|
||||||
|
response, 'new email must be different than curent email'
|
||||||
|
)
|
||||||
|
|
||||||
def test_it_does_not_send_email_when_error_on_updating_email(
|
def test_it_does_not_send_email_when_error_on_updating_email(
|
||||||
self,
|
self,
|
||||||
app: Flask,
|
app: Flask,
|
||||||
@ -1233,6 +1251,52 @@ class TestUpdateUser(ApiTestCaseMixin):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_it_activates_user_account(
|
||||||
|
self, app: Flask, user_1_admin: User, inactive_user: User
|
||||||
|
) -> None:
|
||||||
|
client, auth_token = self.get_test_client_and_auth_token(
|
||||||
|
app, user_1_admin.email
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.patch(
|
||||||
|
f'/api/users/{inactive_user.username}',
|
||||||
|
content_type='application/json',
|
||||||
|
data=json.dumps(dict(activate=True)),
|
||||||
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = json.loads(response.data.decode())
|
||||||
|
assert 'success' in data['status']
|
||||||
|
assert len(data['data']['users']) == 1
|
||||||
|
user = data['data']['users'][0]
|
||||||
|
assert user['email'] == inactive_user.email
|
||||||
|
assert user['is_active'] is True
|
||||||
|
assert inactive_user.confirmation_token is None
|
||||||
|
|
||||||
|
def test_it_can_only_activate_user_account(
|
||||||
|
self, app: Flask, user_1_admin: User, user_2: User
|
||||||
|
) -> None:
|
||||||
|
client, auth_token = self.get_test_client_and_auth_token(
|
||||||
|
app, user_1_admin.email
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.patch(
|
||||||
|
f'/api/users/{user_2.username}',
|
||||||
|
content_type='application/json',
|
||||||
|
data=json.dumps(dict(activate=False)),
|
||||||
|
headers=dict(Authorization=f'Bearer {auth_token}'),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = json.loads(response.data.decode())
|
||||||
|
assert 'success' in data['status']
|
||||||
|
assert len(data['data']['users']) == 1
|
||||||
|
user = data['data']['users'][0]
|
||||||
|
assert user['email'] == user_2.email
|
||||||
|
assert user['is_active'] is True
|
||||||
|
assert user_2.confirmation_token is None
|
||||||
|
|
||||||
|
|
||||||
class TestDeleteUser(ApiTestCaseMixin):
|
class TestDeleteUser(ApiTestCaseMixin):
|
||||||
def test_user_can_delete_its_own_account(
|
def test_user_can_delete_its_own_account(
|
||||||
|
@ -395,7 +395,11 @@ def get_picture(user_name: str) -> Any:
|
|||||||
@authenticate_as_admin
|
@authenticate_as_admin
|
||||||
def update_user(auth_user: User, user_name: str) -> Union[Dict, HttpResponse]:
|
def update_user(auth_user: User, user_name: str) -> Union[Dict, HttpResponse]:
|
||||||
"""
|
"""
|
||||||
Update user to add admin rights
|
Update user account
|
||||||
|
- add/remove admin rights
|
||||||
|
- reset password and send email to update user password
|
||||||
|
- update user email
|
||||||
|
- activate account for an inactive user
|
||||||
|
|
||||||
Only user with admin rights can modify another user
|
Only user with admin rights can modify another user
|
||||||
|
|
||||||
@ -484,11 +488,18 @@ def update_user(auth_user: User, user_name: str) -> Union[Dict, HttpResponse]:
|
|||||||
|
|
||||||
:param string user_name: user name
|
:param string user_name: user name
|
||||||
|
|
||||||
|
:<json boolean activate: activate user account
|
||||||
:<json boolean admin: does the user have administrator rights
|
:<json boolean admin: does the user have administrator rights
|
||||||
|
:<json boolean new_email: new user email
|
||||||
|
:<json boolean reset_password: reset user password
|
||||||
|
|
||||||
:reqheader Authorization: OAuth 2.0 Bearer Token
|
:reqheader Authorization: OAuth 2.0 Bearer Token
|
||||||
|
|
||||||
:statuscode 200: success
|
:statuscode 200: success
|
||||||
|
:statuscode 400:
|
||||||
|
- invalid payload
|
||||||
|
- valid email must be provided
|
||||||
|
- new email must be different than curent email
|
||||||
:statuscode 401:
|
:statuscode 401:
|
||||||
- provide a valid auth token
|
- provide a valid auth token
|
||||||
- signature expired, please log in again
|
- signature expired, please log in again
|
||||||
@ -512,10 +523,11 @@ def update_user(auth_user: User, user_name: str) -> Union[Dict, HttpResponse]:
|
|||||||
if 'admin' in user_data:
|
if 'admin' in user_data:
|
||||||
user.admin = user_data['admin']
|
user.admin = user_data['admin']
|
||||||
|
|
||||||
if (
|
if user_data.get('activate', False):
|
||||||
'reset_password' in user_data
|
user.is_active = True
|
||||||
and user_data['reset_password'] is True
|
user.confirmation_token = None
|
||||||
):
|
|
||||||
|
if user_data.get('reset_password', False):
|
||||||
new_password = secrets.token_urlsafe(30)
|
new_password = secrets.token_urlsafe(30)
|
||||||
user.password = bcrypt.generate_password_hash(
|
user.password = bcrypt.generate_password_hash(
|
||||||
new_password, current_app.config.get('BCRYPT_LOG_ROUNDS')
|
new_password, current_app.config.get('BCRYPT_LOG_ROUNDS')
|
||||||
@ -524,6 +536,10 @@ def update_user(auth_user: User, user_name: str) -> Union[Dict, HttpResponse]:
|
|||||||
|
|
||||||
if 'new_email' in user_data:
|
if 'new_email' in user_data:
|
||||||
if is_valid_email(user_data['new_email']):
|
if is_valid_email(user_data['new_email']):
|
||||||
|
if user_data['new_email'] == user.email:
|
||||||
|
return InvalidPayloadErrorResponse(
|
||||||
|
'new email must be different than curent email'
|
||||||
|
)
|
||||||
user.email_to_confirm = user_data['new_email']
|
user.email_to_confirm = user_data['new_email']
|
||||||
user.confirmation_token = secrets.token_urlsafe(30)
|
user.confirmation_token = secrets.token_urlsafe(30)
|
||||||
send_new_address_email = True
|
send_new_address_email = True
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
{{ capitalize($t('workouts.WORKOUT', 0)) }}
|
{{ capitalize($t('workouts.WORKOUT', 0)) }}
|
||||||
</th>
|
</th>
|
||||||
<th>{{ $t('user.ADMIN') }}</th>
|
<th>{{ $t('user.ADMIN') }}</th>
|
||||||
|
<th>{{ $t('admin.ACTIVE') }}</th>
|
||||||
<th>{{ $t('admin.ACTION') }}</th>
|
<th>{{ $t('admin.ACTION') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -82,6 +83,15 @@
|
|||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<span class="cell-heading">
|
||||||
|
{{ $t('admin.ACTIVE') }}
|
||||||
|
</span>
|
||||||
|
<i
|
||||||
|
:class="`fa fa${user.is_active ? '-check' : ''}-square-o`"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<span class="cell-heading">
|
<span class="cell-heading">
|
||||||
{{ $t('admin.ACTION') }}
|
{{ $t('admin.ACTION') }}
|
||||||
|
@ -17,45 +17,95 @@
|
|||||||
@cancelAction="updateDisplayModal('')"
|
@cancelAction="updateDisplayModal('')"
|
||||||
/>
|
/>
|
||||||
<div class="info-box success-message" v-if="isSuccess">
|
<div class="info-box success-message" v-if="isSuccess">
|
||||||
{{ $t('admin.PASSWORD_RESET_SUCCESSFUL') }}
|
{{
|
||||||
|
$t(
|
||||||
|
`admin.${
|
||||||
|
currentAction === 'password-reset'
|
||||||
|
? 'PASSWORD_RESET'
|
||||||
|
: 'USER_EMAIL_UPDATE'
|
||||||
|
}_SUCCESSFUL`
|
||||||
|
)
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<dl>
|
<AlertMessage
|
||||||
<dt>{{ $t('user.PROFILE.REGISTRATION_DATE') }}:</dt>
|
message="user.THIS_USER_ACCOUNT_IS_INACTIVE"
|
||||||
<dd>{{ registrationDate }}</dd>
|
v-if="!user.is_active"
|
||||||
<dt>{{ $t('user.PROFILE.FIRST_NAME') }}:</dt>
|
/>
|
||||||
<dd>{{ user.first_name }}</dd>
|
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
|
||||||
<dt>{{ $t('user.PROFILE.LAST_NAME') }}:</dt>
|
<div class="email-form form-box" v-if="displayUserEmailForm">
|
||||||
<dd>{{ user.last_name }}</dd>
|
<form
|
||||||
<dt>{{ $t('user.PROFILE.BIRTH_DATE') }}:</dt>
|
:class="{ errors: formErrors }"
|
||||||
<dd>{{ birthDate }}</dd>
|
@submit.prevent="updateUserEmail(user.username)"
|
||||||
<dt>{{ $t('user.PROFILE.LOCATION') }}:</dt>
|
|
||||||
<dd>{{ user.location }}</dd>
|
|
||||||
<dt>{{ $t('user.PROFILE.BIO') }}:</dt>
|
|
||||||
<dd class="user-bio">
|
|
||||||
{{ user.bio }}
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<div class="profile-buttons" v-if="fromAdmin">
|
|
||||||
<button
|
|
||||||
class="danger"
|
|
||||||
v-if="authUser.username !== user.username"
|
|
||||||
@click.prevent="updateDisplayModal('delete')"
|
|
||||||
>
|
>
|
||||||
{{ $t('admin.DELETE_USER') }}
|
<label class="form-items" for="email">
|
||||||
</button>
|
{{ $t('admin.CURRENT_EMAIL') }}
|
||||||
<button
|
<input id="email" type="email" v-model="user.email" disabled />
|
||||||
v-if="authUser.username !== user.username"
|
</label>
|
||||||
@click.prevent="updateDisplayModal('reset')"
|
<label class="form-items" for="email">
|
||||||
>
|
{{ $t('admin.NEW_EMAIL') }}*
|
||||||
{{ $t('admin.RESET_USER_PASSWORD') }}
|
<input id="new-email" type="email" required v-model="newUserEmail" />
|
||||||
</button>
|
</label>
|
||||||
<button @click="$router.go(-1)">{{ $t('buttons.BACK') }}</button>
|
<div class="form-buttons">
|
||||||
|
<button class="confirm" type="submit">
|
||||||
|
{{ $t('buttons.SUBMIT') }}
|
||||||
|
</button>
|
||||||
|
<button class="cancel" @click.prevent="hideEmailForm">
|
||||||
|
{{ $t('buttons.CANCEL') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="profile-buttons" v-else>
|
<div v-else>
|
||||||
<button @click="$router.push('/profile/edit')">
|
<dl>
|
||||||
{{ $t('user.PROFILE.EDIT') }}
|
<dt>{{ $t('user.PROFILE.REGISTRATION_DATE') }}:</dt>
|
||||||
</button>
|
<dd>{{ registrationDate }}</dd>
|
||||||
<button @click="$router.push('/')">{{ $t('common.HOME') }}</button>
|
<dt>{{ $t('user.PROFILE.FIRST_NAME') }}:</dt>
|
||||||
|
<dd>{{ user.first_name }}</dd>
|
||||||
|
<dt>{{ $t('user.PROFILE.LAST_NAME') }}:</dt>
|
||||||
|
<dd>{{ user.last_name }}</dd>
|
||||||
|
<dt>{{ $t('user.PROFILE.BIRTH_DATE') }}:</dt>
|
||||||
|
<dd>{{ birthDate }}</dd>
|
||||||
|
<dt>{{ $t('user.PROFILE.LOCATION') }}:</dt>
|
||||||
|
<dd>{{ user.location }}</dd>
|
||||||
|
<dt>{{ $t('user.PROFILE.BIO') }}:</dt>
|
||||||
|
<dd class="user-bio">
|
||||||
|
{{ user.bio }}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<div class="profile-buttons" v-if="fromAdmin">
|
||||||
|
<button
|
||||||
|
class="danger"
|
||||||
|
v-if="authUser.username !== user.username"
|
||||||
|
@click.prevent="updateDisplayModal('delete')"
|
||||||
|
>
|
||||||
|
{{ $t('admin.DELETE_USER') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="!user.is_active"
|
||||||
|
@click.prevent="confirmUserAccount(user.username)"
|
||||||
|
>
|
||||||
|
{{ $t('admin.ACTIVATE_USER_ACCOUNT') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="authUser.username !== user.username"
|
||||||
|
@click.prevent="displayEmailForm"
|
||||||
|
>
|
||||||
|
{{ $t('admin.UPDATE_USER_EMAIL') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="authUser.username !== user.username"
|
||||||
|
@click.prevent="updateDisplayModal('reset')"
|
||||||
|
>
|
||||||
|
{{ $t('admin.RESET_USER_PASSWORD') }}
|
||||||
|
</button>
|
||||||
|
<button @click="$router.go(-1)">{{ $t('buttons.BACK') }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="profile-buttons" v-else>
|
||||||
|
<button @click="$router.push('/profile/edit')">
|
||||||
|
{{ $t('user.PROFILE.EDIT') }}
|
||||||
|
</button>
|
||||||
|
<button @click="$router.push('/')">{{ $t('common.HOME') }}</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -104,7 +154,14 @@
|
|||||||
const isSuccess = computed(
|
const isSuccess = computed(
|
||||||
() => store.getters[USERS_STORE.GETTERS.USERS_IS_SUCCESS]
|
() => store.getters[USERS_STORE.GETTERS.USERS_IS_SUCCESS]
|
||||||
)
|
)
|
||||||
|
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||||
|
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||||
|
)
|
||||||
let displayModal: Ref<string> = ref('')
|
let displayModal: Ref<string> = ref('')
|
||||||
|
const formErrors = ref(false)
|
||||||
|
const displayUserEmailForm: Ref<boolean> = ref(false)
|
||||||
|
const newUserEmail: Ref<string> = ref('')
|
||||||
|
const currentAction: Ref<string> = ref('')
|
||||||
|
|
||||||
function updateDisplayModal(value: string) {
|
function updateDisplayModal(value: string) {
|
||||||
displayModal.value = value
|
displayModal.value = value
|
||||||
@ -116,31 +173,82 @@
|
|||||||
store.dispatch(USERS_STORE.ACTIONS.DELETE_USER_ACCOUNT, { username })
|
store.dispatch(USERS_STORE.ACTIONS.DELETE_USER_ACCOUNT, { username })
|
||||||
}
|
}
|
||||||
function resetUserPassword(username: string) {
|
function resetUserPassword(username: string) {
|
||||||
|
currentAction.value = 'password-reset'
|
||||||
store.dispatch(USERS_STORE.ACTIONS.UPDATE_USER, {
|
store.dispatch(USERS_STORE.ACTIONS.UPDATE_USER, {
|
||||||
username,
|
username,
|
||||||
resetPassword: true,
|
resetPassword: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
function confirmUserAccount(username: string) {
|
||||||
onUnmounted(() => {
|
store.dispatch(USERS_STORE.ACTIONS.UPDATE_USER, {
|
||||||
|
username,
|
||||||
|
activate: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function displayEmailForm() {
|
||||||
|
resetErrorsAndSuccess()
|
||||||
|
console.log('user.value.email_to_confirm', user.value.email_to_confirm)
|
||||||
|
newUserEmail.value = user.value.email_to_confirm
|
||||||
|
? user.value.email_to_confirm
|
||||||
|
: ''
|
||||||
|
displayUserEmailForm.value = true
|
||||||
|
currentAction.value = 'email-update'
|
||||||
|
}
|
||||||
|
function hideEmailForm() {
|
||||||
|
newUserEmail.value = ''
|
||||||
|
displayUserEmailForm.value = false
|
||||||
|
}
|
||||||
|
function updateUserEmail(username: string) {
|
||||||
|
store.dispatch(USERS_STORE.ACTIONS.UPDATE_USER, {
|
||||||
|
username,
|
||||||
|
new_email: newUserEmail.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function resetErrorsAndSuccess() {
|
||||||
store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||||
store.commit(USERS_STORE.MUTATIONS.UPDATE_IS_SUCCESS, false)
|
store.commit(USERS_STORE.MUTATIONS.UPDATE_IS_SUCCESS, false)
|
||||||
})
|
currentAction.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnmounted(() => resetErrorsAndSuccess())
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => isSuccess.value,
|
() => isSuccess.value,
|
||||||
(newIsSuccess) => {
|
(newIsSuccess) => {
|
||||||
if (newIsSuccess) {
|
if (newIsSuccess) {
|
||||||
updateDisplayModal('')
|
updateDisplayModal('')
|
||||||
|
hideEmailForm()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@import '~@/scss/vars.scss';
|
||||||
#user-infos {
|
#user-infos {
|
||||||
.user-bio {
|
.user-bio {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alert-message {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-form {
|
||||||
|
display: flex;
|
||||||
|
form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.form-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: $default-padding;
|
||||||
|
margin-top: $default-margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ACTION": "Action",
|
"ACTION": "Action",
|
||||||
|
"ACTIVATE_USER_ACCOUNT": "Activate account",
|
||||||
|
"ACTIVE": "Active",
|
||||||
"ADMIN_RIGHTS_DELETE_USER_ACCOUNT": "Add/remove admin rights, delete user account.",
|
"ADMIN_RIGHTS_DELETE_USER_ACCOUNT": "Add/remove admin rights, delete user account.",
|
||||||
"ADMIN": "Admin",
|
"ADMIN": "Admin",
|
||||||
"ADMINISTRATION": "Administration",
|
"ADMINISTRATION": "Administration",
|
||||||
@ -15,8 +17,10 @@
|
|||||||
"BACK_TO_ADMIN": "Back to admin",
|
"BACK_TO_ADMIN": "Back to admin",
|
||||||
"CONFIRM_USER_ACCOUNT_DELETION": "Are you sure you want to delete {0} account? All data will be deleted, this cannot be undone.",
|
"CONFIRM_USER_ACCOUNT_DELETION": "Are you sure you want to delete {0} account? All data will be deleted, this cannot be undone.",
|
||||||
"CONFIRM_USER_PASSWORD_RESET": "Are you sure you want to reset {0} password?",
|
"CONFIRM_USER_PASSWORD_RESET": "Are you sure you want to reset {0} password?",
|
||||||
|
"CURRENT_EMAIL": "Current email",
|
||||||
"DELETE_USER": "Delete user",
|
"DELETE_USER": "Delete user",
|
||||||
"ENABLE_DISABLE_SPORTS": "Enable/disable sports.",
|
"ENABLE_DISABLE_SPORTS": "Enable/disable sports.",
|
||||||
|
"NEW_EMAIL": "New email",
|
||||||
"PASSWORD_RESET_SUCCESSFUL": "The password has been reset.",
|
"PASSWORD_RESET_SUCCESSFUL": "The password has been reset.",
|
||||||
"REGISTRATION_DISABLED": "Registration is currently disabled.",
|
"REGISTRATION_DISABLED": "Registration is currently disabled.",
|
||||||
"REGISTRATION_ENABLED": "Registration is currently enabled.",
|
"REGISTRATION_ENABLED": "Registration is currently enabled.",
|
||||||
@ -31,7 +35,9 @@
|
|||||||
"TITLE": "Sports administration"
|
"TITLE": "Sports administration"
|
||||||
},
|
},
|
||||||
"UPDATE_APPLICATION_DESCRIPTION": "Update application configuration (maximum number of registered users, maximum files size).",
|
"UPDATE_APPLICATION_DESCRIPTION": "Update application configuration (maximum number of registered users, maximum files size).",
|
||||||
|
"UPDATE_USER_EMAIL": "Update email",
|
||||||
"USER": "user | users",
|
"USER": "user | users",
|
||||||
|
"USER_EMAIL_UPDATE_SUCCESSFUL": "The email address has been updated.",
|
||||||
"USERS": {
|
"USERS": {
|
||||||
"TABLE": {
|
"TABLE": {
|
||||||
"ADD_ADMIN_RIGHTS": "Add admin rights",
|
"ADD_ADMIN_RIGHTS": "Add admin rights",
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"invalid token, please log in again": "Invalid token, please log in again.",
|
"invalid token, please log in again": "Invalid token, please log in again.",
|
||||||
"invalid token, please request a new token": "Invalid token, please log in again.",
|
"invalid token, please request a new token": "Invalid token, please log in again.",
|
||||||
"Network Error": "Network Error.",
|
"Network Error": "Network Error.",
|
||||||
|
"new email must be different than curent email": "The new email must be different than curent email",
|
||||||
"no file part": "No file provided.",
|
"no file part": "No file provided.",
|
||||||
"no selected file": "No selected file.",
|
"no selected file": "No selected file.",
|
||||||
"password: password and password confirmation do not match": "Password: password and password confirmation don't match.",
|
"password: password and password confirmation do not match": "Password: password and password confirmation don't match.",
|
||||||
|
@ -100,6 +100,7 @@
|
|||||||
"REGISTER_DISABLED": "Sorry, registration is disabled.",
|
"REGISTER_DISABLED": "Sorry, registration is disabled.",
|
||||||
"RESET_PASSWORD": "Reset your password",
|
"RESET_PASSWORD": "Reset your password",
|
||||||
"SHOW_PASSWORD": "show password",
|
"SHOW_PASSWORD": "show password",
|
||||||
|
"THIS_USER_ACCOUNT_IS_INACTIVE": "This user account is inactive.",
|
||||||
"USER_PICTURE": "user picture",
|
"USER_PICTURE": "user picture",
|
||||||
"USERNAME": "Username",
|
"USERNAME": "Username",
|
||||||
"USERNAME_INFO": "3 to 30 characters required, only alphanumeric characters and the underscore character \"_\" allowed."
|
"USERNAME_INFO": "3 to 30 characters required, only alphanumeric characters and the underscore character \"_\" allowed."
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ACTION": "Action",
|
"ACTION": "Action",
|
||||||
|
"ACTIVATE_USER_ACCOUNT": "Activer le compte",
|
||||||
|
"ACTIVE": "Actif",
|
||||||
"ADMIN_RIGHTS_DELETE_USER_ACCOUNT": "Ajouter/retirer des droits d'administration, supprimer des comptes utilisateurs.",
|
"ADMIN_RIGHTS_DELETE_USER_ACCOUNT": "Ajouter/retirer des droits d'administration, supprimer des comptes utilisateurs.",
|
||||||
"ADMIN": "Admin",
|
"ADMIN": "Admin",
|
||||||
"ADMINISTRATION": "Administration",
|
"ADMINISTRATION": "Administration",
|
||||||
@ -15,8 +17,10 @@
|
|||||||
"BACK_TO_ADMIN": "Revenir à l'admin",
|
"BACK_TO_ADMIN": "Revenir à l'admin",
|
||||||
"CONFIRM_USER_ACCOUNT_DELETION": "Êtes-vous sûr de vouloir supprimer le compte de l'utilisateur {0} ? Toutes les données seront définitivement.",
|
"CONFIRM_USER_ACCOUNT_DELETION": "Êtes-vous sûr de vouloir supprimer le compte de l'utilisateur {0} ? Toutes les données seront définitivement.",
|
||||||
"CONFIRM_USER_PASSWORD_RESET": "Êtes-vous sûr de vouloir réinitialiser le mot de passe de l'utilisateur {0} ?",
|
"CONFIRM_USER_PASSWORD_RESET": "Êtes-vous sûr de vouloir réinitialiser le mot de passe de l'utilisateur {0} ?",
|
||||||
|
"CURRENT_EMAIL": "Adresse email actuelle",
|
||||||
"DELETE_USER": "Supprimer l'utilisateur",
|
"DELETE_USER": "Supprimer l'utilisateur",
|
||||||
"ENABLE_DISABLE_SPORTS": "Activer/désactiver des sports.",
|
"ENABLE_DISABLE_SPORTS": "Activer/désactiver des sports.",
|
||||||
|
"NEW_EMAIL": "Nouvelle adresse email",
|
||||||
"PASSWORD_RESET_SUCCESSFUL": "Le mot de passe a été réinitialisé.",
|
"PASSWORD_RESET_SUCCESSFUL": "Le mot de passe a été réinitialisé.",
|
||||||
"REGISTRATION_DISABLED": "Les inscriptions sont actuellement désactivées.",
|
"REGISTRATION_DISABLED": "Les inscriptions sont actuellement désactivées.",
|
||||||
"REGISTRATION_ENABLED": "Les inscriptions sont actuellement activées.",
|
"REGISTRATION_ENABLED": "Les inscriptions sont actuellement activées.",
|
||||||
@ -31,7 +35,9 @@
|
|||||||
"TITLE": "Administration - Sports"
|
"TITLE": "Administration - Sports"
|
||||||
},
|
},
|
||||||
"UPDATE_APPLICATION_DESCRIPTION": "Configurer l'application (nombre maximum d'utilisateurs inscrits, taille maximale des fichers).",
|
"UPDATE_APPLICATION_DESCRIPTION": "Configurer l'application (nombre maximum d'utilisateurs inscrits, taille maximale des fichers).",
|
||||||
|
"UPDATE_USER_EMAIL": "Changer l'email",
|
||||||
"USER": "utilisateur | utilisateurs",
|
"USER": "utilisateur | utilisateurs",
|
||||||
|
"USER_EMAIL_UPDATE_SUCCESSFUL": "L'adresse email a été mise à jour.",
|
||||||
"USERS": {
|
"USERS": {
|
||||||
"TABLE": {
|
"TABLE": {
|
||||||
"ADD_ADMIN_RIGHTS": "Ajouter les drois d'admin",
|
"ADD_ADMIN_RIGHTS": "Ajouter les drois d'admin",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"no file part": "Pas de fichier fourni.",
|
"no file part": "Pas de fichier fourni.",
|
||||||
"no selected file": "Pas de fichier sélectionné.",
|
"no selected file": "Pas de fichier sélectionné.",
|
||||||
"Network Error": "Erreur Réseau.",
|
"Network Error": "Erreur Réseau.",
|
||||||
|
"new email must be different than curent email": "La nouvelle addresse email doit être differente de l'adresse actuelle",
|
||||||
"password: password and password confirmation do not match": "Mot de passe : les mots de passe saisis sont différents.",
|
"password: password and password confirmation do not match": "Mot de passe : les mots de passe saisis sont différents.",
|
||||||
"provide a valid auth token": "Merci de fournir un jeton de connexion valide.",
|
"provide a valid auth token": "Merci de fournir un jeton de connexion valide.",
|
||||||
"sport does not exist": "Ce sport n'existe pas.",
|
"sport does not exist": "Ce sport n'existe pas.",
|
||||||
|
@ -99,6 +99,7 @@
|
|||||||
"RESENT_ACCOUNT_CONFIRMATION": "Envoyer à nouveau l'email de confirmation de compte",
|
"RESENT_ACCOUNT_CONFIRMATION": "Envoyer à nouveau l'email de confirmation de compte",
|
||||||
"RESET_PASSWORD": "Réinitialiser votre mot de passe",
|
"RESET_PASSWORD": "Réinitialiser votre mot de passe",
|
||||||
"SHOW_PASSWORD": "afficher le mot de passe",
|
"SHOW_PASSWORD": "afficher le mot de passe",
|
||||||
|
"THIS_USER_ACCOUNT_IS_INACTIVE": "Le compte de cet utilisateur est inactif.",
|
||||||
"USER_PICTURE": "photo de l'utilisateur",
|
"USER_PICTURE": "photo de l'utilisateur",
|
||||||
"USERNAME": "Nom d'utilisateur",
|
"USERNAME": "Nom d'utilisateur",
|
||||||
"USERNAME_INFO": "3 à 30 caractères requis, seuls les caractères alphanumériques et le caractère \"_\" sont autorisés."
|
"USERNAME_INFO": "3 à 30 caractères requis, seuls les caractères alphanumériques et le caractère \"_\" sont autorisés."
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
--footer-border-color: #ebeef3;
|
--footer-border-color: #ebeef3;
|
||||||
--footer-color: #8b8c8c;
|
--footer-color: #8b8c8c;
|
||||||
|
|
||||||
--alert-background-color: #c8cdd3;
|
--alert-background-color: #d6dde3;
|
||||||
--alert-color: #3f3f3f;
|
--alert-color: #3f3f3f;
|
||||||
--info-background-color: #e5e7ea;
|
--info-background-color: #e5e7ea;
|
||||||
--info-color: var(--app-color);
|
--info-color: var(--app-color);
|
||||||
|
@ -105,13 +105,19 @@ export const actions: ActionTree<IUsersState, IRootState> & IUsersActions = {
|
|||||||
): void {
|
): void {
|
||||||
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||||
context.commit(USERS_STORE.MUTATIONS.UPDATE_IS_SUCCESS, false)
|
context.commit(USERS_STORE.MUTATIONS.UPDATE_IS_SUCCESS, false)
|
||||||
const data: Record<string, boolean> = {}
|
const data: Record<string, boolean | string> = {}
|
||||||
if (payload.admin !== undefined) {
|
if (payload.admin !== undefined) {
|
||||||
data.admin = payload.admin
|
data.admin = payload.admin
|
||||||
}
|
}
|
||||||
if (payload.resetPassword !== undefined) {
|
if (payload.resetPassword) {
|
||||||
data.reset_password = payload.resetPassword
|
data.reset_password = payload.resetPassword
|
||||||
}
|
}
|
||||||
|
if (payload.activate) {
|
||||||
|
data.activate = payload.activate
|
||||||
|
}
|
||||||
|
if (payload.new_email !== undefined) {
|
||||||
|
data.new_email = payload.new_email
|
||||||
|
}
|
||||||
authApi
|
authApi
|
||||||
.patch(`users/${payload.username}`, data)
|
.patch(`users/${payload.username}`, data)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@ -120,7 +126,15 @@ export const actions: ActionTree<IUsersState, IRootState> & IUsersActions = {
|
|||||||
USERS_STORE.MUTATIONS.UPDATE_USER_IN_USERS,
|
USERS_STORE.MUTATIONS.UPDATE_USER_IN_USERS,
|
||||||
res.data.data.users[0]
|
res.data.data.users[0]
|
||||||
)
|
)
|
||||||
context.commit(USERS_STORE.MUTATIONS.UPDATE_IS_SUCCESS, true)
|
if (payload.resetPassword || payload.new_email) {
|
||||||
|
context.commit(USERS_STORE.MUTATIONS.UPDATE_IS_SUCCESS, true)
|
||||||
|
}
|
||||||
|
if (payload.activate || payload.new_email) {
|
||||||
|
context.commit(
|
||||||
|
USERS_STORE.MUTATIONS.UPDATE_USER,
|
||||||
|
res.data.data.users[0]
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
handleError(context, null)
|
handleError(context, null)
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,8 @@ export interface IAdminUserPayload {
|
|||||||
username: string
|
username: string
|
||||||
admin?: boolean
|
admin?: boolean
|
||||||
resetPassword?: boolean
|
resetPassword?: boolean
|
||||||
|
activate?: boolean
|
||||||
|
new_email?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUserPreferencesPayload {
|
export interface IUserPreferencesPayload {
|
||||||
|
Loading…
Reference in New Issue
Block a user