Fix editing project team member permissions (#5315)
* Fix editing project team member permissions * prepare * add success notifications --------- Co-authored-by: tdgao <mr.trumgao@gmail.com>
This commit is contained in:
@@ -499,9 +499,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
<!--
|
||||||
|
if we save changes and update an org member which:
|
||||||
|
- is not currently overridden (!allOrgMembers[index].oldOverride)
|
||||||
|
- and we're not changing them to be overridden (!allOrgMembers[index].override)
|
||||||
|
|
||||||
|
then we end up editing an org member which, in the backend, doesn't exist.
|
||||||
|
the api doesn't let us do that, we can only do:
|
||||||
|
- !override -> override: POST member
|
||||||
|
- override -> !override: DELETE member
|
||||||
|
- override -> override: PATCH member
|
||||||
|
- !override -> !override: do nothing
|
||||||
|
|
||||||
|
we don't allow clicking the button in that last case.
|
||||||
|
-->
|
||||||
<button
|
<button
|
||||||
class="iconified-button brand-button"
|
class="iconified-button brand-button"
|
||||||
:disabled="(currentMember?.permissions & EDIT_MEMBER) !== EDIT_MEMBER"
|
:disabled="
|
||||||
|
(currentMember?.permissions & EDIT_MEMBER) !== EDIT_MEMBER ||
|
||||||
|
(!allOrgMembers[index].oldOverride && !allOrgMembers[index].override)
|
||||||
|
"
|
||||||
@click="updateOrgMember(index)"
|
@click="updateOrgMember(index)"
|
||||||
>
|
>
|
||||||
<SaveIcon />
|
<SaveIcon />
|
||||||
@@ -565,22 +582,21 @@ function initMembers() {
|
|||||||
|
|
||||||
const selectedMembersForOrg = orgMembers.map((partialOrgMember) => {
|
const selectedMembersForOrg = orgMembers.map((partialOrgMember) => {
|
||||||
const foundMember = allMembers.value.find((tM) => tM.user.id === partialOrgMember.user.id)
|
const foundMember = allMembers.value.find((tM) => tM.user.id === partialOrgMember.user.id)
|
||||||
const returnVal = foundMember ?? partialOrgMember
|
|
||||||
|
|
||||||
// If replacing a partial with a full member, we need to mark as such.
|
const base = foundMember ?? partialOrgMember
|
||||||
returnVal.override = !!foundMember
|
return {
|
||||||
returnVal.oldOverride = !!foundMember
|
...base,
|
||||||
|
override: !!foundMember,
|
||||||
returnVal.is_owner = partialOrgMember.is_owner
|
oldOverride: !!foundMember,
|
||||||
|
is_owner: partialOrgMember.is_owner,
|
||||||
return returnVal
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
allOrgMembers.value = selectedMembersForOrg
|
allOrgMembers.value = selectedMembersForOrg
|
||||||
|
|
||||||
allTeamMembers.value = allMembers.value.filter(
|
allTeamMembers.value = allMembers.value
|
||||||
(x) => !selectedMembersForOrg.some((y) => y.user.id === x.user.id),
|
.filter((x) => !selectedMembersForOrg.some((y) => y.user.id === x.user.id))
|
||||||
)
|
.map((x) => ({ ...x }))
|
||||||
}
|
}
|
||||||
|
|
||||||
watch([allMembers, organization, project, currentMember], initMembers)
|
watch([allMembers, organization, project, currentMember], initMembers)
|
||||||
@@ -688,6 +704,11 @@ const removeTeamMember = async (index) => {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
await updateMembers()
|
await updateMembers()
|
||||||
|
addNotification({
|
||||||
|
title: 'Member removed',
|
||||||
|
text: "Your project's member has been removed.",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
addNotification({
|
addNotification({
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
@@ -748,6 +769,11 @@ const transferOwnership = async (index) => {
|
|||||||
user_id: allTeamMembers.value[index].user.id,
|
user_id: allTeamMembers.value[index].user.id,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
addNotification({
|
||||||
|
title: 'Member ownership transferred',
|
||||||
|
text: `${allTeamMembers.value[index].user.username} is now the owner of the project.`,
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
await updateMembers()
|
await updateMembers()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
addNotification({
|
addNotification({
|
||||||
@@ -795,6 +821,11 @@ async function updateOrgMember(index) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
await updateMembers()
|
await updateMembers()
|
||||||
|
addNotification({
|
||||||
|
title: 'Member(s) updated',
|
||||||
|
text: "Your project's member(s) has been updated.",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
addNotification({
|
addNotification({
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use crate::queue::session::AuthQueue;
|
|||||||
use crate::routes::ApiError;
|
use crate::routes::ApiError;
|
||||||
use actix_web::{HttpRequest, HttpResponse, web};
|
use actix_web::{HttpRequest, HttpResponse, web};
|
||||||
use ariadne::ids::UserId;
|
use ariadne::ids::UserId;
|
||||||
|
use eyre::eyre;
|
||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@@ -708,10 +709,10 @@ pub async fn edit_team_member(
|
|||||||
DBTeamMember::get_from_user_id_pending(id, user_id, &**pool)
|
DBTeamMember::get_from_user_id_pending(id, user_id, &**pool)
|
||||||
.await?
|
.await?
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
ApiError::CustomAuthentication(
|
ApiError::Request(eyre!(
|
||||||
"You don't have permission to edit members of this team"
|
"This member does not exist in this team - \
|
||||||
.to_string(),
|
the member must first be created via `POST`"
|
||||||
)
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut transaction = pool.begin().await?;
|
let mut transaction = pool.begin().await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user