|
14 | 14 | render_template, |
15 | 15 | request, |
16 | 16 | url_for, |
| 17 | + flash, |
17 | 18 | ) |
18 | 19 | from flask_security import ( |
19 | 20 | current_user, |
|
49 | 50 |
|
50 | 51 | from cabotage.server.models.auth import ( |
51 | 52 | Organization, |
| 53 | + User, |
52 | 54 | ) |
| 55 | +from cabotage.server.models.auth_associations import OrganizationMember |
53 | 56 | from cabotage.server.models.projects import ( |
54 | 57 | DEFAULT_POD_CLASS, |
55 | 58 | Application, |
|
73 | 76 | EditApplicationSettingsForm, |
74 | 77 | EditConfigurationForm, |
75 | 78 | ReleaseDeployForm, |
| 79 | + AddOrganizationUserForm, |
76 | 80 | ) |
77 | 81 |
|
78 | 82 | from cabotage.utils.docker_auth import ( |
@@ -1608,3 +1612,102 @@ def github_hooks(): |
1608 | 1612 | process_github_hook.delay(hook_id=hook.id) |
1609 | 1613 | return jsonify({"hook_id": hook.id}) |
1610 | 1614 | abort(403) |
| 1615 | + |
| 1616 | + |
| 1617 | +@user_blueprint.route("/organizations/<org_slug>/users/add", methods=["GET", "POST"]) |
| 1618 | +@login_required |
| 1619 | +def organization_add_user(org_slug): |
| 1620 | + organization = Organization.query.filter_by(slug=org_slug).first_or_404() |
| 1621 | + if not AdministerOrganizationPermission(organization.id).can(): |
| 1622 | + abort(403) |
| 1623 | + |
| 1624 | + form = AddOrganizationUserForm() |
| 1625 | + all_users = User.query.all() if current_user.admin else None |
| 1626 | + |
| 1627 | + if form.validate_on_submit(): |
| 1628 | + if user := User.query.filter_by(email=form.email.data).first(): |
| 1629 | + organization.add_user(user) |
| 1630 | + db.session.commit() |
| 1631 | + flash("User has been added to the organization.", "success") |
| 1632 | + return redirect(url_for("user.organization", org_slug=org_slug)) |
| 1633 | + else: |
| 1634 | + flash("User with this email address does not exist.", "error") |
| 1635 | + return render_template( |
| 1636 | + "user/organization_add_user.html", |
| 1637 | + organization=organization, |
| 1638 | + form=form, |
| 1639 | + all_users=all_users, |
| 1640 | + ) |
| 1641 | + |
| 1642 | + |
| 1643 | +@user_blueprint.route("/organizations/<org_slug>/users/remove", methods=["POST"]) |
| 1644 | +@login_required |
| 1645 | +def organization_remove_user(org_slug): |
| 1646 | + organization = Organization.query.filter_by(slug=org_slug).first_or_404() |
| 1647 | + if not AdministerOrganizationPermission(organization.id).can(): |
| 1648 | + abort(403) |
| 1649 | + |
| 1650 | + user_id = request.form.get("user_id") |
| 1651 | + if user := User.query.get(user_id): |
| 1652 | + org_user_count = len(organization.members) |
| 1653 | + if org_user_count <= 1: |
| 1654 | + flash( |
| 1655 | + "Cannot remove the last user from an organization. Add someone else first!", |
| 1656 | + "warning", |
| 1657 | + ) |
| 1658 | + else: |
| 1659 | + organization.remove_user(user) |
| 1660 | + db.session.commit() |
| 1661 | + flash( |
| 1662 | + f"User {user.email} removed from organization {organization.name}.", |
| 1663 | + "success", |
| 1664 | + ) |
| 1665 | + else: |
| 1666 | + flash("User not found.", "error") |
| 1667 | + return redirect(url_for("user.organization", org_slug=org_slug)) |
| 1668 | + |
| 1669 | + |
| 1670 | +@user_blueprint.route("/organizations/<org_slug>/users/promote", methods=["POST"]) |
| 1671 | +@login_required |
| 1672 | +def organization_promote_user(org_slug): |
| 1673 | + organization = Organization.query.filter_by(slug=org_slug).first_or_404() |
| 1674 | + if not AdministerOrganizationPermission(organization.id).can(): |
| 1675 | + abort(403) |
| 1676 | + |
| 1677 | + user_id = request.form.get("user_id") |
| 1678 | + if user := User.query.get(user_id): |
| 1679 | + if member := OrganizationMember.query.filter_by( |
| 1680 | + user_id=user.id, organization_id=organization.id |
| 1681 | + ).first(): |
| 1682 | + member.admin = True |
| 1683 | + db.session.commit() |
| 1684 | + flash( |
| 1685 | + f"User {user.email} promoted to admin in {organization.name}.", |
| 1686 | + "success", |
| 1687 | + ) |
| 1688 | + else: |
| 1689 | + flash("User not found.", "error") |
| 1690 | + return redirect(url_for("user.organization", org_slug=org_slug)) |
| 1691 | + |
| 1692 | + |
| 1693 | +@user_blueprint.route("/organizations/<org_slug>/users/demote", methods=["POST"]) |
| 1694 | +@login_required |
| 1695 | +def organization_demote_user(org_slug): |
| 1696 | + organization = Organization.query.filter_by(slug=org_slug).first_or_404() |
| 1697 | + if not AdministerOrganizationPermission(organization.id).can(): |
| 1698 | + abort(403) |
| 1699 | + |
| 1700 | + user_id = request.form.get("user_id") |
| 1701 | + if user := User.query.get(user_id): |
| 1702 | + if member := OrganizationMember.query.filter_by( |
| 1703 | + user_id=user.id, organization_id=organization.id |
| 1704 | + ).first(): |
| 1705 | + member.admin = False |
| 1706 | + db.session.commit() |
| 1707 | + flash( |
| 1708 | + f"User {user.email} demoted to member in {organization.name}.", |
| 1709 | + "success", |
| 1710 | + ) |
| 1711 | + else: |
| 1712 | + flash("User not found.", "error") |
| 1713 | + return redirect(url_for("user.organization", org_slug=org_slug)) |
0 commit comments