Skip to content

Commit

Permalink
Merge pull request #3756 from uselagoon/add-to-group-invite
Browse files Browse the repository at this point in the history
feat: add inviteUser boolean to addUserToGroup
  • Loading branch information
tobybellwood authored Jul 4, 2024
2 parents 17b7868 + 87dfda6 commit 32725db
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ mutation PopulateApi {
name
}

UIOrganizationUserInviteToGroup: addUserToGroup(
input: {
user: {
email:"invite@example.com"
}
group: {
name: "lagoon-demo-organization-group"
}
role: GUEST
inviteUser: true
}
) {
name
}

UIOrganizationAddViewer: addUserToOrganization(input: {user: {email: "orgviewer@example.com"}, organization: 1}) {
id
}
Expand Down
15 changes: 15 additions & 0 deletions local-dev/k3d-seed-data/00-populate-kubernetes.gql
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,21 @@ mutation PopulateApi {
name
}

UIOrganizationUserInviteToGroup: addUserToGroup(
input: {
user: {
email:"invite@example.com"
}
group: {
name: "lagoon-demo-organization-group"
}
role: GUEST
inviteUser: true
}
) {
name
}

UIOrganizationAddViewer: addUserToOrganization(input: {user: {email: "orgviewer@example.com"}, organization: 1}) {
id
}
Expand Down
6 changes: 3 additions & 3 deletions services/api/src/models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ export const User = (clients: {
`Username ${R.prop('username', userInput)} exists`
);
} else {
throw new Error(`Error creating Keycloak user: ${err.message}`);
throw new Error(`Error creating Lagoon user account: ${err.message}`);
}
}

Expand Down Expand Up @@ -541,7 +541,7 @@ export const User = (clients: {
if (err.response.status && err.response.status === 404) {
throw new UserNotFoundError(`User not found: ${id}`);
} else {
throw new Error(`Error updating Keycloak user: ${err.message}`);
throw new Error(`Error updating Lagoon user account: ${err.message}`);
}
}
};
Expand Down Expand Up @@ -637,7 +637,7 @@ export const User = (clients: {
if (err.response.status && err.response.status === 404) {
throw new UserNotFoundError(`User not found: ${userInput.id}`);
} else {
throw new Error(`Error updating Keycloak user: ${err.message}`);
throw new Error(`Error updating Lagoon user account: ${err.message}`);
}
}

Expand Down
52 changes: 46 additions & 6 deletions services/api/src/resources/group/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,33 +536,73 @@ export const deleteAllGroups: ResolverFn = async (

export const addUserToGroup: ResolverFn = async (
_root,
{ input: { user: userInput, group: groupInput, role } },
{ input: { user: userInput, group: groupInput, role, inviteUser } },
{ models, hasPermission, userActivityLogger }
) => {
if (R.isEmpty(userInput)) {
throw new Error('You must provide a user id or email');
}

const user = await models.UserModel.loadUserByIdOrUsername({
id: R.prop('id', userInput),
email: R.prop('email', userInput)
});

if (R.isEmpty(groupInput)) {
throw new Error('You must provide a group id or name');
}

const group = await models.GroupModel.loadGroupByIdOrName(groupInput);

let user;
let createUserErr;
try {
// check if user already exists
user = await models.UserModel.loadUserByIdOrUsername({
id: R.prop('id', userInput),
email: R.prop('email', userInput)
});
} catch (e) {
// capture the error
createUserErr = e
// if inviteuser is false, and there is an error, return the error
if (createUserErr && !inviteUser) {
return createUserErr
}
}

if (R.prop('lagoon-organization', group.attributes)) {
// if this is a group in an organization, check that the user adding members to the group in this org is in the org
await hasPermission('organization', 'addGroup', {
organization: R.prop('lagoon-organization', group.attributes)
});
// only organization:addGroup will be able to "invite users" this way
if (createUserErr && createUserErr.message.includes("User not found") && inviteUser) {
const email = R.prop('email', userInput);
// check if email is provided
if (email) {
await hasPermission('user', 'add');
try {
// then create the user account
user = await models.UserModel.addUser({
email: email,
username: email,
}, true);
logger.debug(`UserInvite: User created and password reset requested for ${email}`);
} catch (e) {
return e
}
} else {
// otherwise return whatever error loadUserByIdOrUsername returned
return createUserErr
}
}
} else {
await hasPermission('group', 'addUser', {
group: group.id
});
if (createUserErr && createUserErr.message.includes("User not found") && inviteUser) {
// otherwise return the error
throw new Error('Cannot invite user to group that is not in an organization');
} else {
// otherwise return whatever error loadUserByIdOrUsername returned
return createUserErr
}
}

await models.GroupModel.removeUserFromGroup(user, group);
Expand Down
1 change: 1 addition & 0 deletions services/api/src/typeDefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2289,6 +2289,7 @@ const typeDefs = gql`
user: UserInput!
group: GroupInput!
role: GroupRole!
inviteUser: Boolean
}
input ProjectGroupsInput {
Expand Down

0 comments on commit 32725db

Please sign in to comment.